package db import ( "encoding/json" "fmt" "git.wntrmute.dev/kyle/mcr/internal/policy" ) // ruleBody is the JSON structure stored in the rule_json column. type ruleBody struct { Effect string `json:"effect"` Roles []string `json:"roles,omitempty"` AccountTypes []string `json:"account_types,omitempty"` SubjectUUID string `json:"subject_uuid,omitempty"` Actions []string `json:"actions"` Repositories []string `json:"repositories,omitempty"` } // LoadEnabledPolicyRules returns all enabled policy rules from the database, // ordered by priority ascending. It implements policy.RuleStore. func (d *DB) LoadEnabledPolicyRules() ([]policy.Rule, error) { rows, err := d.Query( `SELECT id, priority, description, rule_json FROM policy_rules WHERE enabled = 1 ORDER BY priority ASC`, ) if err != nil { return nil, fmt.Errorf("db: load policy rules: %w", err) } defer func() { _ = rows.Close() }() var rules []policy.Rule for rows.Next() { var id int64 var priority int var description, ruleJSON string if err := rows.Scan(&id, &priority, &description, &ruleJSON); err != nil { return nil, fmt.Errorf("db: scan policy rule: %w", err) } var body ruleBody if err := json.Unmarshal([]byte(ruleJSON), &body); err != nil { return nil, fmt.Errorf("db: parse rule_json for rule %d: %w", id, err) } rule := policy.Rule{ ID: id, Priority: priority, Description: description, Effect: policy.Effect(body.Effect), Roles: body.Roles, AccountTypes: body.AccountTypes, SubjectUUID: body.SubjectUUID, Repositories: body.Repositories, } for _, a := range body.Actions { rule.Actions = append(rule.Actions, policy.Action(a)) } rules = append(rules, rule) } if err := rows.Err(); err != nil { return nil, fmt.Errorf("db: iterate policy rules: %w", err) } return rules, nil }