Skip to content

Commit ff884dc

Browse files
authored
Merge pull request #143 from supabase/requires_fixes
allows `requires` key in control file to specify only certain allow-listed extensions
2 parents aee31ea + aba084b commit ff884dc

File tree

4 files changed

+188
-5
lines changed

4 files changed

+188
-5
lines changed

cli/src/client.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ pub enum TokenType {
163163
pub struct PublishPackageRequest<'a> {
164164
pub package_name: &'a str,
165165
pub package_description: &'a Option<String>,
166+
pub relocatable: bool,
167+
pub requires: &'a [String],
166168
}
167169

168170
#[derive(Serialize)]

cli/src/commands/publish.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ pub async fn publish(
6666
}
6767

6868
if num_published == 0 {
69-
println!("Nothing to publish");
69+
println!("Updated package properties");
7070
}
7171

7272
Ok(())
@@ -76,6 +76,8 @@ fn create_publish_package_request(payload: &Payload) -> PublishPackageRequest {
7676
PublishPackageRequest {
7777
package_name: &payload.metadata.extension_name,
7878
package_description: &payload.metadata.comment,
79+
relocatable: payload.metadata.relocatable,
80+
requires: &payload.metadata.requires,
7981
}
8082
}
8183

cli/src/models.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ pub struct Metadata {
1414
pub extension_name: String,
1515
pub default_version: String,
1616
pub comment: Option<String>,
17-
pub requires: Option<Vec<String>>,
17+
pub relocatable: bool,
18+
pub requires: Vec<String>,
1819
}
1920

