Browse Source

Merge pull request #3796 from nocodb/feat/3781-app-store

Feat: Limit app store access to super admin
pull/3807/head
navi 2 years ago committed by GitHub
parent
commit
4dc021a737
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      packages/nc-gui/components.d.ts
  2. 5
      packages/nc-gui/components/dashboard/settings/AppStore.vue
  3. 32
      packages/nc-gui/components/dashboard/settings/Modal.vue
  4. 8
      packages/nc-gui/composables/useUIPermission/index.ts
  5. 95
      packages/nc-gui/composables/useUIPermission/rolePermissions.ts
  6. 15
      packages/nc-gui/layouts/base.vue
  7. 10
      packages/nc-gui/middleware/auth.global.ts
  8. 1
      packages/nc-gui/nuxt-shim.d.ts
  9. 19
      packages/nc-gui/pages/index/apps.vue
  10. 6
      packages/nocodb/src/lib/meta/helpers/ncMetaAclMw.ts
  11. 492
      packages/nocodb/src/lib/utils/projectAcl.ts
  12. 38
      scripts/cypress/integration/common/5a_user_role.js
  13. 85
      scripts/cypress/integration/common/5c_super_user_role.js
  14. 269
      scripts/cypress/integration/spec/roleValidation.spec.js
  15. 2
      scripts/cypress/integration/test/pg-restRoles.js
  16. 3
      scripts/cypress/integration/test/restRoles.js
  17. 2
      scripts/cypress/integration/test/xcdb-restRoles.js
  18. 2
      scripts/cypress/support/commands.js

2
packages/nc-gui/components.d.ts vendored

