Colin Watson has proposed merging lp:~cjwatson/launchpad/db-git-permissions 
into lp:launchpad/db-devel.

Commit message:
Add GitRule and GitGrant tables.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers): db
Related bugs:
  Bug #1517559 in Launchpad itself: "git fine-grained permissions"
  https://bugs.launchpad.net/launchpad/+bug/1517559

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/db-git-permissions/+merge/354200

Initial schema changes for fine-grained Git permissions.  See 
https://docs.google.com/document/d/1JW_D_Tgo4X2-vPMZtShSbi3cm1iOsGcNIzeOpa5E_wA 
for the design.

The GitRepository.rule_order array column isn't perfect, because PostgreSQL 
doesn't support arrays of foreign keys and so we lose some referential 
integrity.  However, all the other options I can think of have worse downsides:

 * GitRule.position integer (rearranging rules requires writing to potentially 
many rows)
 * GitRule.position rational so that you can always insert a rule between two 
others (I've seen this seriously suggested on the internet as a solution to 
this class of problem, but good grief it seems unreasonably complex)
 * Store all rules and grants in a single JSON column on GitRepository (would 
become very wide and would require custom and probably slow person merging code)

I therefore propose that we live with reduced referential integrity and enforce 
this constraint in the application instead.  It's not great, but I think it's 
tolerable.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
lp:~cjwatson/launchpad/db-git-permissions into lp:launchpad/db-devel.
=== added file 'database/schema/patch-2209-85-0.sql'
--- database/schema/patch-2209-85-0.sql	1970-01-01 00:00:00 +0000
+++ database/schema/patch-2209-85-0.sql	2018-09-03 17:07:35 +0000
@@ -0,0 +1,63 @@
+-- Copyright 2018 Canonical Ltd.  This software is licensed under the
+-- GNU Affero General Public License version 3 (see the file LICENSE).
+
+SET client_min_messages=ERROR;
+
+CREATE TABLE GitRule (
+    id serial PRIMARY KEY,
+    repository integer NOT NULL REFERENCES gitrepository ON DELETE CASCADE,
+    ref_pattern text NOT NULL,
+    creator integer NOT NULL REFERENCES person,
+    date_created timestamp without time zone DEFAULT (CURRENT_TIMESTAMP AT TIME ZONE 'UTC') NOT NULL,
+    date_last_modified timestamp without time zone DEFAULT (CURRENT_TIMESTAMP AT TIME ZONE 'UTC') NOT NULL
+);
+
+CREATE UNIQUE INDEX gitrule__repository__ref_pattern__key
+    ON GitRule(repository, ref_pattern);
+
+COMMENT ON TABLE GitRule IS 'An access rule for a Git repository.';
+COMMENT ON COLUMN GitRule.repository IS 'The repository that this rule is for.';
+COMMENT ON COLUMN GitRule.ref_pattern IS 'The pattern of references matched by this rule.';
+COMMENT ON COLUMN GitRule.creator IS 'The user who created this rule.';
+COMMENT ON COLUMN GitRule.date_created IS 'The time when this rule was created.';
+COMMENT ON COLUMN GitRule.date_last_modified IS 'The time when this rule was last modified.';
+
+ALTER TABLE GitRepository ADD COLUMN rule_order integer[];
+
+COMMENT ON COLUMN GitRepository.rule_order IS 'An ordered array of access rule IDs in this repository.';
+
+CREATE TABLE GitGrant (
+    id serial PRIMARY KEY,
+    repository integer NOT NULL REFERENCES gitrepository ON DELETE CASCADE,
+    rule integer NOT NULL REFERENCES gitrule ON DELETE CASCADE,
+    grantee_type integer NOT NULL,
+    grantee integer REFERENCES person,
+    can_create boolean DEFAULT false NOT NULL,
+    can_push boolean DEFAULT false NOT NULL,
+    can_force_push boolean DEFAULT false NOT NULL,
+    grantor integer NOT NULL REFERENCES person,
+    date_created timestamp without time zone DEFAULT (CURRENT_TIMESTAMP AT TIME ZONE 'UTC') NOT NULL,
+    date_last_modified timestamp without time zone DEFAULT (CURRENT_TIMESTAMP AT TIME ZONE 'UTC') NOT NULL,
+    -- 2 == PERSON
+    CONSTRAINT has_grantee CHECK ((grantee_type = 2) = (grantee IS NOT NULL)),
+    CONSTRAINT force_push_implies_push CHECK (can_push OR NOT can_force_push)
+);
+
+CREATE INDEX gitgrant__repository__idx
+    ON GitGrant(repository);
+CREATE UNIQUE INDEX gitgrant__rule__grantee_type__grantee_key
+    ON GitGrant(rule, grantee_type, grantee);
+
+COMMENT ON TABLE GitGrant IS 'An access grant for a Git repository rule.';
+COMMENT ON COLUMN GitGrant.repository IS 'The repository that this grant is for.';
+COMMENT ON COLUMN GitGrant.rule IS 'The rule that this grant is for.';
+COMMENT ON COLUMN GitGrant.grantee_type IS 'The type of entity being granted access.';
+COMMENT ON COLUMN GitGrant.grantee IS 'The person or team being granted access.';
+COMMENT ON COLUMN GitGrant.can_create IS 'Whether creating references is allowed.';
+COMMENT ON COLUMN GitGrant.can_push IS 'Whether pushing references is allowed.';
+COMMENT ON COLUMN GitGrant.can_force_push IS 'Whether force-pushing references is allowed.';
+COMMENT ON COLUMN GitGrant.grantor IS 'The user who created this grant.';
+COMMENT ON COLUMN GitGrant.date_created IS 'The time when this grant was created.';
+COMMENT ON COLUMN GitGrant.date_last_modified IS 'The time when this grant was last modified.';
+
+INSERT INTO LaunchpadDatabaseRevision VALUES (2209, 85, 0);

_______________________________________________
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to     : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp

Reply via email to