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}