1package server
2
3import (
4 "time"
5
6 "github.com/bluesky-social/indigo/atproto/atcrypto"
7 "github.com/haileyok/cocoon/internal/helpers"
8 "github.com/haileyok/cocoon/models"
9 "github.com/labstack/echo/v4"
10)
11
12type ServerReserveSigningKeyRequest struct {
13 Did *string `json:"did"`
14}
15
16type ServerReserveSigningKeyResponse struct {
17 SigningKey string `json:"signingKey"`
18}
19
20func (s *Server) handleServerReserveSigningKey(e echo.Context) error {
21 var req ServerReserveSigningKeyRequest
22 if err := e.Bind(&req); err != nil {
23 s.logger.Error("could not bind reserve signing key request", "error", err)
24 return helpers.ServerError(e, nil)
25 }
26
27 if req.Did != nil && *req.Did != "" {
28 var existing models.ReservedKey
29 if err := s.db.Raw("SELECT * FROM reserved_keys WHERE did = ?", nil, *req.Did).Scan(&existing).Error; err == nil && existing.KeyDid != "" {
30 return e.JSON(200, ServerReserveSigningKeyResponse{
31 SigningKey: existing.KeyDid,
32 })
33 }
34 }
35
36 k, err := atcrypto.GeneratePrivateKeyK256()
37 if err != nil {
38 s.logger.Error("error creating signing key", "endpoint", "com.atproto.server.reserveSigningKey", "error", err)
39 return helpers.ServerError(e, nil)
40 }
41
42 pubKey, err := k.PublicKey()
43 if err != nil {
44 s.logger.Error("error getting public key", "endpoint", "com.atproto.server.reserveSigningKey", "error", err)
45 return helpers.ServerError(e, nil)
46 }
47
48 keyDid := pubKey.DIDKey()
49
50 reservedKey := models.ReservedKey{
51 KeyDid: keyDid,
52 Did: req.Did,
53 PrivateKey: k.Bytes(),
54 CreatedAt: time.Now(),
55 }
56
57 if err := s.db.Create(&reservedKey, nil).Error; err != nil {
58 s.logger.Error("error storing reserved key", "endpoint", "com.atproto.server.reserveSigningKey", "error", err)
59 return helpers.ServerError(e, nil)
60 }
61
62 s.logger.Info("reserved signing key", "keyDid", keyDid, "forDid", req.Did)
63
64 return e.JSON(200, ServerReserveSigningKeyResponse{
65 SigningKey: keyDid,
66 })
67}
68
69func (s *Server) getReservedKey(keyDidOrDid string) (*models.ReservedKey, error) {
70 var reservedKey models.ReservedKey
71
72 if err := s.db.Raw("SELECT * FROM reserved_keys WHERE key_did = ?", nil, keyDidOrDid).Scan(&reservedKey).Error; err == nil && reservedKey.KeyDid != "" {
73 return &reservedKey, nil
74 }
75
76 if err := s.db.Raw("SELECT * FROM reserved_keys WHERE did = ?", nil, keyDidOrDid).Scan(&reservedKey).Error; err == nil && reservedKey.KeyDid != "" {
77 return &reservedKey, nil
78 }
79
80 return nil, nil
81}
82
83func (s *Server) deleteReservedKey(keyDid string, did *string) error {
84 if err := s.db.Exec("DELETE FROM reserved_keys WHERE key_did = ?", nil, keyDid).Error; err != nil {
85 return err
86 }
87
88 if did != nil && *did != "" {
89 if err := s.db.Exec("DELETE FROM reserved_keys WHERE did = ?", nil, *did).Error; err != nil {
90 return err
91 }
92 }
93
94 return nil
95}