Mediate.Postgres.Migration (mediate_postgres v0.1.0)

Copy Markdown View Source

The helpers a migration calls. This is the only place the package writes DDL. Every statement runs through the repo the caller passes, under the library exemption, so the seam mediates a migration like any other call.

  • protect!/2 enables row-level security on a table and forces it, so the policies apply to the table's owner as well.
  • policy!/2 adds the SELECT policy of one operation. The helper writes the operation guard itself, current_setting('mediate.operation', true) = '<operation>', and joins the caller's expression to it. Permissive policies combine with OR, so without the guard the policy of one operation widens another. With it, only the policy of the operation in force can hold.
  • gate!/2 adds the write policy of one operation. An answer reads its USING expression before a write. The database applies its WITH CHECK expression to the write itself. An operation whose write is an insert has no row to read first. So its gate is an INSERT policy and carries the WITH CHECK expression alone. A gate carries no operation guard, so the database refuses a write that violates it whether or not anything asked first.
  • admit!/2 adds a permissive true policy for one command. Forced row-level security refuses every statement no policy admits, so a table that takes an insert or a delete outside a decision needs one.
  • exempt!/2 adds the policy that admits one role's statements while no operation is in force. That is the state the seam leaves behind when it admits a call outside a decision. A role that reads every row whatever the settings say takes the same policy without that clause.
  • grant!/2 grants a role the table privileges it needs. Row-level security narrows what a role can reach. The grant is what lets it reach the table at all, and the two go together.
  • publish!/2 reads the policies back from pg_policy and emits the policy version, in the transaction the migration is already in. the events document under "Policy version" has the event.

Every name a helper puts into a statement passes a check first. A name that passes is a plain lowercase identifier within the length an identifier can hold. A name that fails raises, and the raise says which name it refused. The migration's author writes an expression, and it reaches the database as the author wrote it.

Summary

Functions

Add a permissive true policy for one command. Requires table: and command:.

Add the policy that admits a role's statements outside a decision. Requires table: and to:. Takes commands:, every command by default. Takes outside_decision:, false where the role holds the policy whatever operation is in force.

Add the write gate of one operation. Requires table: and operation:. Takes command:, :update by default. An update gate requires using: and with_check:. An insert gate requires with_check: alone.

Grant a role privileges on a table. Requires table:, to:, and commands:.

Add the SELECT policy of one operation. Requires table:, operation:, and using:.

Enable row-level security on the table and force it on the table's owner too.

Read the policies on those tables back and emit the policy version. Requires tables:, version:, author:, and approval:. Takes at: and content_bytes:. The caller passes the moment, and the helper does not read the configured clock, because a migration runs before the configuration boots.

Functions

admit!(repo, options)

@spec admit!(module(), keyword()) :: :ok

Add a permissive true policy for one command. Requires table: and command:.

exempt!(repo, options)

@spec exempt!(module(), keyword()) :: :ok

Add the policy that admits a role's statements outside a decision. Requires table: and to:. Takes commands:, every command by default. Takes outside_decision:, false where the role holds the policy whatever operation is in force.

gate!(repo, options)

@spec gate!(module(), keyword()) :: :ok

Add the write gate of one operation. Requires table: and operation:. Takes command:, :update by default. An update gate requires using: and with_check:. An insert gate requires with_check: alone.

grant!(repo, options)

@spec grant!(module(), keyword()) :: :ok

Grant a role privileges on a table. Requires table:, to:, and commands:.

policy!(repo, options)

@spec policy!(module(), keyword()) :: :ok

Add the SELECT policy of one operation. Requires table:, operation:, and using:.

protect!(repo, table)

@spec protect!(module(), String.t() | atom()) :: :ok

Enable row-level security on the table and force it on the table's owner too.

publish!(repo, options)

@spec publish!(module(), keyword()) :: Mediate.PolicyVersion.t()

Read the policies on those tables back and emit the policy version. Requires tables:, version:, author:, and approval:. Takes at: and content_bytes:. The caller passes the moment, and the helper does not read the configured clock, because a migration runs before the configuration boots.