Skip to content

Commit

Permalink
Merge pull request #3838 from mathesar-foundation/permissions-modals-2
Browse files Browse the repository at this point in the history
Implement basic Table data model on the frontend and Table Permissions modal -> 'Share' tab
  • Loading branch information
seancolsen authored Sep 18, 2024
2 parents 00f93c3 + 08003c1 commit f8b81c2
Show file tree
Hide file tree
Showing 66 changed files with 525 additions and 373 deletions.
50 changes: 45 additions & 5 deletions mathesar_ui/src/api/rpc/tables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,34 @@ import type { RecursivePartial } from '@mathesar/component-library';
import { rpcMethodTypeContainer } from '@mathesar/packages/json-rpc-client-builder';

import type { ColumnTypeOptions } from './columns';
import type { RawDatabase } from './databases';
import type { RawRole } from './roles';

export const allTablePrivileges = [
'SELECT',
'INSERT',
'UPDATE',
'DELETE',
'TRUNCATE',
'REFERENCES',
'TRIGGER',
] as const;
export type TablePrivilege = (typeof allTablePrivileges)[number];

export interface RawTable {
oid: number;
name: string;
/** The OID of the schema containing the table */
schema: number;
description: string | null;
owner_oid: RawRole['oid'];
current_role_priv: TablePrivilege[];
current_role_owns: boolean;
}

export interface RawTablePrivilegesForRole {
role_oid: RawRole['oid'];
direct: TablePrivilege[];
}

