Browse Source

Merge pull request #5272 from nocodb/refactor/cloud

Refactor: disable app store and hasmany relation based on env
pull/5293/head
աɨռɢӄաօռɢ 2 years ago committed by GitHub
parent
commit
b7b3bf6ea8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      packages/nc-gui/components/smartsheet/column/LinkedToAnotherRecordOptions.vue
  2. 28
      packages/nc-gui/components/webhook/Editor.vue
  3. 1
      packages/nc-gui/composables/useGlobal/state.ts
  4. 1
      packages/nc-gui/composables/useGlobal/types.ts
  5. 5
      packages/nc-gui/pages/account/index.vue
  6. 6
      packages/nc-gui/pages/account/index/[page].vue
  7. 13
      packages/nocodb/src/lib/controllers/plugin.ctl.ts
  8. 5
      packages/nocodb/src/lib/services/column.svc.ts
  9. 22
      packages/nocodb/src/lib/services/hook.svc.ts
  10. 1
      packages/nocodb/src/lib/services/util.svc.ts

12
packages/nc-gui/components/smartsheet/column/LinkedToAnotherRecordOptions.vue

@ -10,6 +10,8 @@ const props = defineProps<{
const emit = defineEmits(['update:value']) const emit = defineEmits(['update:value'])
const { appInfo } = $(useGlobal())
const vModel = useVModel(props, 'value', emit) const vModel = useVModel(props, 'value', emit)
const meta = $(inject(MetaInj, ref())) const meta = $(inject(MetaInj, ref()))
@ -31,10 +33,10 @@ if (!vModel.value.childTable) vModel.value.childTable = meta?.table_name
if (!vModel.value.parentTable) vModel.value.parentTable = vModel.value.rtn || '' if (!vModel.value.parentTable) vModel.value.parentTable = vModel.value.rtn || ''
if (!vModel.value.parentColumn) vModel.value.parentColumn = vModel.value.rcn || '' if (!vModel.value.parentColumn) vModel.value.parentColumn = vModel.value.rcn || ''
if (!vModel.value.type) vModel.value.type = 'hm' if (!vModel.value.type) vModel.value.type = 'mm'
if (!vModel.value.onUpdate) vModel.value.onUpdate = onUpdateDeleteOptions[0] if (!vModel.value.onUpdate) vModel.value.onUpdate = onUpdateDeleteOptions[0]
if (!vModel.value.onDelete) vModel.value.onDelete = onUpdateDeleteOptions[0] if (!vModel.value.onDelete) vModel.value.onDelete = onUpdateDeleteOptions[0]
if (!vModel.value.virtual) vModel.value.virtual = sqlUi === SqliteUi if (!vModel.value.virtual) vModel.value.virtual = appInfo.isCloud || sqlUi === SqliteUi
if (!vModel.value.alias) vModel.value.alias = vModel.value.column_name if (!vModel.value.alias) vModel.value.alias = vModel.value.column_name
const advancedOptions = $(ref(false)) const advancedOptions = $(ref(false))
@ -55,7 +57,7 @@ const filterOption = (value: string, option: { key: string }) => option.key.toLo
<div class="border-2 p-6"> <div class="border-2 p-6">
<a-form-item v-bind="validateInfos.type" class="nc-ltar-relation-type"> <a-form-item v-bind="validateInfos.type" class="nc-ltar-relation-type">
<a-radio-group v-model:value="vModel.type" name="type" v-bind="validateInfos.type"> <a-radio-group v-model:value="vModel.type" name="type" v-bind="validateInfos.type">
<a-radio value="hm">Has Many</a-radio> <a-radio value="hm" :disabled="appInfo.isCloud">Has Many</a-radio>
<a-radio value="mm">Many To Many</a-radio> <a-radio value="mm">Many To Many</a-radio>
</a-radio-group> </a-radio-group>
</a-form-item> </a-form-item>
@ -127,7 +129,9 @@ const filterOption = (value: string, option: { key: string }) => option.key.toLo
<div class="flex flex-row"> <div class="flex flex-row">
<a-form-item> <a-form-item>
<a-checkbox v-model:checked="vModel.virtual" name="virtual" @change="onDataTypeChange">Virtual Relation</a-checkbox> <a-checkbox v-model:checked="vModel.virtual" :disabled="appInfo.isCloud" name="virtual" @change="onDataTypeChange"
>Virtual Relation</a-checkbox
>
</a-form-item> </a-form-item>
</div> </div>
</div> </div>

28
packages/nc-gui/components/webhook/Editor.vue

@ -13,6 +13,7 @@ import {
reactive, reactive,
ref, ref,
useApi, useApi,
useGlobal,
useI18n, useI18n,
useNuxtApp, useNuxtApp,
watch, watch,
@ -32,6 +33,8 @@ const { $e } = useNuxtApp()
const { api, isLoading: loading } = useApi() const { api, isLoading: loading } = useApi()
const { appInfo } = $(useGlobal())
const meta = inject(MetaInj, ref()) const meta = inject(MetaInj, ref())
const useForm = Form.useForm const useForm = Form.useForm
@ -170,16 +173,20 @@ const eventList = [
{ text: ['After', 'Delete'], value: ['after', 'delete'] }, { text: ['After', 'Delete'], value: ['after', 'delete'] },
] ]
const notificationList = [ const notificationList = computed(() => {
{ type: 'URL' }, return appInfo.isCloud
{ type: 'Email' }, ? [{ type: 'URL' }]
{ type: 'Slack' }, : [
{ type: 'Microsoft Teams' }, { type: 'URL' },
{ type: 'Discord' }, { type: 'Email' },
{ type: 'Mattermost' }, { type: 'Slack' },
{ type: 'Twilio' }, { type: 'Microsoft Teams' },
{ type: 'Whatsapp Twilio' }, { type: 'Discord' },
] { type: 'Mattermost' },
{ type: 'Twilio' },
{ type: 'Whatsapp Twilio' },
]
})
const methodList = [ const methodList = [
{ title: 'GET' }, { title: 'GET' },
@ -306,6 +313,7 @@ async function onEventChange() {
} }
async function loadPluginList() { async function loadPluginList() {
if (appInfo.isCloud) return
try { try {
const plugins = (await api.plugin.list()).list! const plugins = (await api.plugin.list()).list!

1
packages/nc-gui/composables/useGlobal/state.ts

@ -99,6 +99,7 @@ export function useGlobalState(storageKey = 'nocodb-gui-v2'): State {
version: '0.0.0', version: '0.0.0',
ncAttachmentFieldSize: 20, ncAttachmentFieldSize: 20,
ncMaxAttachmentsAllowed: 10, ncMaxAttachmentsAllowed: 10,
isCloud: false,
}) })
/** reactive token payload */ /** reactive token payload */

1
packages/nc-gui/composables/useGlobal/types.ts

@ -22,6 +22,7 @@ export interface AppInfo {
ee?: boolean ee?: boolean
ncAttachmentFieldSize: number ncAttachmentFieldSize: number
ncMaxAttachmentsAllowed: number ncMaxAttachmentsAllowed: number
isCloud: boolean
} }
export interface StoredState { export interface StoredState {

5
packages/nc-gui/pages/account/index.vue

@ -2,8 +2,11 @@
import { navigateTo, useUIPermission } from '#imports' import { navigateTo, useUIPermission } from '#imports'
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useUIPermission()
const $route = useRoute() const $route = useRoute()
const { appInfo } = useGlobal()
const selectedKeys = computed(() => [ const selectedKeys = computed(() => [
/^\/account\/users\/?$/.test($route.fullPath) /^\/account\/users\/?$/.test($route.fullPath)
? isUIAllowed('superAdminUserManagement') ? isUIAllowed('superAdminUserManagement')
@ -68,7 +71,7 @@ const openKeys = ref([/^\/account\/users/.test($route.fullPath) && 'users'])
</div> </div>
</a-menu-item> </a-menu-item>
<a-menu-item <a-menu-item
v-if="isUIAllowed('appStore')" v-if="isUIAllowed('appStore') && !appInfo.isCloud"
key="apps" key="apps"
class="group active:(!ring-0) hover:(!bg-primary !bg-opacity-25)" class="group active:(!ring-0) hover:(!bg-primary !bg-opacity-25)"
@click="navigateTo('/account/apps')" @click="navigateTo('/account/apps')"

6
packages/nc-gui/pages/account/index/[page].vue

@ -1,7 +1,11 @@
<script setup lang="ts">
const { appInfo } = useGlobal()
</script>
<template> <template>
<AccountUserManagement v-if="$route.params.page === 'users'" /> <AccountUserManagement v-if="$route.params.page === 'users'" />
<AccountToken v-else-if="$route.params.page === 'tokens'" /> <AccountToken v-else-if="$route.params.page === 'tokens'" />
<AccountAppStore v-else-if="$route.params.page === 'apps'" /> <AccountAppStore v-else-if="$route.params.page === 'apps' && !appInfo.isCloud" />
<AccountLicense v-else-if="$route.params.page === 'license'" /> <AccountLicense v-else-if="$route.params.page === 'license'" />
<span v-else></span> <span v-else></span>
</template> </template>

13
packages/nocodb/src/lib/controllers/plugin.ctl.ts

@ -17,6 +17,7 @@ export async function pluginTest(req: Request<any, any>, res: Response) {
export async function pluginRead(req: Request, res: Response) { export async function pluginRead(req: Request, res: Response) {
res.json(await pluginService.pluginRead({ pluginId: req.params.pluginId })); res.json(await pluginService.pluginRead({ pluginId: req.params.pluginId }));
} }
export async function pluginUpdate( export async function pluginUpdate(
req: Request<any, any, PluginType>, req: Request<any, any, PluginType>,
res: Response res: Response
@ -27,36 +28,48 @@ export async function pluginUpdate(
}); });
res.json(plugin); res.json(plugin);
} }
export async function isPluginActive(req: Request, res: Response) { export async function isPluginActive(req: Request, res: Response) {
res.json( res.json(
await pluginService.isPluginActive({ pluginTitle: req.params.pluginTitle }) await pluginService.isPluginActive({ pluginTitle: req.params.pluginTitle })
); );
} }
const blockInCloudMw = (_req, res, next) => {
if (process.env.NC_CLOUD === 'true') {
res.status(403).send('Not allowed');
} else next();
};
const router = Router({ mergeParams: true }); const router = Router({ mergeParams: true });
router.get( router.get(
'/api/v1/db/meta/plugins', '/api/v1/db/meta/plugins',
blockInCloudMw,
metaApiMetrics, metaApiMetrics,
ncMetaAclMw(pluginList, 'pluginList') ncMetaAclMw(pluginList, 'pluginList')
); );
router.post( router.post(
'/api/v1/db/meta/plugins/test', '/api/v1/db/meta/plugins/test',
metaApiMetrics, metaApiMetrics,
blockInCloudMw,
ncMetaAclMw(pluginTest, 'pluginTest') ncMetaAclMw(pluginTest, 'pluginTest')
); );
router.get( router.get(
'/api/v1/db/meta/plugins/:pluginId', '/api/v1/db/meta/plugins/:pluginId',
metaApiMetrics, metaApiMetrics,
blockInCloudMw,
ncMetaAclMw(pluginRead, 'pluginRead') ncMetaAclMw(pluginRead, 'pluginRead')
); );
router.patch( router.patch(
'/api/v1/db/meta/plugins/:pluginId', '/api/v1/db/meta/plugins/:pluginId',
metaApiMetrics, metaApiMetrics,
blockInCloudMw,
ncMetaAclMw(pluginUpdate, 'pluginUpdate') ncMetaAclMw(pluginUpdate, 'pluginUpdate')
); );
router.get( router.get(
'/api/v1/db/meta/plugins/:pluginTitle/status', '/api/v1/db/meta/plugins/:pluginTitle/status',
metaApiMetrics, metaApiMetrics,
blockInCloudMw,
ncMetaAclMw(isPluginActive, 'isPluginActive') ncMetaAclMw(isPluginActive, 'isPluginActive')
); );
export default router; export default router;

5
packages/nocodb/src/lib/services/column.svc.ts

@ -1549,7 +1549,10 @@ async function createLTARColumn(param: {
// todo: create index for virtual relations as well // todo: create index for virtual relations as well
// create index for foreign key in pg // create index for foreign key in pg
if (param.base.type === 'pg') { if (
param.base.type === 'pg' ||
(param.column as LinkToAnotherColumnReqType).virtual
) {
await createColumnIndex({ await createColumnIndex({
column: new Column({ column: new Column({
...newColumn, ...newColumn,

22
packages/nocodb/src/lib/services/hook.svc.ts

@ -1,11 +1,26 @@
import { T } from 'nc-help'; import { T } from 'nc-help';
import { validatePayload } from '../meta/api/helpers'; import { validatePayload } from '../meta/api/helpers';
import { NcError } from '../meta/helpers/catchError';
import { Hook, Model } from '../models'; import { Hook, Model } from '../models';
import { invokeWebhook } from '../meta/helpers/webhookHelpers'; import { invokeWebhook } from '../meta/helpers/webhookHelpers';
import populateSamplePayload from '../meta/helpers/populateSamplePayload'; import populateSamplePayload from '../meta/helpers/populateSamplePayload';
import type { HookReqType, HookTestReqType } from 'nocodb-sdk'; import type { HookReqType, HookTestReqType } from 'nocodb-sdk';
function validateHookPayload(notificationJsonOrObject: string | object) {
let notification: { type?: string } = {};
try {
notification =
typeof notificationJsonOrObject === 'string'
? JSON.parse(notificationJsonOrObject)
: notificationJsonOrObject;
} catch {}
if (notification.type !== 'URL' && process.env.NC_CLOUD === 'true') {
NcError.badRequest('Only URL notification is supported');
}
}
export async function hookList(param: { tableId: string }) { export async function hookList(param: { tableId: string }) {
// todo: pagination // todo: pagination
return await Hook.list({ fk_model_id: param.tableId }); return await Hook.list({ fk_model_id: param.tableId });
@ -17,6 +32,8 @@ export async function hookCreate(param: {
}) { }) {
validatePayload('swagger.json#/components/schemas/HookReq', param.hook); validatePayload('swagger.json#/components/schemas/HookReq', param.hook);
validateHookPayload(param.hook.notification);
T.emit('evt', { evt_type: 'webhooks:created' }); T.emit('evt', { evt_type: 'webhooks:created' });
// todo: type correction // todo: type correction
const hook = await Hook.insert({ const hook = await Hook.insert({
@ -37,6 +54,8 @@ export async function hookUpdate(param: { hookId: string; hook: HookReqType }) {
T.emit('evt', { evt_type: 'webhooks:updated' }); T.emit('evt', { evt_type: 'webhooks:updated' });
validateHookPayload(param.hook.notification);
// todo: correction in swagger // todo: correction in swagger
return await Hook.update(param.hookId, param.hook as any); return await Hook.update(param.hookId, param.hook as any);
} }
@ -50,6 +69,8 @@ export async function hookTest(param: {
param.hookTest param.hookTest
); );
validateHookPayload(param.hookTest.hook?.notification);
const model = await Model.getByIdOrName({ id: param.tableId }); const model = await Model.getByIdOrName({ id: param.tableId });
const { const {
@ -69,6 +90,7 @@ export async function hookTest(param: {
return true; return true;
} }
export async function tableSampleData(param: { export async function tableSampleData(param: {
tableId: string; tableId: string;
operation: 'insert' | 'update'; operation: 'insert' | 'update';

1
packages/nocodb/src/lib/services/util.svc.ts

@ -56,6 +56,7 @@ export async function appInfo(param: { req: { ncSiteUrl: string } }) {
ee: Noco.isEE(), ee: Noco.isEE(),
ncAttachmentFieldSize: NC_ATTACHMENT_FIELD_SIZE, ncAttachmentFieldSize: NC_ATTACHMENT_FIELD_SIZE,
ncMaxAttachmentsAllowed: +(process.env.NC_MAX_ATTACHMENTS_ALLOWED || 10), ncMaxAttachmentsAllowed: +(process.env.NC_MAX_ATTACHMENTS_ALLOWED || 10),
isCloud: process.env.NC_CLOUD === 'true',
}; };
return result; return result;

Loading…
Cancel
Save