Merge lp:~stevenk/launchpad/db-specification-new-access-policy into lp:launchpad/db-devel

Proposed by Steve Kowalik
Status: Merged
Approved by: Steve Kowalik
Approved revision: no longer in the source branch.
Merged at revision: 12272
Proposed branch: lp:~stevenk/launchpad/db-specification-new-access-policy
Merge into: lp:launchpad/db-devel
Diff against target: 158 lines (+126/-1)
4 files modified
database/schema/patch-2209-28-6.sql (+78/-0)
database/schema/security.cfg (+1/-0)
lib/lp/blueprints/tests/test_specification_access_policy_triggers.py (+46/-0)
lib/lp/testing/factory.py (+1/-1)
To merge this branch: bzr merge lp:~stevenk/launchpad/db-specification-new-access-policy
Reviewer Review Type Date Requested Status
Stuart Bishop (community) db Approve
Review via email: mp+143230@code.launchpad.net

Commit message

Add new columns Specification.access_{policy,grants}.

Description of the change

Add new columns on Specification, access_{policy,grants} -- this work mirrors the earlier work done on both Bug and Branch, and brings Specification into line with them.

To post a comment you must log in.
Revision history for this message
Stuart Bishop (stub) wrote :

Looks good.

70 +CREATE OR REPLACE FUNCTION specification_maintain_access_cache_trig() RETURNS trigger
71 + LANGUAGE plpgsql AS $$
72 +BEGIN
73 + PERFORM specification_denorm_access(NEW.id);
74 + RETURN NULL;
75 +END;
76 +$$;

If you want you can add an 'if NEW.id <> OLD.id then specification_denorm_access(OLD.id)' here to cope with someone updating the id column, not that we ever actually do that.

