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
- Variables
- type Dialect
- type Option
- type Store
- func (s *Store) Assign(ctx context.Context, a wardn.Assignment) error
- func (s *Store) Assignments(ctx context.Context, user string, scopes []wardn.Scope) ([]wardn.Assignment, error)
- func (s *Store) CreateRole(ctx context.Context, r wardn.CustomRole) error
- func (s *Store) DeleteRole(ctx context.Context, id string) error
- func (s *Store) Dialect() Dialect
- func (s *Store) ExpiredUnreported(ctx context.Context, t time.Time, limit int) ([]wardn.Assignment, error)
- func (s *Store) InTx(ctx context.Context) bool
- func (s *Store) Link(ctx context.Context, child, parent wardn.Scope) error
- func (s *Store) MarkExpiryReported(ctx context.Context, as []wardn.Assignment) error
- func (s *Store) Members(ctx context.Context, scope wardn.Scope, cursor string, limit int) ([]wardn.Assignment, string, error)
- func (s *Store) Migrate(ctx context.Context) error
- func (s *Store) Parent(ctx context.Context, child wardn.Scope) (wardn.Scope, bool, error)
- func (s *Store) Revoke(ctx context.Context, user, role string, scope wardn.Scope) error
- func (s *Store) RevokeExpired(ctx context.Context, a wardn.Assignment) error
- func (s *Store) RevokeRole(ctx context.Context, role string) error
- func (s *Store) RoleInUse(ctx context.Context, role string) (bool, error)
- func (s *Store) Roles(ctx context.Context, ids []string) ([]wardn.CustomRole, error)
- func (s *Store) RolesOwnedBy(ctx context.Context, owners []wardn.Scope) ([]wardn.CustomRole, error)
- func (s *Store) RunInTx(ctx context.Context, w *wardn.Warden, opts *sql.TxOptions, ...) (err error)
- func (s *Store) SchemaVersion(ctx context.Context) (int, error)
- func (s *Store) TablePrefix() string
- func (s *Store) UpdateRole(ctx context.Context, r wardn.CustomRole, expectedVersion int) error
- func (s *Store) WithTx(ctx context.Context, tx *sql.Tx) context.Context
Constants ¶
const DefaultTablePrefix = "wardn_"
DefaultTablePrefix is prepended to the names of wardn's tables.
const LatestSchemaVersion = 2
LatestSchemaVersion is the schema version this release migrates to.
Variables ¶
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.
type Option ¶
type Option func(*options)
Option configures a Store.
func WithDialect ¶
WithDialect sets the SQL dialect instead of detecting it from the driver.
func WithTablePrefix ¶
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 New ¶
New returns a Store using db. It does not touch the database; call Migrate (wardn.New does) to create the tables.
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 ¶
CreateRole implements wardn.Store.
func (*Store) DeleteRole ¶
DeleteRole implements wardn.Store.
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 ¶
InTx implements wardn.TxStore: it reports whether ctx carries an application transaction for this store.
func (*Store) MarkExpiryReported ¶
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 ¶
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) RevokeExpired ¶
RevokeExpired implements wardn.Store: one conditional DELETE, so an assignment given a new window meanwhile is left alone.
func (*Store) RevokeRole ¶
RevokeRole implements wardn.Store.
func (*Store) RolesOwnedBy ¶
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 ¶
SchemaVersion returns the version of the store's schema in the database, or 0 if it has never been migrated.
func (*Store) TablePrefix ¶
TablePrefix returns the prefix of the store's table names.
func (*Store) UpdateRole ¶
UpdateRole implements wardn.Store.
func (*Store) WithTx ¶
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.