Skip to content

Commit a959e45

Browse files
committed
refactor(database): app and migrations to allow for authenticator role
1 parent d6da5f0 commit a959e45

9 files changed

+143
-186
lines changed

.env.example

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
BASE_IMAGE_NODE_ALPINE=node:15.8.0-alpine3.12
22

3-
POSTGRES_USER=postgres_user
4-
POSTGRES_PASSWORD=pg_pass
5-
POSTGRES_DB=myapp
6-
7-
# actual connection used by Postgraphile
8-
DATABASE_URL=postgres://postgres_user:pg_pass@db/myapp
9-
# used for development purposes
10-
SHADOW_DATABASE_URL=postgres://postgres_user:pg_pass@db/myapp_shadow
11-
# super user account
12-
ROOT_DATABASE_URL=postgres://postgres_user:pg_pass@db/postgres
3+
####
4+
# Create the root user, our database table and connection string
5+
DATABASE_OWNER=myapp_owner
6+
DATABASE_OWNER_PASSWORD=cisecret1
7+
DATABASE_NAME=myapp
8+
DATABASE_HOST=db
9+
DATABASE_URL=postgres://myapp_owner:cisecret1@db/myapp
10+
####
11+
12+
13+
###
14+
# Unprivileged database role, it's what PostGraphile uses.
15+
DATABASE_AUTHENTICATOR=myapp_graphile_authenticator
16+
DATABASE_AUTHENTICATOR_PASSWORD=authenticatorsecretpassword
17+
DATABASE_AUTHENTICATOR_URL=postgres://postgres:postgres@db/template1
18+
###
19+
20+
DATABASE_VISITOR=myapp_visitor

apps/database/.gmrc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@
6262
* these.
6363
*/
6464
"placeholders": {
65-
// ":DATABASE_VISITOR": "!ENV", // Uses process.env.DATABASE_VISITOR
65+
":DATABASE_VISITOR": "!ENV", // Uses process.env.DATABASE_VISITOR
66+
":DATABASE_AUTHENTICATOR": "!ENV",
67+
":DATABASE_AUTHENTICATOR_PASSWORD": "!ENV",
6668
},
6769

6870
/*
@@ -85,7 +87,7 @@
8587
* afterReset: actions executed after a `graphile-migrate reset` command.
8688
*/
8789
"afterReset": [
88-
// "afterReset.sql",
90+
"afterReset.sql",
8991
// { "_": "command", "command": "graphile-worker --schema-only" },
9092
],
9193

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
BEGIN;
2+
3+
DO
4+
$$
5+
BEGIN
6+
CREATE USER :DATABASE_AUTHENTICATOR WITH PASSWORD ':DATABASE_AUTHENTICATOR_PASSWORD';
7+
EXCEPTION
8+
WHEN DUPLICATE_OBJECT THEN
9+
RAISE NOTICE 'not creating authenticator role -- it already exists';
10+
END
11+
$$;
12+
13+
14+
DO
15+
$$
16+
BEGIN
17+
CREATE ROLE :DATABASE_VISITOR;
18+
EXCEPTION
19+
WHEN DUPLICATE_OBJECT THEN
20+
RAISE NOTICE 'not creating viewer role -- it already exists';
21+
END
22+
$$;
23+
24+
GRANT CONNECT ON DATABASE :DATABASE_NAME TO :DATABASE_OWNER;
25+
GRANT CONNECT ON DATABASE :DATABASE_NAME TO :DATABASE_AUTHENTICATOR;
26+
GRANT ALL ON DATABASE :DATABASE_NAME TO :DATABASE_OWNER;
27+
ALTER SCHEMA public OWNER TO :DATABASE_OWNER;
28+
29+
-- Some extensions require superuser privileges, so we create them before migration time.
30+
-- CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
31+
-- CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA public;
32+
CREATE EXTENSION IF NOT EXISTS citext WITH SCHEMA public;
33+
CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA public;
34+
CREATE EXTENSION IF NOT EXISTS unaccent WITH SCHEMA public;
35+
CREATE EXTENSION IF NOT EXISTS "pg_trgm" WITH SCHEMA public;
36+
37+
COMMIT;

apps/database/migrations/committed/000001-schemas-and-roles.sql

