wardnsql

package
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 9, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package wardnsql is a wardn.Store for SQL databases: PostgreSQL, MySQL, MariaDB and SQLite. It uses database/sql, so it works with the driver your application already uses and adds no dependencies of its own.

db, _ := sql.Open("pgx", dsn)
w := wardn.MustNew(wardn.Config{
	File:  "wardn.yaml",
	Store: wardnsql.MustNew(db),
})

wardn.New creates the tables automatically (see Store.Migrate). Every value is passed as a query parameter; table names come only from a validated prefix.

SQLite: set a busy timeout in the DSN (for example "file:wardn.db?_pragma=busy_timeout(5000)" with modernc.org/sqlite) so concurrent writers wait instead of failing.

Index

Constants

View Source
const DefaultTablePrefix = "wardn_"

DefaultTablePrefix is prepended to the names of wardn's tables.

View Source
const LatestSchemaVersion = 2

LatestSchemaVersion is the schema version this release migrates to.

Variables

View Source
var ErrSchemaTooNew = errors.New("wardnsql: database schema is newer than this release of wardn supports")

ErrSchemaTooNew reports a database whose wardn schema was created by a newer release of wardn than the one running. Upgrade wardn rather than running an older release against it.

Functions

This section is empty.

Types

type Dialect

type Dialect int

Dialect selects the SQL flavour a Store speaks.

const (
	// DetectDialect detects the dialect from the database driver. It is the
	// default.
	DetectDialect Dialect = iota
	// Postgres is PostgreSQL 13 or newer.
	Postgres
	// MySQL is MySQL 8.0 or newer, or MariaDB 10.6 or newer.
	MySQL
	// SQLite is SQLite 3.24 or newer.
	SQLite
)

Supported dialects.

func (Dialect) String

func (d Dialect) String() string

type Option

type Option func(*options)

Option configures a Store.

func WithDialect

func WithDialect(d Dialect) Option

WithDialect sets the SQL dialect instead of detecting it from the driver.

func WithTablePrefix

func WithTablePrefix(prefix string) Option

WithTablePrefix sets the prefix of wardn's table names (default "wardn_"). It must be 1–32 characters: lowercase letters, digits and '_', starting with a letter.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store is a wardn.Store backed by a SQL database. It is safe for concurrent use.

func MustNew

func MustNew(db *sql.DB, opts ...Option) *Store

MustNew is like New but panics on error, for use in main().

func New

func New(db *sql.DB, opts ...Option) (*Store, error)

New returns a Store using db. It does not touch the database; call Migrate (wardn.New does) to create the tables.

func (*Store) Assign

func (s *Store) Assign(ctx context.Context, a wardn.Assignment) error

Assign implements wardn.Store.

func (*Store) Assignments

func (s *Store) Assignments(ctx context.Context, user string, scopes []wardn.Scope) ([]wardn.Assignment, error)

Assignments implements wardn.Store.

func (*Store) CreateRole

func (s *Store) CreateRole(ctx context.Context, r wardn.CustomRole) error

CreateRole implements wardn.Store.

func (*Store) DeleteRole

func (s *Store) DeleteRole(ctx context.Context, id string) error

DeleteRole implements wardn.Store.

func (*Store) Dialect

func (s *Store) Dialect() Dialect

Dialect returns the SQL dialect the store uses.

func (*Store) ExpiredUnreported

func (s *Store) ExpiredUnreported(ctx context.Context, t time.Time, limit int) ([]wardn.Assignment, error)

ExpiredUnreported implements wardn.Store.

func (*Store) InTx

func (s *Store) InTx(ctx context.Context) bool

InTx implements wardn.TxStore: it reports whether ctx carries an application transaction for this store.

func (s *Store) Link(ctx context.Context, child, parent wardn.Scope) error

Link implements wardn.Store.

func (*Store) MarkExpiryReported

func (s *Store) MarkExpiryReported(ctx context.Context, as []wardn.Assignment) error

MarkExpiryReported implements wardn.Store. The expires_at condition leaves an assignment unmarked if it was assigned again with a new window.

