1package backend23import (4 "context"5 "errors"6 "time"78 "github.com/charmbracelet/soft-serve/pkg/db"9 "github.com/charmbracelet/soft-serve/pkg/proto"10 "github.com/charmbracelet/soft-serve/pkg/utils"11)1213// CreateAccessToken creates an access token for user.14func (b *Backend) CreateAccessToken(ctx context.Context, user proto.User, name string, expiresAt time.Time) (string, error) {15 token := GenerateToken()16 tokenHash := HashToken(token)17 name = utils.Sanitize(name)1819 if err := b.db.TransactionContext(ctx, func(tx *db.Tx) error {20 _, err := b.store.CreateAccessToken(ctx, tx, name, user.ID(), tokenHash, expiresAt)21 if err != nil {22 return db.WrapError(err)23 }2425 return nil26 }); err != nil {27 return "", err28 }2930 return token, nil31}3233// DeleteAccessToken deletes an access token for a user.34func (b *Backend) DeleteAccessToken(ctx context.Context, user proto.User, id int64) error {35 err := b.db.TransactionContext(ctx, func(tx *db.Tx) error {36 _, err := b.store.GetAccessToken(ctx, tx, id)37 if err != nil {38 return db.WrapError(err)39 }4041 if err := b.store.DeleteAccessTokenForUser(ctx, tx, user.ID(), id); err != nil {42 return db.WrapError(err)43 }44 return nil45 })46 if err != nil {47 if errors.Is(err, db.ErrRecordNotFound) {48 return proto.ErrTokenNotFound49 }50 return err51 }5253 return nil54}5556// ListAccessTokens lists access tokens for a user.57func (b *Backend) ListAccessTokens(ctx context.Context, user proto.User) ([]proto.AccessToken, error) {58 accessTokens, err := b.store.GetAccessTokensByUserID(ctx, b.db, user.ID())59 if err != nil {60 return nil, db.WrapError(err)61 }6263 var tokens []proto.AccessToken64 for _, t := range accessTokens {65 token := proto.AccessToken{66 ID: t.ID,67 Name: t.Name,68 TokenHash: t.Token,69 UserID: t.UserID,70 CreatedAt: t.CreatedAt,71 }72 if t.ExpiresAt.Valid {73 token.ExpiresAt = t.ExpiresAt.Time74 }7576 tokens = append(tokens, token)77 }7879 return tokens, nil80}