Lines changed: 0 additions & 32 deletions
This file was deleted.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
--! Previous: -
2+
--! Hash: sha1:de60470eae2711674026eea0ced5e4917011e6ea
3+
--! Message: schemas-and-timestamp-trigger
4+
5+
--! split: 0001-reset.sql
6+
/*
7+
* Graphile Migrate will run our `current/...` migrations in one batch. Since
8+
* this is our first migration it's defining the entire database, so we first
9+
* drop anything that may have previously been created
10+
* (app_public/app_hidden/app_private) so that we can start from scratch.
11+
*/
12+
13+
DROP SCHEMA IF EXISTS app_public CASCADE;
14+
DROP SCHEMA IF EXISTS app_hidden CASCADE;
15+
DROP SCHEMA IF EXISTS app_private CASCADE;
16+
17+
--! split: 0010-public-permissions.sql
18+
/*
19+
* The `public` *schema* contains things like PostgreSQL extensions. We
20+
* deliberately do not install application logic into the public schema
21+
* (instead storing it to app_public/app_hidden/app_private as appropriate),
22+
* but none the less we don't want untrusted roles to be able to install or
23+
* modify things into the public schema.
24+
*
25+
* The `public` *role* is automatically inherited by all other roles; we only
26+
* want specific roles to be able to access our database so we must revoke
27+
* access to the `public` role.
28+
*/
29+
30+
REVOKE ALL ON SCHEMA public FROM PUBLIC;
31+
32+
ALTER DEFAULT PRIVILEGES REVOKE ALL ON SEQUENCES FROM PUBLIC;
33+
ALTER DEFAULT PRIVILEGES REVOKE ALL ON FUNCTIONS FROM PUBLIC;
34+
35+
-- Of course we want our database owner to be able to do anything inside the
36+
-- database, so we grant access to the `public` schema:
37+
GRANT ALL ON SCHEMA public TO :DATABASE_OWNER;
38+
39+
--! split: 0020-schemas.sql
40+
/*
41+
* Read about our app_public/app_hidden/app_private schemas here:
42+
* https://www.graphile.org/postgraphile/namespaces/#advice
43+
*
44+
* Note this pattern is not required to use PostGraphile, it's merely the
45+
* preference of the author of this package.
46+
*/
47+
48+
CREATE SCHEMA app_public;
49+
CREATE SCHEMA app_hidden;
50+
CREATE SCHEMA app_private;
51+
52+
-- The 'visitor' role (used by PostGraphile to represent an end user) may
53+
-- access the public, app_public and app_hidden schemas (but _NOT_ the
54+
-- app_private schema).
55+
GRANT USAGE ON SCHEMA public, app_public, app_hidden TO :DATABASE_VISITOR;
56+
57+
-- We want the `visitor` role to be able to insert rows (`serial` data type
58+
-- creates sequences, so we need to grant access to that).
59+
ALTER DEFAULT PRIVILEGES IN SCHEMA public, app_public, app_hidden
60+
GRANT USAGE, SELECT ON SEQUENCES TO :DATABASE_VISITOR;
61+
62+
-- And the `visitor` role should be able to call functions too.
63+
ALTER DEFAULT PRIVILEGES IN SCHEMA public, app_public, app_hidden
64+
GRANT EXECUTE ON FUNCTIONS TO :DATABASE_VISITOR;
65+
66+
--! split: 0030-timestamp-trigger.sql
67+
/*
68+
* This trigger is used on tables with created_at and updated_at to ensure that
69+
* these timestamps are kept valid (namely: `created_at` cannot be changed, and
70+
* `updated_at` must be monotonically increasing).
71+
*/
72+
CREATE FUNCTION app_private.tg__timestamps() RETURNS trigger AS
73+
$$
74+
BEGIN
75+
new.created_at = (CASE WHEN tg_op = 'INSERT' THEN NOW() ELSE old.created_at END);
76+
new.updated_at = (CASE
77+
WHEN tg_op = 'UPDATE' AND old.updated_at >= NOW()
78+
THEN old.updated_at + INTERVAL '1 millisecond'
79+
ELSE NOW() END);
80+
RETURN new;
81+
END;
82+
$$ LANGUAGE plpgsql VOLATILE SET search_path TO pg_catalog, public, pg_temp;
83+
COMMENT ON FUNCTION app_private.tg__timestamps() IS
84+
E'This trigger should be called on all tables with created_at, updated_at - it ensures that they cannot be manipulated and that updated_at will always be larger than the previous updated_at.';

apps/database/migrations/committed/000002-updated-at-trigger.sql

Lines changed: 0 additions & 13 deletions
This file was deleted.

apps/database/migrations/committed/000003-user-tables.sql

Lines changed: 0 additions & 61 deletions
This file was deleted.

apps/database/migrations/committed/000004-user-registration.sql

Lines changed: 0 additions & 37 deletions
This file was deleted.

apps/database/migrations/committed/000005-user-authentication.sql

Lines changed: 0 additions & 31 deletions
This file was deleted.

0 commit comments

Comments
 (0)