Files
2026-05-06 10:14:55 +03:00

89 lines
2.7 KiB
Go

package server
import (
"encoding/base64"
"net/mail"
"strings"
"galaxy/backend/internal/auth"
)
// ed25519PublicKeyLen is the fixed size of a raw Ed25519 public key. The
// OpenAPI contract documents `client_public_key` as a "Standard
// base64-encoded raw 32-byte Ed25519 public key"; the handler enforces
// the length after decode so the auth service always operates on the
// canonical shape.
const ed25519PublicKeyLen = 32
// deviceSessionPayload is the JSON body the internal session endpoints
// emit. It mirrors the `DeviceSession` schema in `openapi.yaml`.
type deviceSessionPayload struct {
DeviceSessionID string `json:"device_session_id"`
UserID string `json:"user_id"`
Status string `json:"status"`
ClientPublicKey string `json:"client_public_key,omitempty"`
CreatedAt string `json:"created_at"`
RevokedAt *string `json:"revoked_at,omitempty"`
LastSeenAt *string `json:"last_seen_at,omitempty"`
}
func deviceSessionToWire(s auth.Session) deviceSessionPayload {
out := deviceSessionPayload{
DeviceSessionID: s.DeviceSessionID.String(),
UserID: s.UserID.String(),
Status: s.Status,
CreatedAt: s.CreatedAt.UTC().Format("2006-01-02T15:04:05.000Z07:00"),
}
if len(s.ClientPublicKey) > 0 {
out.ClientPublicKey = base64.StdEncoding.EncodeToString(s.ClientPublicKey)
}
if s.RevokedAt != nil {
formatted := s.RevokedAt.UTC().Format("2006-01-02T15:04:05.000Z07:00")
out.RevokedAt = &formatted
}
if s.LastSeenAt != nil {
formatted := s.LastSeenAt.UTC().Format("2006-01-02T15:04:05.000Z07:00")
out.LastSeenAt = &formatted
}
return out
}
// validateEmail returns the trimmed value when raw parses as an
// addr-spec, or "" when raw is malformed. Auth normalises to lowercase
// internally; the handler only enforces the syntactic shape.
func validateEmail(raw string) string {
addr, err := mail.ParseAddress(strings.TrimSpace(raw))
if err != nil {
return ""
}
return addr.Address
}
// decodeClientPublicKey decodes the wire-format client_public_key into
// raw bytes and validates the length. Standard base64 (with padding) is
// the canonical encoding documented in `openapi.yaml`.
func decodeClientPublicKey(raw string) ([]byte, bool) {
decoded, err := base64.StdEncoding.DecodeString(strings.TrimSpace(raw))
if err != nil {
return nil, false
}
if len(decoded) != ed25519PublicKeyLen {
return nil, false
}
return decoded, true
}
// isDecimalCodeOfLength reports whether s is a string of exactly want
// ASCII digits.
func isDecimalCodeOfLength(s string, want int) bool {
if len(s) != want {
return false
}
for i := 0; i < len(s); i++ {
if s[i] < '0' || s[i] > '9' {
return false
}
}
return true
}