feat(permission): add SQLite repository implementation
Add SQLite migration for permissions table. Add SQLC queries for permission CRUD operations. Implement PermissionRepository with Get, Set, Delete, GetAll methods. Update models and querier for permission support.
- commit
- de0845e529a9858c77efdf919a8dc7e79d377411
- author
- brice · · 2026-01-30 05:01 UTC
- committer
- brice · · 2026-02-07 11:53 UTC
- parent
- 13fbcf4
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
6 files · +267 -0
A internal/infrastructure/persistence/sqlite/migrations/007_permissions.sql +17 -0
| @@ -0,0 +1,17 @@ | |||
| 1 | + | -- +goose Up | |
| 2 | + | -- Permission storage for media access (mic, camera, etc.) | |
| 3 | + | -- Per W3C spec: display capture permissions cannot be persisted | |
| 4 | + | ||
| 5 | + | CREATE TABLE IF NOT EXISTS permissions ( | |
| 6 | + | origin TEXT NOT NULL, | |
| 7 | + | permission_type TEXT NOT NULL, | |
| 8 | + | decision TEXT NOT NULL CHECK(decision IN ('granted', 'denied')), | |
| 9 | + | updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
| 10 | + | PRIMARY KEY (origin, permission_type) | |
| 11 | + | ); | |
| 12 | + | ||
| 13 | + | CREATE INDEX IF NOT EXISTS idx_permissions_origin ON permissions(origin); | |
| 14 | + | CREATE INDEX IF NOT EXISTS idx_permissions_updated_at ON permissions(updated_at); | |
| 15 | + | ||
| 16 | + | -- +goose Down | |
| 17 | + | DROP TABLE IF EXISTS permissions; | |
| @@ -0,0 +1,17 @@ | |||||
| 1 | + | -- +goose Up | |||
| 2 | + | -- Permission storage for media access (mic, camera, etc.) | |||
| 3 | + | -- Per W3C spec: display capture permissions cannot be persisted | |||
| 4 | + | ||||
| 5 | + | CREATE TABLE IF NOT EXISTS permissions ( | |||
| 6 | + | origin TEXT NOT NULL, | |||
| 7 | + | permission_type TEXT NOT NULL, | |||
| 8 | + | decision TEXT NOT NULL CHECK(decision IN ('granted', 'denied')), | |||
| 9 | + | updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |||
| 10 | + | PRIMARY KEY (origin, permission_type) | |||
| 11 | + | ); | |||
| 12 | + | ||||
| 13 | + | CREATE INDEX IF NOT EXISTS idx_permissions_origin ON permissions(origin); | |||
| 14 | + | CREATE INDEX IF NOT EXISTS idx_permissions_updated_at ON permissions(updated_at); | |||
| 15 | + | ||||
| 16 | + | -- +goose Down | |||
| 17 | + | DROP TABLE IF EXISTS permissions; | |||
A internal/infrastructure/persistence/sqlite/permission_repo.go +92 -0
| @@ -0,0 +1,92 @@ | |||
| 1 | + | package sqlite | |
| 2 | + | ||
| 3 | + | import ( | |
| 4 | + | "context" | |
| 5 | + | "database/sql" | |
| 6 | + | "errors" | |
| 7 | + | ||
| 8 | + | "github.com/bnema/dumber/internal/domain/entity" | |
| 9 | + | "github.com/bnema/dumber/internal/domain/repository" | |
| 10 | + | "github.com/bnema/dumber/internal/infrastructure/persistence/sqlite/sqlc" | |
| 11 | + | "github.com/bnema/dumber/internal/logging" | |
| 12 | + | ) | |
| 13 | + | ||
| 14 | + | type permissionRepo struct { | |
| 15 | + | queries *sqlc.Queries | |
| 16 | + | } | |
| 17 | + | ||
| 18 | + | // NewPermissionRepository creates a new SQLite-backed permission repository. | |
| 19 | + | func NewPermissionRepository(db *sql.DB) repository.PermissionRepository { | |
| 20 | + | return &permissionRepo{queries: sqlc.New(db)} | |
| 21 | + | } | |
| 22 | + | ||
| 23 | + | func (r *permissionRepo) Get(ctx context.Context, origin string, permType entity.PermissionType) (*entity.PermissionRecord, error) { | |
| 24 | + | log := logging.FromContext(ctx) | |
| 25 | + | log.Debug().Str("origin", origin).Str("type", string(permType)).Msg("getting permission") | |
| 26 | + | ||
| 27 | + | row, err := r.queries.GetPermission(ctx, sqlc.GetPermissionParams{ | |
| 28 | + | Origin: origin, | |
| 29 | + | PermissionType: string(permType), | |
| 30 | + | }) | |
| 31 | + | if err != nil { | |
| 32 | + | if errors.Is(err, sql.ErrNoRows) { | |
| 33 | + | return nil, nil | |
| 34 | + | } | |
| 35 | + | return nil, err | |
| 36 | + | } | |
| 37 | + | ||
| 38 | + | return permissionFromRow(row), nil | |
| 39 | + | } | |
| 40 | + | ||
| 41 | + | func (r *permissionRepo) Set(ctx context.Context, record *entity.PermissionRecord) error { | |
| 42 | + | log := logging.FromContext(ctx) | |
| 43 | + | log.Debug(). | |
| 44 | + | Str("origin", record.Origin). | |
| 45 | + | Str("type", string(record.Type)). | |
| 46 | + | Str("decision", string(record.Decision)). | |
| 47 | + | Msg("setting permission") | |
| 48 | + | ||
| 49 | + | return r.queries.SetPermission(ctx, sqlc.SetPermissionParams{ | |
| 50 | + | Origin: record.Origin, | |
| 51 | + | PermissionType: string(record.Type), | |
| 52 | + | Decision: string(record.Decision), | |
| 53 | + | }) | |
| 54 | + | } | |
| 55 | + | ||
| 56 | + | func (r *permissionRepo) Delete(ctx context.Context, origin string, permType entity.PermissionType) error { | |
| 57 | + | log := logging.FromContext(ctx) | |
| 58 | + | log.Debug().Str("origin", origin).Str("type", string(permType)).Msg("deleting permission") | |
| 59 | + | ||
| 60 | + | return r.queries.DeletePermission(ctx, sqlc.DeletePermissionParams{ | |
| 61 | + | Origin: origin, | |
| 62 | + | PermissionType: string(permType), | |
| 63 | + | }) | |
| 64 | + | } | |
| 65 | + | ||
| 66 | + | func (r *permissionRepo) GetAll(ctx context.Context, origin string) ([]*entity.PermissionRecord, error) { | |
| 67 | + | log := logging.FromContext(ctx) | |
| 68 | + | log.Debug().Str("origin", origin).Msg("getting all permissions for origin") | |
| 69 | + | ||
| 70 | + | rows, err := r.queries.ListPermissionsByOrigin(ctx, origin) | |
| 71 | + | if err != nil { | |
| 72 | + | return nil, err | |
| 73 | + | } | |
| 74 | + | ||
| 75 | + | records := make([]*entity.PermissionRecord, len(rows)) | |
| 76 | + | for i, row := range rows { | |
| 77 | + | records[i] = permissionFromRow(row) | |
| 78 | + | } | |
| 79 | + | return records, nil | |
| 80 | + | } | |
| 81 | + | ||
| 82 | + | func permissionFromRow(row sqlc.Permission) *entity.PermissionRecord { | |
| 83 | + | record := &entity.PermissionRecord{ | |
| 84 | + | Origin: row.Origin, | |
| 85 | + | Type: entity.PermissionType(row.PermissionType), | |
| 86 | + | Decision: entity.PermissionDecision(row.Decision), | |
| 87 | + | } | |
| 88 | + | if row.UpdatedAt.Valid { | |
| 89 | + | record.UpdatedAt = row.UpdatedAt.Time | |
| 90 | + | } | |
| 91 | + | return record | |
| 92 | + | } | |
| @@ -0,0 +1,92 @@ | |||||
| 1 | + | package sqlite | |||
| 2 | + | ||||
| 3 | + | import ( | |||
| 4 | + | "context" | |||
| 5 | + | "database/sql" | |||
| 6 | + | "errors" | |||
| 7 | + | ||||
| 8 | + | "github.com/bnema/dumber/internal/domain/entity" | |||
| 9 | + | "github.com/bnema/dumber/internal/domain/repository" | |||
| 10 | + | "github.com/bnema/dumber/internal/infrastructure/persistence/sqlite/sqlc" | |||
| 11 | + | "github.com/bnema/dumber/internal/logging" | |||
| 12 | + | ) | |||
| 13 | + | ||||
| 14 | + | type permissionRepo struct { | |||
| 15 | + | queries *sqlc.Queries | |||
| 16 | + | } | |||
| 17 | + | ||||
| 18 | + | // NewPermissionRepository creates a new SQLite-backed permission repository. | |||
| 19 | + | func NewPermissionRepository(db *sql.DB) repository.PermissionRepository { | |||
| 20 | + | return &permissionRepo{queries: sqlc.New(db)} | |||
| 21 | + | } | |||
| 22 | + | ||||
| 23 | + | func (r *permissionRepo) Get(ctx context.Context, origin string, permType entity.PermissionType) (*entity.PermissionRecord, error) { | |||
| 24 | + | log := logging.FromContext(ctx) | |||
| 25 | + | log.Debug().Str("origin", origin).Str("type", string(permType)).Msg("getting permission") | |||
| 26 | + | ||||
| 27 | + | row, err := r.queries.GetPermission(ctx, sqlc.GetPermissionParams{ | |||
| 28 | + | Origin: origin, | |||
| 29 | + | PermissionType: string(permType), | |||
| 30 | + | }) | |||
| 31 | + | if err != nil { | |||
| 32 | + | if errors.Is(err, sql.ErrNoRows) { | |||
| 33 | + | return nil, nil | |||
| 34 | + | } | |||
| 35 | + | return nil, err | |||
| 36 | + | } | |||
| 37 | + | ||||
| 38 | + | return permissionFromRow(row), nil | |||
| 39 | + | } | |||
| 40 | + | ||||
| 41 | + | func (r *permissionRepo) Set(ctx context.Context, record *entity.PermissionRecord) error { | |||
| 42 | + | log := logging.FromContext(ctx) | |||
| 43 | + | log.Debug(). | |||
| 44 | + | Str("origin", record.Origin). | |||
| 45 | + | Str("type", string(record.Type)). | |||
| 46 | + | Str("decision", string(record.Decision)). | |||
| 47 | + | Msg("setting permission") | |||
| 48 | + | ||||
| 49 | + | return r.queries.SetPermission(ctx, sqlc.SetPermissionParams{ | |||
| 50 | + | Origin: record.Origin, | |||
| 51 | + | PermissionType: string(record.Type), | |||
| 52 | + | Decision: string(record.Decision), | |||
| 53 | + | }) | |||
| 54 | + | } | |||
| 55 | + | ||||
| 56 | + | func (r *permissionRepo) Delete(ctx context.Context, origin string, permType entity.PermissionType) error { | |||
| 57 | + | log := logging.FromContext(ctx) | |||
| 58 | + | log.Debug().Str("origin", origin).Str("type", string(permType)).Msg("deleting permission") | |||
| 59 | + | ||||
| 60 | + | return r.queries.DeletePermission(ctx, sqlc.DeletePermissionParams{ | |||
| 61 | + | Origin: origin, | |||
| 62 | + | PermissionType: string(permType), | |||
| 63 | + | }) | |||
| 64 | + | } | |||
| 65 | + | ||||
| 66 | + | func (r *permissionRepo) GetAll(ctx context.Context, origin string) ([]*entity.PermissionRecord, error) { | |||
| 67 | + | log := logging.FromContext(ctx) | |||
| 68 | + | log.Debug().Str("origin", origin).Msg("getting all permissions for origin") | |||
| 69 | + | ||||
| 70 | + | rows, err := r.queries.ListPermissionsByOrigin(ctx, origin) | |||
| 71 | + | if err != nil { | |||
| 72 | + | return nil, err | |||
| 73 | + | } | |||
| 74 | + | ||||
| 75 | + | records := make([]*entity.PermissionRecord, len(rows)) | |||
| 76 | + | for i, row := range rows { | |||
| 77 | + | records[i] = permissionFromRow(row) | |||
| 78 | + | } | |||
| 79 | + | return records, nil | |||
| 80 | + | } | |||
| 81 | + | ||||
| 82 | + | func permissionFromRow(row sqlc.Permission) *entity.PermissionRecord { | |||
| 83 | + | record := &entity.PermissionRecord{ | |||
| 84 | + | Origin: row.Origin, | |||
| 85 | + | Type: entity.PermissionType(row.PermissionType), | |||
| 86 | + | Decision: entity.PermissionDecision(row.Decision), | |||
| 87 | + | } | |||
| 88 | + | if row.UpdatedAt.Valid { | |||
| 89 | + | record.UpdatedAt = row.UpdatedAt.Time | |||
| 90 | + | } | |||
| 91 | + | return record | |||
| 92 | + | } | |||
A internal/infrastructure/persistence/sqlite/queries/permissions.sql +18 -0
| @@ -0,0 +1,18 @@ | |||
| 1 | + | -- name: GetPermission :one | |
| 2 | + | SELECT * FROM permissions WHERE origin = ? AND permission_type = ? LIMIT 1; | |
| 3 | + | ||
| 4 | + | -- name: SetPermission :exec | |
| 5 | + | INSERT INTO permissions (origin, permission_type, decision, updated_at) | |
| 6 | + | VALUES (?, ?, ?, CURRENT_TIMESTAMP) | |
| 7 | + | ON CONFLICT(origin, permission_type) DO UPDATE SET | |
| 8 | + | decision = excluded.decision, | |
| 9 | + | updated_at = CURRENT_TIMESTAMP; | |
| 10 | + | ||
| 11 | + | -- name: DeletePermission :exec | |
| 12 | + | DELETE FROM permissions WHERE origin = ? AND permission_type = ?; | |
| 13 | + | ||
| 14 | + | -- name: ListPermissionsByOrigin :many | |
| 15 | + | SELECT * FROM permissions WHERE origin = ? ORDER BY updated_at DESC; | |
| 16 | + | ||
| 17 | + | -- name: ListAllPermissions :many | |
| 18 | + | SELECT * FROM permissions ORDER BY origin, permission_type; | |
| @@ -0,0 +1,18 @@ | |||||
| 1 | + | -- name: GetPermission :one | |||
| 2 | + | SELECT * FROM permissions WHERE origin = ? AND permission_type = ? LIMIT 1; | |||
| 3 | + | ||||
| 4 | + | -- name: SetPermission :exec | |||
| 5 | + | INSERT INTO permissions (origin, permission_type, decision, updated_at) | |||
| 6 | + | VALUES (?, ?, ?, CURRENT_TIMESTAMP) | |||
| 7 | + | ON CONFLICT(origin, permission_type) DO UPDATE SET | |||
| 8 | + | decision = excluded.decision, | |||
| 9 | + | updated_at = CURRENT_TIMESTAMP; | |||
| 10 | + | ||||
| 11 | + | -- name: DeletePermission :exec | |||
| 12 | + | DELETE FROM permissions WHERE origin = ? AND permission_type = ?; | |||
| 13 | + | ||||
| 14 | + | -- name: ListPermissionsByOrigin :many | |||
| 15 | + | SELECT * FROM permissions WHERE origin = ? ORDER BY updated_at DESC; | |||
| 16 | + | ||||
| 17 | + | -- name: ListAllPermissions :many | |||
| 18 | + | SELECT * FROM permissions ORDER BY origin, permission_type; | |||
M internal/infrastructure/persistence/sqlite/sqlc/models.go +7 -0
| @@ -63,6 +63,13 @@ type HistoryFt struct { | |||
| 63 | 63 | Title string `json:"title"` | |
| 64 | 64 | } | |
| 65 | 65 | ||
| 66 | + | type Permission struct { | |
| 67 | + | Origin string `json:"origin"` | |
| 68 | + | PermissionType string `json:"permission_type"` | |
| 69 | + | Decision string `json:"decision"` | |
| 70 | + | UpdatedAt sql.NullTime `json:"updated_at"` | |
| 71 | + | } | |
| 72 | + | ||
| 66 | 73 | type Session struct { | |
| 67 | 74 | ID string `json:"id"` | |
| 68 | 75 | Type string `json:"type"` | |
| @@ -63,6 +63,13 @@ type HistoryFt struct { | |||||
| 63 | Title string `json:"title"` | 63 | Title string `json:"title"` | ||
| 64 | } | 64 | } | ||
| 65 | 65 | ||||
| 66 | + | type Permission struct { | |||
| 67 | + | Origin string `json:"origin"` | |||
| 68 | + | PermissionType string `json:"permission_type"` | |||
| 69 | + | Decision string `json:"decision"` | |||
| 70 | + | UpdatedAt sql.NullTime `json:"updated_at"` | |||
| 71 | + | } | |||
| 72 | + | ||||
| 66 | type Session struct { | 73 | type Session struct { | ||
| 67 | ID string `json:"id"` | 74 | ID string `json:"id"` | ||
| 68 | Type string `json:"type"` | 75 | Type string `json:"type"` | ||
A internal/infrastructure/persistence/sqlite/sqlc/permissions.sql.go +128 -0
| @@ -0,0 +1,128 @@ | |||
| 1 | + | // Code generated by sqlc. DO NOT EDIT. | |
| 2 | + | // versions: | |
| 3 | + | // sqlc v1.30.0 | |
| 4 | + | // source: permissions.sql | |
| 5 | + | ||
| 6 | + | package sqlc | |
| 7 | + | ||
| 8 | + | import ( | |
| 9 | + | "context" | |
| 10 | + | ) | |
| 11 | + | ||
| 12 | + | const DeletePermission = `-- name: DeletePermission :exec | |
| 13 | + | DELETE FROM permissions WHERE origin = ? AND permission_type = ? | |
| 14 | + | ` | |
| 15 | + | ||
| 16 | + | type DeletePermissionParams struct { | |
| 17 | + | Origin string `json:"origin"` | |
| 18 | + | PermissionType string `json:"permission_type"` | |
| 19 | + | } | |
| 20 | + | ||
| 21 | + | func (q *Queries) DeletePermission(ctx context.Context, arg DeletePermissionParams) error { | |
| 22 | + | _, err := q.db.ExecContext(ctx, DeletePermission, arg.Origin, arg.PermissionType) | |
| 23 | + | return err | |
| 24 | + | } | |
| 25 | + | ||
| 26 | + | const GetPermission = `-- name: GetPermission :one | |
| 27 | + | SELECT origin, permission_type, decision, updated_at FROM permissions WHERE origin = ? AND permission_type = ? LIMIT 1 | |
| 28 | + | ` | |
| 29 | + | ||
| 30 | + | type GetPermissionParams struct { | |
| 31 | + | Origin string `json:"origin"` | |
| 32 | + | PermissionType string `json:"permission_type"` | |
| 33 | + | } | |
| 34 | + | ||
| 35 | + | func (q *Queries) GetPermission(ctx context.Context, arg GetPermissionParams) (Permission, error) { | |
| 36 | + | row := q.db.QueryRowContext(ctx, GetPermission, arg.Origin, arg.PermissionType) | |
| 37 | + | var i Permission | |
| 38 | + | err := row.Scan( | |
| 39 | + | &i.Origin, | |
| 40 | + | &i.PermissionType, | |
| 41 | + | &i.Decision, | |
| 42 | + | &i.UpdatedAt, | |
| 43 | + | ) | |
| 44 | + | return i, err | |
| 45 | + | } | |
| 46 | + | ||
| 47 | + | const ListAllPermissions = `-- name: ListAllPermissions :many | |
| 48 | + | SELECT origin, permission_type, decision, updated_at FROM permissions ORDER BY origin, permission_type | |
| 49 | + | ` | |
| 50 | + | ||
| 51 | + | func (q *Queries) ListAllPermissions(ctx context.Context) ([]Permission, error) { | |
| 52 | + | rows, err := q.db.QueryContext(ctx, ListAllPermissions) | |
| 53 | + | if err != nil { | |
| 54 | + | return nil, err | |
| 55 | + | } | |
| 56 | + | defer rows.Close() | |
| 57 | + | items := []Permission{} | |
| 58 | + | for rows.Next() { | |
| 59 | + | var i Permission | |
| 60 | + | if err := rows.Scan( | |
| 61 | + | &i.Origin, | |
| 62 | + | &i.PermissionType, | |
| 63 | + | &i.Decision, | |
| 64 | + | &i.UpdatedAt, | |
| 65 | + | ); err != nil { | |
| 66 | + | return nil, err | |
| 67 | + | } | |
| 68 | + | items = append(items, i) | |
| 69 | + | } | |
| 70 | + | if err := rows.Close(); err != nil { | |
| 71 | + | return nil, err | |
| 72 | + | } | |
| 73 | + | if err := rows.Err(); err != nil { | |
| 74 | + | return nil, err | |
| 75 | + | } | |
| 76 | + | return items, nil | |
| 77 | + | } | |
| 78 | + | ||
| 79 | + | const ListPermissionsByOrigin = `-- name: ListPermissionsByOrigin :many | |
| 80 | + | SELECT origin, permission_type, decision, updated_at FROM permissions WHERE origin = ? ORDER BY updated_at DESC | |
| 81 | + | ` | |
| 82 | + | ||
| 83 | + | func (q *Queries) ListPermissionsByOrigin(ctx context.Context, origin string) ([]Permission, error) { | |
| 84 | + | rows, err := q.db.QueryContext(ctx, ListPermissionsByOrigin, origin) | |
| 85 | + | if err != nil { | |
| 86 | + | return nil, err | |
| 87 | + | } | |
| 88 | + | defer rows.Close() | |
| 89 | + | items := []Permission{} | |
| 90 | + | for rows.Next() { | |
| 91 | + | var i Permission | |
| 92 | + | if err := rows.Scan( | |
| 93 | + | &i.Origin, | |
| 94 | + | &i.PermissionType, | |
| 95 | + | &i.Decision, | |
| 96 | + | &i.UpdatedAt, | |
| 97 | + | ); err != nil { | |
| 98 | + | return nil, err | |
| 99 | + | } | |
| 100 | + | items = append(items, i) | |
| 101 | + | } | |
| 102 | + | if err := rows.Close(); err != nil { | |
| 103 | + | return nil, err | |
| 104 | + | } | |
| 105 | + | if err := rows.Err(); err != nil { | |
| 106 | + | return nil, err | |
| 107 | + | } | |
| 108 | + | return items, nil | |
| 109 | + | } | |
| 110 | + | ||
| 111 | + | const SetPermission = `-- name: SetPermission :exec | |
| 112 | + | INSERT INTO permissions (origin, permission_type, decision, updated_at) | |
| 113 | + | VALUES (?, ?, ?, CURRENT_TIMESTAMP) | |
| 114 | + | ON CONFLICT(origin, permission_type) DO UPDATE SET | |
| 115 | + | decision = excluded.decision, | |
| 116 | + | updated_at = CURRENT_TIMESTAMP | |
| 117 | + | ` | |
| 118 | + | ||
| 119 | + | type SetPermissionParams struct { | |
| 120 | + | Origin string `json:"origin"` | |
| 121 | + | PermissionType string `json:"permission_type"` | |
| 122 | + | Decision string `json:"decision"` | |
| 123 | + | } | |
| 124 | + | ||
| 125 | + | func (q *Queries) SetPermission(ctx context.Context, arg SetPermissionParams) error { | |
| 126 | + | _, err := q.db.ExecContext(ctx, SetPermission, arg.Origin, arg.PermissionType, arg.Decision) | |
| 127 | + | return err | |
| 128 | + | } | |
| @@ -0,0 +1,128 @@ | |||||
| 1 | + | // Code generated by sqlc. DO NOT EDIT. | |||
| 2 | + | // versions: | |||
| 3 | + | // sqlc v1.30.0 | |||
| 4 | + | // source: permissions.sql | |||
| 5 | + | ||||
| 6 | + | package sqlc | |||
| 7 | + | ||||
| 8 | + | import ( | |||
| 9 | + | "context" | |||
| 10 | + | ) | |||
| 11 | + | ||||
| 12 | + | const DeletePermission = `-- name: DeletePermission :exec | |||
| 13 | + | DELETE FROM permissions WHERE origin = ? AND permission_type = ? | |||
| 14 | + | ` | |||
| 15 | + | ||||
| 16 | + | type DeletePermissionParams struct { | |||
| 17 | + | Origin string `json:"origin"` | |||
| 18 | + | PermissionType string `json:"permission_type"` | |||
| 19 | + | } | |||
| 20 | + | ||||
| 21 | + | func (q *Queries) DeletePermission(ctx context.Context, arg DeletePermissionParams) error { | |||
| 22 | + | _, err := q.db.ExecContext(ctx, DeletePermission, arg.Origin, arg.PermissionType) | |||
| 23 | + | return err | |||
| 24 | + | } | |||
| 25 | + | ||||
| 26 | + | const GetPermission = `-- name: GetPermission :one | |||
| 27 | + | SELECT origin, permission_type, decision, updated_at FROM permissions WHERE origin = ? AND permission_type = ? LIMIT 1 | |||
| 28 | + | ` | |||
| 29 | + | ||||
| 30 | + | type GetPermissionParams struct { | |||
| 31 | + | Origin string `json:"origin"` | |||
| 32 | + | PermissionType string `json:"permission_type"` | |||
| 33 | + | } | |||
| 34 | + | ||||
| 35 | + | func (q *Queries) GetPermission(ctx context.Context, arg GetPermissionParams) (Permission, error) { | |||
| 36 | + | row := q.db.QueryRowContext(ctx, GetPermission, arg.Origin, arg.PermissionType) | |||
| 37 | + | var i Permission | |||
| 38 | + | err := row.Scan( | |||
| 39 | + | &i.Origin, | |||
| 40 | + | &i.PermissionType, | |||
| 41 | + | &i.Decision, | |||
| 42 | + | &i.UpdatedAt, | |||
| 43 | + | ) | |||
| 44 | + | return i, err | |||
| 45 | + | } | |||
| 46 | + | ||||
| 47 | + | const ListAllPermissions = `-- name: ListAllPermissions :many | |||
| 48 | + | SELECT origin, permission_type, decision, updated_at FROM permissions ORDER BY origin, permission_type | |||
| 49 | + | ` | |||
| 50 | + | ||||
| 51 | + | func (q *Queries) ListAllPermissions(ctx context.Context) ([]Permission, error) { | |||
| 52 | + | rows, err := q.db.QueryContext(ctx, ListAllPermissions) | |||
| 53 | + | if err != nil { | |||
| 54 | + | return nil, err | |||
| 55 | + | } | |||
| 56 | + | defer rows.Close() | |||
| 57 | + | items := []Permission{} | |||
| 58 | + | for rows.Next() { | |||
| 59 | + | var i Permission | |||
| 60 | + | if err := rows.Scan( | |||
| 61 | + | &i.Origin, | |||
| 62 | + | &i.PermissionType, | |||
| 63 | + | &i.Decision, | |||
| 64 | + | &i.UpdatedAt, | |||
| 65 | + | ); err != nil { | |||
| 66 | + | return nil, err | |||
| 67 | + | } | |||
| 68 | + | items = append(items, i) | |||
| 69 | + | } | |||
| 70 | + | if err := rows.Close(); err != nil { | |||
| 71 | + | return nil, err | |||
| 72 | + | } | |||
| 73 | + | if err := rows.Err(); err != nil { | |||
| 74 | + | return nil, err | |||
| 75 | + | } | |||
| 76 | + | return items, nil | |||
| 77 | + | } | |||
| 78 | + | ||||
| 79 | + | const ListPermissionsByOrigin = `-- name: ListPermissionsByOrigin :many | |||
| 80 | + | SELECT origin, permission_type, decision, updated_at FROM permissions WHERE origin = ? ORDER BY updated_at DESC | |||
| 81 | + | ` | |||
| 82 | + | ||||
| 83 | + | func (q *Queries) ListPermissionsByOrigin(ctx context.Context, origin string) ([]Permission, error) { | |||
| 84 | + | rows, err := q.db.QueryContext(ctx, ListPermissionsByOrigin, origin) | |||
| 85 | + | if err != nil { | |||
| 86 | + | return nil, err | |||
| 87 | + | } | |||
| 88 | + | defer rows.Close() | |||
| 89 | + | items := []Permission{} | |||
| 90 | + | for rows.Next() { | |||
| 91 | + | var i Permission | |||
| 92 | + | if err := rows.Scan( | |||
| 93 | + | &i.Origin, | |||
| 94 | + | &i.PermissionType, | |||
| 95 | + | &i.Decision, | |||
| 96 | + | &i.UpdatedAt, | |||
| 97 | + | ); err != nil { | |||
| 98 | + | return nil, err | |||
| 99 | + | } | |||
| 100 | + | items = append(items, i) | |||
| 101 | + | } | |||
| 102 | + | if err := rows.Close(); err != nil { | |||
| 103 | + | return nil, err | |||
| 104 | + | } | |||
| 105 | + | if err := rows.Err(); err != nil { | |||
| 106 | + | return nil, err | |||
| 107 | + | } | |||
| 108 | + | return items, nil | |||
| 109 | + | } | |||
| 110 | + | ||||
| 111 | + | const SetPermission = `-- name: SetPermission :exec | |||
| 112 | + | INSERT INTO permissions (origin, permission_type, decision, updated_at) | |||
| 113 | + | VALUES (?, ?, ?, CURRENT_TIMESTAMP) | |||
| 114 | + | ON CONFLICT(origin, permission_type) DO UPDATE SET | |||
| 115 | + | decision = excluded.decision, | |||
| 116 | + | updated_at = CURRENT_TIMESTAMP | |||
| 117 | + | ` | |||
| 118 | + | ||||
| 119 | + | type SetPermissionParams struct { | |||
| 120 | + | Origin string `json:"origin"` | |||
| 121 | + | PermissionType string `json:"permission_type"` | |||
| 122 | + | Decision string `json:"decision"` | |||
| 123 | + | } | |||
| 124 | + | ||||
| 125 | + | func (q *Queries) SetPermission(ctx context.Context, arg SetPermissionParams) error { | |||
| 126 | + | _, err := q.db.ExecContext(ctx, SetPermission, arg.Origin, arg.PermissionType, arg.Decision) | |||
| 127 | + | return err | |||
| 128 | + | } | |||
M internal/infrastructure/persistence/sqlite/sqlc/querier.go +5 -0
| @@ -26,6 +26,7 @@ type Querier interface { | |||
| 26 | 26 | DeleteHistoryOlderThan(ctx context.Context, lastVisited sql.NullTime) error | |
| 27 | 27 | // Deletes exited browser sessions beyond the keep limit, keeping the most recent ones. | |
| 28 | 28 | DeleteOldestExitedSessions(ctx context.Context, offset int64) (int64, error) | |
| 29 | + | DeletePermission(ctx context.Context, arg DeletePermissionParams) error | |
| 29 | 30 | DeleteSession(ctx context.Context, id string) error | |
| 30 | 31 | DeleteSessionState(ctx context.Context, sessionID string) error | |
| 31 | 32 | DeleteTag(ctx context.Context, id int64) error | |
| @@ -51,6 +52,7 @@ type Querier interface { | |||
| 51 | 52 | GetHistoryStats(ctx context.Context) (GetHistoryStatsRow, error) | |
| 52 | 53 | GetHourlyDistribution(ctx context.Context) ([]GetHourlyDistributionRow, error) | |
| 53 | 54 | GetMostVisited(ctx context.Context, datetime interface{}) ([]History, error) | |
| 55 | + | GetPermission(ctx context.Context, arg GetPermissionParams) (Permission, error) | |
| 54 | 56 | GetRecentHistory(ctx context.Context, arg GetRecentHistoryParams) ([]History, error) | |
| 55 | 57 | GetRecentHistorySince(ctx context.Context, datetime interface{}) ([]History, error) | |
| 56 | 58 | GetRecentSessions(ctx context.Context, limit int64) ([]Session, error) | |
| @@ -67,6 +69,8 @@ type Querier interface { | |||
| 67 | 69 | IncrementVisitCountByDelta(ctx context.Context, arg IncrementVisitCountByDeltaParams) error | |
| 68 | 70 | InsertSession(ctx context.Context, arg InsertSessionParams) error | |
| 69 | 71 | IsWhitelisted(ctx context.Context, domain string) (int64, error) | |
| 72 | + | ListAllPermissions(ctx context.Context) ([]Permission, error) | |
| 73 | + | ListPermissionsByOrigin(ctx context.Context, origin string) ([]Permission, error) | |
| 70 | 74 | ListZoomLevels(ctx context.Context) ([]ZoomLevel, error) | |
| 71 | 75 | MarkSessionEnded(ctx context.Context, arg MarkSessionEndedParams) error | |
| 72 | 76 | RemoveFromWhitelist(ctx context.Context, domain string) error | |
| @@ -77,6 +81,7 @@ type Querier interface { | |||
| 77 | 81 | SearchHistoryFTSUrlWithDomainBoost(ctx context.Context, arg SearchHistoryFTSUrlWithDomainBoostParams) ([]SearchHistoryFTSUrlWithDomainBoostRow, error) | |
| 78 | 82 | SetFavoriteFolder(ctx context.Context, arg SetFavoriteFolderParams) error | |
| 79 | 83 | SetFavoriteShortcut(ctx context.Context, arg SetFavoriteShortcutParams) error | |
| 84 | + | SetPermission(ctx context.Context, arg SetPermissionParams) error | |
| 80 | 85 | SetZoomLevel(ctx context.Context, arg SetZoomLevelParams) error | |
| 81 | 86 | UpdateFavorite(ctx context.Context, arg UpdateFavoriteParams) error | |
| 82 | 87 | UpdateFavoritePosition(ctx context.Context, arg UpdateFavoritePositionParams) error | |
| @@ -26,6 +26,7 @@ type Querier interface { | |||||
| 26 | DeleteHistoryOlderThan(ctx context.Context, lastVisited sql.NullTime) error | 26 | DeleteHistoryOlderThan(ctx context.Context, lastVisited sql.NullTime) error | ||
| 27 | // Deletes exited browser sessions beyond the keep limit, keeping the most recent ones. | 27 | // Deletes exited browser sessions beyond the keep limit, keeping the most recent ones. | ||
| 28 | DeleteOldestExitedSessions(ctx context.Context, offset int64) (int64, error) | 28 | DeleteOldestExitedSessions(ctx context.Context, offset int64) (int64, error) | ||
| 29 | + | DeletePermission(ctx context.Context, arg DeletePermissionParams) error | |||
| 29 | DeleteSession(ctx context.Context, id string) error | 30 | DeleteSession(ctx context.Context, id string) error | ||
| 30 | DeleteSessionState(ctx context.Context, sessionID string) error | 31 | DeleteSessionState(ctx context.Context, sessionID string) error | ||
| 31 | DeleteTag(ctx context.Context, id int64) error | 32 | DeleteTag(ctx context.Context, id int64) error | ||
| @@ -51,6 +52,7 @@ type Querier interface { | |||||
| 51 | GetHistoryStats(ctx context.Context) (GetHistoryStatsRow, error) | 52 | GetHistoryStats(ctx context.Context) (GetHistoryStatsRow, error) | ||
| 52 | GetHourlyDistribution(ctx context.Context) ([]GetHourlyDistributionRow, error) | 53 | GetHourlyDistribution(ctx context.Context) ([]GetHourlyDistributionRow, error) | ||
| 53 | GetMostVisited(ctx context.Context, datetime interface{}) ([]History, error) | 54 | GetMostVisited(ctx context.Context, datetime interface{}) ([]History, error) | ||
| 55 | + | GetPermission(ctx context.Context, arg GetPermissionParams) (Permission, error) | |||
| 54 | GetRecentHistory(ctx context.Context, arg GetRecentHistoryParams) ([]History, error) | 56 | GetRecentHistory(ctx context.Context, arg GetRecentHistoryParams) ([]History, error) | ||
| 55 | GetRecentHistorySince(ctx context.Context, datetime interface{}) ([]History, error) | 57 | GetRecentHistorySince(ctx context.Context, datetime interface{}) ([]History, error) | ||
| 56 | GetRecentSessions(ctx context.Context, limit int64) ([]Session, error) | 58 | GetRecentSessions(ctx context.Context, limit int64) ([]Session, error) | ||
| @@ -67,6 +69,8 @@ type Querier interface { | |||||
| 67 | IncrementVisitCountByDelta(ctx context.Context, arg IncrementVisitCountByDeltaParams) error | 69 | IncrementVisitCountByDelta(ctx context.Context, arg IncrementVisitCountByDeltaParams) error | ||
| 68 | InsertSession(ctx context.Context, arg InsertSessionParams) error | 70 | InsertSession(ctx context.Context, arg InsertSessionParams) error | ||
| 69 | IsWhitelisted(ctx context.Context, domain string) (int64, error) | 71 | IsWhitelisted(ctx context.Context, domain string) (int64, error) | ||
| 72 | + | ListAllPermissions(ctx context.Context) ([]Permission, error) | |||
| 73 | + | ListPermissionsByOrigin(ctx context.Context, origin string) ([]Permission, error) | |||
| 70 | ListZoomLevels(ctx context.Context) ([]ZoomLevel, error) | 74 | ListZoomLevels(ctx context.Context) ([]ZoomLevel, error) | ||
| 71 | MarkSessionEnded(ctx context.Context, arg MarkSessionEndedParams) error | 75 | MarkSessionEnded(ctx context.Context, arg MarkSessionEndedParams) error | ||
| 72 | RemoveFromWhitelist(ctx context.Context, domain string) error | 76 | RemoveFromWhitelist(ctx context.Context, domain string) error | ||
| @@ -77,6 +81,7 @@ type Querier interface { | |||||
| 77 | SearchHistoryFTSUrlWithDomainBoost(ctx context.Context, arg SearchHistoryFTSUrlWithDomainBoostParams) ([]SearchHistoryFTSUrlWithDomainBoostRow, error) | 81 | SearchHistoryFTSUrlWithDomainBoost(ctx context.Context, arg SearchHistoryFTSUrlWithDomainBoostParams) ([]SearchHistoryFTSUrlWithDomainBoostRow, error) | ||
| 78 | SetFavoriteFolder(ctx context.Context, arg SetFavoriteFolderParams) error | 82 | SetFavoriteFolder(ctx context.Context, arg SetFavoriteFolderParams) error | ||
| 79 | SetFavoriteShortcut(ctx context.Context, arg SetFavoriteShortcutParams) error | 83 | SetFavoriteShortcut(ctx context.Context, arg SetFavoriteShortcutParams) error | ||
| 84 | + | SetPermission(ctx context.Context, arg SetPermissionParams) error | |||
| 80 | SetZoomLevel(ctx context.Context, arg SetZoomLevelParams) error | 85 | SetZoomLevel(ctx context.Context, arg SetZoomLevelParams) error | ||
| 81 | UpdateFavorite(ctx context.Context, arg UpdateFavoriteParams) error | 86 | UpdateFavorite(ctx context.Context, arg UpdateFavoriteParams) error | ||
| 82 | UpdateFavoritePosition(ctx context.Context, arg UpdateFavoritePositionParams) error | 87 | UpdateFavoritePosition(ctx context.Context, arg UpdateFavoritePositionParams) error | ||