Files
motr-enclave/internal/keybase/actions_credential.go

156 lines
3.9 KiB
Go

package keybase
import (
"context"
"encoding/json"
"fmt"
)
type NewCredentialInput struct {
CredentialID string `json:"credential_id"`
PublicKey string `json:"public_key"`
PublicKeyAlg int64 `json:"public_key_alg"`
AAGUID string `json:"aaguid,omitempty"`
Transports []string `json:"transports"`
DeviceName string `json:"device_name"`
DeviceType string `json:"device_type"`
Authenticator string `json:"authenticator,omitempty"`
IsDiscoverable bool `json:"is_discoverable"`
BackedUp bool `json:"backed_up"`
}
func (am *ActionManager) CreateCredential(ctx context.Context, params NewCredentialInput) (*CredentialResult, error) {
am.kb.mu.Lock()
defer am.kb.mu.Unlock()
if am.kb.didID == 0 {
return nil, fmt.Errorf("DID not initialized")
}
var aaguid, authenticator *string
if params.AAGUID != "" {
aaguid = &params.AAGUID
}
if params.Authenticator != "" {
authenticator = &params.Authenticator
}
transports, err := json.Marshal(params.Transports)
if err != nil {
return nil, fmt.Errorf("marshal transports: %w", err)
}
var isDiscoverable, backedUp int64
if params.IsDiscoverable {
isDiscoverable = 1
}
if params.BackedUp {
backedUp = 1
}
cred, err := am.kb.queries.CreateCredential(ctx, CreateCredentialParams{
DidID: am.kb.didID,
CredentialID: params.CredentialID,
PublicKey: params.PublicKey,
PublicKeyAlg: params.PublicKeyAlg,
Aaguid: aaguid,
Transports: transports,
DeviceName: params.DeviceName,
DeviceType: params.DeviceType,
Authenticator: authenticator,
IsDiscoverable: isDiscoverable,
BackedUp: backedUp,
})
if err != nil {
return nil, fmt.Errorf("create credential: %w", err)
}
return credentialToResult(&cred), nil
}
func (am *ActionManager) UpdateCredentialCounter(ctx context.Context, credentialID string, signCount int64) error {
am.kb.mu.Lock()
defer am.kb.mu.Unlock()
cred, err := am.kb.queries.GetCredentialByID(ctx, credentialID)
if err != nil {
return fmt.Errorf("get credential: %w", err)
}
return am.kb.queries.UpdateCredentialCounter(ctx, UpdateCredentialCounterParams{
SignCount: signCount,
ID: cred.ID,
})
}
func (am *ActionManager) RenameCredential(ctx context.Context, credentialID string, newName string) error {
am.kb.mu.Lock()
defer am.kb.mu.Unlock()
cred, err := am.kb.queries.GetCredentialByID(ctx, credentialID)
if err != nil {
return fmt.Errorf("get credential: %w", err)
}
return am.kb.queries.RenameCredential(ctx, RenameCredentialParams{
DeviceName: newName,
ID: cred.ID,
})
}
func (am *ActionManager) DeleteCredential(ctx context.Context, credentialID string) error {
am.kb.mu.Lock()
defer am.kb.mu.Unlock()
if am.kb.didID == 0 {
return fmt.Errorf("DID not initialized")
}
cred, err := am.kb.queries.GetCredentialByID(ctx, credentialID)
if err != nil {
return fmt.Errorf("get credential: %w", err)
}
return am.kb.queries.DeleteCredential(ctx, DeleteCredentialParams{
ID: cred.ID,
DidID: am.kb.didID,
})
}
func (am *ActionManager) CountCredentialsByDID(ctx context.Context) (int64, error) {
am.kb.mu.RLock()
defer am.kb.mu.RUnlock()
if am.kb.didID == 0 {
return 0, nil
}
return am.kb.queries.CountCredentialsByDID(ctx, am.kb.didID)
}
func credentialToResult(cred *Credential) *CredentialResult {
var transports []string
if err := json.Unmarshal(cred.Transports, &transports); err != nil {
transports = []string{}
}
authenticator := ""
if cred.Authenticator != nil {
authenticator = *cred.Authenticator
}
return &CredentialResult{
ID: cred.ID,
CredentialID: cred.CredentialID,
DeviceName: cred.DeviceName,
DeviceType: cred.DeviceType,
Authenticator: authenticator,
Transports: transports,
SignCount: cred.SignCount,
IsDiscoverable: cred.IsDiscoverable == 1,
BackedUp: cred.BackedUp == 1,
CreatedAt: cred.CreatedAt,
LastUsed: cred.LastUsed,
}
}