schemarp

package
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Feb 16, 2024 License: MPL-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package schemarp provides a reification of the repo.Schema interface making it possible to create or drop different schema, foreign server, or manage database user roles.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ChangePasswords

func ChangePasswords(
	ctx context.Context,
	tx *postgres.Tx,
	roleSuffix repo.Role,
	hasher scram.Hasher,
	roles []repo.Role,
	passwords []string,
) error

ChangePasswords updates the passwords of the given roles in the current transaction. The roles and passwords slices must have the same number of entries, so they can be used in pair. These fields are not combined as a struct with two role and password fields because passing items separately ensures that all items are initialized explicitly in constrast to a struct which its fields can be zero-initialized and are more suitable to pass a set of optional fields.

The `roles` role names may be suffixed by `roleSuffix` if it is not empty. This is useful to have distinct role names if repo.Role predefined constants are not desirable. The `hasher` will be used for hashing of the `passwords` before sending them to the DBMS (so they may not leak in plaintext). This SCRAM hasher format must conform with the DBMS expected format.

func CreateRoleIfNotExists

func CreateRoleIfNotExists[Q postgres.Queryer](
	ctx context.Context, q Q, roleSuffix repo.Role, role repo.Role,
) error

CreateRoleIfNotExists creates the `role` role if it does not exist right now. Although the login option is enabled for the created role, but no specific password will be set for it. The ChangePasswords method may be used for setting a password if desired. Otherwise, that user may not login effectively (but using the trust or local identity methods).

The `role` role name may be suffixed by `roleSuffix` if it is not empty. This is useful to have distinct role names if repo.Role predefined constants are not desirable.

func CreateSchema

func CreateSchema[Q postgres.Queryer](
	ctx context.Context, q Q, schema string,
) error

CreateSchema tries to create the `schema` schema. There must be no other schema with the `schema` name, otherwise, this operation will fail.

Caller is responsible to pass a trusted schema name string.

func DropCascade

func DropCascade[Q postgres.Queryer](
	ctx context.Context, q Q, schema string,
) error

DropCascade drops `schema` schema with cascading, dropping all dependent objects recursively. The `schema` must exist, otherwise, an error will be returned. This method is useful for dropping the intermediate schema which are created during a migration.

Caller is responsible to pass a trusted schema name string.

func DropIfExists

func DropIfExists[Q postgres.Queryer](
	ctx context.Context, q Q, schema string,
) error

DropIfExists drops the `schema` schema without cascading if it exists. That is, if `schema` does not exist, a nil error will be returned without any change. And if `schema` exists and is empty, it will be dropped. But if `schema` exists and is not empty, an error will be returned.

Caller is responsible to pass a trusted schema name string.

func DropServerIfExists

func DropServerIfExists(
	ctx context.Context, c *postgres.Conn, serverName string,
) error

DropServerIfExists drops the `serverName` foreign server, if it exists, with cascade. That is, dependent objects such as its user mapping will be dropped too.

Caller is responsible to pass a trusted serverName string.

func GrantFDWUsage

func GrantFDWUsage[Q postgres.Queryer](
	ctx context.Context, q Q, roleSuffix repo.Role, role repo.Role,
) error

GrantFDWUsage grants the USAGE privilege on the postgres_fdw extension to the `role` role. Thereafter, that `role` role can use the postgres_fdw extension in order to create a foreign server or create a user mapping for it.

The `role` role name may be suffixed by `roleSuffix` if it is not empty. This is useful to have distinct role names if repo.Role predefined constants are not desirable.

func GrantPrivileges

func GrantPrivileges[Q postgres.Queryer](
	ctx context.Context,
	q Q,
	roleSuffix repo.Role,
	schema string,
	role repo.Role,
) error

GrantPrivileges grants ALL privileges on the `schema` schema to the `role` role, so it may create or access tables in that schema and run relevant queries.

The `role` role name may be suffixed by `roleSuffix` if it is not empty. This is useful to have distinct role names if repo.Role predefined constants are not desirable.

func InstallFDWExtensionIfMissing

func InstallFDWExtensionIfMissing(
	ctx context.Context, c *postgres.Conn,
) error

InstallFDWExtensionIfMissing creates the postgres_fdw extension assuming that its relavant .so files are available in proper paths. If the extension is already created, calling this method causes no change.

func SetSearchPath

func SetSearchPath[Q postgres.Queryer](
	ctx context.Context,
	q Q,
	roleSuffix repo.Role,
	schema string,
	role repo.Role,
) error

SetSearchPath alters the given database role and sets its default search_path to the given schema name alone.

Types

type Repo

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

Repo represents a schema management repository.

func New

func New(roleSuffix repo.Role, h scram.Hasher) *Repo

New instantiates a schema management Repo struct. This method improves the caller code readability as schemarp.New makes this package to look alike a data type. The `roleSuffix` which may be empty specifies a suffix for role names. The CreateRoleIfNotExists, GrantPrivileges, SetSearchPath, GrantFDWUsage, and ChangePasswords will append it to their role arguments.

The `h` SCRAM hasher will be included in the returned *Repo instance so it may hash database role passwords properly. This hasher must conform with the configured format in the DBMS, otherwise, the passwords which are created may not be used for authentication.

func (*Repo) Conn

func (schema *Repo) Conn(c repo.Conn) repo.SchemaConnQueryer

Conn unwraps the given repo.Conn instance, expecting to find an instance of *postgres.Conn as created by this adapter layer. Otherwise, it will panic. Unwrapped connection will be wrapped and returned as an instance of repo.SchemaConnQueryer interface, so it can be used in the use cases layer without requiring to type assert again and again. Returned querier instance can be used to run the connection-specific queries in addition to queries which support connections and transactions.

Currently, two operations mandate a connection. The InstallFDWExtensionIfMissing creates an extension which will be accessible by roles based on their granted privileges. That installation should be performed independent of a failed or successful migration and it is not required to uninstall it later too. Also, it requires the extension related files to be installed previously. So it is not possible to confine all of its steps in a transaction anyway. The DropServerIfExists drops a foreign server and its user mapping. Thereafter, it should be created with a distinct user role. And it should be attempted only after dropping the main and intermediate schema successfully. So, asking a connection helps to guarantee that other removals are completed (in their transaction or auto-commit transaction) beforehand. By the way, result of this operation can affect multiple user roles.

func (*Repo) Tx

func (schema *Repo) Tx(tx repo.Tx) repo.SchemaTxQueryer

Tx unwraps the given repo.Tx instance, expecting to find an instance of *postgres.Tx as created by this adapter layer. Otherwise, it will panic. Unwrapped transaction will be wrapped and returned as an instance of repo.SchemaTxQueryer interface, so it can be used in the use cases layer without requiring to type assert again and again. Returned querier instance can be used to run the transaction-specific queries in addition to queries which support connections and transactions.

Currently, one operation mandate a transaction. ChangePasswords updates passwords of some roles. When creating roles for the first time, it is desired to change/set their passwords before making them visible by committing the transaction. Also, it may be desired to call this method multiple times if all roles and passwords may not be identified as the same time. So, a transaction is required since there are scenarios that other operation must be performed in the same transaction and caller must specify the proper point of commitment.

Jump to

Keyboard shortcuts

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