2021
impl Metadata {
@@ -23,6 +24,7 @@ impl Metadata {
2324
extension_name: control_file_ref.extension_name()?.clone(),
2425
default_version: control_file_ref.default_version()?.clone(),
2526
comment: control_file_ref.comment()?.clone(),
27+
relocatable: control_file_ref.relocatable()?,
2628
requires: control_file_ref.requires()?.clone(),
2729
})
2830
}
@@ -261,16 +263,26 @@ impl ControlFileRef {
261263

262264
// A list of names of extensions that this extension depends on, for example requires = 'foo,
263265
// bar'. Those extensions must be installed before this one can be installed.
264-
fn requires(&self) -> anyhow::Result<Option<Vec<String>>> {
266+
fn requires(&self) -> anyhow::Result<Vec<String>> {
265267
for line in self.contents.lines() {
266268
if line.starts_with("requires") {
267269
let value = self.read_control_line_value(line)?;
268270
let required_packages: Vec<String> =
269271
value.split(',').map(|x| x.trim().to_string()).collect();
270-
return Ok(Some(required_packages));
272+
return Ok(required_packages);
271273
}
272274
}
273-
Ok(None)
275+
Ok(vec![])
276+
}
277+
278+
fn relocatable(&self) -> anyhow::Result<bool> {
279+
for line in self.contents.lines() {
280+
if line.starts_with("relocatable") {
281+
let value: bool = self.read_control_line_value(line)?.parse()?;
282+
return Ok(value);
283+
}
284+
}
285+
Ok(false)
274286
}
275287

276288
fn default_version(&self) -> anyhow::Result<String> {
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
-- A list of extensions which are allowed in the requires key of the control file
2+
create table app.allowed_extensions (
3+
name text primary key
4+
);
5+
6+
insert into app.allowed_extensions (name)
7+
values
8+
-- extensions available on Supabase
9+
('citext'),
10+
('pg_cron'),
11+
('pg_graphql'),
12+
('pg_stat_statements'),
13+
('pg_trgm'),
14+
('pg_crypto'),
15+
('pg_jwt'),
16+
('pg_sodium'),
17+
('plpgsql'),
18+
('uuid-ossp'),
19+
('address_standardizer'),
20+
('address_standardizer_data_us'),
21+
('autoinc'),
22+
('bloom'),
23+
('btree_gin'),
24+
('btree_gist'),
25+
('cube'),
26+
('dblink'),
27+
('dict_int'),
28+
('dict_xsyn'),
29+
('earthdistance'),
30+
('fuzzystrmatch'),
31+
('hstore'),
32+
('http'),
33+
('hypopg'),
34+
('insert_username'),
35+
('intarray'),
36+
('isn'),
37+
('ltree'),
38+
('moddatetime'),
39+
('pg_hashids'),
40+
('pg_jsonschema'),
41+
('pg_net'),
42+
('pg_repack'),
43+
('pg_stat_monitor'),
44+
('pg_walinspect'),
45+
('pgaudit'),
46+
('pgroonga'),
47+
('pgroonga_database'),
48+
('pgrouting'),
49+
('pgrowlocks'),
50+
('pgtap'),
51+
('plcoffee'),
52+
('pljava'),
53+
('plls'),
54+
('plpgsql_check'),
55+
('plv8'),
56+
('postgis'),
57+
('postgis_raster'),
58+
('postgis_sfcgal'),
59+
('postgis_tiger_geocoder'),
60+
('postgis_topology'),
61+
('postgres_fdw'),
62+
('refint'),
63+
('rum'),
64+
('seg'),
65+
('sslinfo'),
66+
('supautils'),
67+
('tablefunc'),
68+
('tcn'),
69+
('timescaledb'),
70+
('tsm_system_rows'),
71+
('tsm_system_time'),
72+
('unaccent'),
73+
('vector'),
74+
('wrappers'),
75+
76+
-- extensions available on AWS (except those already in Supabase)
77+
-- full list here: https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html
78+
('amcheck'),
79+
('aws_commons'),
80+
('aws_lambda'),
81+
('aws_s3'),
82+
('bool_plperl'),
83+
('decoder_raw'),
84+
('h3-pg'),
85+
('hll'),
86+
('hstore_plperl'),
87+
('intagg'),
88+
('ip4r'),
89+
('jsonb_plperl'),
90+
('lo'),
91+
('log_fdw'),
92+
('mysql_fdw'),
93+
('old_snapshot'),
94+
('oracle_fdw'),
95+
('orafce'),
96+
('pageinspect'),
97+
('pg_bigm'),
98+
('pg_buffercache'),
99+
('pg_freespacemap'),
100+
('pg_hint_plan'),
101+
('pg_partman'),
102+
('pg_prewarm'),
103+
('pg_proctab'),
104+
('pg_similarity'),
105+
('pg_tle'),
106+
('pg_transport'),
107+
('pg_visibility'),
108+
('pgcrypto'),
109+
('pgstattuple'),
110+
('pgvector'),
111+
('plperl'),
112+
('plprofiler'),
113+
('plrust'),
114+
('pltcl'),
115+
('prefix'),
116+
('rdkit'),
117+
('rds_tools'),
118+
('tds_fdw'),
119+
('test_parser'),
120+
('wal2json');
121+
122+
grant insert (partial_name, handle, control_description, control_relocatable, control_requires)
123+
on app.packages
124+
to authenticated;
125+
126+
grant update (control_description, control_relocatable, control_requires)
127+
on app.packages
128+
to authenticated;
129+
130+
create or replace function public.publish_package(
131+
package_name app.valid_name,
132+
package_description varchar(1000),
133+
relocatable bool default false,
134+
requires text[] default '{}'
135+
)
136+
returns void
137+
language plpgsql
138+
as $$
139+
declare
140+
account app.accounts = account from app.accounts account where id = auth.uid();
141+
require text;
142+
begin
143+
if account.handle is null then
144+
raise exception 'user not logged in';
145+
end if;
146+
147+
foreach require in array requires
148+
loop
149+
if not exists (
150+
select true
151+
from app.allowed_extensions
152+
where
153+
name = require
154+
) then
155+
raise exception '`requires` in the control file can''t have `%` in it', require;
156+
end if;
157+
end loop;
158+
159+
insert into app.packages(handle, partial_name, control_description, control_relocatable, control_requires)
160+
values (account.handle, package_name, package_description, relocatable, requires)
161+
on conflict on constraint packages_handle_partial_name_key
162+
do update
163+
set control_description = excluded.control_description,
164+
control_relocatable = excluded.control_relocatable,
165+
control_requires = excluded.control_requires;
166+
end;
167+
$$;

0 commit comments

Comments
 (0)