Browse Source

refactor: move readonly props from meta to new cols for better stability

pull/8708/head
Pranav C 6 months ago
parent
commit
4561423226
  1. 2
      packages/nc-gui/components/dashboard/TreeView/CreateViewBtn.vue
  2. 18
      packages/nc-gui/components/dashboard/settings/data-sources/CreateBase.vue
  3. 28
      packages/nc-gui/components/dashboard/settings/data-sources/EditBase.vue
  4. 10
      packages/nc-gui/composables/useRoles/index.ts
  5. 2
      packages/nc-gui/lib/acl.ts
  6. 4
      packages/nocodb-sdk/src/lib/enums.ts
  7. 4
      packages/nocodb/src/meta/migrations/XcMigrationSourcev2.ts
  8. 18
      packages/nocodb/src/meta/migrations/v2/nc_051_source_readonly_columns.ts
  9. 8
      packages/nocodb/src/middlewares/extract-ids/extract-ids.middleware.ts
  10. 6
      packages/nocodb/src/models/Source.ts
  11. 8
      packages/nocodb/src/modules/jobs/jobs/export-import/duplicate.controller.ts
  12. 8
      packages/nocodb/src/schema/swagger-v2.json
  13. 8
      packages/nocodb/src/schema/swagger.json
  14. 6
      packages/nocodb/src/services/columns.service.ts
  15. 2
      packages/nocodb/src/services/forms.service.ts
  16. 2
      packages/nocodb/src/services/public-datas.service.ts
  17. 2
      packages/nocodb/src/utils/acl.ts

2
packages/nc-gui/components/dashboard/TreeView/CreateViewBtn.vue

