diff --git a/.gitignore b/.gitignore index fae1481dff..a103054aed 100644 --- a/.gitignore +++ b/.gitignore @@ -41,10 +41,7 @@ node_modules # Ignore any SQL files copied from build tasks deployment/postgres-init-db/sql/**/*.sql -!deployment/postgres-init-db/sql/ui/init.sql -!deployment/postgres-init-db/sql/ui/tables/view.sql -!deployment/postgres-init-db/sql/ui/tables/schema_migrations.sql -!deployment/postgres-init-db/sql/ui/applied_migrations.sql +!deployment/postgres-init-db/sql/ui # Ignore Gradle project-specific cache directory .gradle diff --git a/deployment/hasura/metadata/databases/AerieUI/tables/public_extension_roles.yaml b/deployment/hasura/metadata/databases/AerieUI/tables/public_extension_roles.yaml new file mode 100644 index 0000000000..668ba7a755 --- /dev/null +++ b/deployment/hasura/metadata/databases/AerieUI/tables/public_extension_roles.yaml @@ -0,0 +1,37 @@ +table: + name: extension_roles + schema: public +object_relationships: + - name: extension + using: + foreign_key_constraint_on: extension_id +select_permissions: + - role: aerie_admin + permission: + columns: '*' + filter: {} + allow_aggregations: true + - role: user + permission: + columns: '*' + filter: {} + allow_aggregations: true + - role: viewer + permission: + columns: '*' + filter: {} + allow_aggregations: true +insert_permissions: + - role: aerie_admin + permission: + columns: [extension_id, role] + check: {} +update_permissions: + - role: aerie_admin + permission: + columns: [extension_id, role] + filter: {} +delete_permissions: + - role: aerie_admin + permission: + filter: {} diff --git a/deployment/hasura/metadata/databases/AerieUI/tables/public_extensions.yaml b/deployment/hasura/metadata/databases/AerieUI/tables/public_extensions.yaml new file mode 100644 index 0000000000..6932ed610b --- /dev/null +++ b/deployment/hasura/metadata/databases/AerieUI/tables/public_extensions.yaml @@ -0,0 +1,43 @@ +table: + name: extensions + schema: public +array_relationships: + - name: extension_roles + using: + foreign_key_constraint_on: + column: extension_id + table: + name: extension_roles + schema: public +select_permissions: + - role: aerie_admin + permission: + columns: '*' + filter: {} + allow_aggregations: true + - role: user + permission: + columns: '*' + filter: {} + allow_aggregations: true + - role: viewer + permission: + columns: '*' + filter: {} + allow_aggregations: true +insert_permissions: + - role: aerie_admin + permission: + columns: [description, label, url] + check: {} + set: + owner: "x-hasura-user-id" +update_permissions: + - role: aerie_admin + permission: + columns: [description, label, owner, url] + filter: {} +delete_permissions: + - role: aerie_admin + permission: + filter: {} diff --git a/deployment/hasura/metadata/databases/AerieUI/tables/tables.yaml b/deployment/hasura/metadata/databases/AerieUI/tables/tables.yaml index 9c21739162..5adc44d7f2 100644 --- a/deployment/hasura/metadata/databases/AerieUI/tables/tables.yaml +++ b/deployment/hasura/metadata/databases/AerieUI/tables/tables.yaml @@ -1 +1,3 @@ +- "!include public_extension_roles.yaml" +- "!include public_extensions.yaml" - "!include public_view.yaml" diff --git a/deployment/hasura/migrations/AerieUI/2_extensions/down.sql b/deployment/hasura/migrations/AerieUI/2_extensions/down.sql new file mode 100644 index 0000000000..b760368160 --- /dev/null +++ b/deployment/hasura/migrations/AerieUI/2_extensions/down.sql @@ -0,0 +1,8 @@ +drop table extension_roles; + +drop trigger extensions_set_timestamp on extensions; +drop function extensions_set_updated_at(); + +drop table extensions; + +call migrations.mark_migration_rolled_back('2'); diff --git a/deployment/hasura/migrations/AerieUI/2_extensions/up.sql b/deployment/hasura/migrations/AerieUI/2_extensions/up.sql new file mode 100644 index 0000000000..70f0d16791 --- /dev/null +++ b/deployment/hasura/migrations/AerieUI/2_extensions/up.sql @@ -0,0 +1,57 @@ +create table extensions ( + id integer generated always as identity, + description text, + label text not null, + owner text, + url text not null, + updated_at timestamptz not null default now(), + + constraint extensions_primary_key primary key (id) +); + +comment on table extensions is e'' + 'External extension APIs the user can call from within Aerie UI.'; +comment on column extensions.description is e'' + 'An optional description of the external extension.'; +comment on column extensions.label is e'' + 'The name of the extension that is displayed in the UI.'; +comment on column extensions.owner is e'' + 'The user who owns the extension.'; +comment on column extensions.url is e'' + 'The URL of the API to be called.'; +comment on column extensions.updated_at is e'' + 'The time the extension was last updated.'; + +create function extensions_set_updated_at() + returns trigger + language plpgsql as $$begin + new.updated_at = now(); + return new; +end$$; + +create trigger extensions_set_timestamp + before update on extensions + for each row +execute function extensions_set_updated_at(); + +create table extension_roles ( + id integer generated always as identity, + extension_id integer not null, + role text not null, + + constraint extension_roles_primary_key primary key (id), + constraint extension_roles_to_extension + foreign key (extension_id) + references "extensions" + on update cascade + on delete cascade +); + +comment on table extension_roles is e'' + 'A mapping of extensions to what roles can access them.'; +comment on column extension_roles.extension_id is e'' + 'The extension that the role is defined for.'; +comment on column extension_roles.role is e'' + 'The role that is allowed to access the extension.'; + +call migrations.mark_migration_applied('2'); diff --git a/deployment/postgres-init-db/sql/ui/applied_migrations.sql b/deployment/postgres-init-db/sql/ui/applied_migrations.sql index 6191790699..83e3e220cc 100644 --- a/deployment/postgres-init-db/sql/ui/applied_migrations.sql +++ b/deployment/postgres-init-db/sql/ui/applied_migrations.sql @@ -4,3 +4,4 @@ This file denotes which migrations occur "before" this version of the schema. call migrations.mark_migration_applied('0'); call migrations.mark_migration_applied('1'); +call migrations.mark_migration_applied('2'); diff --git a/deployment/postgres-init-db/sql/ui/init.sql b/deployment/postgres-init-db/sql/ui/init.sql index e60884b8ad..8c462d7add 100644 --- a/deployment/postgres-init-db/sql/ui/init.sql +++ b/deployment/postgres-init-db/sql/ui/init.sql @@ -4,5 +4,7 @@ begin; \ir applied_migrations.sql -- Tables. + \ir tables/extensions.sql + \ir tables/extension_roles.sql \ir tables/view.sql end; diff --git a/deployment/postgres-init-db/sql/ui/tables/extension_roles.sql b/deployment/postgres-init-db/sql/ui/tables/extension_roles.sql new file mode 100644 index 0000000000..dc6e4bd8d7 --- /dev/null +++ b/deployment/postgres-init-db/sql/ui/tables/extension_roles.sql @@ -0,0 +1,19 @@ +create table extension_roles ( + id integer generated always as identity, + extension_id integer not null, + role text not null, + + constraint extension_roles_primary_key primary key (id), + constraint extension_roles_to_extension + foreign key (extension_id) + references "extensions" + on update cascade + on delete cascade +); + +comment on table extension_roles is e'' + 'A mapping of extensions to what roles can access them.'; +comment on column extension_roles.extension_id is e'' + 'The extension that the role is defined for.'; +comment on column extension_roles.role is e'' + 'The role that is allowed to access the extension.'; diff --git a/deployment/postgres-init-db/sql/ui/tables/extensions.sql b/deployment/postgres-init-db/sql/ui/tables/extensions.sql new file mode 100644 index 0000000000..8753df55c6 --- /dev/null +++ b/deployment/postgres-init-db/sql/ui/tables/extensions.sql @@ -0,0 +1,35 @@ +create table extensions ( + id integer generated always as identity, + description text, + label text not null, + owner text, + url text not null, + updated_at timestamptz not null default now(), + + constraint extensions_primary_key primary key (id) +); + +comment on table extensions is e'' + 'External extension APIs the user can call from within Aerie UI.'; +comment on column extensions.description is e'' + 'An optional description of the external extension.'; +comment on column extensions.label is e'' + 'The name of the extension that is displayed in the UI.'; +comment on column extensions.owner is e'' + 'The user who owns the extension.'; +comment on column extensions.url is e'' + 'The URL of the API to be called.'; +comment on column extensions.updated_at is e'' + 'The time the extension was last updated.'; + +create function extensions_set_updated_at() +returns trigger +language plpgsql as $$begin + new.updated_at = now(); + return new; +end$$; + +create trigger extensions_set_timestamp + before update on extensions + for each row +execute function extensions_set_updated_at();