db.go
1package abac
2
3import (
4 "database/sql"
5 "embed"
6 "fmt"
7 "log/slog"
8
9 "git.kilimanjaro.io/rtw/pkg/log"
10 "github.com/pressly/goose/v3"
11)
12
13//go:generate lit -t schema.lit
14
15//go:embed schema/*.sql
16var migrations embed.FS
17
18func Migrate(db *sql.DB) error {
19 goose.SetBaseFS(migrations)
20 goose.SetLogger(log.GooseLogger(slog.String("migrations", "pkg/abac/schema")))
21
22 if err := goose.SetDialect("sqlite3"); err != nil {
23 return fmt.Errorf("error setting abac database type: %w", err)
24 }
25
26 if err := goose.Up(db, "schema", goose.WithNoVersioning()); err != nil {
27 return fmt.Errorf("error migrating abac tables: %w", err)
28 }
29 return nil
30}
31
32//go:embed get_permissions_for_user.sql
33var getPermsForUser string
34
35type UserPermission struct {
36 ResourceType string
37 ResourceID int64
38 Permission Permission
39}
40
41// GetPermissionsForUser returns all permissions directly assigned to a user.
42func GetPermissionsForUser(db *sql.DB, userID int64) ([]UserPermission, error) {
43 rows, err := db.Query(getPermsForUser, userID)
44 if err != nil {
45 return nil, fmt.Errorf("failed querying permissions for user_id=%d: %w", userID, err)
46 }
47 defer rows.Close()
48
49 var perms []UserPermission
50 for rows.Next() {
51 var p UserPermission
52 if err := rows.Scan(&p.ResourceType, &p.ResourceID, &p.Permission); err != nil {
53 return nil, fmt.Errorf("failed scanning permission for user_id=%d: %w", userID, err)
54 }
55 perms = append(perms, p)
56 }
57 if err := rows.Err(); err != nil {
58 return nil, fmt.Errorf("failed iterating permissions for user_id=%d: %w", userID, err)
59 }
60 return perms, nil
61}
62
63//go:embed get_permission.sql
64var getStmt string
65
66// GetPermission
67func GetPermission(db *sql.DB, resourceType string, resourceID int64, userID int64) (Permission, error) {
68 var p Permission
69 err := db.QueryRow(getStmt, resourceType, resourceID, userID).Scan(&p)
70 return p, err
71}
72
73//go:embed set_default_for_type.sql
74var setDefType string
75
76// SetDefaulteForType
77func SetDefaultForType(db *sql.DB, resourceType string, p Permission) error {
78 _, err := db.Exec(setDefType, resourceType, p)
79 if err != nil {
80 return fmt.Errorf("failed setting permissions for resource type=%s: %w", resourceType, err)
81 }
82 return nil
83}
84
85//go:embed set_default_for_resource.sql
86var setDefRes string
87
88// SetDefaultForResource
89func SetDefaultForResource(db *sql.DB, resourceType string, resourceID int64, p Permission) error {
90 _, err := db.Exec(setDefRes, resourceType, resourceID, p)
91 if err != nil {
92 return fmt.Errorf("failed setting permissions for resource type=%s, resource_id=%d: %w", resourceType, resourceID, err)
93 }
94 return nil
95}
96
97//go:embed set_permission_for_user.sql
98var setPermUser string
99
100// SetPermissionForUser
101func SetPermissionForUser(db *sql.DB, resourceType string, resourceID int64, userID int64, p Permission) error {
102 _, err := db.Exec(setPermUser, resourceType, resourceID, userID, p)
103 if err != nil {
104 return fmt.Errorf("failed setting permissions for resource type=%s, resource_id=%d, user_id=%d: %w", resourceType, resourceID, userID, err)
105 }
106 return nil
107}
108
109//go:embed set_default_for_user.sql
110var setDefUser string
111
112// SetDefaultForUser
113func SetDefaultForUser(db *sql.DB, resourceType string, userID int64, p Permission) error {
114 _, err := db.Exec(setDefUser, resourceType, userID, p)
115 if err != nil {
116 return fmt.Errorf("failed setting default permissions for resource type=%s, user_id=%d: %w", resourceType, userID, err)
117 }
118 return nil
119}
120
121//go:embed set_permission_for_attribute.sql
122var setPermAttr string
123
124// SetPermissionForAttribute
125func SetPermissionForAttribute(db *sql.DB, resourceType string, resourceID int64, key string, value any, p Permission) error {
126 _, err := db.Exec(setPermAttr, key, value, resourceType, resourceID, key, value, p)
127 if err != nil {
128 return fmt.Errorf("failed setting permissions for resource type=%s, resource_id=%d, attribute=(%s, %v): %w", resourceType, resourceID, key, value, err)
129 }
130 return nil
131}
132
133//go:embed set_default_for_attribute.sql
134var setDefAttr string
135
136// SetDefaultForAttribute
137func SetDefaultForAttribute(db *sql.DB, resourceType string, key string, value any, p Permission) error {
138 _, err := db.Exec(setDefAttr, key, value, resourceType, key, value, p)
139 if err != nil {
140 return fmt.Errorf("failed setting default permissions for resource type=%s, attribute=(%s, %v): %w", resourceType, key, value, err)
141 }
142 return nil
143}
144
145//go:embed set_attribute_for_user.sql
146var setAttrUser string
147
148// SetAttributeForUser
149func SetAttributeForUser(db *sql.DB, key string, value any, userID int64) error {
150 // uniqueness constraints on these tables ensure only one row for every unique attribute key, value combo
151 _, err := db.Exec(setAttrUser, key, value, key, value, userID)
152 if err != nil {
153 return fmt.Errorf("failed inserting attributes (%s, %s) for user=%d: %w", key, value, userID, err)
154 }
155 return nil
156}