@ -190,6 +190,8 @@ declare module '@vue/runtime-core' {
MdiSort: typeof import('~icons/mdi/sort')['default'] MdiSort: typeof import('~icons/mdi/sort')['default']
MdiStar: typeof import('~icons/mdi/star')['default'] MdiStar: typeof import('~icons/mdi/star')['default']
MdiStarOutline: typeof import('~icons/mdi/star-outline')['default'] MdiStarOutline: typeof import('~icons/mdi/star-outline')['default']
MdiStorefrontOutline: typeof import('~icons/mdi/storefront-outline')['default']
MdiStorefrontSutline: typeof import('~icons/mdi/storefront-sutline')['default']
MdiTable: typeof import('~icons/mdi/table')['default'] MdiTable: typeof import('~icons/mdi/table')['default']
MdiTableArrowRight: typeof import('~icons/mdi/table-arrow-right')['default'] MdiTableArrowRight: typeof import('~icons/mdi/table-arrow-right')['default']
MdiTableLarge: typeof import('~icons/mdi/table-large')['default'] MdiTableLarge: typeof import('~icons/mdi/table-large')['default']

5
packages/nc-gui/components/dashboard/settings/AppStore.vue

@ -115,7 +115,7 @@ onMounted(async () => {
:body-style="{ width: '100%' }" :body-style="{ width: '100%' }"
> >
<div class="install-btn flex flex-row justify-end space-x-1"> <div class="install-btn flex flex-row justify-end space-x-1">
<a-button v-if="app.parsedInput" size="small" outlined @click="showInstallPluginModal(app)"> <a-button v-if="app.parsedInput" size="small" type="primary" @click="showInstallPluginModal(app)">
<div class="flex flex-row justify-center items-center caption capitalize nc-app-store-card-edit"> <div class="flex flex-row justify-center items-center caption capitalize nc-app-store-card-edit">
<MdiEditIcon class="pr-0.5" :height="12" /> <MdiEditIcon class="pr-0.5" :height="12" />
Edit Edit
@ -127,7 +127,7 @@ onMounted(async () => {
<div class="flex ml-0.5">Reset</div> <div class="flex ml-0.5">Reset</div>
</div> </div>
</a-button> </a-button>
<a-button v-else size="small" outlined type="primary" ghost @click="showInstallPluginModal(app)"> <a-button v-else size="small" type="primary" @click="showInstallPluginModal(app)">
<div class="flex flex-row justify-center items-center caption capitalize nc-app-store-card-install"> <div class="flex flex-row justify-center items-center caption capitalize nc-app-store-card-install">
<MdiPlusIcon /> <MdiPlusIcon />
Install Install
@ -185,7 +185,6 @@ onMounted(async () => {
.caption { .caption {
font-size: 0.7rem; font-size: 0.7rem;
color: #242f3e;
} }
.avatar { .avatar {

32
packages/nc-gui/components/dashboard/settings/Modal.vue

@ -77,20 +77,24 @@ const tabsInfo: TabGroup = {
$e('c:settings:team-auth') $e('c:settings:team-auth')
}, },
}, },
appStore: { ...(isUIAllowed('appStore')
// App Store ? {
title: t('title.appStore'), appStore: {
icon: StoreFrontOutline, // App Store
subTabs: { title: t('title.appStore'),
new: { icon: StoreFrontOutline,
title: 'Apps', subTabs: {
body: AppStore, new: {
}, title: 'Apps',
}, body: AppStore,
onClick: () => { },
$e('c:settings:appstore') },
}, onClick: () => {
}, $e('c:settings:appstore')
},
},
}
: {}),
projMetaData: { projMetaData: {
// Project Metadata // Project Metadata
title: t('title.projMeta'), title: t('title.projMeta'),

8
packages/nc-gui/composables/useUIPermission/index.ts

@ -11,6 +11,14 @@ const hasPermission = (role: Role | ProjectRole, hasRole: boolean, permission: P
if (isString(rolePermission) && rolePermission === '*') return true if (isString(rolePermission) && rolePermission === '*') return true
if ('include' in rolePermission && rolePermission.include) {
return !!rolePermission.include[permission as keyof typeof rolePermission.include]
}
if ('exclude' in rolePermission && rolePermission.exclude) {
return !rolePermission.exclude[permission as keyof typeof rolePermission.exclude]
}
return rolePermission[permission as keyof typeof rolePermission] return rolePermission[permission as keyof typeof rolePermission]
} }

95
packages/nc-gui/composables/useUIPermission/rolePermissions.ts

@ -2,58 +2,81 @@ import { ProjectRole, Role } from '~/lib'
const rolePermissions = { const rolePermissions = {
// general role permissions // general role permissions
/**
* Each permission value means the following
* `*` - which is wildcard, means all permissions are allowed
* `include` - which is an object, means only the permissions listed in the object are allowed
* `exclude` - which is an object, means all permissions are allowed except the ones listed in the object
* `undefined` or `{}` - which is the default value, means no permissions are allowed
* */
/** todo: enable wildcard permission /** todo: enable wildcard permission
* limited permission due to unexpected behaviour in shared base if opened in same window */ * limited permission due to unexpected behaviour in shared base if opened in same window */
[Role.Super]: { [Role.Super]: '*',
projectTheme: true, [Role.Admin]: {} as Record<string, boolean>,
}, [Role.Guest]: {} as Record<string, boolean>,
[Role.Admin]: {},
[Role.Guest]: {},
[Role.User]: { [Role.User]: {
projectCreate: true, include: {
projectActions: true, projectCreate: true,
projectSettings: true, projectActions: true,
projectSettings: true,
},
}, },
// Project role permissions // Project role permissions
[ProjectRole.Creator]: '*', [ProjectRole.Creator]: {
[ProjectRole.Owner]: '*', exclude: {
appStore: true,
},
},
[ProjectRole.Owner]: {
exclude: {
appStore: true,
},
},
[ProjectRole.Editor]: { [ProjectRole.Editor]: {
smartSheet: true, include: {
xcDatatableEditable: true, smartSheet: true,
column: true, xcDatatableEditable: true,
tableAttachment: true, column: true,
tableRowUpdate: true, tableAttachment: true,
dataInsert: true, tableRowUpdate: true,
rowComments: true, dataInsert: true,
gridViewOptions: true, rowComments: true,
sortSync: true, gridViewOptions: true,
fieldsSync: true, sortSync: true,
gridColUpdate: true, fieldsSync: true,
filterSync: true, gridColUpdate: true,
csvImport: true, filterSync: true,
apiDocs: true, csvImport: true,
projectSettings: true, apiDocs: true,
newUser: false, projectSettings: true,
newUser: false,
},
}, },
[ProjectRole.Commenter]: { [ProjectRole.Commenter]: {
smartSheet: true, include: {
column: true, smartSheet: true,
rowComments: true, column: true,
projectSettings: true, rowComments: true,
projectSettings: true,
},
}, },
[ProjectRole.Viewer]: { [ProjectRole.Viewer]: {
smartSheet: true, include: {
column: true, smartSheet: true,
projectSettings: true, column: true,
projectSettings: true,
},
}, },
} as const } as const
type RolePermissions = Omit<typeof rolePermissions, 'creator' | 'owner' | 'guest' | 'admin'> type RolePermissions = Omit<typeof rolePermissions, 'guest' | 'admin' | 'super'>
type GetKeys<T> = T extends Record<string, any> ? keyof T : never type GetKeys<T> = T extends Record<any, Record<infer Key, boolean>> ? Key : never
export type Permission<K extends keyof RolePermissions = keyof RolePermissions> = RolePermissions[K] extends Record<string, any> export type Permission<K extends keyof RolePermissions = keyof RolePermissions> = RolePermissions[K] extends Record<any, any>
? GetKeys<RolePermissions[K]> ? GetKeys<RolePermissions[K]>
: never : never

15
packages/nc-gui/layouts/base.vue

@ -13,6 +13,8 @@ const hasSider = ref(false)
const sidebar = ref<HTMLDivElement>() const sidebar = ref<HTMLDivElement>()
const { isUIAllowed } = useUIPermission()
const logout = () => { const logout = () => {
signOut() signOut()
navigateTo('/signin') navigateTo('/signin')
@ -87,6 +89,19 @@ hooks.hook('page:finish', () => {
</nuxt-link> </nuxt-link>
</a-menu-item> </a-menu-item>
<a-menu-divider class="!m-0" />
<a-menu-item v-if="isUIAllowed('appStore')" key="0" class="!rounded-t">
<nuxt-link
v-e="['c:settings:appstore', { page: true }]"
class="nc-project-menu-item group !no-underline"
to="/apps"
>
<MdiStorefrontOutline class="mt-1 group-hover:text-accent" />&nbsp;
<span class="prose group-hover:text-primary">{{ $t('title.appStore') }}</span>
</nuxt-link>
</a-menu-item>
<a-menu-divider class="!m-0" /> <a-menu-divider class="!m-0" />
<a-menu-item key="1" class="!rounded-b group"> <a-menu-item key="1" class="!rounded-b group">

10
packages/nc-gui/middleware/auth.global.ts

@ -1,6 +1,6 @@
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import { defineNuxtRouteMiddleware, navigateTo } from '#app' import { defineNuxtRouteMiddleware, navigateTo } from '#app'
import { useApi, useGlobal } from '#imports' import { useApi, useGlobal, useRoles } from '#imports'
/** /**
* Global auth middleware * Global auth middleware
@ -38,6 +38,8 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
const { api } = useApi() const { api } = useApi()
const { allRoles } = useRoles()
/** if user isn't signed in and google auth is enabled, try to check if sign-in data is present */ /** if user isn't signed in and google auth is enabled, try to check if sign-in data is present */
if (!state.signedIn && state.appInfo.value.googleAuthEnabled) await tryGoogleAuth() if (!state.signedIn && state.appInfo.value.googleAuthEnabled) await tryGoogleAuth()
@ -68,6 +70,12 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
return navigateTo(from.path) return navigateTo(from.path)
} }
} else { } else {
/** If page is limited to certain users verify the user have the roles */
if (to.meta.allowedRoles && to.meta.allowedRoles.every((role) => !allRoles.value[role])) {
message.error("You don't have enough permission to access the page.")
return navigateTo('/')
}
/** if users are accessing the projects without having enough permissions, redirect to My Projects page */ /** if users are accessing the projects without having enough permissions, redirect to My Projects page */
if (to.params.projectId && from.params.projectId !== to.params.projectId) { if (to.params.projectId && from.params.projectId !== to.params.projectId) {
const user = await api.auth.me({ project_id: to?.params?.projectId as string }) const user = await api.auth.me({ project_id: to?.params?.projectId as string })

1
packages/nc-gui/nuxt-shim.d.ts vendored

@ -28,6 +28,7 @@ declare module 'vue-router' {
public?: boolean public?: boolean
hideHeader?: boolean hideHeader?: boolean
title?: string title?: string
allowedRoles?: Role[]
} }
interface RouteParams { interface RouteParams {

19
packages/nc-gui/pages/index/apps.vue

@ -0,0 +1,19 @@
<script lang="ts" setup>
import AppStore from '~/components/dashboard/settings/AppStore.vue'
import { Role } from '~/lib'
definePageMeta({
requiresAuth: true,
allowedRoles: [Role.Super],
title: 'title.appStore',
})
</script>
<template>
<div class="p-10 h-full overflow-auto">
<h1 class="text-3xl text-center mb-11 nc-app-store-title">{{ $t('title.appStore') }}</h1>
<AppStore />
</div>
</template>
<style scoped></style>

6
packages/nocodb/src/lib/meta/helpers/ncMetaAclMw.ts

@ -57,7 +57,11 @@ export default function (handlerFn, permissionName) {
return ( return (
hasRole && hasRole &&
projectAcl[name] && projectAcl[name] &&
(projectAcl[name] === '*' || projectAcl[name][permissionName]) (projectAcl[name] === '*' ||
(projectAcl[name].exclude &&
!projectAcl[name].exclude[permissionName]) ||
(projectAcl[name].include &&
projectAcl[name].include[permissionName]))
); );
}); });
if (!isAllowed) { if (!isAllowed) {

492
packages/nocodb/src/lib/utils/projectAcl.ts

@ -1,273 +1,299 @@
export default { export default {
owner: '*', owner: {
creator: '*', exclude: {
pluginList: true,
pluginTest: true,
pluginRead: true,
pluginUpdate: true,
isPluginActive: true,
},
},
creator: {
exclude: {
pluginList: true,
pluginTest: true,
pluginRead: true,
pluginUpdate: true,
isPluginActive: true,
},
},
guest: {}, guest: {},
editor: { editor: {
hideAllColumns: true, include: {
showAllColumns: true, hideAllColumns: true,
auditRowUpdate: true, showAllColumns: true,
passwordChange: true, auditRowUpdate: true,
// new permissions passwordChange: true,
// project // new permissions
projectGet: true, // project
projectList: true, projectGet: true,
projectCost: true, projectList: true,
//table projectCost: true,
tableList: true, //table
tableGet: true, tableList: true,
tableGet: true,
// data // data
dataList: true, dataList: true,
dataUpdate: true, dataUpdate: true,
dataDelete: true, dataDelete: true,
dataInsert: true, dataInsert: true,
dataRead: true, dataRead: true,
dataExist: true, dataExist: true,
dataFindOne: true, dataFindOne: true,
dataGroupBy: true, dataGroupBy: true,
commentsCount: true, commentsCount: true,
exportCsv: true, exportCsv: true,
exportExcel: true, exportExcel: true,
viewList: true, viewList: true,
columnList: true, columnList: true,
viewColumnUpdate: true, viewColumnUpdate: true,
sortList: true, sortList: true,
sortCreate: true, sortCreate: true,
sortUpdate: true, sortUpdate: true,
sortDelete: true, sortDelete: true,
filterList: true, filterList: true,
filterCreate: true, filterCreate: true,
filterUpdate: true, filterUpdate: true,
filterDelete: true, filterDelete: true,
filterGet: true, filterGet: true,
filterChildrenRead: true, filterChildrenRead: true,
mmList: true, mmList: true,
hmList: true, hmList: true,
mmExcludedList: true, mmExcludedList: true,
hmExcludedList: true, hmExcludedList: true,
btExcludedList: true, btExcludedList: true,
commentList: true, commentList: true,
commentRow: true, commentRow: true,
formViewGet: true, formViewGet: true,
projectInfoGet: true, projectInfoGet: true,
gridColumnUpdate: true, gridColumnUpdate: true,
galleryViewGet: true, galleryViewGet: true,
// old // old
xcTableAndViewList: true, xcTableAndViewList: true,
xcAuditCreate: true, xcAuditCreate: true,
xcAttachmentUpload: true, xcAttachmentUpload: true,
xcVirtualTableList: true, xcVirtualTableList: true,
rolesGet: true, rolesGet: true,
tableXcModelGet: true, tableXcModelGet: true,
xcRelationsGet: true, xcRelationsGet: true,
xcModelsList: true, xcModelsList: true,
xcViewModelsList: true, xcViewModelsList: true,
xcProcedureModelsList: true, xcProcedureModelsList: true,
xcFunctionModelsList: true, xcFunctionModelsList: true,
xcTableModelsList: true, xcTableModelsList: true,
xcCronList: true, xcCronList: true,
xcRelationList: true, xcRelationList: true,
tableMetaCreate: true, tableMetaCreate: true,
tableMetaDelete: true, tableMetaDelete: true,
tableMetaRecreate: true, tableMetaRecreate: true,
viewMetaCreate: true, viewMetaCreate: true,
viewMetaDelete: true, viewMetaDelete: true,
viewMetaRecreate: true, viewMetaRecreate: true,
procedureMetaCreate: true, procedureMetaCreate: true,
procedureMetaDelete: true, procedureMetaDelete: true,
procedureMetaRecreate: true, procedureMetaRecreate: true,
functionMetaCreate: true, functionMetaCreate: true,
functionMetaDelete: true, functionMetaDelete: true,
functionMetaRecreate: true, functionMetaRecreate: true,
tableCreateStatement: true, tableCreateStatement: true,
tableInsertStatement: true, tableInsertStatement: true,
tableUpdateStatement: true, tableUpdateStatement: true,
tableSelectStatement: true, tableSelectStatement: true,
tableDeleteStatement: true, tableDeleteStatement: true,
functionList: true, functionList: true,
sequenceList: true, sequenceList: true,
procedureList: true, procedureList: true,
triggerList: true, triggerList: true,
relationList: true, relationList: true,
relationListAll: true, relationListAll: true,
indexList: true, indexList: true,
list: true, list: true,
viewRead: true, viewRead: true,
functionRead: true, functionRead: true,
procedureRead: true, procedureRead: true,
getKnexDataTypes: true, getKnexDataTypes: true,
DB_PROJECT_OPEN_BY_WEB: true, DB_PROJECT_OPEN_BY_WEB: true,
PROJECT_READ_BY_WEB: true, PROJECT_READ_BY_WEB: true,
projectGenerateBackend: true, projectGenerateBackend: true,
projectGenerateBackendGql: true, projectGenerateBackendGql: true,
projectGetTsPolicyPath: true, projectGetTsPolicyPath: true,
projectGetPolicyPath: true, projectGetPolicyPath: true,
projectGetGqlPolicyPath: true, projectGetGqlPolicyPath: true,
handleApiCall: true, handleApiCall: true,
executeRawQuery: true, executeRawQuery: true,
projectHasDb: true, projectHasDb: true,
testConnection: true, testConnection: true,
projectChangeEnv: true, projectChangeEnv: true,
xcRoutesPolicyAllGet: true, xcRoutesPolicyAllGet: true,
grpcProtoDownloadZip: true, grpcProtoDownloadZip: true,
xcModelRowAuditAndCommentList: true, xcModelRowAuditAndCommentList: true,
xcAuditCommentInsert: true, xcAuditCommentInsert: true,
xcAuditModelCommentsCount: true, xcAuditModelCommentsCount: true,
xcExportAsCsv: true, xcExportAsCsv: true,
bulkDataInsert: true, bulkDataInsert: true,
bulkDataUpdate: true, bulkDataUpdate: true,
bulkDataUpdateAll: true, bulkDataUpdateAll: true,
bulkDataDelete: true, bulkDataDelete: true,
bulkDataDeleteAll: true, bulkDataDeleteAll: true,
relationDataRemove: true, relationDataRemove: true,
relationDataAdd: true, relationDataAdd: true,
dataCount: true, dataCount: true,
upload: true, upload: true,
uploadViaURL: true, uploadViaURL: true,
},
}, },
commenter: { commenter: {
formViewGet: true, include: {
passwordChange: true, formViewGet: true,
// project passwordChange: true,
projectGet: true, // project
exportCsv: true, projectGet: true,
exportExcel: true, exportCsv: true,
exportExcel: true,
//table //table
tableGet: true, tableGet: true,
// sort & filter // sort & filter
sortList: true, sortList: true,
viewList: true, viewList: true,
columnList: true, columnList: true,
mmList: true, mmList: true,
hmList: true, hmList: true,
commentList: true, commentList: true,
commentRow: true, commentRow: true,
projectInfoGet: true, projectInfoGet: true,
// data // data
dataList: true, dataList: true,
dataRead: true, dataRead: true,
dataExist: true, dataExist: true,
dataFindOne: true, dataFindOne: true,
dataGroupBy: true, dataGroupBy: true,
commentsCount: true, commentsCount: true,
galleryViewGet: true, galleryViewGet: true,
xcTableAndViewList: true, xcTableAndViewList: true,
xcVirtualTableList: true, xcVirtualTableList: true,
projectList: true, projectList: true,
projectCost: true, projectCost: true,
PROJECT_READ_BY_WEB: true, PROJECT_READ_BY_WEB: true,
tableXcModelGet: true, tableXcModelGet: true,
xcRelationList: true, xcRelationList: true,
tableList: true, tableList: true,
functionList: true, functionList: true,
sequenceList: true, sequenceList: true,
procedureList: true, procedureList: true,
triggerList: true, triggerList: true,
relationList: true, relationList: true,
relationListAll: true, relationListAll: true,
indexList: true, indexList: true,
list: true, list: true,
xcModelRowAuditAndCommentList: true, xcModelRowAuditAndCommentList: true,
xcAuditCommentInsert: true, xcAuditCommentInsert: true,
xcAuditModelCommentsCount: true, xcAuditModelCommentsCount: true,
xcExportAsCsv: true, xcExportAsCsv: true,
dataCount: true, dataCount: true,
},
}, },
viewer: { viewer: {
formViewGet: true, include: {
passwordChange: true, formViewGet: true,
// project passwordChange: true,
projectGet: true, // project
//table projectGet: true,
tableGet: true, //table
// data tableGet: true,
dataList: true, // data
dataRead: true, dataList: true,
dataExist: true, dataRead: true,
dataFindOne: true, dataExist: true,
dataGroupBy: true, dataFindOne: true,
commentsCount: true, dataGroupBy: true,
exportCsv: true, commentsCount: true,
exportExcel: true, exportCsv: true,
exportExcel: true,
// sort & filter // sort & filter
sortList: true, sortList: true,
filterList: true, filterList: true,
projectInfoGet: true, projectInfoGet: true,
galleryViewGet: true, galleryViewGet: true,
mmList: true, mmList: true,
hmList: true, hmList: true,
commentList: true, commentList: true,
commentRow: false, commentRow: false,
xcTableAndViewList: true, xcTableAndViewList: true,
xcVirtualTableList: true, xcVirtualTableList: true,
projectList: true, projectList: true,
projectCost: true, projectCost: true,
PROJECT_READ_BY_WEB: true, PROJECT_READ_BY_WEB: true,
tableXcModelGet: true, tableXcModelGet: true,
xcRelationList: true, xcRelationList: true,
tableList: true, tableList: true,
viewList: true, viewList: true,
functionList: true, functionList: true,
sequenceList: true, sequenceList: true,
procedureList: true, procedureList: true,
columnList: true, columnList: true,
triggerList: true, triggerList: true,
relationList: true, relationList: true,
relationListAll: true, relationListAll: true,
indexList: true, indexList: true,
list: true, list: true,
xcExportAsCsv: true, xcExportAsCsv: true,
dataCount: true dataCount: true,
},
}, },
user_new: { user_new: {
passwordChange: true, include: {
projectList: true, passwordChange: true,
projectList: true,
},
}, },
super: '*', super: '*',
user: { user: {
upload: true, include: {
uploadViaURL: true, upload: true,
passwordChange: true, uploadViaURL: true,
pluginList: true, passwordChange: true,
pluginRead: true, pluginList: true,
pluginTest: true, pluginRead: true,
isPluginActive: true, pluginTest: true,
pluginUpdate: true, isPluginActive: true,
projectCreate: true, pluginUpdate: true,
projectList: true, projectCreate: true,
projectCost: true, projectList: true,
handleAxiosCall: true, projectCost: true,
testConnection: true, handleAxiosCall: true,
projectCreateByWeb: true, testConnection: true,
projectCreateByWebWithXCDB: true, projectCreateByWeb: true,
xcPluginRead: true, projectCreateByWebWithXCDB: true,
xcMetaTablesImportZipToLocalFsAndDb: true, xcPluginRead: true,
xcMetaTablesExportDbToZip: true, xcMetaTablesImportZipToLocalFsAndDb: true,
auditRowUpdate: true, xcMetaTablesExportDbToZip: true,
auditRowUpdate: true,
},
}, },
}; };

38
scripts/cypress/integration/common/5a_user_role.js

@ -184,13 +184,17 @@ export const genTest = (apiType, dbType) => {
it(`[${roles[roleType].name}] Left navigation menu, New User add`, () => { it(`[${roles[roleType].name}] Left navigation menu, New User add`, () => {
// project configuration settings // project configuration settings
// //
_advSettings(roleType, "userRole"); if (roleType !== "owner") {
_advSettings(roleType, "userRole");
}
}); });
it(`[${roles[roleType].name}] Access control`, () => { it(`[${roles[roleType].name}] Access control`, () => {
// Access control validation // Access control validation
// //
_accessControl(roleType, "userRole"); if (roleType !== "owner") {
_accessControl(roleType, "userRole");
}
}); });
it(`[${roles[roleType].name}] Schema: create table, add/modify/delete column`, () => { it(`[${roles[roleType].name}] Schema: create table, add/modify/delete column`, () => {
@ -198,14 +202,18 @@ export const genTest = (apiType, dbType) => {
// - Add/delete table // - Add/delete table
// - Add/Update/delete column // - Add/Update/delete column
// //
_editSchema(roleType, "userRole"); if (roleType !== "owner") {
_editSchema(roleType, "userRole");
}
}); });
it(`[${roles[roleType].name}] Data: add/modify/delete row, update cell contents`, () => { it(`[${roles[roleType].name}] Data: add/modify/delete row, update cell contents`, () => {
// Table data related validations // Table data related validations
// - Add/delete/modify row // - Add/delete/modify row
// //
_editData(roleType, "userRole"); if (roleType !== "owner") {
_editData(roleType, "userRole");
}
}); });
it(`[${roles[roleType].name}] Comments: view/add`, () => { it(`[${roles[roleType].name}] Comments: view/add`, () => {
@ -213,19 +221,27 @@ export const genTest = (apiType, dbType) => {
// Viewer: only allowed to read // Viewer: only allowed to read
// Everyone else: read &/ update // Everyone else: read &/ update
// //
_editComment(roleType, "userRole"); if (roleType !== "owner") {
_editComment(roleType, "userRole");
}
}); });
it(`[${roles[roleType].name}] Right navigation menu, share view`, () => { it(`[${roles[roleType].name}] Right navigation menu, share view`, () => {
// right navigation menu bar // right navigation menu bar
// Editor/Viewer/Commenter : can only view 'existing' views // Editor/Viewer/Commenter : can only view 'existing' views
// Rest: can create/edit // Rest: can create/edit
_viewMenu(roleType, "userRole"); if (roleType !== "owner") {
_viewMenu(roleType, "userRole");
}
}); });
it(`[${roles[roleType].name}] Download files`, () => { it(`[${roles[roleType].name}] Download files`, () => {
// to be fixed // to be fixed
if (roleType === "commenter" || roleType === "viewer") { if (
roleType === "commenter" ||
roleType === "viewer" ||
roleType === "owner"
) {
} else { } else {
// viewer & commenter doesn't contain hideField option in ncv2 // viewer & commenter doesn't contain hideField option in ncv2
// #ID, City, LastUpdate, City => Address, Country <= City, + // #ID, City, LastUpdate, City => Address, Country <= City, +
@ -259,11 +275,17 @@ export const genTest = (apiType, dbType) => {
mainPage.unhideField("LastUpdate"); mainPage.unhideField("LastUpdate");
} }
}); });
it(`[${roles[roleType].name}] App store accessibility`, () => {
cy.visit("/#/apps").then(r =>{
cy.toastWait('You don\'t have enough permission to access the page.')
})
});
}); });
}; };
// skip owner validation as rest of the cases pretty much cover the same // skip owner validation as rest of the cases pretty much cover the same
// roleValidation('owner') // roleValidation("owner");
roleValidation("creator"); roleValidation("creator");
roleValidation("editor"); roleValidation("editor");
roleValidation("commenter"); roleValidation("commenter");

85
scripts/cypress/integration/common/5c_super_user_role.js

@ -0,0 +1,85 @@
import { loginPage } from '../../support/page_objects/navigation';
import { roles } from '../../support/page_objects/projectConstants';
export const genTest = (apiType, dbType) => {
describe(`${apiType.toUpperCase()} api - Super user test`, () => {
before(() => {
loginPage.signIn(roles.owner.credentials);
cy.saveLocalStorage();
});
beforeEach(() => {
cy.restoreLocalStorage();
});
afterEach(() => {
cy.saveLocalStorage();
});
after(() => {
});
it(`Open App store page and check slack app`, () => {
cy.visit('/#/apps').then(win => {
cy.get('.nc-app-store-title').should('exist');
cy.get('.nc-app-store-card-Slack').should('exist');
// install slack app
cy.get('.nc-app-store-card-Slack .install-btn')
.invoke('attr', 'style', 'right: 10px')
cy.get('.nc-app-store-card-Slack .install-btn .nc-app-store-card-install')
.click();
cy.getActiveModal('.nc-modal-plugin-install')
.find('[placeholder="Channel Name"]')
.type('Test channel')
cy.getActiveModal('.nc-modal-plugin-install')
.find('[placeholder="Webhook URL"]')
.type('http://test.com')
cy.getActiveModal('.nc-modal-plugin-install')
.find('button:contains("Save")')
.click()
cy.toastWait('Successfully installed')
cy.get('.nc-app-store-card-Slack .install-btn .nc-app-store-card-install').should('not.exist');
// update slack app config
cy.get('.nc-app-store-card-Slack .install-btn .nc-app-store-card-edit').should('exist').click()
cy.getActiveModal('.nc-modal-plugin-install')
.should('exist')
.find('[placeholder="Channel Name"]')
.should('have.value', 'Test channel')
.clear()
.type('Test channel 2')
cy.getActiveModal('.nc-modal-plugin-install')
.get('button:contains("Save")')
.click()
cy.toastWait('Successfully installed')
// reset slack app
cy.get('.nc-app-store-card-Slack .install-btn .nc-app-store-card-reset').should('exist').click()
cy.getActiveModal('.nc-modal-plugin-uninstall')
.should('exist')
.find('button:contains("Confirm")')
.click()
cy.toastWait('Plugin uninstalled successfully')
});
});
});
}

269
scripts/cypress/integration/spec/roleValidation.spec.js

@ -1,5 +1,5 @@
import { mainPage, settingsPage } from "../../support/page_objects/mainPage"; import { mainPage, settingsPage } from '../../support/page_objects/mainPage';
import { roles } from "../../support/page_objects/projectConstants"; import { roles } from '../../support/page_objects/projectConstants';
// Left hand navigation bar, validation for // Left hand navigation bar, validation for
// 1. Audit menu // 1. Audit menu
@ -9,61 +9,62 @@ import { roles } from "../../support/page_objects/projectConstants";
export function _advSettings(roleType, mode) { export function _advSettings(roleType, mode) {
cy.log(roleType, mode); cy.log(roleType, mode);
if (mode === "baseShare") { if (mode === 'baseShare') {
// open modal // open modal
cy.get(".nc-project-menu").should("exist").click(); cy.get('.nc-project-menu').should('exist').click();
cy.getActiveMenu(".nc-dropdown-project-menu") cy.getActiveMenu('.nc-dropdown-project-menu')
.find(`[data-menu-id="language"]`) .find(`[data-menu-id="language"]`)
.should("exist"); .should('exist');
// click again to close modal // click again to close modal
cy.get(".nc-project-menu").should("exist").click(); cy.get('.nc-project-menu').should('exist').click();
return; return;
} }
let validationString = let validationString =
true == roles[roleType].validations.advSettings ? "exist" : "not.exist"; true == roles[roleType].validations.advSettings ? 'exist' : 'not.exist';
// cy.get(".nc-team-settings").should(validationString); // cy.get(".nc-team-settings").should(validationString);
cy.get(".nc-project-menu").should("exist").click(); cy.get('.nc-project-menu').should('exist').click();
cy.getActiveMenu(".nc-dropdown-project-menu") cy.getActiveMenu('.nc-dropdown-project-menu')
.find(`[data-menu-id="preview-as"]`) .find(`[data-menu-id="preview-as"]`)
.should(validationString); .should(validationString);
cy.getActiveMenu(".nc-dropdown-project-menu") cy.getActiveMenu('.nc-dropdown-project-menu')
.find(`[data-menu-id="teamAndSettings"]:visible`) .find(`[data-menu-id="teamAndSettings"]:visible`)
.should(validationString); .should(validationString);
if (true === roles[roleType].validations.advSettings) { if (true === roles[roleType].validations.advSettings) {
cy.getActiveMenu(".nc-dropdown-project-menu") cy.getActiveMenu('.nc-dropdown-project-menu')
.find(`[data-menu-id="teamAndSettings"]:visible`) .find(`[data-menu-id="teamAndSettings"]:visible`)
.should(validationString) .should(validationString)
.click(); .click();
cy.get(`[data-menu-id="teamAndAuth"]`).should("exist"); cy.get(`[data-menu-id="teamAndAuth"]`).should('exist');
cy.get(`[data-menu-id="appStore"]`).should("exist"); if (roleType === 'owner')
cy.get(`[data-menu-id="projMetaData"]`).should("exist"); cy.get(`[data-menu-id="appStore"]`).should('exist');
cy.get(`[data-menu-id="audit"]`).should("exist"); cy.get(`[data-menu-id="projMetaData"]`).should('exist');
cy.get(`[data-menu-id="audit"]`).should('exist');
settingsPage.closeMenu(); settingsPage.closeMenu();
} else { } else {
cy.get(".nc-project-menu").should("exist").click(); cy.get('.nc-project-menu').should('exist').click();
} }
// float menu in preview mode // float menu in preview mode
if ("preview" === mode) { if ('preview' === mode) {
cy.get(".nc-floating-preview-btn").should("exist"); cy.get('.nc-floating-preview-btn').should('exist');
cy.get(".nc-floating-preview-btn") cy.get('.nc-floating-preview-btn')
.find(`[type="radio"][value="${roles[roleType].name}"]`) .find(`[type="radio"][value="${roles[roleType].name}"]`)
.should("be.checked"); .should('be.checked');
} }
// cy.get("body").click("bottomRight"); // cy.get("body").click("bottomRight");
} }
export function _editSchema(roleType, mode) { export function _editSchema(roleType, mode) {
let columnName = "City"; let columnName = 'City';
let validationString = let validationString =
true === roles[roleType].validations.editSchema ? "exist" : "not.exist"; true === roles[roleType].validations.editSchema ? 'exist' : 'not.exist';
cy.openTableTab(columnName, 25); cy.openTableTab(columnName, 25);
@ -71,18 +72,18 @@ export function _editSchema(roleType, mode) {
cy.get(`.nc-add-new-table`).should(validationString); cy.get(`.nc-add-new-table`).should(validationString);
// delete table option // delete table option
cy.get(`.nc-project-tree-tbl-City`).should("exist").rightclick(); cy.get(`.nc-project-tree-tbl-City`).should('exist').rightclick();
cy.get(".ant-dropdown-content:visible").should(validationString); cy.get('.ant-dropdown-content:visible').should(validationString);
if (validationString === "exist") { if (validationString === 'exist') {
cy.getActiveMenu(".nc-dropdown-tree-view-context-menu") cy.getActiveMenu('.nc-dropdown-tree-view-context-menu')
.find('[role="menuitem"]') .find('[role="menuitem"]')
.contains("Delete") .contains('Delete')
.should("exist"); .should('exist');
cy.getActiveMenu(".nc-dropdown-tree-view-context-menu") cy.getActiveMenu('.nc-dropdown-tree-view-context-menu')
.find('[role="menuitem"]') .find('[role="menuitem"]')
.contains("Rename") .contains('Rename')
.should("exist"); .should('exist');
// click on a cell to close table context menu // click on a cell to close table context menu
mainPage.getCell(columnName, 3).click(); mainPage.getCell(columnName, 3).click();
@ -90,104 +91,104 @@ export function _editSchema(roleType, mode) {
// add new column option // add new column option
// //
cy.get(".nc-column-add").should(validationString); cy.get('.nc-column-add').should(validationString);
// update column (edit/ delete menu) // update column (edit/ delete menu)
cy.get(".nc-ui-dt-dropdown").should(validationString); cy.get('.nc-ui-dt-dropdown').should(validationString);
if (validationString === "exist") { if (validationString === 'exist') {
cy.get(".nc-import-menu").should("exist").click(); cy.get('.nc-import-menu').should('exist').click();
cy.getActiveMenu(".nc-dropdown-import-menu").should("exist"); cy.getActiveMenu('.nc-dropdown-import-menu').should('exist');
cy.getActiveMenu(".nc-dropdown-import-menu") cy.getActiveMenu('.nc-dropdown-import-menu')
.find(".ant-dropdown-menu-item") .find('.ant-dropdown-menu-item')
.contains("Airtable"); .contains('Airtable');
cy.getActiveMenu(".nc-dropdown-import-menu") cy.getActiveMenu('.nc-dropdown-import-menu')
.find(".ant-dropdown-menu-item") .find('.ant-dropdown-menu-item')
.contains("CSV file"); .contains('CSV file');
cy.getActiveMenu(".nc-dropdown-import-menu") cy.getActiveMenu('.nc-dropdown-import-menu')
.find(".ant-dropdown-menu-item") .find('.ant-dropdown-menu-item')
.contains("JSON file"); .contains('JSON file');
cy.getActiveMenu(".nc-dropdown-import-menu") cy.getActiveMenu('.nc-dropdown-import-menu')
.find(".ant-dropdown-menu-item") .find('.ant-dropdown-menu-item')
.contains("Microsoft Excel"); .contains('Microsoft Excel');
} }
} }
export function _editData(roleType, mode) { export function _editData(roleType, mode) {
let columnName = "City"; let columnName = 'City';
let validationString = let validationString =
true === roles[roleType].validations.editData ? "exist" : "not.exist"; true === roles[roleType].validations.editData ? 'exist' : 'not.exist';
cy.openTableTab(columnName, 25); cy.openTableTab(columnName, 25);
// add row button // add row button
cy.get(".nc-add-new-row-btn:visible").should(validationString); cy.get('.nc-add-new-row-btn:visible').should(validationString);
// add button at bottom of page // add button at bottom of page
mainPage.getCell(columnName, 25).scrollIntoView(); mainPage.getCell(columnName, 25).scrollIntoView();
cy.get(".nc-grid-add-new-cell:visible").should(validationString); cy.get('.nc-grid-add-new-cell:visible').should(validationString);
// update row option (right click) // update row option (right click)
// //
mainPage.getCell("City", 5).rightclick(); mainPage.getCell('City', 5).rightclick();
cy.wait(100); cy.wait(100);
cy.get(".ant-dropdown-content:visible").should(validationString); cy.get('.ant-dropdown-content:visible').should(validationString);
if (validationString === "exist") { if (validationString === 'exist') {
// right click options will exist (only for 'exist' case) // right click options will exist (only for 'exist' case)
// //
cy.getActiveMenu(".nc-dropdown-grid-context-menu") cy.getActiveMenu('.nc-dropdown-grid-context-menu')
.contains("Insert New Row") .contains('Insert New Row')
.should(validationString); .should(validationString);
cy.getActiveMenu(".nc-dropdown-grid-context-menu") cy.getActiveMenu('.nc-dropdown-grid-context-menu')
.contains("Clear cell") .contains('Clear cell')
.should(validationString); .should(validationString);
cy.getActiveMenu(".nc-dropdown-grid-context-menu") cy.getActiveMenu('.nc-dropdown-grid-context-menu')
.contains("Delete Row") .contains('Delete Row')
.should(validationString); .should(validationString);
cy.getActiveMenu(".nc-dropdown-grid-context-menu") cy.getActiveMenu('.nc-dropdown-grid-context-menu')
.contains("Delete Selected Rows") .contains('Delete Selected Rows')
.should(validationString); .should(validationString);
// cy.get("body").type("{esc}"); // cy.get("body").type("{esc}");
mainPage.getCell("City", 13).click(); mainPage.getCell('City', 13).click();
// update cell contents option using row expander should be enabled // update cell contents option using row expander should be enabled
// //
mainPage mainPage
.getRow(1) .getRow(1)
.find(".nc-row-no") .find('.nc-row-no')
.should("exist") .should('exist')
.eq(0) .eq(0)
.trigger("mouseover", { force: true }); .trigger('mouseover', { force: true });
cy.get(".nc-row-expand").should("exist").eq(10).click({ force: true }); cy.get('.nc-row-expand').should('exist').eq(10).click({ force: true });
cy.getActiveDrawer(".nc-drawer-expanded-form") cy.getActiveDrawer('.nc-drawer-expanded-form')
.find("button") .find('button')
.contains("Save row") .contains('Save row')
.should("exist"); .should('exist');
cy.getActiveDrawer(".nc-drawer-expanded-form") cy.getActiveDrawer('.nc-drawer-expanded-form')
.find("button") .find('button')
.contains("Cancel") .contains('Cancel')
.should("exist") .should('exist')
.click(); .click();
} else { } else {
// update cell contents option using row expander should be disabled // update cell contents option using row expander should be disabled
// //
cy.get(".nc-row-expand").should("exist").eq(10).click({ force: true }); cy.get('.nc-row-expand').should('exist').eq(10).click({ force: true });
cy.getActiveDrawer(".nc-drawer-expanded-form") cy.getActiveDrawer('.nc-drawer-expanded-form')
.find("button:disabled") .find('button:disabled')
.contains("Save row") .contains('Save row')
.should("exist"); .should('exist');
cy.getActiveDrawer(".nc-drawer-expanded-form") cy.getActiveDrawer('.nc-drawer-expanded-form')
.find("button") .find('button')
.contains("Cancel") .contains('Cancel')
.should("exist") .should('exist')
.click(); .click();
} }
// double click cell entries to edit // double click cell entries to edit
// //
mainPage.getCell("City", 5).dblclick().find("input").should(validationString); mainPage.getCell('City', 5).dblclick().find('input').should(validationString);
} }
// read &/ update comment // read &/ update comment
@ -195,11 +196,11 @@ export function _editData(roleType, mode) {
// Everyone else: read &/ update // Everyone else: read &/ update
// //
export function _editComment(roleType, mode) { export function _editComment(roleType, mode) {
let columnName = "City"; let columnName = 'City';
let validationString = let validationString =
true === roles[roleType].validations.editComment true === roles[roleType].validations.editComment
? "Comment added successfully" ? 'Comment added successfully'
: "Not allowed"; : 'Not allowed';
cy.openTableTab(columnName, 25); cy.openTableTab(columnName, 25);
@ -207,7 +208,7 @@ export function _editComment(roleType, mode) {
// click on comment icon & type comment // click on comment icon & type comment
// //
cy.get(".nc-row-expand").should("exist").eq(10).click({ force: true }); cy.get('.nc-row-expand').should('exist').eq(10).click({ force: true });
// Expected response: // Expected response:
// Viewer: Not able to see comment option // Viewer: Not able to see comment option
@ -216,32 +217,32 @@ export function _editComment(roleType, mode) {
// cy.wait(3000); // cy.wait(3000);
if ("viewer" === roleType) { if ('viewer' === roleType) {
cy.getActiveDrawer(".nc-drawer-expanded-form") cy.getActiveDrawer('.nc-drawer-expanded-form')
.should("exist") .should('exist')
.find(".nc-toggle-comments") .find('.nc-toggle-comments')
.should("not.exist"); .should('not.exist');
} else { } else {
cy.getActiveDrawer(".nc-drawer-expanded-form") cy.getActiveDrawer('.nc-drawer-expanded-form')
.should("exist") .should('exist')
.find(".nc-toggle-comments") .find('.nc-toggle-comments')
.should("exist") .should('exist')
.click(); .click();
cy.getActiveDrawer(".nc-drawer-expanded-form") cy.getActiveDrawer('.nc-drawer-expanded-form')
.find(".nc-comment-box") .find('.nc-comment-box')
.should("exist") .should('exist')
.type("Comment-1{enter}"); .type('Comment-1{enter}');
// cy.toastWait('Comment added successfully') // cy.toastWait('Comment added successfully')
cy.getActiveDrawer(".nc-drawer-expanded-form") cy.getActiveDrawer('.nc-drawer-expanded-form')
.find(".nc-toggle-comments") .find('.nc-toggle-comments')
.click(); .click();
} }
cy.getActiveDrawer(".nc-drawer-expanded-form") cy.getActiveDrawer('.nc-drawer-expanded-form')
.find("button") .find('button')
.contains("Cancel") .contains('Cancel')
.should("exist") .should('exist')
.click(); .click();
} }
@ -249,7 +250,7 @@ export function _editComment(roleType, mode) {
// Editor/Viewer/Commenter : can only view 'existing' views // Editor/Viewer/Commenter : can only view 'existing' views
// Rest: can create/edit // Rest: can create/edit
export function _viewMenu(roleType, mode) { export function _viewMenu(roleType, mode) {
let columnName = "City"; let columnName = 'City';
// Lock, Download, Upload // Lock, Download, Upload
let menuWithSubmenuCount = 3; let menuWithSubmenuCount = 3;
@ -260,16 +261,16 @@ export function _viewMenu(roleType, mode) {
cy.openTableTab(columnName, 25); cy.openTableTab(columnName, 25);
let validationString = let validationString =
true === roles[roleType].validations.shareView ? "exist" : "not.exist"; true === roles[roleType].validations.shareView ? 'exist' : 'not.exist';
if (roleType === "editor") { if (roleType === 'editor') {
// Download / Upload CSV // Download / Upload CSV
menuWithSubmenuCount = 2; menuWithSubmenuCount = 2;
// Get API Snippet and ERD // Get API Snippet and ERD
menuWithoutSubmenuCount = 2; menuWithoutSubmenuCount = 2;
// ERD // ERD
if (mode === "baseShare") menuWithoutSubmenuCount = 1; if (mode === 'baseShare') menuWithoutSubmenuCount = 1;
} else if (roleType === "commenter" || roleType === "viewer") { } else if (roleType === 'commenter' || roleType === 'viewer') {
// Download CSV & Download excel // Download CSV & Download excel
menuWithSubmenuCount = 0; menuWithSubmenuCount = 0;
// Get API Snippet and ERD // Get API Snippet and ERD
@ -277,7 +278,7 @@ export function _viewMenu(roleType, mode) {
} }
// view list field (default GRID view) // view list field (default GRID view)
cy.get(`.nc-view-item`).should("exist"); cy.get(`.nc-view-item`).should('exist');
// view create option, exists only for owner/ creator // view create option, exists only for owner/ creator
cy.get(`.nc-create-grid-view`).should(validationString); cy.get(`.nc-create-grid-view`).should(validationString);
@ -287,47 +288,47 @@ export function _viewMenu(roleType, mode) {
// share view permissions are role specific // share view permissions are role specific
// actions menu (more), only download csv should be visible for non-previlaged users // actions menu (more), only download csv should be visible for non-previlaged users
cy.get(".nc-actions-menu-btn").click(); cy.get('.nc-actions-menu-btn').click();
cy.getActiveMenu(".nc-dropdown-actions-menu") cy.getActiveMenu('.nc-dropdown-actions-menu')
.find(".ant-dropdown-menu-submenu:visible") .find('.ant-dropdown-menu-submenu:visible')
.should("have.length", menuWithSubmenuCount); .should('have.length', menuWithSubmenuCount);
cy.getActiveMenu(".nc-dropdown-actions-menu") cy.getActiveMenu('.nc-dropdown-actions-menu')
.find(".ant-dropdown-menu-item:visible") .find('.ant-dropdown-menu-item:visible')
.should("have.length", menuWithoutSubmenuCount); .should('have.length', menuWithoutSubmenuCount);
// click again to close menu // click again to close menu
cy.get(".nc-actions-menu-btn").click(); cy.get('.nc-actions-menu-btn').click();
} }
export function _topRightMenu(roleType, mode) { export function _topRightMenu(roleType, mode) {
// kludge; download csv menu persists until clicked // kludge; download csv menu persists until clicked
let columnName = "City"; let columnName = 'City';
// cy.closeTableTab(columnName); // cy.closeTableTab(columnName);
// cy.openTableTab(columnName, 25); // cy.openTableTab(columnName, 25);
let validationString = let validationString =
true == roles[roleType].validations.shareView ? "exist" : "not.exist"; true == roles[roleType].validations.shareView ? 'exist' : 'not.exist';
cy.get(`.nc-share-base`).should(validationString); cy.get(`.nc-share-base`).should(validationString);
cy.get(".nc-menu-translate").should("exist"); cy.get('.nc-menu-translate').should('exist');
cy.get(".nc-menu-accounts").should("exist"); cy.get('.nc-menu-accounts').should('exist');
} }
// Access control list // Access control list
// //
export function disableTableAccess(tbl, role) { export function disableTableAccess(tbl, role) {
const cls = `.nc-acl-${tbl}-${role}-chkbox`; const cls = `.nc-acl-${tbl}-${role}-chkbox`;
cy.get(cls).find("input").should("be.checked").click({ force: true }); cy.get(cls).find('input').should('be.checked').click({ force: true });
cy.get(cls).find("input").should("not.be.checked"); cy.get(cls).find('input').should('not.be.checked');
} }
export function enableTableAccess(tbl, role) { export function enableTableAccess(tbl, role) {
const cls = `.nc-acl-${tbl}-${role}-chkbox`; const cls = `.nc-acl-${tbl}-${role}-chkbox`;
cy.get(cls).find("input").should("not.be.checked").click({ force: true }); cy.get(cls).find('input').should('not.be.checked').click({ force: true });
cy.get(cls).find("input").should("be.checked"); cy.get(cls).find('input').should('be.checked');
} }
export function _accessControl(roleType, previewMode) { export function _accessControl(roleType, previewMode) {
let validationString = roleType === "creator" ? "exist" : "not.exist"; let validationString = roleType === 'creator' ? 'exist' : 'not.exist';
cy.get(`.nc-project-tree-tbl-Language`).should(validationString); cy.get(`.nc-project-tree-tbl-Language`).should(validationString);
cy.get(`.nc-project-tree-tbl-CustomerList`).should(validationString); cy.get(`.nc-project-tree-tbl-CustomerList`).should(validationString);

2
scripts/cypress/integration/test/pg-restRoles.js

@ -2,6 +2,7 @@ let t0 = require("./explicitLogin");
let t01 = require("../common/00_pre_configurations"); let t01 = require("../common/00_pre_configurations");
let t5a = require("../common/5a_user_role"); let t5a = require("../common/5a_user_role");
let t5b = require("../common/5b_preview_role"); let t5b = require("../common/5b_preview_role");
let t5c = require("../common/5c_super_user_role");
const { const {
setCurrentMode, setCurrentMode,
} = require("../../support/page_objects/projectConstants"); } = require("../../support/page_objects/projectConstants");
@ -12,6 +13,7 @@ const nocoTestSuite = (apiType, dbType) => {
t5a.genTest(apiType, dbType); t5a.genTest(apiType, dbType);
// t5b.genTest(apiType, dbType); // t5b.genTest(apiType, dbType);
t5c.genTest(apiType, dbType);
}; };
nocoTestSuite("rest", "postgres"); nocoTestSuite("rest", "postgres");

3
scripts/cypress/integration/test/restRoles.js

@ -2,6 +2,7 @@ let t0 = require("./explicitLogin");
let t01 = require("../common/00_pre_configurations"); let t01 = require("../common/00_pre_configurations");
let t5a = require("../common/5a_user_role"); let t5a = require("../common/5a_user_role");
let t5b = require("../common/5b_preview_role"); let t5b = require("../common/5b_preview_role");
let t5c = require("../common/5c_super_user_role");
const { const {
setCurrentMode, setCurrentMode,
} = require("../../support/page_objects/projectConstants"); } = require("../../support/page_objects/projectConstants");
@ -12,6 +13,8 @@ const nocoTestSuite = (apiType, dbType) => {
t5a.genTest(apiType, dbType); t5a.genTest(apiType, dbType);
// t5b.genTest(apiType, dbType); // t5b.genTest(apiType, dbType);
t5c.genTest(apiType, dbType);
}; };
nocoTestSuite("rest", "mysql"); nocoTestSuite("rest", "mysql");

2
scripts/cypress/integration/test/xcdb-restRoles.js

@ -2,6 +2,7 @@ let t0 = require("./explicitLogin");
let t01 = require("../common/00_pre_configurations"); let t01 = require("../common/00_pre_configurations");
let t5a = require("../common/5a_user_role"); let t5a = require("../common/5a_user_role");
let t5b = require("../common/5b_preview_role"); let t5b = require("../common/5b_preview_role");
let t5c = require("../common/5c_super_user_role");
const { const {
setCurrentMode, setCurrentMode,
} = require("../../support/page_objects/projectConstants"); } = require("../../support/page_objects/projectConstants");
@ -12,6 +13,7 @@ const nocoTestSuite = (apiType, dbType) => {
t5a.genTest(apiType, dbType); t5a.genTest(apiType, dbType);
// t5b.genTest(apiType, dbType); // t5b.genTest(apiType, dbType);
t5c.genTest(apiType, dbType);
}; };
nocoTestSuite("rest", "xcdb"); nocoTestSuite("rest", "xcdb");

2
scripts/cypress/support/commands.js

@ -479,7 +479,7 @@ Cypress.Commands.add("signOut", () => {
cy.get(".nc-menu-accounts", { timeout: 30000 }).should("exist").click(); cy.get(".nc-menu-accounts", { timeout: 30000 }).should("exist").click();
cy.getActiveMenu(".nc-dropdown-user-accounts-menu") cy.getActiveMenu(".nc-dropdown-user-accounts-menu")
.find(".ant-dropdown-menu-item") .find(".ant-dropdown-menu-item")
.eq(1) .last()
.click(); .click();
// cy.wait(5000); // cy.wait(5000);

Loading…
Cancel
Save