mirror of https://github.com/nocodb/nocodb
Pranav C
2 years ago
5 changed files with 208 additions and 0 deletions
@ -0,0 +1,20 @@ |
|||||||
|
import { Test, TestingModule } from '@nestjs/testing'; |
||||||
|
import { ModelVisibilitiesController } from './model-visibilities.controller'; |
||||||
|
import { ModelVisibilitiesService } from './model-visibilities.service'; |
||||||
|
|
||||||
|
describe('ModelVisibilitiesController', () => { |
||||||
|
let controller: ModelVisibilitiesController; |
||||||
|
|
||||||
|
beforeEach(async () => { |
||||||
|
const module: TestingModule = await Test.createTestingModule({ |
||||||
|
controllers: [ModelVisibilitiesController], |
||||||
|
providers: [ModelVisibilitiesService], |
||||||
|
}).compile(); |
||||||
|
|
||||||
|
controller = module.get<ModelVisibilitiesController>(ModelVisibilitiesController); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should be defined', () => { |
||||||
|
expect(controller).toBeDefined(); |
||||||
|
}); |
||||||
|
}); |
@ -0,0 +1,49 @@ |
|||||||
|
import { |
||||||
|
Body, |
||||||
|
Controller, |
||||||
|
Get, |
||||||
|
Param, |
||||||
|
Post, |
||||||
|
Query, |
||||||
|
UseGuards, |
||||||
|
} from '@nestjs/common'; |
||||||
|
import { |
||||||
|
Acl, |
||||||
|
ExtractProjectIdMiddleware, |
||||||
|
} from '../../middlewares/extract-project-id/extract-project-id.middleware'; |
||||||
|
import { ModelVisibilitiesService } from './model-visibilities.service'; |
||||||
|
import { AuthGuard } from '@nestjs/passport'; |
||||||
|
|
||||||
|
@Controller('model-visibilities') |
||||||
|
@UseGuards(ExtractProjectIdMiddleware, AuthGuard('jwt')) |
||||||
|
export class ModelVisibilitiesController { |
||||||
|
constructor( |
||||||
|
private readonly modelVisibilitiesService: ModelVisibilitiesService, |
||||||
|
) {} |
||||||
|
|
||||||
|
@Post('/api/v1/db/meta/projects/:projectId/visibility-rules') |
||||||
|
@Acl('modelVisibilitySet') |
||||||
|
async xcVisibilityMetaSetAll( |
||||||
|
@Param('projectId') projectId: string, |
||||||
|
@Body() body: any, |
||||||
|
) { |
||||||
|
await this.modelVisibilitiesService.xcVisibilityMetaSetAll({ |
||||||
|
visibilityRule: body, |
||||||
|
projectId, |
||||||
|
}); |
||||||
|
|
||||||
|
return { msg: 'UI ACL has been created successfully' }; |
||||||
|
} |
||||||
|
|
||||||
|
@Get('/api/v1/db/meta/projects/:projectId/visibility-rules') |
||||||
|
@Acl('modelVisibilityList') |
||||||
|
async modelVisibilityList( |
||||||
|
@Param('projectId') projectId: string, |
||||||
|
@Query('includeM2M') includeM2M: boolean | string, |
||||||
|
) { |
||||||
|
return await this.modelVisibilitiesService.xcVisibilityMetaGet({ |
||||||
|
projectId, |
||||||
|
includeM2M: includeM2M === true || includeM2M === 'true', |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
import { Module } from '@nestjs/common'; |
||||||
|
import { ModelVisibilitiesService } from './model-visibilities.service'; |
||||||
|
import { ModelVisibilitiesController } from './model-visibilities.controller'; |
||||||
|
|
||||||
|
@Module({ |
||||||
|
controllers: [ModelVisibilitiesController], |
||||||
|
providers: [ModelVisibilitiesService] |
||||||
|
}) |
||||||
|
export class ModelVisibilitiesModule {} |
@ -0,0 +1,18 @@ |
|||||||
|
import { Test, TestingModule } from '@nestjs/testing'; |
||||||
|
import { ModelVisibilitiesService } from './model-visibilities.service'; |
||||||
|
|
||||||
|
describe('ModelVisibilitiesService', () => { |
||||||
|
let service: ModelVisibilitiesService; |
||||||
|
|
||||||
|
beforeEach(async () => { |
||||||
|
const module: TestingModule = await Test.createTestingModule({ |
||||||
|
providers: [ModelVisibilitiesService], |
||||||
|
}).compile(); |
||||||
|
|
||||||
|
service = module.get<ModelVisibilitiesService>(ModelVisibilitiesService); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should be defined', () => { |
||||||
|
expect(service).toBeDefined(); |
||||||
|
}); |
||||||
|
}); |
@ -0,0 +1,112 @@ |
|||||||
|
import { Injectable } from '@nestjs/common'; |
||||||
|
import { VisibilityRuleReqType } from 'nocodb-sdk'; |
||||||
|
import { validatePayload } from '../../helpers'; |
||||||
|
import { NcError } from '../../helpers/catchError'; |
||||||
|
import { Model, ModelRoleVisibility, View } from '../../models'; |
||||||
|
import { T } from 'nc-help'; |
||||||
|
|
||||||
|
@Injectable() |
||||||
|
export class ModelVisibilitiesService { |
||||||
|
async xcVisibilityMetaSetAll(param: { |
||||||
|
visibilityRule: VisibilityRuleReqType; |
||||||
|
projectId: string; |
||||||
|
}) { |
||||||
|
validatePayload( |
||||||
|
'swagger.json#/components/schemas/VisibilityRuleReq', |
||||||
|
param.visibilityRule, |
||||||
|
); |
||||||
|
T.emit('evt', { evt_type: 'uiAcl:updated' }); |
||||||
|
for (const d of param.visibilityRule) { |
||||||
|
for (const role of Object.keys(d.disabled)) { |
||||||
|
const view = await View.get(d.id); |
||||||
|
|
||||||
|
if (view.project_id !== param.projectId) { |
||||||
|
NcError.badRequest('View does not belong to the project'); |
||||||
|
} |
||||||
|
|
||||||
|
const dataInDb = await ModelRoleVisibility.get({ |
||||||
|
role, |
||||||
|
fk_view_id: d.id, |
||||||
|
}); |
||||||
|
if (dataInDb) { |
||||||
|
if (d.disabled[role]) { |
||||||
|
if (!dataInDb.disabled) { |
||||||
|
await ModelRoleVisibility.update(d.id, role, { |
||||||
|
disabled: d.disabled[role], |
||||||
|
}); |
||||||
|
} |
||||||
|
} else { |
||||||
|
await dataInDb.delete(); |
||||||
|
} |
||||||
|
} else if (d.disabled[role]) { |
||||||
|
await ModelRoleVisibility.insert({ |
||||||
|
fk_view_id: d.id, |
||||||
|
disabled: d.disabled[role], |
||||||
|
role, |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
T.emit('evt', { evt_type: 'uiAcl:updated' }); |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
async xcVisibilityMetaGet(param: { |
||||||
|
projectId: string; |
||||||
|
includeM2M?: boolean; |
||||||
|
models?: Model[]; |
||||||
|
}) { |
||||||
|
const { includeM2M = true, projectId, models: _models } = param ?? {}; |
||||||
|
|
||||||
|
// todo: move to
|
||||||
|
const roles = [ |
||||||
|
'owner', |
||||||
|
'creator', |
||||||
|
'viewer', |
||||||
|
'editor', |
||||||
|
'commenter', |
||||||
|
'guest', |
||||||
|
]; |
||||||
|
|
||||||
|
const defaultDisabled = roles.reduce((o, r) => ({ ...o, [r]: false }), {}); |
||||||
|
|
||||||
|
let models = |
||||||
|
_models || |
||||||
|
(await Model.list({ |
||||||
|
project_id: projectId, |
||||||
|
base_id: undefined, |
||||||
|
})); |
||||||
|
|
||||||
|
models = includeM2M ? models : (models.filter((t) => !t.mm) as Model[]); |
||||||
|
|
||||||
|
const result = await models.reduce(async (_obj, model) => { |
||||||
|
const obj = await _obj; |
||||||
|
|
||||||
|
const views = await model.getViews(); |
||||||
|
for (const view of views) { |
||||||
|
obj[view.id] = { |
||||||
|
ptn: model.table_name, |
||||||
|
_ptn: model.title, |
||||||
|
ptype: model.type, |
||||||
|
tn: view.title, |
||||||
|
_tn: view.title, |
||||||
|
table_meta: model.meta, |
||||||
|
...view, |
||||||
|
disabled: { ...defaultDisabled }, |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
return obj; |
||||||
|
}, Promise.resolve({})); |
||||||
|
|
||||||
|
const disabledList = await ModelRoleVisibility.list(projectId); |
||||||
|
|
||||||
|
for (const d of disabledList) { |
||||||
|
if (result[d.fk_view_id]) |
||||||
|
result[d.fk_view_id].disabled[d.role] = !!d.disabled; |
||||||
|
} |
||||||
|
|
||||||
|
return Object.values(result); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue