Coverage for dak/dakdb/update83.py: 61%
68 statements
« prev ^ index » next coverage.py v7.6.0, created at 2026-08-03 16:46 +0000
« prev ^ index » next coverage.py v7.6.0, created at 2026-08-03 16:46 +0000
1"""
2switch to new ACL implementation and add pre-suite NEW
4@contact: Debian FTP Master <ftpmaster@debian.org>
5@copyright: 2012 Ansgar Burchardt <ansgar@debian.org>
6@license: GNU General Public License version 2 or later
7"""
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23################################################################################
25import psycopg2.extensions
27################################################################################
29_statements = [
30 """ALTER TABLE suite ADD COLUMN new_queue_id INT REFERENCES policy_queue(id)""",
31 """CREATE TABLE acl (
32 id SERIAL PRIMARY KEY NOT NULL,
33 name TEXT NOT NULL,
34 is_global BOOLEAN NOT NULL DEFAULT 'f',
36 match_fingerprint BOOLEAN NOT NULL DEFAULT 'f',
37 match_keyring_id INTEGER REFERENCES keyrings(id),
39 allow_new BOOLEAN NOT NULL DEFAULT 'f',
40 allow_source BOOLEAN NOT NULL DEFAULT 'f',
41 allow_binary BOOLEAN NOT NULL DEFAULT 'f',
42 allow_binary_all BOOLEAN NOT NULL DEFAULT 'f',
43 allow_binary_only BOOLEAN NOT NULL DEFAULT 'f',
44 allow_hijack BOOLEAN NOT NULL DEFAULT 'f',
45 allow_per_source BOOLEAN NOT NULL DEFAULT 'f',
46 deny_per_source BOOLEAN NOT NULL DEFAULT 'f'
47 )""",
48 """CREATE TABLE acl_architecture_map (
49 acl_id INTEGER NOT NULL REFERENCES acl(id) ON DELETE CASCADE,
50 architecture_id INTEGER NOT NULL REFERENCES architecture(id) ON DELETE CASCADE,
51 PRIMARY KEY (acl_id, architecture_id)
52 )""",
53 """CREATE TABLE acl_fingerprint_map (
54 acl_id INTEGER NOT NULL REFERENCES acl(id) ON DELETE CASCADE,
55 fingerprint_id INTEGER NOT NULL REFERENCES fingerprint(id) ON DELETE CASCADE,
56 PRIMARY KEY (acl_id, fingerprint_id)
57 )""",
58 """CREATE TABLE acl_per_source (
59 acl_id INTEGER NOT NULL REFERENCES acl(id) ON DELETE CASCADE,
60 fingerprint_id INTEGER NOT NULL REFERENCES fingerprint(id) ON DELETE CASCADE,
61 source TEXT NOT NULL,
62 reason TEXT,
63 PRIMARY KEY (acl_id, fingerprint_id, source)
64 )""",
65 """CREATE TABLE suite_acl_map (
66 suite_id INTEGER NOT NULL REFERENCES suite(id) ON DELETE CASCADE,
67 acl_id INTEGER NOT NULL REFERENCES acl(id),
68 PRIMARY KEY (suite_id, acl_id)
69 )""",
70]
72################################################################################
75def get_buildd_acl_id(c, keyring_id):
76 c.execute(
77 """
78 SELECT 'buildd-' || STRING_AGG(a.arch_string, '+' ORDER BY a.arch_string)
79 FROM keyring_acl_map kam
80 JOIN architecture a ON kam.architecture_id = a.id
81 WHERE kam.keyring_id = %(keyring_id)s
82 """,
83 {"keyring_id": keyring_id},
84 )
85 (acl_name,) = c.fetchone()
87 c.execute("SELECT id FROM acl WHERE name = %(acl_name)s", {"acl_name": acl_name})
88 row = c.fetchone()
89 if row is not None:
90 return row[0]
92 c.execute(
93 """
94 INSERT INTO acl
95 ( name, allow_new, allow_source, allow_binary, allow_binary_all, allow_binary_only, allow_hijack)
96 VALUES (%(acl_name)s, 't', 'f', 't', 'f', 't', 't')
97 RETURNING id""",
98 {"acl_name": acl_name},
99 )
100 (acl_id,) = c.fetchone()
102 c.execute(
103 """INSERT INTO acl_architecture_map (acl_id, architecture_id)
104 SELECT %(acl_id)s, architecture_id
105 FROM keyring_acl_map
106 WHERE keyring_id = %(keyring_id)s""",
107 {"acl_id": acl_id, "keyring_id": keyring_id},
108 )
110 return acl_id
113def get_acl_id(c, acl_dd, acl_dm, keyring_id, source_acl_id, binary_acl_id):
114 c.execute(
115 "SELECT access_level FROM source_acl WHERE id = %(source_acl_id)s",
116 {"source_acl_id": source_acl_id},
117 )
118 row = c.fetchone()
119 if row is not None: 119 ↛ 122line 119 didn't jump to line 122 because the condition on line 119 was always true
120 source_acl = row[0]
121 else:
122 source_acl = None
124 c.execute(
125 "SELECT access_level FROM binary_acl WHERE id = %(binary_acl_id)s",
126 {"binary_acl_id": binary_acl_id},
127 )
128 row = c.fetchone()
129 if row is not None: 129 ↛ 132line 129 didn't jump to line 132 because the condition on line 129 was always true
130 binary_acl = row[0]
131 else:
132 binary_acl = None
134 if source_acl == "full" and binary_acl == "full": 134 ↛ 136line 134 didn't jump to line 136 because the condition on line 134 was always true
135 return acl_dd
136 elif source_acl == "dm" and binary_acl == "full":
137 return acl_dm
138 elif source_acl is None and binary_acl == "map":
139 return get_buildd_acl_id(c, keyring_id)
141 raise Exception(
142 "Cannot convert ACL combination automatically: binary_acl={0}, source_acl={1}".format(
143 binary_acl, source_acl
144 )
145 )
148def do_update(c: psycopg2.extensions.cursor) -> None:
149 for stmt in _statements:
150 c.execute(stmt)
152 c.execute(
153 """
154 INSERT INTO acl
155 (name, allow_new, allow_source, allow_binary, allow_binary_all, allow_binary_only, allow_hijack)
156 VALUES ('dd', 't', 't', 't', 't', 't', 't')
157 RETURNING id"""
158 )
159 row = c.fetchone()
160 assert row is not None
161 (acl_dd,) = row
163 c.execute(
164 """
165 INSERT INTO acl
166 (name, allow_new, allow_source, allow_binary, allow_binary_all, allow_binary_only, allow_per_source, allow_hijack)
167 VALUES ('dm', 'f', 't', 't', 't', 'f', 't', 'f')
168 RETURNING id"""
169 )
170 row = c.fetchone()
171 assert row is not None
172 (acl_dm,) = row
174 # convert per-fingerprint ACLs
176 c.execute("ALTER TABLE fingerprint ADD COLUMN acl_id INTEGER REFERENCES acl(id)")
177 c.execute(
178 """SELECT id, keyring, source_acl_id, binary_acl_id
179 FROM fingerprint
180 WHERE source_acl_id IS NOT NULL OR binary_acl_id IS NOT NULL"""
181 )
182 for fingerprint_id, keyring_id, source_acl_id, binary_acl_id in c.fetchall(): 182 ↛ 183line 182 didn't jump to line 183 because the loop on line 182 never started
183 acl_id = get_acl_id(c, acl_dd, acl_dm, keyring_id, source_acl_id, binary_acl_id)
184 c.execute(
185 "UPDATE fingerprint SET acl_id = %(acl_id)s WHERE id = %(fingerprint_id)s",
186 {"acl_id": acl_id, "fingerprint_id": fingerprint_id},
187 )
188 c.execute(
189 """ALTER TABLE fingerprint
190 DROP COLUMN source_acl_id,
191 DROP COLUMN binary_acl_id,
192 DROP COLUMN binary_reject"""
193 )
195 # convert per-keyring ACLs
196 c.execute("ALTER TABLE keyrings ADD COLUMN acl_id INTEGER REFERENCES acl(id)")
197 c.execute("SELECT id, default_source_acl_id, default_binary_acl_id FROM keyrings")
198 for keyring_id, source_acl_id, binary_acl_id in c.fetchall():
199 acl_id = get_acl_id(c, acl_dd, acl_dm, keyring_id, source_acl_id, binary_acl_id)
200 c.execute(
201 "UPDATE keyrings SET acl_id = %(acl_id)s WHERE id = %(keyring_id)s",
202 {"acl_id": acl_id, "keyring_id": keyring_id},
203 )
204 c.execute(
205 """ALTER TABLE keyrings
206 DROP COLUMN default_source_acl_id,
207 DROP COLUMN default_binary_acl_id,
208 DROP COLUMN default_binary_reject"""
209 )
211 c.execute("DROP TABLE keyring_acl_map")
212 c.execute("DROP TABLE binary_acl_map")
213 c.execute("DROP TABLE binary_acl")
214 c.execute("DROP TABLE source_acl")
216 # convert upload blocks
217 c.execute(
218 """
219 INSERT INTO acl
220 ( name, is_global, allow_new, allow_source, allow_binary, allow_binary_all, allow_hijack, allow_binary_only, deny_per_source)
221 VALUES ('blocks', 't', 't', 't', 't', 't', 't', 't', 't')
222 RETURNING id"""
223 )
224 row = c.fetchone()
225 assert row is not None
226 (acl_block,) = row
227 c.execute("SELECT source, fingerprint_id, reason FROM upload_blocks")
228 for source, fingerprint_id, reason in c.fetchall(): 228 ↛ 229line 228 didn't jump to line 229 because the loop on line 228 never started
229 if fingerprint_id is None:
230 raise Exception(
231 "ERROR: upload blocks based on uid are no longer supported\n"
232 "=========================================================\n"
233 "\n"
234 "dak now only supports upload blocks based on fingerprints. Please remove\n"
235 "any uid-specific block by running\n"
236 " DELETE FROM upload_blocks WHERE fingerprint_id IS NULL\n"
237 "and try again."
238 )
240 c.execute(
241 "INSERT INTO acl_match_source_map (acl_id, fingerprint_id, source, reason) VALUES (%(acl_id)s, %(fingerprint_id)s, %(source)s, %(reason)s)",
242 {
243 "acl_id": acl_block,
244 "fingerprint_id": fingerprint_id,
245 "source": source,
246 "reason": reason,
247 },
248 )
249 c.execute("DROP TABLE upload_blocks")