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