abac/sqlite_store.go

146 lines
3.0 KiB
Go
Raw Normal View History

package abac
import (
"database/sql"
"github.com/google/uuid"
_ "github.com/mattn/go-sqlite3"
)
type SQLiteStore struct {
db *sql.DB
}
func NewSQLiteStore(dbPath string) (*SQLiteStore, error) {
db, err := sql.Open("sqlite3", dbPath)
if err != nil {
return nil, err
}
store := &SQLiteStore{db: db}
err = store.createTables(db)
if err != nil {
return nil, err
}
return store, nil
}
func (s *SQLiteStore) Close() error {
return s.db.Close()
}
func (s *SQLiteStore) GetUserAttributes(userID string) ([]Attribute, error) {
rows, err := s.db.Query(`
SELECT a.key, a.value
FROM attributes a
JOIN user_attributes ua ON a.id = ua.attribute_id
WHERE ua.user_id = ?;
`, userID)
if err != nil {
return nil, err
}
defer rows.Close()
var attributes []Attribute
for rows.Next() {
var attribute Attribute
err := rows.Scan(&attribute.Key, &attribute.Value)
if err != nil {
return nil, err
}
attributes = append(attributes, attribute)
}
return attributes, nil
}
func (s *SQLiteStore) GetResourceAttributes(resourceID string) ([]Attribute, error) {
rows, err := s.db.Query(`
SELECT a.key, a.value
FROM attributes a
JOIN resource_attributes ra ON a.id = ra.attribute_id
WHERE ra.resource_id = ?;
`, resourceID)
if err != nil {
return nil, err
}
defer rows.Close()
var attributes []Attribute
for rows.Next() {
var attribute Attribute
err := rows.Scan(&attribute.Key, &attribute.Value)
if err != nil {
return nil, err
}
attributes = append(attributes, attribute)
}
return attributes, nil
}
func newID() string {
uuid, err := uuid.NewV7()
if err != nil {
panic(err)
}
return uuid.String()
}
func (s *SQLiteStore) CreatePolicy(effect, action, conditionAttributeKey, conditionAttributeValue string) error {
_, err := s.db.Exec(`
INSERT INTO policies (id, effect, action, condition_attribute_key, condition_attribute_value)
VALUES (?, ?, ?, ?, ?);
`, newID(), effect, action, conditionAttributeKey, conditionAttributeValue)
return err
}
func (s *SQLiteStore) createTables(db *sql.DB) error {
_, err := db.Exec(`
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
username TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS resources (
id TEXT PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS attributes (
id TEXT PRIMARY KEY,
key TEXT NOT NULL,
value TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS user_attributes (
user_id TEXT NOT NULL,
attribute_id INTEGER NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (attribute_id) REFERENCES attributes(id)
);
CREATE TABLE IF NOT EXISTS resource_attributes (
resource_id TEXT NOT NULL,
attribute_id TEXT NOT NULL,
FOREIGN KEY (resource_id) REFERENCES resources(id),
FOREIGN KEY (attribute_id) REFERENCES attributes(id)
);
CREATE TABLE IF NOT EXISTS policies (
id TEXT PRIMARY KEY,
effect TEXT NOT NULL CHECK(effect IN ('Allow', 'Deny')),
action TEXT NOT NULL,
condition_attribute_key TEXT,
condition_attribute_value TEXT
);
`)
return err
}