interface TableMetadata {
Expand All @@ -28,15 +49,15 @@ interface TableMetadata {
record_summary_template: string | null;
}

export interface Table extends RawTable {
export interface RawTableWithMetadata extends RawTable {
metadata: TableMetadata | null;
}

/** [table oid, column attnum][] */
export type JoinPath = [number, number][][];

export interface JoinableTable {
target: Table['oid'];
target: RawTableWithMetadata['oid'];
join_path: JoinPath;
/**
* [Constraint OID, is_reversed]
Expand All @@ -62,7 +83,7 @@ export interface JoinableTablesResult {
target_table_info: Record<
string,
{
name: Table['name'];
name: RawTableWithMetadata['name'];
/** Keys are stringified column attnum values */
columns: Record<
string,
Expand Down Expand Up @@ -100,7 +121,7 @@ export const tables = {
database_id: number;
schema_oid: number;
},
Table[]
RawTableWithMetadata[]
>(),

get: rpcMethodTypeContainer<
Expand All @@ -116,7 +137,7 @@ export const tables = {
database_id: number;
table_oid: number;
},
Table
RawTableWithMetadata
>(),

/** Returns the oid of the table created */
Expand Down Expand Up @@ -205,4 +226,23 @@ export const tables = {
void
>(),
},

privileges: {
list_direct: rpcMethodTypeContainer<
{
database_id: RawDatabase['id'];
table_oid: RawTable['oid'];
},
Array<RawTablePrivilegesForRole>
>(),

replace_for_roles: rpcMethodTypeContainer<
{
database_id: RawDatabase['id'];
table_oid: RawTable['oid'];
privileges: Array<RawTablePrivilegesForRole>;
},
Array<RawTablePrivilegesForRole>
>(),
},
};
2 changes: 1 addition & 1 deletion mathesar_ui/src/components/SelectTable.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import type { Table } from '@mathesar/api/rpc/tables';
import type { Table } from '@mathesar/models/Table';
import { Select } from '@mathesar-component-library';
import type { SelectProps } from '@mathesar-component-library/types';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import type { Table } from '@mathesar/api/rpc/tables';
import type { Table } from '@mathesar/models/Table';
import { importVerifiedTables } from '@mathesar/stores/tables';
import type { SelectProps } from '@mathesar-component-library/types';
Expand Down
2 changes: 1 addition & 1 deletion mathesar_ui/src/components/TableName.svelte
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script lang="ts">
import type { ComponentProps } from 'svelte';
import type { Table } from '@mathesar/api/rpc/tables';
import { iconTable } from '@mathesar/icons';
import type { Table } from '@mathesar/models/Table';
import { tableRequiresImportConfirmation } from '@mathesar/utils/tables';
import NameWithIcon from './NameWithIcon.svelte';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import type { Table } from '@mathesar/api/rpc/tables';
import { iconExpandRight } from '@mathesar/icons';
import type { Table } from '@mathesar/models/Table';
import { getRecordSelectorFromContext } from '@mathesar/systems/record-selector/RecordSelectorController';
import { Button, Icon, iconSearch } from '@mathesar-component-library';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import { meta } from 'tinro';
import type { QueryInstance } from '@mathesar/api/rest/types/queries';
import type { Table } from '@mathesar/api/rpc/tables';
import { iconTable } from '@mathesar/icons';
import type { Database } from '@mathesar/models/Database';
import type { Schema } from '@mathesar/models/Schema';
import type { Table } from '@mathesar/models/Table';
import { getExplorationPageUrl } from '@mathesar/routes/urls';
import { queries as queriesStore } from '@mathesar/stores/queries';
import { currentTableId, currentTables } from '@mathesar/stores/tables';
Expand Down
2 changes: 1 addition & 1 deletion mathesar_ui/src/components/breadcrumb/breadcrumbTypes.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { QueryInstance } from '@mathesar/api/rest/types/queries';
import type { Table } from '@mathesar/api/rpc/tables';
import type {
ComponentAndProps,
IconProps,
} from '@mathesar/component-library/types';
import type { Database } from '@mathesar/models/Database';
import type { Schema } from '@mathesar/models/Schema';
import type { Table } from '@mathesar/models/Table';

export interface BreadcrumbItemHome {
type: 'home';
Expand Down
2 changes: 1 addition & 1 deletion mathesar_ui/src/components/cell-fabric/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Column } from '@mathesar/api/rpc/columns';
import type { Table } from '@mathesar/api/rpc/tables';
import type { Table } from '@mathesar/models/Table';
import type { CellInfo } from '@mathesar/stores/abstract-types/types';
import type { RecordSummariesForSheet } from '@mathesar/stores/table-data/record-summaries/recordSummaryUtils';
import type { ComponentAndProps } from '@mathesar-component-library/types';
Expand Down
11 changes: 11 additions & 0 deletions mathesar_ui/src/i18n/languages/en/dict.json
Original file line number Diff line number Diff line change
Expand Up @@ -566,14 +566,24 @@
"sync_external_changes_data_help": "External changes to data (e.g. adding or editing rows) will be automatically reflected without clicking this button.",
"sync_external_changes_structure_help": "If you make structural changes to the database outside Mathesar (e.g. using another tool to add a schema, table, or column), those changes will not be reflected in Mathesar until you manually sync them with this button.",
"table": "Table",
"table_access_read_help": "Can read table records",
"table_access_write_help": "Can read, update, delete, and create table records",
"table_delete_permanent_warning": "Warning: This action is permanent and once deleted, the table cannot be recovered.",
"table_does_not_link": "This table does not link to any other tables",
"table_name": "Table Name",
"table_name_already_exists": "A table with that name already exists.",
"table_name_cannot_be_empty": "The table name cannot be empty.",
"table_not_found": "Table not found.",
"table_not_shared": "This table is currently not shared.",
"table_permissions": "Table Permissions",
"table_preview": "Table Preview",
"table_privilege_delete_help": "Allow deletion of records within the table.",
"table_privilege_insert_help": "Allow creation of new records within the table.",
"table_privilege_references_help": "Allow creation of foreign key references to the table.",
"table_privilege_select_help": "Allow reading data from the table.",
"table_privilege_trigger_help": "Allow creation of triggers on the table.",
"table_privilege_truncate_help": "Allow truncation (removal of all records) of the table.",
"table_privilege_update_help": "Allow updating of records within the table.",
"table_with_name_already_exists": "A table with that name already exists.",
"tables": "Tables",
"tables_matching_search": "{count, plural, one {{count} table matches [searchValue]} other {{count} tables match [searchValue]}}",
Expand Down Expand Up @@ -660,6 +670,7 @@
"while_upgrading": "While Upgrading",
"why_is_this_needed": "Why is this needed?",
"window_remains_open_mathesar_unusable": "This window will remain open but all features within Mathesar will be unusable.",
"write": "Write",
"yes": "Yes",
"yes_summarize_as_list": "Yes, summarize as a list",
"yesterday": "Yesterday"
Expand Down
5 changes: 3 additions & 2 deletions mathesar_ui/src/models/Schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,14 @@ export class Schema {

readonly current_role_owns: boolean;

readonly isPublicSchema = derived(this.name, ($name) => $name === 'public');
readonly isPublicSchema;

readonly database: Database;

constructor(props: { database: Database; rawSchema: RawSchema }) {
this.oid = props.rawSchema.oid;
this._name = writable(props.rawSchema.name);
this.isPublicSchema = derived(this._name, ($name) => $name === 'public');
this._description = writable(props.rawSchema.description);
this._tableCount = writable(props.rawSchema.table_count);
this.owner_oid = props.rawSchema.owner_oid;
Expand Down Expand Up @@ -75,7 +76,7 @@ export class Schema {
);
}

updateTableCount(count: number) {
setTableCount(count: number) {
this._tableCount.set(count);
}

Expand Down
54 changes: 54 additions & 0 deletions mathesar_ui/src/models/Table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { api } from '@mathesar/api/rpc';
import type {
RawTableWithMetadata,
TablePrivilege,
} from '@mathesar/api/rpc/tables';
import AsyncRpcApiStore from '@mathesar/stores/AsyncRpcApiStore';
import { ImmutableMap } from '@mathesar-component-library';

import type { Role } from './Role';
import type { Schema } from './Schema';

export class Table {
oid: number;

name: string;

description: string | null;

metadata;

schema;

owner_oid: Role['oid'];

current_role_priv: TablePrivilege[];

current_role_owns: boolean;

constructor(props: {
schema: Schema;
rawTableWithMetadata: RawTableWithMetadata;
}) {
this.oid = props.rawTableWithMetadata.oid;
this.name = props.rawTableWithMetadata.name;
this.description = props.rawTableWithMetadata.description;
this.metadata = props.rawTableWithMetadata.metadata;
this.owner_oid = props.rawTableWithMetadata.owner_oid;
this.current_role_priv = props.rawTableWithMetadata.current_role_priv;
this.current_role_owns = props.rawTableWithMetadata.current_role_owns;
this.schema = props.schema;
}

constructTablePrivilegesStore() {
return new AsyncRpcApiStore(api.tables.privileges.list_direct, {
postProcess: (rawTablePrivilegesForRoles) =>
new ImmutableMap(
rawTablePrivilegesForRoles.map((rawTablePrivilegesForRole) => [
rawTablePrivilegesForRole.role_oid,
rawTablePrivilegesForRole,
]),
),
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
onProceed: async () => {
await deleteSchemaAPI(schema);
// TODO: Create common util to handle data clearing & sync between stores
removeTablesStore(database, schema);
removeTablesStore(schema);
},
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<div>
{#if user}
<div>{userName}</div>
<div>{user.email}</div>
<div>{user.email ?? ''}</div>
{:else}
{collaborator.userId}
{/if}
Expand Down
5 changes: 2 additions & 3 deletions mathesar_ui/src/pages/exploration/Header.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
import { getExplorationEditorPageUrl } from '@mathesar/routes/urls';
import { Button, Icon } from '@mathesar-component-library';
import ShareExplorationDropdown from './ShareExplorationDropdown.svelte';
export let database: Database;
export let schema: Schema;
export let query: QueryInstance;
Expand All @@ -33,7 +31,8 @@
>
<span>{$_('edit_in_data_explorer')}</span>
</a>
<ShareExplorationDropdown id={query.id} />
<!-- TODO: Display Share option when we re-implement it with the new permissions structure -->
<!-- <ShareExplorationDropdown id={query.id} /> -->
{/if}
<Button
appearance="secondary"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import type { DataFile } from '@mathesar/api/rest/types/dataFiles';
import { api } from '@mathesar/api/rpc';
import type { Column } from '@mathesar/api/rpc/columns';
import type { ColumnPreviewSpec, Table } from '@mathesar/api/rpc/tables';
import type { ColumnPreviewSpec } from '@mathesar/api/rpc/tables';
import {
Field,
FieldLayout,
Expand All @@ -15,8 +15,8 @@
} from '@mathesar/components/form';
import InfoBox from '@mathesar/components/message-boxes/InfoBox.svelte';
import { iconDeleteMajor } from '@mathesar/icons';
import type { Database } from '@mathesar/models/Database';
import type { Schema } from '@mathesar/models/Schema';
import type { Table } from '@mathesar/models/Table';
import { runner } from '@mathesar/packages/json-rpc-client-builder';
import {
getImportPreviewPageUrl,
Expand Down Expand Up @@ -171,7 +171,7 @@
async function finishImport() {
try {
await updateTable({
database: schema.database,
schema,
table: {
oid: table.oid,
name: $customizedTableName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
}
$: void (async () => {
const table = (await tableFetch.run({ database, tableOid: tableId }))
const table = (await tableFetch.run({ schema, tableOid: tableId }))
.resolvedValue;
if (!table) {
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { dataFilesApi } from '@mathesar/api/rest/dataFiles';
import type { DataFile } from '@mathesar/api/rest/types/dataFiles';
import type { Column } from '@mathesar/api/rpc/columns';
import type { Table } from '@mathesar/api/rpc/tables';
import { getCellCap } from '@mathesar/components/cell-fabric/utils';
import type { Database } from '@mathesar/models/Database';

Check warning on line 5 in mathesar_ui/src/pages/import/preview/importPreviewPageUtils.ts

View workflow job for this annotation

GitHub Actions / Run front end linter

'Database' is defined but never used
import type { Schema } from '@mathesar/models/Schema';
import type { Table } from '@mathesar/models/Table';
import { getAbstractTypeForDbType } from '@mathesar/stores/abstract-types';
import type {
AbstractType,
Expand Down
5 changes: 2 additions & 3 deletions mathesar_ui/src/pages/record/RecordPage.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
<script lang="ts">
import type { Table } from '@mathesar/api/rpc/tables';
import LayoutWithHeader from '@mathesar/layouts/LayoutWithHeader.svelte';
import type { Table } from '@mathesar/models/Table';
import { makeSimplePageTitle } from '@mathesar/pages/pageTitleUtils';
import { abstractTypesMap } from '@mathesar/stores/abstract-types';
import { currentDatabase } from '@mathesar/stores/databases';
import { TableStructure } from '@mathesar/stores/table-data';
import { currentTable } from '@mathesar/stores/tables';
Expand All @@ -15,7 +14,7 @@
$: table = $currentTable as Table;
$: tableStructure = new TableStructure({
database: $currentDatabase,
database: table.schema.database,
table,
abstractTypesMap,
});
Expand Down
Loading

0 comments on commit f8b81c2

Please sign in to comment.