func (*Store) Members

func (s *Store) Members(ctx context.Context, scope wardn.Scope, cursor string, limit int) ([]wardn.Assignment, string, error)

Members implements wardn.Store.

func (*Store) Migrate

func (s *Store) Migrate(ctx context.Context) error

Migrate creates or upgrades the store's tables. It is safe to run concurrently from several application instances: Postgres and MySQL migrations hold a database lock, and every statement is idempotent. wardn.New calls it automatically unless Config.ManualMigrations is set.

func (*Store) Parent

func (s *Store) Parent(ctx context.Context, child wardn.Scope) (wardn.Scope, bool, error)

Parent implements wardn.Store.

func (*Store) Revoke

func (s *Store) Revoke(ctx context.Context, user, role string, scope wardn.Scope) error

Revoke implements wardn.Store.

func (*Store) RevokeExpired

func (s *Store) RevokeExpired(ctx context.Context, a wardn.Assignment) error

RevokeExpired implements wardn.Store: one conditional DELETE, so an assignment given a new window meanwhile is left alone.

func (*Store) RevokeRole

func (s *Store) RevokeRole(ctx context.Context, role string) error

RevokeRole implements wardn.Store.

func (*Store) RoleInUse

func (s *Store) RoleInUse(ctx context.Context, role string) (bool, error)

RoleInUse implements wardn.Store.

func (*Store) Roles

func (s *Store) Roles(ctx context.Context, ids []string) ([]wardn.CustomRole, error)

Roles implements wardn.Store.

func (*Store) RolesOwnedBy

func (s *Store) RolesOwnedBy(ctx context.Context, owners []wardn.Scope) ([]wardn.CustomRole, error)

RolesOwnedBy implements wardn.Store.

func (*Store) RunInTx

func (s *Store) RunInTx(ctx context.Context, w *wardn.Warden, opts *sql.TxOptions, fn func(ctx context.Context, tx *sql.Tx) error) (err error)

RunInTx runs fn in a new transaction on the store's database, and commits it if fn returns nil. If fn fails or panics, it rolls back. The ctx passed to fn is ready for wardn changes in that transaction (WithTx and w.Transaction), so access commits or rolls back with the application's own writes through tx:

err := store.RunInTx(ctx, w, nil, func(ctx context.Context, tx *sql.Tx) error {
	if _, err := tx.ExecContext(ctx, insertMember, orgID, userID); err != nil {
		return err
	}
	return w.Assign(ctx, userID, "agent", product)
})

RunInTx ends wardn's transaction after the commit or rollback, which is easy to get wrong by hand. It returns fn's error, or else the commit's. If the transaction committed but invalidating the cache then failed, it returns an error matching wardn.ErrCacheInvalidation: the changes are saved, and other instances may serve the old state for up to the cache TTL.

opts sets the isolation level and read-only mode, as in sql.DB.BeginTx; nil uses the database's defaults.

func (*Store) SchemaVersion

func (s *Store) SchemaVersion(ctx context.Context) (int, error)

SchemaVersion returns the version of the store's schema in the database, or 0 if it has never been migrated.

func (*Store) TablePrefix

func (s *Store) TablePrefix() string

TablePrefix returns the prefix of the store's table names.

func (*Store) UpdateRole

func (s *Store) UpdateRole(ctx context.Context, r wardn.CustomRole, expectedVersion int) error

UpdateRole implements wardn.Store.

func (*Store) WithTx

func (s *Store) WithTx(ctx context.Context, tx *sql.Tx) context.Context

WithTx returns a copy of ctx in which the store reads and writes through tx, the application's own transaction, instead of starting its own. A change to access then commits or rolls back with the application's other writes. tx must be a transaction on the store's database.

Pass the result to wardn.Warden.Transaction before making changes with it; wardn refuses changes otherwise (wardn.ErrNoTransaction). The store wraps each of its writes in a savepoint, so a write that fails, such as a custom role whose name is taken, leaves the transaction usable.

Keep row-level security, locks and isolation in mind: wardn's queries run with whatever the transaction has set.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL