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
24 var req ServerReserveSigningKeyRequest
25 if err := e.Bind(&req); err != nil {
26 s.logger.Error("could not bind reserve signing key request", "error", err)
27 return helpers.ServerError(e, nil)
28 }
29
30 if req.Did != nil && *req.Did != "" {
31 var existing models.ReservedKey
32 if err := s.db.Raw(ctx, "SELECT * FROM reserved_keys WHERE did = ?", nil, *req.Did).Scan(&existing).Error; err == nil && existing.KeyDid != "" {
33 return e.JSON(200, ServerReserveSigningKeyResponse{
34 SigningKey: existing.KeyDid,
35 })
36 }
37 }
38
39 k, err := atcrypto.GeneratePrivateKeyK256()
40 if err != nil {
41 s.logger.Error("error creating signing key", "endpoint", "com.atproto.server.reserveSigningKey", "error", err)
42 return helpers.ServerError(e, nil)
43 }
44
45 pubKey, err := k.PublicKey()
46 if err != nil {
47 s.logger.Error("error getting public key", "endpoint", "com.atproto.server.reserveSigningKey", "error", err)
48 return helpers.ServerError(e, nil)
49 }
50
51 keyDid := pubKey.DIDKey()
52
53 reservedKey := models.ReservedKey{
54 KeyDid: keyDid,
55 Did: req.Did,
56 PrivateKey: k.Bytes(),
57 CreatedAt: time.Now(),
58 }
59
60 if err := s.db.Create(ctx, &reservedKey, nil).Error; err != nil {
61 s.logger.Error("error storing reserved key", "endpoint", "com.atproto.server.reserveSigningKey", "error", err)
62 return helpers.ServerError(e, nil)
63 }
64
65 s.logger.Info("reserved signing key", "keyDid", keyDid, "forDid", req.Did)
66
67 return e.JSON(200, ServerReserveSigningKeyResponse{
68 SigningKey: keyDid,
69 })
70}
71
72func (s *Server) getReservedKey(ctx context.Context, keyDidOrDid string) (*models.ReservedKey, error) {
73 var reservedKey models.ReservedKey
74
75 if err := s.db.Raw(ctx, "SELECT * FROM reserved_keys WHERE key_did = ?", nil, keyDidOrDid).Scan(&reservedKey).Error; err == nil && reservedKey.KeyDid != "" {
76 return &reservedKey, nil
77 }
78
79 if err := s.db.Raw(ctx, "SELECT * FROM reserved_keys WHERE did = ?", nil, keyDidOrDid).Scan(&reservedKey).Error; err == nil && reservedKey.KeyDid != "" {
80 return &reservedKey, nil
81 }
82
83 return nil, nil
84}
85
86func (s *Server) deleteReservedKey(ctx context.Context, keyDid string, did *string) error {
87 if err := s.db.Exec(ctx, "DELETE FROM reserved_keys WHERE key_did = ?", nil, keyDid).Error; err != nil {
88 return err
89 }
90
91 if did != nil && *did != "" {
92 if err := s.db.Exec(ctx, "DELETE FROM reserved_keys WHERE did = ?", nil, *did).Error; err != nil {
93 return err
94 }
95 }
96
97 return nil
98}