@@ -3,43 +3,146 @@ package arangodb
33import (
44 "context"
55 "fmt"
6+ "time"
7+
8+ arangoDriver "github.com/arangodb/go-driver"
9+ "github.com/google/uuid"
610
711 "github.com/authorizerdev/authorizer/internal/graph/model"
812 "github.com/authorizerdev/authorizer/internal/storage/schemas"
913)
1014
1115// AddTrustedIssuer creates a new trusted issuer record.
12- // TODO(phase1-pr3): implement ArangoDB provider.
13- func (p * provider ) AddTrustedIssuer (_ context.Context , _ * schemas.TrustedIssuer ) (* schemas.TrustedIssuer , error ) {
14- return nil , fmt .Errorf ("arangodb: AddTrustedIssuer not implemented" )
16+ func (p * provider ) AddTrustedIssuer (ctx context.Context , issuer * schemas.TrustedIssuer ) (* schemas.TrustedIssuer , error ) {
17+ if issuer .ID == "" {
18+ issuer .ID = uuid .New ().String ()
19+ }
20+ issuer .Key = issuer .ID
21+ now := time .Now ().Unix ()
22+ issuer .CreatedAt = now
23+ issuer .UpdatedAt = now
24+ issuerCollection , _ := p .db .Collection (ctx , schemas .Collections .TrustedIssuer )
25+ meta , err := issuerCollection .CreateDocument (ctx , issuer )
26+ if err != nil {
27+ return nil , err
28+ }
29+ issuer .Key = meta .Key
30+ issuer .ID = meta .ID .String ()
31+ return issuer , nil
1532}
1633
1734// UpdateTrustedIssuer updates a trusted issuer record.
18- // TODO(phase1-pr3): implement ArangoDB provider.
19- func (p * provider ) UpdateTrustedIssuer (_ context.Context , _ * schemas.TrustedIssuer ) (* schemas.TrustedIssuer , error ) {
20- return nil , fmt .Errorf ("arangodb: UpdateTrustedIssuer not implemented" )
35+ // Callers MUST load the existing record and mutate it before calling this
36+ // method — the document replace writes every field.
37+ func (p * provider ) UpdateTrustedIssuer (ctx context.Context , issuer * schemas.TrustedIssuer ) (* schemas.TrustedIssuer , error ) {
38+ if issuer .CreatedAt == 0 {
39+ return nil , fmt .Errorf ("UpdateTrustedIssuer: caller must load record before updating (CreatedAt is zero — partial struct detected)" )
40+ }
41+ issuer .UpdatedAt = time .Now ().Unix ()
42+ issuerCollection , _ := p .db .Collection (ctx , schemas .Collections .TrustedIssuer )
43+ meta , err := issuerCollection .UpdateDocument (ctx , issuer .Key , issuer )
44+ if err != nil {
45+ return nil , err
46+ }
47+ issuer .Key = meta .Key
48+ issuer .ID = meta .ID .String ()
49+ return issuer , nil
2150}
2251
2352// DeleteTrustedIssuer removes a trusted issuer record.
24- // TODO(phase1-pr3): implement ArangoDB provider.
25- func (p * provider ) DeleteTrustedIssuer (_ context.Context , _ * schemas.TrustedIssuer ) error {
26- return fmt .Errorf ("arangodb: DeleteTrustedIssuer not implemented" )
53+ func (p * provider ) DeleteTrustedIssuer (ctx context.Context , issuer * schemas.TrustedIssuer ) error {
54+ issuerCollection , _ := p .db .Collection (ctx , schemas .Collections .TrustedIssuer )
55+ _ , err := issuerCollection .RemoveDocument (ctx , issuer .Key )
56+ if err != nil {
57+ return err
58+ }
59+ return nil
2760}
2861
2962// GetTrustedIssuerByID fetches a trusted issuer by primary key.
30- // TODO(phase1-pr3): implement ArangoDB provider.
31- func (p * provider ) GetTrustedIssuerByID (_ context.Context , _ string ) (* schemas.TrustedIssuer , error ) {
32- return nil , fmt .Errorf ("arangodb: GetTrustedIssuerByID not implemented" )
63+ func (p * provider ) GetTrustedIssuerByID (ctx context.Context , id string ) (* schemas.TrustedIssuer , error ) {
64+ var issuer * schemas.TrustedIssuer
65+ query := fmt .Sprintf ("FOR d in %s FILTER d._id == @id LIMIT 1 RETURN d" , schemas .Collections .TrustedIssuer )
66+ bindVars := map [string ]interface {}{
67+ "id" : id ,
68+ }
69+ cursor , err := p .db .Query (ctx , query , bindVars )
70+ if err != nil {
71+ return nil , err
72+ }
73+ defer func () { _ = cursor .Close () }()
74+ for {
75+ if ! cursor .HasMore () {
76+ if issuer == nil {
77+ return nil , fmt .Errorf ("trusted issuer not found" )
78+ }
79+ break
80+ }
81+ _ , err := cursor .ReadDocument (ctx , & issuer )
82+ if err != nil {
83+ return nil , err
84+ }
85+ }
86+ return issuer , nil
3387}
3488
3589// GetTrustedIssuerByIssuerURL fetches a trusted issuer by its unique issuer URL.
36- // TODO(phase1-pr3): implement ArangoDB provider.
37- func (p * provider ) GetTrustedIssuerByIssuerURL (_ context.Context , _ string ) (* schemas.TrustedIssuer , error ) {
38- return nil , fmt .Errorf ("arangodb: GetTrustedIssuerByIssuerURL not implemented" )
90+ // Called on every client_assertion validation — kept as a single indexed lookup.
91+ func (p * provider ) GetTrustedIssuerByIssuerURL (ctx context.Context , issuerURL string ) (* schemas.TrustedIssuer , error ) {
92+ var issuer * schemas.TrustedIssuer
93+ query := fmt .Sprintf ("FOR d in %s FILTER d.issuer_url == @issuer_url LIMIT 1 RETURN d" , schemas .Collections .TrustedIssuer )
94+ bindVars := map [string ]interface {}{
95+ "issuer_url" : issuerURL ,
96+ }
97+ cursor , err := p .db .Query (ctx , query , bindVars )
98+ if err != nil {
99+ return nil , err
100+ }
101+ defer func () { _ = cursor .Close () }()
102+ for {
103+ if ! cursor .HasMore () {
104+ if issuer == nil {
105+ return nil , fmt .Errorf ("trusted issuer not found" )
106+ }
107+ break
108+ }
109+ _ , err := cursor .ReadDocument (ctx , & issuer )
110+ if err != nil {
111+ return nil , err
112+ }
113+ }
114+ return issuer , nil
39115}
40116
41117// ListTrustedIssuers returns paginated trusted issuers, optionally filtered by serviceAccountID.
42- // TODO(phase1-pr3): implement ArangoDB provider.
43- func (p * provider ) ListTrustedIssuers (_ context.Context , _ string , _ * model.Pagination ) ([]* schemas.TrustedIssuer , * model.Pagination , error ) {
44- return nil , nil , fmt .Errorf ("arangodb: ListTrustedIssuers not implemented" )
118+ func (p * provider ) ListTrustedIssuers (ctx context.Context , serviceAccountID string , pagination * model.Pagination ) ([]* schemas.TrustedIssuer , * model.Pagination , error ) {
119+ issuers := []* schemas.TrustedIssuer {}
120+ filter := ""
121+ bindVars := map [string ]interface {}{}
122+ if serviceAccountID != "" {
123+ filter = "FILTER d.service_account_id == @service_account_id "
124+ bindVars ["service_account_id" ] = serviceAccountID
125+ }
126+ query := fmt .Sprintf ("FOR d in %s %sSORT d.created_at DESC LIMIT %d, %d RETURN d" , schemas .Collections .TrustedIssuer , filter , pagination .Offset , pagination .Limit )
127+ sctx := arangoDriver .WithQueryFullCount (ctx )
128+ cursor , err := p .db .Query (sctx , query , bindVars )
129+ if err != nil {
130+ return nil , nil , err
131+ }
132+ defer func () { _ = cursor .Close () }()
133+ paginationClone := pagination
134+ paginationClone .Total = cursor .Statistics ().FullCount ()
135+ for {
136+ var issuer * schemas.TrustedIssuer
137+ meta , err := cursor .ReadDocument (ctx , & issuer )
138+ if arangoDriver .IsNoMoreDocuments (err ) {
139+ break
140+ } else if err != nil {
141+ return nil , nil , err
142+ }
143+ if meta .Key != "" {
144+ issuers = append (issuers , issuer )
145+ }
146+ }
147+ return issuers , paginationClone , nil
45148}
0 commit comments