@ -126,7 +126,7 @@ async function onOpenModal({
</div>
</NcMenuItem>
<NcMenuItem v-if="!source.meta?.[SourceRestriction.DATA_READONLY]" @click="onOpenModal({ type: ViewTypes.FORM })">
<NcMenuItem v-if="!source.is_schema_readonly" @click="onOpenModal({ type: ViewTypes.FORM })">
<div class="item" data-testid="sidebar-view-create-form">
<div class="item-inner">
<GeneralViewIcon :meta="{ type: ViewTypes.FORM }" />

18
packages/nc-gui/components/dashboard/settings/data-sources/CreateBase.vue

@ -56,9 +56,8 @@ const formState = ref<ProjectCreateForm>({
},
sslUse: SSLUsage.No,
extraParameters: [],
meta: {
[SourceRestriction.META_READONLY]: true,
[SourceRestriction.DATA_READONLY]: false,
'is_schema_readonly': true,
'is_data_readonly': false,
},
})
@ -249,7 +248,8 @@ const createSource = async () => {
config,
inflection_column: formState.value.inflection.inflectionColumn,
inflection_table: formState.value.inflection.inflectionTable,
meta: formState.value.meta,
is_schema_readonly: formState.value.is_schema_readonly,
is_data_readonly: formState.value.is_data_readonly,
})
$poller.subscribe(
@ -401,18 +401,16 @@ const toggleModal = (val: boolean) => {
}
const allowMetaWrite = computed({
get: () => !formState.value.meta[SourceRestriction.META_READONLY],
get: () => !formState.value.is_schema_readonly,
set: (v) => {
formState.value.meta = formState.value.meta || {}
formState.value.meta[SourceRestriction.META_READONLY] = !v
formState.value.is_schema_readonly = !v
},
})
const allowDataWrite = computed({
get: () => !formState.value.meta[SourceRestriction.DATA_READONLY],
get: () => !formState.value.is_data_readonly,
set: (v) => {
formState.value.meta = formState.value.meta || {}
formState.value.meta[SourceRestriction.DATA_READONLY] = !v
formState.value.is_data_readonly = !v
},
})
</script>

28
packages/nc-gui/components/dashboard/settings/data-sources/EditBase.vue

@ -61,10 +61,8 @@ const formState = ref<ProjectCreateForm>({
},
sslUse: SSLUsage.No,
extraParameters: [],
meta: {
[SourceRestriction.META_READONLY]: true,
[SourceRestriction.DATA_READONLY]: false,
},
is_schema_readonly: true,
is_data_readonly: false,
})
const customFormState = ref<ProjectCreateForm>({
@ -76,10 +74,8 @@ const customFormState = ref<ProjectCreateForm>({
},
sslUse: SSLUsage.No,
extraParameters: [],
meta: {
[SourceRestriction.META_READONLY]: true,
[SourceRestriction.DATA_READONLY]: false,
},
is_schema_readonly: true,
is_data_readonly: false,
})
const validators = computed(() => {
@ -237,7 +233,8 @@ const editBase = async () => {
config,
inflection_column: formState.value.inflection.inflectionColumn,
inflection_table: formState.value.inflection.inflectionTable,
meta: formState.value.meta || {},
is_schema_readonly: formState.value.is_schema_readonly,
is_data_readonly: formState.value.is_data_readonly,
})
$e('a:source:edit:extdb')
@ -349,7 +346,8 @@ onMounted(async () => {
},
extraParameters: tempParameters,
sslUse: SSLUsage.No,
meta: activeBase.meta || {},
is_schema_readonly: activeBase.is_schema_readonly,
is_data_readonly: activeBase.is_data_readonly,
}
updateSSLUse()
}
@ -369,18 +367,16 @@ watch(
)
const allowMetaWrite = computed({
get: () => !formState.value.meta[SourceRestriction.META_READONLY],
get: () => !formState.value.is_schema_readonly,
set: (v) => {
formState.value.meta = formState.value.meta || {}
formState.value.meta[SourceRestriction.META_READONLY] = !v
formState.value.is_schema_readonly = !v
},
})
const allowDataWrite = computed({
get: () => !formState.value.meta[SourceRestriction.DATA_READONLY],
get: () => !formState.value.is_data_readonly,
set: (v) => {
formState.value.meta = formState.value.meta || {}
formState.value.meta[SourceRestriction.DATA_READONLY] = !v
formState.value.is_data_readonly = !v
},
})
</script>

10
packages/nc-gui/composables/useRoles/index.ts

@ -150,7 +150,7 @@ export const useRolesShared = createSharedComposable(() => {
if (
!args.skipSourceCheck &&
(sourceRestrictions[SourceRestriction.DATA_READONLY][permission] ||
sourceRestrictions[SourceRestriction.META_READONLY][permission])
sourceRestrictions[SourceRestriction.SCHEMA_READONLY][permission])
) {
const source = unref(args.source || null)
@ -159,10 +159,10 @@ export const useRolesShared = createSharedComposable(() => {
return false
}
if (source?.meta?.[SourceRestriction.DATA_READONLY] && sourceRestrictions[SourceRestriction.DATA_READONLY][permission]) {
if (source?.is_data_readonly && sourceRestrictions[SourceRestriction.DATA_READONLY][permission]) {
return false
}
if (source?.meta?.[SourceRestriction.META_READONLY] && sourceRestrictions[SourceRestriction.META_READONLY][permission]) {
if (source?.is_schema_readonly && sourceRestrictions[SourceRestriction.SCHEMA_READONLY][permission]) {
return false
}
}
@ -186,11 +186,11 @@ export const useRoles = () => {
const useRolesRes = useRolesShared()
const isMetaReadOnly = computed(() => {
return currentSource.value?.meta?.[SourceRestriction.META_READONLY] || false
return currentSource.value?.is_schema_readonly || false
})
const isDataReadOnly = computed(() => {
return currentSource.value?.meta?.[SourceRestriction.DATA_READONLY] || false
return currentSource.value?.is_schema_readonly || false
})
return {

2
packages/nc-gui/lib/acl.ts

@ -134,7 +134,7 @@ export const sourceRestrictions = {
duplicateModel: true,
tableDuplicate: true,
},
[SourceRestriction.META_READONLY]: {
[SourceRestriction.SCHEMA_READONLY]: {
tableCreate: true,
tableRename: true,
tableDelete: true,

4
packages/nocodb-sdk/src/lib/enums.ts

@ -329,8 +329,8 @@ export enum APIContext {
export enum SourceRestriction {
META_READONLY = 'metaReadOnly',
DATA_READONLY = 'dataReadOnly',
SCHEMA_READONLY = 'is_schema_readonly',
DATA_READONLY = 'is_data_readonly',
}

4
packages/nocodb/src/meta/migrations/XcMigrationSourcev2.ts

@ -37,6 +37,7 @@ import * as nc_047_comment_migration from '~/meta/migrations/v2/nc_047_comment_m
import * as nc_048_view_links from '~/meta/migrations/v2/nc_048_view_links';
import * as nc_049_clear_notifications from '~/meta/migrations/v2/nc_049_clear_notifications';
import * as nc_050_tenant_isolation from '~/meta/migrations/v2/nc_050_tenant_isolation';
import * as nc_051_source_readonly_columns from '~/meta/migrations/v2/nc_051_source_readonly_columns';
// Create a custom migration source class
export default class XcMigrationSourcev2 {
@ -85,6 +86,7 @@ export default class XcMigrationSourcev2 {
'nc_048_view_links',
'nc_049_clear_notifications',
'nc_050_tenant_isolation',
'nc_051_source_readonly_columns',
]);
}
@ -172,6 +174,8 @@ export default class XcMigrationSourcev2 {
return nc_049_clear_notifications;
case 'nc_050_tenant_isolation':
return nc_050_tenant_isolation;
case 'nc_051_source_readonly_columns':
return nc_051_source_readonly_columns;
}
}
}

18
packages/nocodb/src/meta/migrations/v2/nc_051_source_readonly_columns.ts

@ -0,0 +1,18 @@
import type { Knex } from 'knex';
import { MetaTable } from '~/utils/globals';
const up = async (knex: Knex) => {
await knex.schema.alterTable(MetaTable.BASES, (table) => {
table.boolean('is_schema_readonly').defaultTo(false);
table.boolean('is_data_readonly').defaultTo(false);
});
};
const down = async (knex: Knex) => {
await knex.schema.alterTable(MetaTable.BASES, (table) => {
table.dropColumn('is_schema_readonly');
table.dropColumn('is_data_readonly');
});
};
export { up, down };

8
packages/nocodb/src/middlewares/extract-ids/extract-ids.middleware.ts

@ -471,7 +471,7 @@ export class AclMiddleware implements NestInterceptor {
// 1. Check if it's present in the source restriction list
// 2. If present, check if write permission is allowed
if (
sourceRestrictions[SourceRestriction.META_READONLY][permissionName] ||
sourceRestrictions[SourceRestriction.SCHEMA_READONLY][permissionName] ||
sourceRestrictions[SourceRestriction.DATA_READONLY][permissionName]
) {
let source: Source;
@ -496,14 +496,14 @@ export class AclMiddleware implements NestInterceptor {
}
if (
source.meta?.[SourceRestriction.META_READONLY] &&
sourceRestrictions[SourceRestriction.META_READONLY][permissionName]
source.is_schema_readonly &&
sourceRestrictions[SourceRestriction.SCHEMA_READONLY][permissionName]
) {
NcError.sourceMetaReadOnly(source.alias);
}
if (
source.meta?.[SourceRestriction.DATA_READONLY] &&
source.is_data_readonly &&
sourceRestrictions[SourceRestriction.DATA_READONLY][permissionName]
) {
NcError.sourceDataReadOnly(source.alias);

6
packages/nocodb/src/models/Source.ts

@ -33,6 +33,8 @@ export default class Source implements SourceType {
alias?: string;
type?: DriverClient;
is_meta?: BoolType;
is_schema_readonly?: BoolType;
is_data_readonly?: BoolType;
config?: string;
inflection_column?: string;
inflection_table?: string;
@ -70,6 +72,8 @@ export default class Source implements SourceType {
'order',
'enabled',
'meta',
'is_schema_readonly',
'is_data_readonly',
]);
insertObj.config = CryptoJS.AES.encrypt(
@ -130,6 +134,8 @@ export default class Source implements SourceType {
'meta',
'deleted',
'fk_sql_executor_id',
'is_schema_readonly',
'is_data_readonly',
]);
if (updateObj.config) {

8
packages/nocodb/src/modules/jobs/jobs/export-import/duplicate.controller.ts

@ -214,10 +214,10 @@ export class DuplicateController {
const source = await Source.get(context, model.source_id);
// if data/schema is readonly, then restrict duplication
if (source.meta?.[SourceRestriction.META_READONLY]) {
if (source.is_schema_readonly) {
NcError.sourceMetaReadOnly(source.alias);
}
if (source.meta?.[SourceRestriction.DATA_READONLY]) {
if (source.is_data_readonly) {
NcError.sourceDataReadOnly(source.alias);
}
@ -288,10 +288,10 @@ export class DuplicateController {
const source = await Source.get(context, model.source_id);
// if data/schema is readonly, then restrict duplication
if (source.meta?.[SourceRestriction.META_READONLY]) {
if (source.is_schema_readonly) {
NcError.sourceMetaReadOnly(source.alias);
}
if (source.meta?.[SourceRestriction.DATA_READONLY]) {
if (source.is_data_readonly) {
NcError.sourceDataReadOnly(source.alias);
}

8
packages/nocodb/src/schema/swagger-v2.json

@ -12166,6 +12166,14 @@
"$ref": "#/components/schemas/Bool",
"description": "Is the data source minimal db"
},
"is_schema_readonly": {
"$ref": "#/components/schemas/Bool",
"description": "Is the data source minimal db"
},
"is_data_readonly": {
"$ref": "#/components/schemas/Bool",
"description": "Is the data source minimal db"
},
"order": {
"description": "The order of the list of sources",
"example": 1,

8
packages/nocodb/src/schema/swagger.json

@ -18215,6 +18215,14 @@
"$ref": "#/components/schemas/Bool",
"description": "Is the data source minimal db"
},
"is_schema_readonly": {
"$ref": "#/components/schemas/Bool",
"description": "Is the data source minimal db"
},
"is_data_readonly": {
"$ref": "#/components/schemas/Bool",
"description": "Is the data source minimal db"
},
"order": {
"description": "The order of the list of sources",
"example": 1,

6
packages/nocodb/src/services/columns.service.ts

@ -201,7 +201,7 @@ export class ColumnsService {
// check if source is readonly and column type is not allowed
if (
source?.meta?.[SourceRestriction.META_READONLY] &&
source?.is_schema_readonly &&
(!readonlyMetaAllowedTypes.includes(column.uidt) ||
(param.column.uidt &&
!readonlyMetaAllowedTypes.includes(param.column.uidt as UITypes)))
@ -1496,7 +1496,7 @@ export class ColumnsService {
// check if source is readonly and column type is not allowed
if (
source?.meta?.[SourceRestriction.META_READONLY] &&
source?.is_schema_readonly &&
!readonlyMetaAllowedTypes.includes(param.column.uidt as UITypes)
) {
NcError.sourceMetaReadOnly(source.alias);
@ -2064,7 +2064,7 @@ export class ColumnsService {
// check if source is readonly and column type is not allowed
if (
source?.meta?.[SourceRestriction.META_READONLY] &&
source?.is_schema_readonly &&
!readonlyMetaAllowedTypes.includes(column.uidt)
) {
NcError.sourceMetaReadOnly(source.alias);

2
packages/nocodb/src/services/forms.service.ts

@ -40,7 +40,7 @@ export class FormsService {
const source = await Source.get(context, model.source_id);
if (source.meta?.[SourceRestriction.DATA_READONLY]) {
if (source.is_data_readonly) {
NcError.sourceDataReadOnly(source.alias);
}

2
packages/nocodb/src/services/public-datas.service.ts

@ -299,7 +299,7 @@ export class PublicDatasService {
const source = await Source.get(context, model.source_id);
if (source?.meta?.[SourceRestriction.DATA_READONLY]) {
if (source?.is_data_readonly) {
NcError.sourceDataReadOnly(source.alias);
}

2
packages/nocodb/src/utils/acl.ts

@ -462,7 +462,7 @@ export const sourceRestrictions = {
jsonImport: true,
excelImport: true,
},
[SourceRestriction.META_READONLY]: {
[SourceRestriction.SCHEMA_READONLY]: {
tableCreate: true,
tableRename: true,
tableDelete: true,

Loading…
Cancel
Save