package store import ( "context" "encoding/json" "atlas9.dev/c/core" "atlas9.dev/c/core/dbi" "atlas9.dev/c/core/iam" "atlas9.dev/c/demo/lib" ) type SqliteRoleStore struct { db dbi.DBI guard lib.Guard } var _ iam.RoleStore = (*SqliteRoleStore)(nil) func NewSqliteRoleStore(db dbi.DBI, guard lib.Guard) *SqliteRoleStore { return &SqliteRoleStore{db: db, guard: guard} } func (s *SqliteRoleStore) Save(ctx context.Context, role *iam.Role) error { if err := s.guard.Check(ctx, iam.CapRolesSave, role.Tenant, ""); err != nil { return err } caps, err := json.Marshal(role.Caps) if err != nil { return err } _, err = s.db.Exec(ctx, ` INSERT INTO roles (slug, tenant, name, caps) VALUES ($1, $2, $3, $4) ON CONFLICT (slug, tenant) DO UPDATE SET name = $3, caps = $4 `, role.Slug, role.Tenant, role.Name, string(caps)) return err } func (s *SqliteRoleStore) Delete(ctx context.Context, tenant core.ID, slug string) error { var role iam.Role if err := s.Get(ctx, tenant, slug, &role); err != nil { return err } if err := s.guard.Check(ctx, iam.CapRolesDelete, role.Tenant, ""); err != nil { return err } _, err := s.db.Exec(ctx, `DELETE FROM roles WHERE slug = $1 AND tenant = $2`, slug, tenant) return err } func (s *SqliteRoleStore) Get(ctx context.Context, tenant core.ID, slug string, out *iam.Role) error { if err := s.guard.Check(ctx, iam.CapRolesGet, tenant, ""); err != nil { return err } row := s.db.QueryRow(ctx, `SELECT slug, tenant, name, caps FROM roles WHERE slug = $1 AND tenant = $2`, slug, tenant) var capsJSON string if err := row.Scan(&out.Slug, &out.Tenant, &out.Name, &capsJSON); err != nil { return err } if err := json.Unmarshal([]byte(capsJSON), &out.Caps); err != nil { return err } return nil } func (s *SqliteRoleStore) List(ctx context.Context, tenant core.ID, page core.PageReq, out *core.Page[iam.Role]) error { limit := page.Limit if limit <= 0 { limit = 100 } rows, err := s.db.Query(ctx, ` SELECT slug, tenant, name, caps FROM roles WHERE tenant = $1 AND slug > $2 ORDER BY slug LIMIT $3 `, tenant, page.Cursor, limit) if err != nil { return err } defer rows.Close() for rows.Next() { var r iam.Role var capsJSON string if err := rows.Scan(&r.Slug, &r.Tenant, &r.Name, &capsJSON); err != nil { return err } if err := json.Unmarshal([]byte(capsJSON), &r.Caps); err != nil { return err } out.Items = append(out.Items, r) } if err := rows.Err(); err != nil { return err } if len(out.Items) == limit { out.Cursor = out.Items[limit-1].Slug } return nil // return &core.Page[iam.Role]{Items: items, Cursor: cursor}, nil }