review: Approve (db)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'database/schema/patch-2209-28-6.sql'
2--- database/schema/patch-2209-28-6.sql 1970-01-01 00:00:00 +0000
3+++ database/schema/patch-2209-28-6.sql 2013-01-15 05:37:22 +0000
4@@ -0,0 +1,78 @@
5+-- Copyright 2013 Canonical Ltd. This software is licensed under the
6+-- GNU Affero General Public License version 3 (see the file LICENSE).
7+
8+SET client_min_messages=ERROR;
9+
10+-- Create new access policy for Specification.
11+ALTER TABLE Specification ADD COLUMN access_policy integer;
12+ALTER TABLE Specification ADD COLUMN access_grants integer[];
13+
14+-- New specification function, like bug_flatten_access.
15+CREATE OR REPLACE FUNCTION specification_denorm_access(spec_id integer)
16+ RETURNS void LANGUAGE sql SECURITY DEFINER SET search_path = public AS $$
17+ UPDATE specification
18+ SET access_policy = policies[1], access_grants = grants
19+ FROM
20+ build_access_cache(
21+ (SELECT id FROM accessartifact WHERE specification = $1),
22+ (SELECT information_type FROM specification WHERE id = $1))
23+ AS (policies integer[], grants integer[])
24+ WHERE id = $1;
25+$$;
26+
27+CREATE OR REPLACE FUNCTION accessartifact_denorm_to_artifacts(artifact_id integer)
28+ RETURNS void
29+ LANGUAGE plpgsql
30+ AS $$
31+DECLARE
32+ artifact_row accessartifact%ROWTYPE;
33+BEGIN
34+ SELECT * INTO artifact_row FROM accessartifact WHERE id = artifact_id;
35+ IF artifact_row.bug IS NOT NULL THEN
36+ PERFORM bug_flatten_access(artifact_row.bug);
37+ END IF;
38+ IF artifact_row.branch IS NOT NULL THEN
39+ PERFORM branch_denorm_access(artifact_row.branch);
40+ END IF;
41+ IF artifact_row.specification IS NOT NULL THEN
42+ PERFORM specification_denorm_access(artifact_row.specification);
43+ END IF;
44+ RETURN;
45+END;
46+$$;
47+COMMENT ON FUNCTION accessartifact_denorm_to_artifacts(artifact_id integer) IS
48+ 'Denormalize the policy access and artifact grants to bugs, branches and specifications.';
49+
50+CREATE OR REPLACE FUNCTION accessartifact_maintain_denorm_to_artifacts_trig()
51+ RETURNS trigger
52+ LANGUAGE plpgsql
53+ AS $$
54+BEGIN
55+ IF TG_OP = 'INSERT' THEN
56+ PERFORM accessartifact_denorm_to_artifacts(NEW.artifact);
57+ ELSIF TG_OP = 'UPDATE' THEN
58+ PERFORM accessartifact_denorm_to_artifacts(NEW.artifact);
59+ IF OLD.artifact != NEW.artifact THEN
60+ PERFORM accessartifact_denorm_to_artifacts(OLD.artifact);
61+ END IF;
62+ ELSIF TG_OP = 'DELETE' THEN
63+ PERFORM accessartifact_denorm_to_artifacts(OLD.artifact);
64+ END IF;
65+ RETURN NULL;
66+END;
67+$$;
68+
69+-- A trigger to handle specification.information_type changes.
70+CREATE OR REPLACE FUNCTION specification_maintain_access_cache_trig() RETURNS trigger
71+ LANGUAGE plpgsql AS $$
72+BEGIN
73+ PERFORM specification_denorm_access(NEW.id);
74+ RETURN NULL;
75+END;
76+$$;
77+
78+CREATE TRIGGER specification_maintain_access_cache
79+ AFTER INSERT OR UPDATE OF information_type ON specification
80+ FOR EACH ROW EXECUTE PROCEDURE specification_maintain_access_cache_trig();
81+
82+INSERT INTO LaunchpadDatabaseRevision VALUES (2209, 28, 6);
83
84=== modified file 'database/schema/security.cfg'
85--- database/schema/security.cfg 2012-12-14 04:42:41 +0000
86+++ database/schema/security.cfg 2013-01-15 05:37:22 +0000
87@@ -77,6 +77,7 @@
88 public.replication_lag(integer) = EXECUTE
89 public.sane_version(text) = EXECUTE
90 public.sha1(text) = EXECUTE
91+public.specification_denorm_access(integer) = EXECUTE
92 public.ulower(text) = EXECUTE
93 public.update_database_disk_utilization() =
94 public.valid_absolute_url(text) = EXECUTE
95
96=== added file 'lib/lp/blueprints/tests/test_specification_access_policy_triggers.py'
97--- lib/lp/blueprints/tests/test_specification_access_policy_triggers.py 1970-01-01 00:00:00 +0000
98+++ lib/lp/blueprints/tests/test_specification_access_policy_triggers.py 2013-01-15 05:37:22 +0000
99@@ -0,0 +1,46 @@
100+# Copyright 2013 Canonical Ltd. This software is licensed under the
101+# GNU Affero General Public License version 3 (see the file LICENSE).
102+
103+__metaclass__ = type
104+
105+from zope.component import getUtility
106+from zope.security.proxy import removeSecurityProxy
107+
108+from lp.app.enums import InformationType
109+from lp.blueprints.model.specification import Specification
110+from lp.registry.interfaces.accesspolicy import IAccessPolicySource
111+from lp.services.database.lpstorm import IStore
112+from lp.testing import TestCaseWithFactory
113+from lp.testing.layers import DatabaseFunctionalLayer
114+
115+
116+class TestSpecificationAccessPolicyTriggers(TestCaseWithFactory):
117+ layer = DatabaseFunctionalLayer
118+
119+ def fetchPolicies(self, specification):
120+ # We may be dealing with private specs, so just ignore security.
121+ return IStore(Specification).execute(
122+ "SELECT access_policy, access_grants FROM specification WHERE "
123+ "id = ?", (removeSecurityProxy(specification).id,)).get_one()
124+
125+ def assertAccess(self, specification, expected_policy, expected_grants):
126+ policy, grants = self.fetchPolicies(specification)
127+ self.assertEqual(expected_policy, policy)
128+ self.assertEqual(expected_grants, grants)
129+
130+ def test_no_access_policy_for_public_specifications(self):
131+ # A public specification has no access policy or grants.
132+ self.assertAccess(self.factory.makeSpecification(), None, None)
133+
134+ def test_adding_aag_with_private_specification(self):
135+ # Adding a new AAG updates the specification columns via trigger.
136+ owner = self.factory.makePerson()
137+ specification = self.factory.makeSpecification(
138+ information_type=InformationType.PROPRIETARY, owner=owner)
139+ [ap] = getUtility(IAccessPolicySource).find(
140+ [(removeSecurityProxy(specification).product,
141+ InformationType.PROPRIETARY)])
142+ self.assertAccess(specification, ap.id, [])
143+ artifact = self.factory.makeAccessArtifact(concrete=specification)
144+ grant = self.factory.makeAccessArtifactGrant(artifact=artifact)
145+ self.assertAccess(specification, ap.id, [grant.grantee.id])
146
147=== modified file 'lib/lp/testing/factory.py'
148--- lib/lp/testing/factory.py 2012-12-26 01:12:37 +0000
149+++ lib/lp/testing/factory.py 2013-01-15 05:37:22 +0000
150@@ -2097,7 +2097,7 @@
151 if distribution is None and product is None:
152 if proprietary:
153 specification_sharing_policy = (
154- SpecificationSharingPolicy.EMBARGOED_OR_PROPRIETARY)
155+ SpecificationSharingPolicy.EMBARGOED_OR_PROPRIETARY)
156 else:
157 specification_sharing_policy = None
158 product = self.makeProduct(

Subscribers

People subscribed via source and target branches

to status/vote changes: