chore: project controller ok

This commit is contained in:
xiaojunnuo
2026-02-13 21:28:17 +08:00
parent 3f87752d1f
commit 4ee6e38a94
42 changed files with 399 additions and 198 deletions
+3
View File
@@ -122,6 +122,9 @@ export type TaskInstanceContext = {
//用户信息 //用户信息
user: UserInfo; user: UserInfo;
//项目id
projectId?: number;
emitter: TaskEmitter; emitter: TaskEmitter;
//service 容器 //service 容器
@@ -65,7 +65,13 @@ export abstract class BaseController {
if (!isEnterprise()) { if (!isEnterprise()) {
return null return null
} }
const projectIdStr = this.ctx.headers["project-id"] as string; let projectIdStr = this.ctx.headers["project-id"] as string;
if (!projectIdStr){
projectIdStr = this.ctx.request.query["projectId"] as string;
}
if (!projectIdStr){
return null
}
if (!projectIdStr) { if (!projectIdStr) {
throw new Error("projectId 不能为空") throw new Error("projectId 不能为空")
} }
@@ -233,13 +233,14 @@ export abstract class BaseService<T> {
throw new PermissionException('权限不足'); throw new PermissionException('权限不足');
} }
async batchDelete(ids: number[], userId: number) { async batchDelete(ids: number[], userId: number,projectId?:number) {
if(userId >0){ if(userId!=null){
const list = await this.getRepository().find({ const list = await this.getRepository().find({
where: { where: {
// @ts-ignore // @ts-ignore
id: In(ids), id: In(ids),
userId, userId,
projectId,
}, },
}) })
// @ts-ignore // @ts-ignore
@@ -2,17 +2,19 @@ import { IAccessService } from '@certd/pipeline';
export class AccessGetter implements IAccessService { export class AccessGetter implements IAccessService {
userId: number; userId: number;
getter: <T>(id: any, userId?: number) => Promise<T>; projectId?: number;
constructor(userId: number, getter: (id: any, userId: number) => Promise<any>) { getter: <T>(id: any, userId?: number, projectId?: number) => Promise<T>;
constructor(userId: number, projectId: number, getter: (id: any, userId: number, projectId?: number) => Promise<any>) {
this.userId = userId; this.userId = userId;
this.projectId = projectId;
this.getter = getter; this.getter = getter;
} }
async getById<T = any>(id: any) { async getById<T = any>(id: any) {
return await this.getter<T>(id, this.userId); return await this.getter<T>(id, this.userId, this.projectId);
} }
async getCommonById<T = any>(id: any) { async getCommonById<T = any>(id: any) {
return await this.getter<T>(id, 0); return await this.getter<T>(id, 0,null);
} }
} }
@@ -129,10 +129,11 @@ export class AccessService extends BaseService<AccessEntity> {
id: entity.id, id: entity.id,
name: entity.name, name: entity.name,
userId: entity.userId, userId: entity.userId,
projectId: entity.projectId,
}; };
} }
async getAccessById(id: any, checkUserId: boolean, userId?: number): Promise<any> { async getAccessById(id: any, checkUserId: boolean, userId?: number, projectId?: number): Promise<any> {
const entity = await this.info(id); const entity = await this.info(id);
if (entity == null) { if (entity == null) {
throw new Error(`该授权配置不存在,请确认是否已被删除:id=${id}`); throw new Error(`该授权配置不存在,请确认是否已被删除:id=${id}`);
@@ -145,6 +146,9 @@ export class AccessService extends BaseService<AccessEntity> {
throw new PermissionException('您对该Access授权无访问权限'); throw new PermissionException('您对该Access授权无访问权限');
} }
} }
if (projectId != null && projectId !== entity.projectId) {
throw new PermissionException('您对该Access授权无访问权限');
}
// const access = accessRegistry.get(entity.type); // const access = accessRegistry.get(entity.type);
const setting = this.decryptAccessEntity(entity); const setting = this.decryptAccessEntity(entity);
@@ -152,12 +156,12 @@ export class AccessService extends BaseService<AccessEntity> {
id: entity.id, id: entity.id,
...setting, ...setting,
}; };
const accessGetter = new AccessGetter(userId, this.getById.bind(this)); const accessGetter = new AccessGetter(userId,projectId, this.getById.bind(this));
return await newAccess(entity.type, input,accessGetter); return await newAccess(entity.type, input,accessGetter);
} }
async getById(id: any, userId: number): Promise<any> { async getById(id: any, userId: number, projectId?: number): Promise<any> {
return await this.getAccessById(id, true, userId); return await this.getAccessById(id, true, userId, projectId);
} }
decryptAccessEntity(entity: AccessEntity): any { decryptAccessEntity(entity: AccessEntity): any {
@@ -188,7 +192,7 @@ export class AccessService extends BaseService<AccessEntity> {
} }
async getSimpleByIds(ids: number[], userId: any) { async getSimpleByIds(ids: number[], userId: any, projectId?: number) {
if (ids.length === 0) { if (ids.length === 0) {
return []; return [];
} }
@@ -199,12 +203,14 @@ export class AccessService extends BaseService<AccessEntity> {
where: { where: {
id: In(ids), id: In(ids),
userId, userId,
projectId,
}, },
select: { select: {
id: true, id: true,
name: true, name: true,
type: true, type: true,
userId:true userId:true,
projectId:true,
}, },
}); });
@@ -70,7 +70,8 @@ export class AddonService extends BaseService<AddonEntity> {
name: entity.name, name: entity.name,
userId: entity.userId, userId: entity.userId,
addonType: entity.addonType, addonType: entity.addonType,
type: entity.type type: entity.type,
projectId: entity.projectId
}; };
} }
@@ -84,7 +85,7 @@ export class AddonService extends BaseService<AddonEntity> {
} }
async getSimpleByIds(ids: number[], userId: any) { async getSimpleByIds(ids: number[], userId: any,projectId?:number) {
if (ids.length === 0) { if (ids.length === 0) {
return []; return [];
} }
@@ -94,7 +95,8 @@ export class AddonService extends BaseService<AddonEntity> {
return await this.repository.find({ return await this.repository.find({
where: { where: {
id: In(ids), id: In(ids),
userId userId,
projectId
}, },
select: { select: {
id: true, id: true,
@@ -109,11 +111,12 @@ export class AddonService extends BaseService<AddonEntity> {
} }
async getDefault(userId: number, addonType: string): Promise<any> { async getDefault(userId: number, addonType: string,projectId?:number): Promise<any> {
const res = await this.repository.findOne({ const res = await this.repository.findOne({
where: { where: {
userId, userId,
addonType addonType,
projectId
}, },
order: { order: {
isDefault: "DESC" isDefault: "DESC"
@@ -133,11 +136,12 @@ export class AddonService extends BaseService<AddonEntity> {
type: res.type, type: res.type,
name: res.name, name: res.name,
userId: res.userId, userId: res.userId,
setting setting,
projectId: res.projectId
}; };
} }
async setDefault(id: number, userId: number, addonType: string) { async setDefault(id: number, userId: number, addonType: string,projectId?:number) {
if (!id) { if (!id) {
throw new ValidateException("id不能为空"); throw new ValidateException("id不能为空");
} }
@@ -147,7 +151,8 @@ export class AddonService extends BaseService<AddonEntity> {
await this.repository.update( await this.repository.update(
{ {
userId, userId,
addonType addonType,
projectId
}, },
{ {
isDefault: false isDefault: false
@@ -157,7 +162,8 @@ export class AddonService extends BaseService<AddonEntity> {
{ {
id, id,
userId, userId,
addonType addonType,
projectId
}, },
{ {
isDefault: true isDefault: true
@@ -165,12 +171,12 @@ export class AddonService extends BaseService<AddonEntity> {
); );
} }
async getOrCreateDefault(opts: { addonType: string, type: string, inputs: any, userId: any }) { async getOrCreateDefault(opts: { addonType: string, type: string, inputs: any, userId: any,projectId?:number }) {
const { addonType, type, inputs, userId } = opts; const { addonType, type, inputs, userId,projectId } = opts;
const addonDefine = this.getDefineByType(type, addonType); const addonDefine = this.getDefineByType(type, addonType);
const defaultConfig = await this.getDefault(userId, addonType); const defaultConfig = await this.getDefault(userId, addonType,projectId);
if (defaultConfig) { if (defaultConfig) {
return defaultConfig; return defaultConfig;
} }
@@ -183,17 +189,19 @@ export class AddonService extends BaseService<AddonEntity> {
type: type, type: type,
name: addonDefine.title, name: addonDefine.title,
setting: JSON.stringify(setting), setting: JSON.stringify(setting),
isDefault: true isDefault: true,
projectId
}); });
return this.buildAddonInstanceConfig(res); return this.buildAddonInstanceConfig(res);
} }
async getOneByType(req:{addonType:string,type:string,userId:number}) { async getOneByType(req:{addonType:string,type:string,userId:number,projectId?:number}) {
return await this.repository.findOne({ return await this.repository.findOne({
where: { where: {
addonType: req.addonType, addonType: req.addonType,
type: req.type, type: req.type,
userId: req.userId userId: req.userId,
projectId: req.projectId
} }
}); });
} }
@@ -7,9 +7,9 @@
</a-menu-item> </a-menu-item>
</a-menu> </a-menu>
</template> </template>
<div class="rounded pl-3 pr-3 px-2 py-1 flex-center flex pointer items-center bg-accent h-10 button-text"> <div class="rounded pl-3 pr-3 px-2 py-1 flex-center flex pointer items-center bg-accent h-10 button-text" title="当前项目">
<fs-icon icon="ion:apps" class="mr-1"></fs-icon> <fs-icon icon="ion:apps" class="mr-1"></fs-icon>
{{ projectStore.currentProject?.name || "..." }} 当前项目{{ projectStore.currentProject?.name || "..." }}
<fs-icon icon="ion:chevron-down-outline" class="ml-1"></fs-icon> <fs-icon icon="ion:chevron-down-outline" class="ml-1"></fs-icon>
</div> </div>
</a-dropdown> </a-dropdown>
@@ -34,8 +34,8 @@ function handleMenuClick({ key }: any) {
<style lang="less"> <style lang="less">
.project-selector { .project-selector {
&.button-text { &.button-text {
min-width: 100px; min-width: 150px;
max-width: 150px; max-width: 250px;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
@@ -10,6 +10,7 @@ import PageFooter from "./components/footer/index.vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import MaxKBChat from "/@/components/ai/index.vue"; import MaxKBChat from "/@/components/ai/index.vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useProjectStore } from "../store/project";
const { t } = useI18n(); const { t } = useI18n();
@@ -77,15 +78,13 @@ const openChat = (q: string) => {
chatBox.value.openChat({ q }); chatBox.value.openChat({ q });
}; };
provide("fn:ai.open", openChat); provide("fn:ai.open", openChat);
const projectStore = useProjectStore();
</script> </script>
<template> <template>
<BasicLayout @clear-preferences-and-logout="handleLogout"> <BasicLayout @clear-preferences-and-logout="handleLogout">
<template #header-left-0> <template #header-left-0> </template>
<div class="ml-1 mr-2">
<project-selector class="flex-center header-btn" />
</div>
</template>
<template #user-dropdown> <template #user-dropdown>
<UserDropdown :avatar="avatar" :menus="menus" :text="userStore.userInfo?.nickName || userStore.userInfo?.username" description="" tag-text="" @logout="handleLogout" /> <UserDropdown :avatar="avatar" :menus="menus" :text="userStore.userInfo?.nickName || userStore.userInfo?.username" description="" tag-text="" @logout="handleLogout" />
</template> </template>
@@ -93,6 +92,9 @@ provide("fn:ai.open", openChat);
<LockScreen :avatar @to-login="handleLogout" /> <LockScreen :avatar @to-login="handleLogout" />
</template> </template>
<template #header-right-0> <template #header-right-0>
<div v-if="projectStore.isEnterprise" class="ml-1 mr-2">
<project-selector class="flex-center header-btn" />
</div>
<div class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full hidden md:block"> <div class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full hidden md:block">
<tutorial-button class="flex-center header-btn" mode="nav" /> <tutorial-button class="flex-center header-btn" mode="nav" />
</div> </div>
@@ -1,6 +1,7 @@
import { useSettingStore } from "/@/store/settings"; import { useSettingStore } from "/@/store/settings";
import aboutResource from "/@/router/source/modules/about"; import aboutResource from "/@/router/source/modules/about";
import i18n from "/@/locales/i18n"; import i18n from "/@/locales/i18n";
import { useProjectStore } from "/@/store/project";
export const certdResources = [ export const certdResources = [
{ {
@@ -20,7 +21,10 @@ export const certdResources = [
path: "/certd/project", path: "/certd/project",
component: "/certd/project/index.vue", component: "/certd/project/index.vue",
meta: { meta: {
show: true, show: () => {
const projectStore = useProjectStore();
return projectStore.isEnterprise;
},
icon: "ion:apps", icon: "ion:apps",
permission: "sys:settings:edit", permission: "sys:settings:edit",
keepAlive: true, keepAlive: true,
@@ -210,9 +210,11 @@ const headerSlots = computed(() => {
</template> </template>
<!-- 侧边额外区域 --> <!-- 侧边额外区域 -->
<template #side-extra> <template #side-extra>
1111
<LayoutExtraMenu :accordion="preferences.navigation.accordion" :collapse="preferences.sidebar.extraCollapse" :menus="wrapperMenus(extraMenus)" :rounded="isMenuRounded" :theme="sidebarTheme" /> <LayoutExtraMenu :accordion="preferences.navigation.accordion" :collapse="preferences.sidebar.extraCollapse" :menus="wrapperMenus(extraMenus)" :rounded="isMenuRounded" :theme="sidebarTheme" />
</template> </template>
<template #side-extra-title> <template #side-extra-title>
234234234
<VbenLogo v-if="preferences.logo.enable" :text="preferences.app.name" :theme="theme" /> <VbenLogo v-if="preferences.logo.enable" :text="preferences.app.name" :theme="theme" />
</template> </template>
@@ -54,6 +54,19 @@ CREATE INDEX "index_history_log_project_id" ON "pi_history_log" ("project_id");
ALTER TABLE pi_template ADD COLUMN project_id integer; ALTER TABLE pi_template ADD COLUMN project_id integer;
CREATE INDEX "index_template_project_id" ON "pi_template" ("project_id"); CREATE INDEX "index_template_project_id" ON "pi_template" ("project_id");
ALTER TABLE pi_sub_domain ADD COLUMN project_id integer;
CREATE INDEX "index_sub_domain_project_id" ON "pi_sub_domain" ("project_id");
ALTER TABLE cd_cname_record ADD COLUMN project_id integer;
CREATE INDEX "index_cname_record_project_id" ON "cd_cname_record" ("project_id");
ALTER TABLE cd_domain ADD COLUMN project_id integer;
CREATE INDEX "index_domain_project_id" ON "cd_domain" ("project_id");
ALTER TABLE user_settings ADD COLUMN project_id integer;
CREATE INDEX "index_user_settings_project_id" ON "user_settings" ("project_id");
CREATE TABLE "cd_project_member" CREATE TABLE "cd_project_member"
@@ -32,10 +32,12 @@ export class AddonController extends CrudController<AddonService> {
@Post("/page", { summary: Constants.per.authOnly }) @Post("/page", { summary: Constants.per.authOnly })
async page(@Body(ALL) body) { async page(@Body(ALL) body) {
const {projectId,userId} = await this.getProjectUserIdRead();
body.query = body.query ?? {}; body.query = body.query ?? {};
delete body.query.userId; delete body.query.userId;
body.query.projectId = projectId;
const buildQuery = qb => { const buildQuery = qb => {
qb.andWhere("user_id = :userId", { userId: this.getUserId() }); qb.andWhere("user_id = :userId", { userId });
}; };
const res = await this.service.page({ const res = await this.service.page({
query: body.query, query: body.query,
@@ -48,14 +50,18 @@ export class AddonController extends CrudController<AddonService> {
@Post("/list", { summary: Constants.per.authOnly }) @Post("/list", { summary: Constants.per.authOnly })
async list(@Body(ALL) body) { async list(@Body(ALL) body) {
const {projectId,userId} = await this.getProjectUserIdRead();
body.query = body.query ?? {}; body.query = body.query ?? {};
body.query.userId = this.getUserId(); body.query.userId = userId;
body.query.projectId = projectId;
return super.list(body); return super.list(body);
} }
@Post("/add", { summary: Constants.per.authOnly }) @Post("/add", { summary: Constants.per.authOnly })
async add(@Body(ALL) bean) { async add(@Body(ALL) bean) {
bean.userId = this.getUserId(); const {userId,projectId} = await this.getProjectUserIdRead();
bean.userId = userId;
bean.projectId = projectId;
const type = bean.type; const type = bean.type;
const addonType = bean.addonType; const addonType = bean.addonType;
if (!type || !addonType) { if (!type || !addonType) {
@@ -73,7 +79,7 @@ export class AddonController extends CrudController<AddonService> {
@Post("/update", { summary: Constants.per.authOnly }) @Post("/update", { summary: Constants.per.authOnly })
async update(@Body(ALL) bean) { async update(@Body(ALL) bean) {
await this.service.checkUserId(bean.id, this.getUserId()); await this.checkOwner(this.getService(), bean.id, "write");
const old = await this.service.info(bean.id); const old = await this.service.info(bean.id);
if (!old) { if (!old) {
throw new ValidateException("Addon配置不存在"); throw new ValidateException("Addon配置不存在");
@@ -90,18 +96,19 @@ export class AddonController extends CrudController<AddonService> {
} }
} }
delete bean.userId; delete bean.userId;
delete bean.projectId;
return super.update(bean); return super.update(bean);
} }
@Post("/info", { summary: Constants.per.authOnly }) @Post("/info", { summary: Constants.per.authOnly })
async info(@Query("id") id: number) { async info(@Query("id") id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id, "read");
return super.info(id); return super.info(id);
} }
@Post("/delete", { summary: Constants.per.authOnly }) @Post("/delete", { summary: Constants.per.authOnly })
async delete(@Query("id") id: number) { async delete(@Query("id") id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id, "write");
return super.delete(id); return super.delete(id);
} }
@@ -133,38 +140,42 @@ export class AddonController extends CrudController<AddonService> {
async simpleInfo(@Query("addonType") addonType: string, @Query("id") id: number) { async simpleInfo(@Query("addonType") addonType: string, @Query("id") id: number) {
if (id === 0) { if (id === 0) {
//获取默认 //获取默认
const res = await this.service.getDefault(this.getUserId(), addonType); const {projectId,userId} = await this.getProjectUserIdRead();
const res = await this.service.getDefault(userId, addonType,projectId);
if (!res) { if (!res) {
throw new ValidateException("默认Addon配置不存在"); throw new ValidateException("默认Addon配置不存在");
} }
const simple = await this.service.getSimpleInfo(res.id); const simple = await this.service.getSimpleInfo(res.id);
return this.ok(simple); return this.ok(simple);
} }
await this.authService.checkUserIdButAllowAdmin(this.ctx, this.service, id); await this.checkOwner(this.getService(), id, "read",true);
const res = await this.service.getSimpleInfo(id); const res = await this.service.getSimpleInfo(id);
return this.ok(res); return this.ok(res);
} }
@Post("/getDefaultId", { summary: Constants.per.authOnly }) @Post("/getDefaultId", { summary: Constants.per.authOnly })
async getDefaultId(@Query("addonType") addonType: string) { async getDefaultId(@Query("addonType") addonType: string) {
const res = await this.service.getDefault(this.getUserId(), addonType); const {projectId,userId} = await this.getProjectUserIdRead();
const res = await this.service.getDefault(userId, addonType,projectId);
return this.ok(res?.id); return this.ok(res?.id);
} }
@Post("/setDefault", { summary: Constants.per.authOnly }) @Post("/setDefault", { summary: Constants.per.authOnly })
async setDefault(@Query("addonType") addonType: string, @Query("id") id: number) { async setDefault(@Query("addonType") addonType: string, @Query("id") id: number) {
await this.service.checkUserId(id, this.getUserId()); const {projectId,userId} = await this.checkOwner(this.getService(), id, "write",true);
const res = await this.service.setDefault(id, this.getUserId(), addonType); const res = await this.service.setDefault(id, userId, addonType,projectId);
return this.ok(res); return this.ok(res);
} }
@Post("/options", { summary: Constants.per.authOnly }) @Post("/options", { summary: Constants.per.authOnly })
async options(@Query("addonType") addonType: string) { async options(@Query("addonType") addonType: string) {
const {projectId,userId} = await this.getProjectUserIdRead();
const res = await this.service.list({ const res = await this.service.list({
query: { query: {
userId: this.getUserId(), userId,
addonType addonType,
projectId
} }
}); });
for (const item of res) { for (const item of res) {
@@ -176,22 +187,16 @@ export class AddonController extends CrudController<AddonService> {
@Post("/handle", { summary: Constants.per.authOnly }) @Post("/handle", { summary: Constants.per.authOnly })
async handle(@Body(ALL) body: AddonRequestHandleReq) { async handle(@Body(ALL) body: AddonRequestHandleReq) {
const userId = this.getUserId();
let inputAddon = body.input.addon; let inputAddon = body.input.addon;
if (body.input.id > 0) { if (body.input.id > 0) {
await this.checkOwner(this.getService(), body.input.id, "write",true);
const oldEntity = await this.service.info(body.input.id); const oldEntity = await this.service.info(body.input.id);
if (oldEntity) { if (oldEntity) {
if (oldEntity.userId !== userId) {
throw new Error("addon not found");
}
// const param: any = {
// type: body.typeName,
// setting: JSON.stringify(body.input.access),
// };
inputAddon = JSON.parse(oldEntity.setting); inputAddon = JSON.parse(oldEntity.setting);
} }
} }
const serviceGetter = this.taskServiceBuilder.create({ userId }); const {projectId,userId} = await this.getProjectUserIdRead();
const serviceGetter = this.taskServiceBuilder.create({ userId,projectId });
const ctx = { const ctx = {
http: http, http: http,
@@ -20,10 +20,12 @@ export class GroupController extends CrudController<GroupService> {
@Post('/page', { summary: Constants.per.authOnly }) @Post('/page', { summary: Constants.per.authOnly })
async page(@Body(ALL) body: any) { async page(@Body(ALL) body: any) {
const {projectId,userId} = await this.getProjectUserIdRead();
body.query = body.query ?? {}; body.query = body.query ?? {};
body.query.projectId = projectId;
delete body.query.userId; delete body.query.userId;
const buildQuery = qb => { const buildQuery = qb => {
qb.andWhere('user_id = :userId', { userId: this.getUserId() }); qb.andWhere('user_id = :userId', { userId });
}; };
const res = await this.service.page({ const res = await this.service.page({
query: body.query, query: body.query,
@@ -36,40 +38,47 @@ export class GroupController extends CrudController<GroupService> {
@Post('/list', { summary: Constants.per.authOnly }) @Post('/list', { summary: Constants.per.authOnly })
async list(@Body(ALL) body: any) { async list(@Body(ALL) body: any) {
const {projectId,userId} = await this.getProjectUserIdRead();
body.query = body.query ?? {}; body.query = body.query ?? {};
body.query.userId = this.getUserId(); body.query.projectId = projectId;
body.query.userId = userId;
return await super.list(body); return await super.list(body);
} }
@Post('/add', { summary: Constants.per.authOnly }) @Post('/add', { summary: Constants.per.authOnly })
async add(@Body(ALL) bean: any) { async add(@Body(ALL) bean: any) {
bean.userId = this.getUserId(); const {projectId,userId} = await this.getProjectUserIdRead();
bean.projectId = projectId;
bean.userId = userId;
return await super.add(bean); return await super.add(bean);
} }
@Post('/update', { summary: Constants.per.authOnly }) @Post('/update', { summary: Constants.per.authOnly })
async update(@Body(ALL) bean) { async update(@Body(ALL) bean) {
await this.service.checkUserId(bean.id, this.getUserId()); await this.checkOwner(this.getService(), bean.id, "write");
delete bean.userId; delete bean.userId;
delete bean.projectId;
return await super.update(bean); return await super.update(bean);
} }
@Post('/info', { summary: Constants.per.authOnly }) @Post('/info', { summary: Constants.per.authOnly })
async info(@Query('id') id: number) { async info(@Query('id') id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id, "read");
return await super.info(id); return await super.info(id);
} }
@Post('/delete', { summary: Constants.per.authOnly }) @Post('/delete', { summary: Constants.per.authOnly })
async delete(@Query('id') id: number) { async delete(@Query('id') id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id, "write");
return await super.delete(id); return await super.delete(id);
} }
@Post('/all', { summary: Constants.per.authOnly }) @Post('/all', { summary: Constants.per.authOnly })
async all(@Query('type') type: string) { async all(@Query('type') type: string) {
const {projectId,userId} = await this.getProjectUserIdRead();
const list: any = await this.service.find({ const list: any = await this.service.find({
where: { where: {
userId: this.getUserId(), projectId,
userId,
type, type,
}, },
}); });
@@ -18,8 +18,10 @@ export class DomainController extends CrudController<DomainService> {
@Post('/page', { summary: Constants.per.authOnly }) @Post('/page', { summary: Constants.per.authOnly })
async page(@Body(ALL) body: any) { async page(@Body(ALL) body: any) {
const {projectId,userId} = await this.getProjectUserIdRead();
body.query = body.query ?? {}; body.query = body.query ?? {};
body.query.userId = this.getUserId(); body.query.projectId = projectId;
body.query.userId = userId;
const domain = body.query.domain; const domain = body.query.domain;
delete body.query.domain; delete body.query.domain;
@@ -40,41 +42,48 @@ export class DomainController extends CrudController<DomainService> {
@Post('/list', { summary: Constants.per.authOnly }) @Post('/list', { summary: Constants.per.authOnly })
async list(@Body(ALL) body: any) { async list(@Body(ALL) body: any) {
const {projectId,userId} = await this.getProjectUserIdRead();
body.query = body.query ?? {}; body.query = body.query ?? {};
body.query.userId = this.getUserId(); body.query.projectId = projectId;
body.query.userId = userId;
const list = await this.getService().list(body); const list = await this.getService().list(body);
return this.ok(list); return this.ok(list);
} }
@Post('/add', { summary: Constants.per.authOnly }) @Post('/add', { summary: Constants.per.authOnly })
async add(@Body(ALL) bean: any) { async add(@Body(ALL) bean: any) {
bean.userId = this.getUserId(); const {projectId,userId} = await this.getProjectUserIdRead();
bean.projectId = projectId;
bean.userId = userId;
return super.add(bean); return super.add(bean);
} }
@Post('/update', { summary: Constants.per.authOnly }) @Post('/update', { summary: Constants.per.authOnly })
async update(@Body(ALL) bean: any) { async update(@Body(ALL) bean: any) {
await this.service.checkUserId(bean.id, this.getUserId()); await this.checkOwner(this.getService(), bean.id, "write");
delete bean.userId; delete bean.userId;
delete bean.projectId;
return super.update(bean); return super.update(bean);
} }
@Post('/info', { summary: Constants.per.authOnly }) @Post('/info', { summary: Constants.per.authOnly })
async info(@Query('id') id: number) { async info(@Query('id') id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id, "read");
return super.info(id); return super.info(id);
} }
@Post('/delete', { summary: Constants.per.authOnly }) @Post('/delete', { summary: Constants.per.authOnly })
async delete(@Query('id') id: number) { async delete(@Query('id') id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id, "write");
return super.delete(id); return super.delete(id);
} }
@Post('/deleteByIds', { summary: Constants.per.authOnly }) @Post('/deleteByIds', { summary: Constants.per.authOnly })
async deleteByIds(@Body(ALL) body: any) { async deleteByIds(@Body(ALL) body: any) {
const {projectId,userId} = await this.getProjectUserIdRead();
await this.service.delete(body.ids, { await this.service.delete(body.ids, {
userId: this.getUserId(), userId: userId,
projectId: projectId,
}); });
return this.ok(); return this.ok();
} }
@@ -83,9 +92,12 @@ export class DomainController extends CrudController<DomainService> {
@Post('/import/start', { summary: Constants.per.authOnly }) @Post('/import/start', { summary: Constants.per.authOnly })
async importStart(@Body(ALL) body: any) { async importStart(@Body(ALL) body: any) {
checkPlus(); checkPlus();
const {projectId,userId} = await this.getProjectUserIdRead();
const { key } = body; const { key } = body;
const req = { const req = {
key, userId: this.getUserId(), key,
userId: userId,
projectId: projectId,
} }
await this.service.startDomainImportTask(req); await this.service.startDomainImportTask(req);
return this.ok(); return this.ok();
@@ -93,8 +105,10 @@ export class DomainController extends CrudController<DomainService> {
@Post('/import/status', { summary: Constants.per.authOnly }) @Post('/import/status', { summary: Constants.per.authOnly })
async importStatus() { async importStatus() {
const {projectId,userId} = await this.getProjectUserIdRead();
const req = { const req = {
userId: this.getUserId(), userId: userId,
projectId: projectId,
} }
const task = await this.service.getDomainImportTaskStatus(req); const task = await this.service.getDomainImportTaskStatus(req);
return this.ok(task); return this.ok(task);
@@ -103,9 +117,11 @@ export class DomainController extends CrudController<DomainService> {
@Post('/import/delete', { summary: Constants.per.authOnly }) @Post('/import/delete', { summary: Constants.per.authOnly })
async importDelete(@Body(ALL) body: any) { async importDelete(@Body(ALL) body: any) {
const {projectId,userId} = await this.getProjectUserIdRead();
const { key } = body; const { key } = body;
const req = { const req = {
userId: this.getUserId(), userId: userId,
projectId: projectId,
key, key,
} }
await this.service.deleteDomainImportTask(req); await this.service.deleteDomainImportTask(req);
@@ -115,9 +131,11 @@ export class DomainController extends CrudController<DomainService> {
@Post('/import/save', { summary: Constants.per.authOnly }) @Post('/import/save', { summary: Constants.per.authOnly })
async importSave(@Body(ALL) body: any) { async importSave(@Body(ALL) body: any) {
checkPlus(); checkPlus();
const {projectId,userId} = await this.getProjectUserIdRead();
const { dnsProviderType, dnsProviderAccessId, key } = body; const { dnsProviderType, dnsProviderAccessId, key } = body;
const req = { const req = {
userId: this.getUserId(), userId: userId,
projectId: projectId,
dnsProviderType, dnsProviderAccessId, key dnsProviderType, dnsProviderAccessId, key
} }
const item = await this.service.saveDomainImportTask(req); const item = await this.service.saveDomainImportTask(req);
@@ -127,15 +145,19 @@ export class DomainController extends CrudController<DomainService> {
@Post('/sync/expiration/start', { summary: Constants.per.authOnly }) @Post('/sync/expiration/start', { summary: Constants.per.authOnly })
async syncExpirationStart(@Body(ALL) body: any) { async syncExpirationStart(@Body(ALL) body: any) {
const {projectId,userId} = await this.getProjectUserIdRead();
await this.service.startSyncExpirationTask({ await this.service.startSyncExpirationTask({
userId: this.getUserId(), userId: userId,
projectId: projectId,
}) })
return this.ok(); return this.ok();
} }
@Post('/sync/expiration/status', { summary: Constants.per.authOnly }) @Post('/sync/expiration/status', { summary: Constants.per.authOnly })
async syncExpirationStatus(@Body(ALL) body: any) { async syncExpirationStatus(@Body(ALL) body: any) {
const {projectId,userId} = await this.getProjectUserIdRead();
const status = await this.service.getSyncExpirationTaskStatus({ const status = await this.service.getSyncExpirationTaskStatus({
userId: this.getUserId(), userId: userId,
projectId: projectId,
}) })
return this.ok(status); return this.ok(status);
} }
@@ -17,8 +17,10 @@ export class CnameRecordController extends CrudController<CnameRecordService> {
@Post('/page', { summary: Constants.per.authOnly }) @Post('/page', { summary: Constants.per.authOnly })
async page(@Body(ALL) body: any) { async page(@Body(ALL) body: any) {
const {userId,projectId} = await this.getProjectUserIdRead();
body.query = body.query ?? {}; body.query = body.query ?? {};
body.query.userId = this.getUserId(); body.query.userId = userId;
body.query.projectId = projectId;
const domain = body.query.domain; const domain = body.query.domain;
delete body.query.domain; delete body.query.domain;
@@ -39,22 +41,27 @@ export class CnameRecordController extends CrudController<CnameRecordService> {
@Post('/list', { summary: Constants.per.authOnly }) @Post('/list', { summary: Constants.per.authOnly })
async list(@Body(ALL) body: any) { async list(@Body(ALL) body: any) {
const {userId,projectId} = await this.getProjectUserIdRead();
body.query = body.query ?? {}; body.query = body.query ?? {};
body.query.userId = this.getUserId(); body.query.userId = userId;
body.query.projectId = projectId;
const list = await this.getService().list(body); const list = await this.getService().list(body);
return this.ok(list); return this.ok(list);
} }
@Post('/add', { summary: Constants.per.authOnly }) @Post('/add', { summary: Constants.per.authOnly })
async add(@Body(ALL) bean: any) { async add(@Body(ALL) bean: any) {
bean.userId = this.getUserId(); const {userId,projectId} = await this.getProjectUserIdWrite();
bean.userId = userId;
bean.projectId = projectId;
return super.add(bean); return super.add(bean);
} }
@Post('/update', { summary: Constants.per.authOnly }) @Post('/update', { summary: Constants.per.authOnly })
async update(@Body(ALL) bean: any) { async update(@Body(ALL) bean: any) {
await this.service.checkUserId(bean.id, this.getUserId()); await this.checkOwner(this.getService(), bean.id, "write");
delete bean.userId; delete bean.userId;
delete bean.projectId;
return super.update(bean); return super.update(bean);
} }
@@ -22,7 +22,7 @@ export class UserTwoFactorSettingController extends BaseController {
@Post("/get", { summary: Constants.per.authOnly }) @Post("/get", { summary: Constants.per.authOnly })
async get() { async get() {
const userId = this.getUserId(); const userId = this.getUserId();
const setting = await this.service.getSetting<UserTwoFactorSetting>(userId, UserTwoFactorSetting); const setting = await this.service.getSetting<UserTwoFactorSetting>(userId,null, UserTwoFactorSetting);
return this.ok(setting); return this.ok(setting);
} }
@@ -41,7 +41,7 @@ export class UserTwoFactorSettingController extends BaseController {
setting.authenticator.verified = false; setting.authenticator.verified = false;
} }
await this.service.saveSetting(userId, setting); await this.service.saveSetting(userId,null, setting);
return this.ok({}); return this.ok({});
} }
@@ -65,13 +65,14 @@ export class UserSettingsController extends CrudController<UserSettingsService>
@Post('/get', { summary: Constants.per.authOnly }) @Post('/get', { summary: Constants.per.authOnly })
async get(@Query('key') key: string) { async get(@Query('key') key: string) {
const entity = await this.service.getByKey(key, this.getUserId()); const {projectId,userId} = await this.getProjectUserIdRead();
const entity = await this.service.getByKey(key, userId, projectId);
return this.ok(entity); return this.ok(entity);
} }
@Post("/grant/get", { summary: Constants.per.authOnly }) @Post("/grant/get", { summary: Constants.per.authOnly })
async grantSettingsGet() { async grantSettingsGet() {
const userId = this.getUserId(); const userId = this.getUserId();
const setting = await this.service.getSetting<UserGrantSetting>(userId, UserGrantSetting); const setting = await this.service.getSetting<UserGrantSetting>(userId, null, UserGrantSetting);
return this.ok(setting); return this.ok(setting);
} }
@@ -84,7 +85,7 @@ export class UserSettingsController extends CrudController<UserSettingsService>
const setting = new UserGrantSetting(); const setting = new UserGrantSetting();
merge(setting, bean); merge(setting, bean);
await this.service.saveSetting(userId, setting); await this.service.saveSetting(userId,null, setting);
return this.ok({}); return this.ok({});
} }
@@ -123,6 +123,7 @@ export class CertInfoController extends CrudController<CertInfoService> {
async update(@Body(ALL) bean) { async update(@Body(ALL) bean) {
await this.checkOwner(this.service,bean.id,"write"); await this.checkOwner(this.service,bean.id,"write");
delete bean.userId; delete bean.userId;
delete bean.projectId;
return await super.update(bean); return await super.update(bean);
} }
@Post('/info', { summary: Constants.per.authOnly }) @Post('/info', { summary: Constants.per.authOnly })
@@ -80,6 +80,7 @@ export class SiteInfoController extends CrudController<SiteInfoService> {
async update(@Body(ALL) bean) { async update(@Body(ALL) bean) {
await this.checkOwner(this.service,bean.id,"write"); await this.checkOwner(this.service,bean.id,"write");
delete bean.userId; delete bean.userId;
delete bean.projectId;
await this.service.update(bean); await this.service.update(bean);
const entity = await this.service.info(bean.id); const entity = await this.service.info(bean.id);
if (entity.disabled) { if (entity.disabled) {
@@ -62,6 +62,7 @@ export class SiteInfoController extends CrudController<SiteIpService> {
async update(@Body(ALL) bean) { async update(@Body(ALL) bean) {
await this.checkOwner(this.service,bean.id,"write"); await this.checkOwner(this.service,bean.id,"write");
delete bean.userId; delete bean.userId;
delete bean.projectId;
await this.service.update(bean); await this.service.update(bean);
const siteEntity = await this.siteInfoService.info(bean.siteId); const siteEntity = await this.siteInfoService.info(bean.siteId);
if(!siteEntity.disabled){ if(!siteEntity.disabled){
@@ -19,8 +19,10 @@ export class OpenKeyController extends CrudController<OpenKeyService> {
@Post('/page', { summary: Constants.per.authOnly }) @Post('/page', { summary: Constants.per.authOnly })
async page(@Body(ALL) body: any) { async page(@Body(ALL) body: any) {
const {projectId,userId} = await this.getProjectUserIdRead();
body.query = body.query ?? {}; body.query = body.query ?? {};
body.query.userId = this.getUserId(); body.query.projectId = projectId;
body.query.userId = userId;
const res = await this.service.page({ const res = await this.service.page({
query: body.query, query: body.query,
page: body.page, page: body.page,
@@ -31,40 +33,45 @@ export class OpenKeyController extends CrudController<OpenKeyService> {
@Post('/list', { summary: Constants.per.authOnly }) @Post('/list', { summary: Constants.per.authOnly })
async list(@Body(ALL) body: any) { async list(@Body(ALL) body: any) {
const {projectId,userId} = await this.getProjectUserIdRead();
body.query = body.query ?? {}; body.query = body.query ?? {};
body.query.userId = this.getUserId(); body.query.projectId = projectId;
body.query.userId = userId;
return await super.list(body); return await super.list(body);
} }
@Post('/add', { summary: Constants.per.authOnly }) @Post('/add', { summary: Constants.per.authOnly })
async add(@Body(ALL) body: any) { async add(@Body(ALL) body: any) {
body.userId = this.getUserId(); const {projectId,userId} = await this.getProjectUserIdRead();
body.projectId = projectId;
body.userId = userId;
const res = await this.service.add(body); const res = await this.service.add(body);
return this.ok(res); return this.ok(res);
} }
@Post('/update', { summary: Constants.per.authOnly }) @Post('/update', { summary: Constants.per.authOnly })
async update(@Body(ALL) bean) { async update(@Body(ALL) bean) {
await this.service.checkUserId(bean.id, this.getUserId()); await this.checkOwner(this.getService(), bean.id, "write");
delete bean.userId; delete bean.userId;
delete bean.projectId;
await this.service.update(bean); await this.service.update(bean);
return this.ok(); return this.ok();
} }
@Post('/info', { summary: Constants.per.authOnly }) @Post('/info', { summary: Constants.per.authOnly })
async info(@Query('id') id: number) { async info(@Query('id') id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id, "read");
return await super.info(id); return await super.info(id);
} }
@Post('/delete', { summary: Constants.per.authOnly }) @Post('/delete', { summary: Constants.per.authOnly })
async delete(@Query('id') id: number) { async delete(@Query('id') id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id, "write");
return await super.delete(id); return await super.delete(id);
} }
@Post('/getApiToken', { summary: Constants.per.authOnly }) @Post('/getApiToken', { summary: Constants.per.authOnly })
async getApiToken(@Body('id') id: number) { async getApiToken(@Body('id') id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id, "write");
const token = await this.service.getApiToken(id); const token = await this.service.getApiToken(id);
return this.ok(token); return this.ok(token);
} }
@@ -21,9 +21,11 @@ export class AccessController extends CrudController<AccessService> {
@Post('/page', { summary: Constants.per.authOnly }) @Post('/page', { summary: Constants.per.authOnly })
async page(@Body(ALL) body) { async page(@Body(ALL) body) {
const { projectId, userId } = await this.getProjectUserIdRead()
body.query = body.query ?? {}; body.query = body.query ?? {};
delete body.query.userId; delete body.query.userId;
body.query.userId = this.getUserId() body.query.userId = userId;
body.query.projectId = projectId;
let name = body.query?.name; let name = body.query?.name;
delete body.query.name; delete body.query.name;
const buildQuery = qb => { const buildQuery = qb => {
@@ -42,32 +44,37 @@ export class AccessController extends CrudController<AccessService> {
@Post('/list', { summary: Constants.per.authOnly }) @Post('/list', { summary: Constants.per.authOnly })
async list(@Body(ALL) body) { async list(@Body(ALL) body) {
const { projectId, userId } = await this.getProjectUserIdRead()
body.query = body.query ?? {}; body.query = body.query ?? {};
body.query.userId = this.getUserId(); body.query.userId = userId;
body.query.projectId = projectId;
return super.list(body); return super.list(body);
} }
@Post('/add', { summary: Constants.per.authOnly }) @Post('/add', { summary: Constants.per.authOnly })
async add(@Body(ALL) bean) { async add(@Body(ALL) bean) {
bean.userId = this.getUserId(); const { projectId, userId } = await this.getProjectUserIdWrite()
bean.userId = userId;
bean.projectId = projectId;
return super.add(bean); return super.add(bean);
} }
@Post('/update', { summary: Constants.per.authOnly }) @Post('/update', { summary: Constants.per.authOnly })
async update(@Body(ALL) bean) { async update(@Body(ALL) bean) {
await this.service.checkUserId(bean.id, this.getUserId()); await this.checkOwner(this.getService(), bean.id, "write");
delete bean.userId; delete bean.userId;
delete bean.projectId;
return super.update(bean); return super.update(bean);
} }
@Post('/info', { summary: Constants.per.authOnly }) @Post('/info', { summary: Constants.per.authOnly })
async info(@Query('id') id: number) { async info(@Query('id') id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id, "read");
return super.info(id); return super.info(id);
} }
@Post('/delete', { summary: Constants.per.authOnly }) @Post('/delete', { summary: Constants.per.authOnly })
async delete(@Query('id') id: number) { async delete(@Query('id') id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id, "write");
return super.delete(id); return super.delete(id);
} }
@@ -79,7 +86,8 @@ export class AccessController extends CrudController<AccessService> {
@Post('/getSecretPlain', { summary: Constants.per.authOnly }) @Post('/getSecretPlain', { summary: Constants.per.authOnly })
async getSecretPlain(@Body(ALL) body: { id: number; key: string }) { async getSecretPlain(@Body(ALL) body: { id: number; key: string }) {
const value = await this.service.getById(body.id, this.getUserId()); const {userId, projectId} = await this.checkOwner(this.getService(), body.id, "read");
const value = await this.service.getById(body.id, userId, projectId);
return this.ok(value[body.key]); return this.ok(value[body.key]);
} }
@@ -102,14 +110,16 @@ export class AccessController extends CrudController<AccessService> {
@Post('/simpleInfo', { summary: Constants.per.authOnly }) @Post('/simpleInfo', { summary: Constants.per.authOnly })
async simpleInfo(@Query('id') id: number) { async simpleInfo(@Query('id') id: number) {
await this.authService.checkUserIdButAllowAdmin(this.ctx, this.service, id); // await this.authService.checkUserIdButAllowAdmin(this.ctx, this.service, id);
await this.checkOwner(this.getService(), id, "read",true);
const res = await this.service.getSimpleInfo(id); const res = await this.service.getSimpleInfo(id);
return this.ok(res); return this.ok(res);
} }
@Post('/getDictByIds', { summary: Constants.per.authOnly }) @Post('/getDictByIds', { summary: Constants.per.authOnly })
async getDictByIds(@Body('ids') ids: number[]) { async getDictByIds(@Body('ids') ids: number[]) {
const res = await this.service.getSimpleByIds(ids, this.getUserId()); const { userId, projectId } = await this.getProjectUserIdRead()
const res = await this.service.getSimpleByIds(ids, userId, projectId);
return this.ok(res); return this.ok(res);
} }
} }
@@ -21,9 +21,8 @@ export class CertController extends BaseController {
@Post('/get', { summary: Constants.per.authOnly }) @Post('/get', { summary: Constants.per.authOnly })
async getCert(@Query('id') id: number) { async getCert(@Query('id') id: number) {
const userId = this.getUserId();
const {userId} = await this.getProjectUserIdRead()
const pipleinUserId = await this.pipelineService.getPipelineUserId(id); const pipleinUserId = await this.pipelineService.getPipelineUserId(id);
@@ -34,7 +33,7 @@ export class CertController extends BaseController {
throw new PermissionException(); throw new PermissionException();
} }
// 是否允许管理员查看 // 是否允许管理员查看
const setting = await this.userSettingsService.getSetting<UserGrantSetting>(pipleinUserId, UserGrantSetting, false); const setting = await this.userSettingsService.getSetting<UserGrantSetting>(pipleinUserId,null, UserGrantSetting, false);
if (setting?.allowAdminViewCerts !== true) { if (setting?.allowAdminViewCerts !== true) {
//不允许管理员查看 //不允许管理员查看
throw new PermissionException("该流水线的用户还未授权管理员查看证书,请先让用户在”设置->授权委托“中打开开关"); throw new PermissionException("该流水线的用户还未授权管理员查看证书,请先让用户在”设置->授权委托“中打开开关");
@@ -14,7 +14,6 @@ export class DnsProviderController extends BaseController {
@Post('/list', { summary: Constants.per.authOnly }) @Post('/list', { summary: Constants.per.authOnly })
async list(@Query(ALL) query: any) { async list(@Query(ALL) query: any) {
query.userId = this.getUserId();
const list = this.service.getList(); const list = this.service.getList();
return this.ok(list); return this.ok(list);
} }
@@ -34,7 +34,7 @@ export class HandleController extends BaseController {
@Post('/access', { summary: Constants.per.authOnly }) @Post('/access', { summary: Constants.per.authOnly })
async accessRequest(@Body(ALL) body: AccessRequestHandleReq) { async accessRequest(@Body(ALL) body: AccessRequestHandleReq) {
const userId = this.getUserId(); const {projectId,userId} = await this.getProjectUserIdRead()
let inputAccess = body.input.access; let inputAccess = body.input.access;
if (body.input.id > 0) { if (body.input.id > 0) {
const oldEntity = await this.accessService.info(body.input.id); const oldEntity = await this.accessService.info(body.input.id);
@@ -42,6 +42,9 @@ export class HandleController extends BaseController {
if (oldEntity.userId !== this.getUserId()) { if (oldEntity.userId !== this.getUserId()) {
throw new Error('access not found'); throw new Error('access not found');
} }
if (oldEntity.projectId && oldEntity.projectId !== projectId) {
throw new Error('access not found');
}
const param: any = { const param: any = {
type: body.typeName, type: body.typeName,
setting: JSON.stringify(body.input.access), setting: JSON.stringify(body.input.access),
@@ -50,7 +53,7 @@ export class HandleController extends BaseController {
inputAccess = this.accessService.decryptAccessEntity(param); inputAccess = this.accessService.decryptAccessEntity(param);
} }
} }
const accessGetter = new AccessGetter(userId, this.accessService.getById.bind(this.accessService)); const accessGetter = new AccessGetter(userId,projectId, this.accessService.getById.bind(this.accessService));
const access = await newAccess(body.typeName, inputAccess,accessGetter); const access = await newAccess(body.typeName, inputAccess,accessGetter);
mergeUtils.merge(access, body.input); mergeUtils.merge(access, body.input);
@@ -77,7 +80,7 @@ export class HandleController extends BaseController {
@Post('/plugin', { summary: Constants.per.authOnly }) @Post('/plugin', { summary: Constants.per.authOnly })
async pluginRequest(@Body(ALL) body: PluginRequestHandleReq) { async pluginRequest(@Body(ALL) body: PluginRequestHandleReq) {
const userId = this.getUserId(); const {projectId,userId} = await this.getProjectUserIdRead()
const pluginDefine = pluginRegistry.get(body.typeName); const pluginDefine = pluginRegistry.get(body.typeName);
const pluginCls = await pluginDefine.target(); const pluginCls = await pluginDefine.target();
if (pluginCls == null) { if (pluginCls == null) {
@@ -98,7 +101,7 @@ export class HandleController extends BaseController {
}); });
}; };
const taskServiceGetter = this.taskServiceBuilder.create({userId}) const taskServiceGetter = this.taskServiceBuilder.create({userId,projectId})
const accessGetter = await taskServiceGetter.get<IAccessService>("accessService") const accessGetter = await taskServiceGetter.get<IAccessService>("accessService")
//@ts-ignore //@ts-ignore
@@ -118,6 +121,7 @@ export class HandleController extends BaseController {
fileStore: undefined, fileStore: undefined,
signal: undefined, signal: undefined,
user: {id:userId,role:"user"}, user: {id:userId,role:"user"},
projectId,
// pipelineContext: this.pipelineContext, // pipelineContext: this.pipelineContext,
// userContext: this.contextFactory.getContext('user', this.options.userId), // userContext: this.contextFactory.getContext('user', this.options.userId),
// fileStore: new FileStore({ // fileStore: new FileStore({
@@ -161,6 +161,7 @@ export class HistoryController extends CrudController<HistoryService> {
async update(@Body(ALL) bean) { async update(@Body(ALL) bean) {
await this.checkOwner(this.getService(), bean.id,"write",true); await this.checkOwner(this.getService(), bean.id,"write",true);
delete bean.userId; delete bean.userId;
delete bean.projectId;
return super.update(bean); return super.update(bean);
} }
@@ -22,10 +22,12 @@ export class NotificationController extends CrudController<NotificationService>
@Post('/page', { summary: Constants.per.authOnly }) @Post('/page', { summary: Constants.per.authOnly })
async page(@Body(ALL) body) { async page(@Body(ALL) body) {
const {projectId,userId} = await this.getProjectUserIdRead();
body.query = body.query ?? {}; body.query = body.query ?? {};
delete body.query.userId; delete body.query.userId;
body.query.projectId = projectId;
const buildQuery = qb => { const buildQuery = qb => {
qb.andWhere('user_id = :userId', { userId: this.getUserId() }); qb.andWhere('user_id = :userId', { userId: userId});
}; };
const res = await this.service.page({ const res = await this.service.page({
query: body.query, query: body.query,
@@ -38,14 +40,18 @@ export class NotificationController extends CrudController<NotificationService>
@Post('/list', { summary: Constants.per.authOnly }) @Post('/list', { summary: Constants.per.authOnly })
async list(@Body(ALL) body) { async list(@Body(ALL) body) {
const {projectId,userId} = await this.getProjectUserIdRead();
body.query = body.query ?? {}; body.query = body.query ?? {};
body.query.userId = this.getUserId(); body.query.userId = userId;
body.query.projectId = projectId;
return super.list(body); return super.list(body);
} }
@Post('/add', { summary: Constants.per.authOnly }) @Post('/add', { summary: Constants.per.authOnly })
async add(@Body(ALL) bean) { async add(@Body(ALL) bean) {
bean.userId = this.getUserId(); const {projectId,userId} = await this.getProjectUserIdRead();
bean.userId = userId;
bean.projectId = projectId;
const type = bean.type; const type = bean.type;
const define: NotificationDefine = this.service.getDefineByType(type); const define: NotificationDefine = this.service.getDefineByType(type);
if (!define) { if (!define) {
@@ -59,7 +65,7 @@ export class NotificationController extends CrudController<NotificationService>
@Post('/update', { summary: Constants.per.authOnly }) @Post('/update', { summary: Constants.per.authOnly })
async update(@Body(ALL) bean) { async update(@Body(ALL) bean) {
await this.service.checkUserId(bean.id, this.getUserId()); await this.checkOwner(this.getService(), bean.id,"write");
const old = await this.service.info(bean.id); const old = await this.service.info(bean.id);
if (!old) { if (!old) {
throw new ValidateException('通知配置不存在'); throw new ValidateException('通知配置不存在');
@@ -75,17 +81,18 @@ export class NotificationController extends CrudController<NotificationService>
} }
} }
delete bean.userId; delete bean.userId;
delete bean.projectId;
return super.update(bean); return super.update(bean);
} }
@Post('/info', { summary: Constants.per.authOnly }) @Post('/info', { summary: Constants.per.authOnly })
async info(@Query('id') id: number) { async info(@Query('id') id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id,"read");
return super.info(id); return super.info(id);
} }
@Post('/delete', { summary: Constants.per.authOnly }) @Post('/delete', { summary: Constants.per.authOnly })
async delete(@Query('id') id: number) { async delete(@Query('id') id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id,"write");
return super.delete(id); return super.delete(id);
} }
@@ -118,44 +125,50 @@ export class NotificationController extends CrudController<NotificationService>
@Post('/simpleInfo', { summary: Constants.per.authOnly }) @Post('/simpleInfo', { summary: Constants.per.authOnly })
async simpleInfo(@Query('id') id: number) { async simpleInfo(@Query('id') id: number) {
const {projectId,userId} = await this.getProjectUserIdRead();
if (id === 0) { if (id === 0) {
//获取默认 //获取默认
const res = await this.service.getDefault(this.getUserId()); const res = await this.service.getDefault(userId,projectId);
if (!res) { if (!res) {
throw new ValidateException('默认通知配置不存在'); throw new ValidateException('默认通知配置不存在');
} }
const simple = await this.service.getSimpleInfo(res.id); const simple = await this.service.getSimpleInfo(res.id);
return this.ok(simple); return this.ok(simple);
} }
await this.authService.checkUserIdButAllowAdmin(this.ctx, this.service, id); await this.checkOwner(this.getService(), id,"read",true);
const res = await this.service.getSimpleInfo(id); const res = await this.service.getSimpleInfo(id);
return this.ok(res); return this.ok(res);
} }
@Post('/getDefaultId', { summary: Constants.per.authOnly }) @Post('/getDefaultId', { summary: Constants.per.authOnly })
async getDefaultId() { async getDefaultId() {
const res = await this.service.getDefault(this.getUserId()); const {projectId,userId} = await this.getProjectUserIdRead();
const res = await this.service.getDefault(userId,projectId);
return this.ok(res?.id); return this.ok(res?.id);
} }
@Post('/setDefault', { summary: Constants.per.authOnly }) @Post('/setDefault', { summary: Constants.per.authOnly })
async setDefault(@Query('id') id: number) { async setDefault(@Query('id') id: number) {
await this.service.checkUserId(id, this.getUserId()); const {projectId,userId} = await this.getProjectUserIdRead();
const res = await this.service.setDefault(id, this.getUserId()); await this.checkOwner(this.getService(), id,"write");
const res = await this.service.setDefault(id, userId,projectId);
return this.ok(res); return this.ok(res);
} }
@Post('/getOrCreateDefault', { summary: Constants.per.authOnly }) @Post('/getOrCreateDefault', { summary: Constants.per.authOnly })
async getOrCreateDefault(@Body('email') email: string) { async getOrCreateDefault(@Body('email') email: string) {
const res = await this.service.getOrCreateDefault(email, this.getUserId()); const {projectId,userId} = await this.getProjectUserIdRead();
const res = await this.service.getOrCreateDefault(email, userId,projectId);
return this.ok(res); return this.ok(res);
} }
@Post('/options', { summary: Constants.per.authOnly }) @Post('/options', { summary: Constants.per.authOnly })
async options() { async options() {
const {projectId,userId} = await this.getProjectUserIdRead();
const res = await this.service.list({ const res = await this.service.list({
query: { query: {
userId: this.getUserId(), userId: userId,
projectId: projectId,
}, },
}); });
for (const item of res) { for (const item of res) {
@@ -97,6 +97,7 @@ export class PipelineController extends CrudController<PipelineService> {
async update(@Body(ALL) bean) { async update(@Body(ALL) bean) {
await this.checkOwner(this.getService(), bean.id,"write",true); await this.checkOwner(this.getService(), bean.id,"write",true);
delete bean.userId; delete bean.userId;
delete bean.projectId;
return super.update(bean); return super.update(bean);
} }
@@ -140,6 +141,7 @@ export class PipelineController extends CrudController<PipelineService> {
async disabled(@Body(ALL) bean) { async disabled(@Body(ALL) bean) {
await this.checkOwner(this.getService(), bean.id,"write",true); await this.checkOwner(this.getService(), bean.id,"write",true);
delete bean.userId; delete bean.userId;
delete bean.projectId;
await this.service.disabled(bean.id, bean.disabled); await this.service.disabled(bean.id, bean.disabled);
return this.ok({}); return this.ok({});
} }
@@ -20,10 +20,12 @@ export class PipelineGroupController extends CrudController<PipelineGroupService
@Post('/page', { summary: Constants.per.authOnly }) @Post('/page', { summary: Constants.per.authOnly })
async page(@Body(ALL) body: any) { async page(@Body(ALL) body: any) {
const {projectId,userId} = await this.getProjectUserIdRead();
body.query = body.query ?? {}; body.query = body.query ?? {};
delete body.query.userId; delete body.query.userId;
body.query.projectId = projectId;
const buildQuery = qb => { const buildQuery = qb => {
qb.andWhere('user_id = :userId', { userId: this.getUserId() }); qb.andWhere('user_id = :userId', { userId: userId });
}; };
const res = await this.service.page({ const res = await this.service.page({
query: body.query, query: body.query,
@@ -36,40 +38,47 @@ export class PipelineGroupController extends CrudController<PipelineGroupService
@Post('/list', { summary: Constants.per.authOnly }) @Post('/list', { summary: Constants.per.authOnly })
async list(@Body(ALL) body: any) { async list(@Body(ALL) body: any) {
const {projectId,userId} = await this.getProjectUserIdRead();
body.query = body.query ?? {}; body.query = body.query ?? {};
body.query.userId = this.getUserId(); body.query.userId = userId;
body.query.projectId = projectId;
return await super.list(body); return await super.list(body);
} }
@Post('/add', { summary: Constants.per.authOnly }) @Post('/add', { summary: Constants.per.authOnly })
async add(@Body(ALL) bean: any) { async add(@Body(ALL) bean: any) {
bean.userId = this.getUserId(); const {projectId,userId} = await this.getProjectUserIdRead();
bean.userId = userId;
bean.projectId = projectId;
return await super.add(bean); return await super.add(bean);
} }
@Post('/update', { summary: Constants.per.authOnly }) @Post('/update', { summary: Constants.per.authOnly })
async update(@Body(ALL) bean) { async update(@Body(ALL) bean) {
await this.service.checkUserId(bean.id, this.getUserId()); await this.checkOwner(this.getService(), bean.id, "write");
delete bean.userId; delete bean.userId;
delete bean.projectId;
return await super.update(bean); return await super.update(bean);
} }
@Post('/info', { summary: Constants.per.authOnly }) @Post('/info', { summary: Constants.per.authOnly })
async info(@Query('id') id: number) { async info(@Query('id') id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id, "read");
return await super.info(id); return await super.info(id);
} }
@Post('/delete', { summary: Constants.per.authOnly }) @Post('/delete', { summary: Constants.per.authOnly })
async delete(@Query('id') id: number) { async delete(@Query('id') id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id, "write");
return await super.delete(id); return await super.delete(id);
} }
@Post('/all', { summary: Constants.per.authOnly }) @Post('/all', { summary: Constants.per.authOnly })
async all() { async all() {
const {projectId,userId} = await this.getProjectUserIdRead();
const list: any = await this.service.find({ const list: any = await this.service.find({
where: { where: {
userId: this.getUserId(), userId: userId,
projectId: projectId,
}, },
}); });
return this.ok(list); return this.ok(list);
@@ -18,21 +18,18 @@ export class PluginController extends BaseController {
@Post('/list', { summary: Constants.per.authOnly }) @Post('/list', { summary: Constants.per.authOnly })
async list(@Query(ALL) query: any) { async list(@Query(ALL) query: any) {
query.userId = this.getUserId();
const list = await this.service.getEnabledBuiltInList(); const list = await this.service.getEnabledBuiltInList();
return this.ok(list); return this.ok(list);
} }
@Post('/groups', { summary: Constants.per.authOnly }) @Post('/groups', { summary: Constants.per.authOnly })
async groups(@Query(ALL) query: any) { async groups(@Query(ALL) query: any) {
query.userId = this.getUserId();
const group = await this.service.getEnabledBuildInGroup(); const group = await this.service.getEnabledBuildInGroup();
return this.ok(group); return this.ok(group);
} }
@Post('/groupsList', { summary: Constants.per.authOnly }) @Post('/groupsList', { summary: Constants.per.authOnly })
async groupsList(@Query(ALL) query: any) { async groupsList(@Query(ALL) query: any) {
query.userId = this.getUserId();
const groups = pluginGroups const groups = pluginGroups
const groupsList:any = [] const groupsList:any = []
for (const key in groups) { for (const key in groups) {
@@ -22,8 +22,8 @@ export class SubDomainController extends CrudController<SubDomainService> {
@Post('/parseDomain', { summary: Constants.per.authOnly }) @Post('/parseDomain', { summary: Constants.per.authOnly })
async parseDomain(@Body("fullDomain") fullDomain:string) { async parseDomain(@Body("fullDomain") fullDomain:string) {
const userId = this.getUserId() const {projectId,userId} = await this.getProjectUserIdRead();
const taskService = this.taskServiceBuilder.create({ userId: userId }); const taskService = this.taskServiceBuilder.create({ userId: userId, projectId: projectId });
const subDomainGetter = await taskService.getSubDomainsGetter(); const subDomainGetter = await taskService.getSubDomainsGetter();
const domainParser = new DomainParser(subDomainGetter) const domainParser = new DomainParser(subDomainGetter)
const domain = await domainParser.parse(fullDomain) const domain = await domainParser.parse(fullDomain)
@@ -33,10 +33,12 @@ export class SubDomainController extends CrudController<SubDomainService> {
@Post('/page', { summary: Constants.per.authOnly }) @Post('/page', { summary: Constants.per.authOnly })
async page(@Body(ALL) body) { async page(@Body(ALL) body) {
const {userId,projectId} = await this.getProjectUserIdRead();
body.query = body.query ?? {}; body.query = body.query ?? {};
delete body.query.userId; delete body.query.userId;
body.query.projectId = projectId;
const buildQuery = qb => { const buildQuery = qb => {
qb.andWhere('user_id = :userId', { userId: this.getUserId() }); qb.andWhere('user_id = :userId', { userId: userId });
}; };
const res = await this.service.page({ const res = await this.service.page({
query: body.query, query: body.query,
@@ -49,38 +51,44 @@ export class SubDomainController extends CrudController<SubDomainService> {
@Post('/list', { summary: Constants.per.authOnly }) @Post('/list', { summary: Constants.per.authOnly })
async list(@Body(ALL) body) { async list(@Body(ALL) body) {
const {userId,projectId} = await this.getProjectUserIdRead();
body.query = body.query ?? {}; body.query = body.query ?? {};
body.query.userId = this.getUserId(); body.query.userId = userId;
body.query.projectId = projectId;
return super.list(body); return super.list(body);
} }
@Post('/add', { summary: Constants.per.authOnly }) @Post('/add', { summary: Constants.per.authOnly })
async add(@Body(ALL) bean) { async add(@Body(ALL) bean) {
bean.userId = this.getUserId(); const {userId,projectId} = await this.getProjectUserIdRead();
bean.userId = userId;
bean.projectId = projectId;
return super.add(bean); return super.add(bean);
} }
@Post('/update', { summary: Constants.per.authOnly }) @Post('/update', { summary: Constants.per.authOnly })
async update(@Body(ALL) bean) { async update(@Body(ALL) bean) {
await this.service.checkUserId(bean.id, this.getUserId()); await this.checkOwner(this.getService(), bean.id, "write");
delete bean.userId; delete bean.userId;
delete bean.projectId;
return super.update(bean); return super.update(bean);
} }
@Post('/info', { summary: Constants.per.authOnly }) @Post('/info', { summary: Constants.per.authOnly })
async info(@Query('id') id: number) { async info(@Query('id') id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id, "read");
return super.info(id); return super.info(id);
} }
@Post('/delete', { summary: Constants.per.authOnly }) @Post('/delete', { summary: Constants.per.authOnly })
async delete(@Query('id') id: number) { async delete(@Query('id') id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id, "write");
return super.delete(id); return super.delete(id);
} }
@Post('/batchDelete', { summary: Constants.per.authOnly }) @Post('/batchDelete', { summary: Constants.per.authOnly })
async batchDelete(@Body('ids') ids: number[]) { async batchDelete(@Body('ids') ids: number[]) {
await this.service.batchDelete(ids, this.getUserId()); const {userId,projectId} = await this.getProjectUserIdWrite();
await this.service.batchDelete(ids, userId, projectId);
return this.ok({}); return this.ok({});
} }
} }
@@ -59,6 +59,7 @@ export class TemplateController extends CrudController<TemplateService> {
async update(@Body(ALL) bean) { async update(@Body(ALL) bean) {
await this.checkOwner(this.service, bean.id, "write"); await this.checkOwner(this.service, bean.id, "write");
delete bean.userId; delete bean.userId;
delete bean.projectId;
return super.update(bean); return super.update(bean);
} }
@Post('/info', { summary: Constants.per.authOnly }) @Post('/info', { summary: Constants.per.authOnly })
@@ -22,6 +22,9 @@ export class GroupEntity {
@Column({ name: 'type', comment: '类型', length: 512 }) @Column({ name: 'type', comment: '类型', length: 512 })
type: string; type: string;
@Column({ name: 'project_id', comment: '项目Id' })
projectId: number;
@Column({ @Column({
name: 'create_time', name: 'create_time',
comment: '创建时间', comment: '创建时间',
@@ -44,6 +44,9 @@ export class DomainEntity {
@Column({ comment: 'http上传根目录', name: 'http_upload_root_dir', length: 512 }) @Column({ comment: 'http上传根目录', name: 'http_upload_root_dir', length: 512 })
httpUploadRootDir: string; httpUploadRootDir: string;
@Column({ name: 'project_id', comment: '项目Id' })
projectId: number;
@Column({ @Column({
comment: '创建时间', comment: '创建时间',
name: 'create_time', name: 'create_time',
@@ -18,6 +18,7 @@ import { DomainEntity } from '../entity/domain.js';
export interface SyncFromProviderReq { export interface SyncFromProviderReq {
userId: number; userId: number;
projectId: number;
dnsProviderType: string; dnsProviderType: string;
dnsProviderAccessId: number; dnsProviderAccessId: number;
} }
@@ -215,9 +216,9 @@ export class DomainService extends BaseService<DomainEntity> {
} }
async startDomainImportTask(req: { userId: number, key: string }) { async startDomainImportTask(req: { userId: number, projectId: number, key: string }) {
const key = req.key const key = req.key
const setting = await this.userSettingService.getSetting<UserDomainImportSetting>(req.userId, UserDomainImportSetting) const setting = await this.userSettingService.getSetting<UserDomainImportSetting>(req.userId, req.projectId, UserDomainImportSetting)
const item = setting.domainImportList.find(item => item.key === key) const item = setting.domainImportList.find(item => item.key === key)
if (!item) { if (!item) {
@@ -232,6 +233,7 @@ export class DomainService extends BaseService<DomainEntity> {
run: async (task: BackTask) => { run: async (task: BackTask) => {
await this._syncFromProvider({ await this._syncFromProvider({
userId: req.userId, userId: req.userId,
projectId: req.projectId,
dnsProviderType, dnsProviderType,
dnsProviderAccessId, dnsProviderAccessId,
}, task) }, task)
@@ -240,13 +242,13 @@ export class DomainService extends BaseService<DomainEntity> {
} }
private async _syncFromProvider(req: SyncFromProviderReq, task: BackTask) { private async _syncFromProvider(req: SyncFromProviderReq, task: BackTask) {
const { userId, dnsProviderType, dnsProviderAccessId } = req; const { userId, projectId, dnsProviderType, dnsProviderAccessId } = req;
const serviceGetter = this.taskServiceBuilder.create({ userId }); const serviceGetter = this.taskServiceBuilder.create({ userId, projectId });
const subDomainGetter = await serviceGetter.getSubDomainsGetter(); const subDomainGetter = await serviceGetter.getSubDomainsGetter();
const domainParser = new DomainParser(subDomainGetter) const domainParser = new DomainParser(subDomainGetter)
const access = await this.accessService.getById(dnsProviderAccessId, userId); const access = await this.accessService.getById(dnsProviderAccessId, userId, projectId);
const context = { access, logger, http, utils, domainParser, serviceGetter }; const context = { access, logger, http, utils, domainParser, serviceGetter };
// 翻页查询dns的记录 // 翻页查询dns的记录
const dnsProvider = await createDnsProvider({ dnsProviderType, context }) const dnsProvider = await createDnsProvider({ dnsProviderType, context })
@@ -272,6 +274,7 @@ export class DomainService extends BaseService<DomainEntity> {
where: { where: {
domain, domain,
userId, userId,
projectId,
} }
}) })
if (old) { if (old) {
@@ -296,6 +299,7 @@ export class DomainService extends BaseService<DomainEntity> {
//添加 //添加
await this.add({ await this.add({
userId, userId,
projectId,
domain, domain,
dnsProviderType, dnsProviderType,
dnsProviderAccess: dnsProviderAccessId, dnsProviderAccess: dnsProviderAccessId,
@@ -314,10 +318,11 @@ export class DomainService extends BaseService<DomainEntity> {
logger.info(`从域名提供商${dnsProviderType}导入域名完成(${key}),共导入${task.total}个域名,跳过${task.getSkipCount()}个域名,成功${task.getSuccessCount()}个域名,失败${task.getErrorCount()}个域名`) logger.info(`从域名提供商${dnsProviderType}导入域名完成(${key}),共导入${task.total}个域名,跳过${task.getSkipCount()}个域名,成功${task.getSuccessCount()}个域名,失败${task.getErrorCount()}个域名`)
} }
async getDomainImportTaskStatus(req: { userId?: number }) { async getDomainImportTaskStatus(req: { userId?: number ,projectId?: number}) {
const userId = req.userId || 0 const userId = req.userId || 0
const projectId = req.projectId
const setting = await this.userSettingService.getSetting<UserDomainImportSetting>(userId, UserDomainImportSetting) const setting = await this.userSettingService.getSetting<UserDomainImportSetting>(userId, projectId, UserDomainImportSetting)
const list = setting?.domainImportList || [] const list = setting?.domainImportList || []
const taskList: any = [] const taskList: any = []
@@ -335,8 +340,9 @@ export class DomainService extends BaseService<DomainEntity> {
return taskList return taskList
} }
async getProviderTitle(req: { userId?: number, dnsProviderType: string, dnsProviderAccessId: number }) { async getProviderTitle(req: { userId?: number, projectId?: number, dnsProviderType: string, dnsProviderAccessId: number }) {
const userId = req.userId || 0 const userId = req.userId || 0
const projectId = req.projectId
const { dnsProviderType, dnsProviderAccessId } = req const { dnsProviderType, dnsProviderAccessId } = req
const dnsProviderDefine = dnsProviderRegistry.getDefine(dnsProviderType) const dnsProviderDefine = dnsProviderRegistry.getDefine(dnsProviderType)
if (!dnsProviderDefine) { if (!dnsProviderDefine) {
@@ -346,6 +352,9 @@ export class DomainService extends BaseService<DomainEntity> {
if (!access || access.userId !== userId) { if (!access || access.userId !== userId) {
throw new Error(`该授权(${dnsProviderAccessId})不存在,请检查是否已被删除`) throw new Error(`该授权(${dnsProviderAccessId})不存在,请检查是否已被删除`)
} }
if (projectId && access.projectId !== projectId) {
throw new Error(`该授权(${dnsProviderAccessId})不存在,请检查是否已被删除`)
}
return { return {
title: `${dnsProviderDefine.title}_${access.name || ''}`, title: `${dnsProviderDefine.title}_${access.name || ''}`,
//@ts-ignore //@ts-ignore
@@ -353,21 +362,22 @@ export class DomainService extends BaseService<DomainEntity> {
} }
} }
async addDomainImportTask(req: { userId?: number, dnsProviderType: string, dnsProviderAccessId: number, index?: number }) { async addDomainImportTask(req: { userId?: number, projectId?: number, dnsProviderType: string, dnsProviderAccessId: number, index?: number }) {
const userId = req.userId || 0 const userId = req.userId || 0
const projectId = req.projectId
const { dnsProviderType, dnsProviderAccessId, index = 0 } = req const { dnsProviderType, dnsProviderAccessId, index = 0 } = req
const key = `user_${userId}_${dnsProviderType}_${dnsProviderAccessId}` const key = `user_${userId}_${dnsProviderType}_${dnsProviderAccessId}`
const { title, icon } = await this.getProviderTitle(req) const { title, icon } = await this.getProviderTitle(req)
const setting = await this.userSettingService.getSetting<UserDomainImportSetting>(userId, UserDomainImportSetting) const setting = await this.userSettingService.getSetting<UserDomainImportSetting>(userId, projectId, UserDomainImportSetting)
setting.domainImportList = setting.domainImportList || [] setting.domainImportList = setting.domainImportList || []
if (setting.domainImportList.find(item => item.key === key)) { if (setting.domainImportList.find(item => item.key === key)) {
throw new Error(`该域名导入任务${key}已存在`) throw new Error(`该域名导入任务${key}已存在`)
} }
const access = await this.accessService.getAccessById(dnsProviderAccessId, true, userId) const access = await this.accessService.getAccessById(dnsProviderAccessId, true, userId, projectId)
if (!access) { if (!access) {
throw new Error(`该授权(${dnsProviderAccessId})不存在,请检查是否已被删除`) throw new Error(`该授权(${dnsProviderAccessId})不存在,请检查是否已被删除`)
} }
@@ -380,16 +390,17 @@ export class DomainService extends BaseService<DomainEntity> {
icon: icon || '', icon: icon || '',
} }
setting.domainImportList.splice(index, 0, item) setting.domainImportList.splice(index, 0, item)
await this.userSettingService.saveSetting(userId, setting) await this.userSettingService.saveSetting(userId, projectId, setting)
return item return item
} }
async deleteDomainImportTask(req: { userId?: number, key: string }) { async deleteDomainImportTask(req: { userId?: number, projectId?: number, key: string }) {
const userId = req.userId || 0 const userId = req.userId || 0
const { key } = req const { key } = req
const setting = await this.userSettingService.getSetting<UserDomainImportSetting>(userId, UserDomainImportSetting) const projectId = req.projectId
const setting = await this.userSettingService.getSetting<UserDomainImportSetting>(userId, projectId, UserDomainImportSetting)
setting.domainImportList = setting.domainImportList || [] setting.domainImportList = setting.domainImportList || []
const index = setting.domainImportList.findIndex(item => item.key === key) const index = setting.domainImportList.findIndex(item => item.key === key)
if (index === -1) { if (index === -1) {
@@ -397,13 +408,14 @@ export class DomainService extends BaseService<DomainEntity> {
} }
setting.domainImportList.splice(index, 1) setting.domainImportList.splice(index, 1)
taskExecutor.clear(DOMAIN_IMPORT_TASK_TYPE, key) taskExecutor.clear(DOMAIN_IMPORT_TASK_TYPE, key)
await this.userSettingService.saveSetting(userId, setting) await this.userSettingService.saveSetting(userId, projectId, setting)
} }
async saveDomainImportTask(req: { userId?: number, dnsProviderType: string, dnsProviderAccessId: number, key?: string }) { async saveDomainImportTask(req: { userId?: number, projectId?: number, dnsProviderType: string, dnsProviderAccessId: number, key?: string }) {
const userId = req.userId || 0 const userId = req.userId || 0
const projectId = req.projectId
const { dnsProviderType, dnsProviderAccessId, key } = req const { dnsProviderType, dnsProviderAccessId, key } = req
const setting = await this.userSettingService.getSetting<UserDomainImportSetting>(userId, UserDomainImportSetting) const setting = await this.userSettingService.getSetting<UserDomainImportSetting>(userId, projectId, UserDomainImportSetting)
setting.domainImportList = setting.domainImportList || [] setting.domainImportList = setting.domainImportList || []
let index = 0 let index = 0
@@ -412,36 +424,46 @@ export class DomainService extends BaseService<DomainEntity> {
if (index === -1) { if (index === -1) {
throw new Error(`该域名导入任务${key}不存在`) throw new Error(`该域名导入任务${key}不存在`)
} }
await this.deleteDomainImportTask({ userId, key }) await this.deleteDomainImportTask({ userId, projectId, key })
} }
return await this.addDomainImportTask({ userId, dnsProviderType, dnsProviderAccessId, index })
return await this.addDomainImportTask({ userId, projectId, dnsProviderType, dnsProviderAccessId, index })
} }
async getSyncExpirationTaskStatus(req: { userId?: number }) { async getSyncExpirationTaskStatus(req: { userId?: number, projectId?: number }) {
const userId = req.userId ?? 'all' const userId = req.userId ?? 'all'
const key = `user_${userId}` const projectId = req.projectId
let key = `user_${userId}`
if (projectId!=null) {
key += `_${projectId}`
}
const task = taskExecutor.get(DOMAIN_EXPIRE_TASK_TYPE, key) const task = taskExecutor.get(DOMAIN_EXPIRE_TASK_TYPE, key)
return task return task
} }
async startSyncExpirationTask(req: { userId?: number }) { async startSyncExpirationTask(req: { userId?: number, projectId?: number }) {
const userId = req.userId const userId = req.userId
const key = `user_${userId ?? 'all'}` const projectId = req.projectId
let key = `user_${userId ?? 'all'}`
if (projectId!=null) {
key += `_${projectId}`
}
taskExecutor.start(new BackTask({ taskExecutor.start(new BackTask({
type: DOMAIN_EXPIRE_TASK_TYPE, type: DOMAIN_EXPIRE_TASK_TYPE,
key, key,
title: `同步注册域名过期时间(${key}))`, title: `同步注册域名过期时间(${key}))`,
run: async (task: BackTask) => { run: async (task: BackTask) => {
await this._syncDomainsExpirationDate({ userId, task }) await this._syncDomainsExpirationDate({ userId, projectId, task })
} }
})) }))
} }
private async _syncDomainsExpirationDate(req: { userId?: number, task: BackTask }) { private async _syncDomainsExpirationDate(req: { userId?: number, projectId?: number, task: BackTask }) {
//同步所有域名的过期时间 //同步所有域名的过期时间
const pager = new Pager({ const pager = new Pager({
pageNo: 1, pageNo: 1,
@@ -498,6 +520,9 @@ export class DomainService extends BaseService<DomainEntity> {
if (req.userId != null) { if (req.userId != null) {
query.userId = req.userId query.userId = req.userId
} }
if (req.projectId != null) {
query.projectId = req.projectId
}
const getDomainPage = async (pager: Pager) => { const getDomainPage = async (pager: Pager) => {
const pageRes = await this.page({ const pageRes = await this.page({
query: query, query: query,
@@ -549,5 +574,4 @@ export class DomainService extends BaseService<DomainEntity> {
logger.info(`同步用户(${key})注册域名过期时间完成(${req.task.getSuccessCount()}个成功,${req.task.getErrorCount()}个失败)`) logger.info(`同步用户(${key})注册域名过期时间完成(${req.task.getSuccessCount()}个成功,${req.task.getErrorCount()}个失败)`)
} }
} }
@@ -31,6 +31,9 @@ export class CnameRecordEntity {
@Column({ comment: '错误信息' }) @Column({ comment: '错误信息' })
error: string error: string
@Column({ name: 'project_id', comment: '项目Id' })
projectId: number;
@Column({ @Column({
comment: '创建时间', comment: '创建时间',
name: 'create_time', name: 'create_time',
@@ -15,6 +15,9 @@ export class UserSettingsEntity {
@Column({ name: 'setting', comment: '设置', length: 1024, nullable: true }) @Column({ name: 'setting', comment: '设置', length: 1024, nullable: true })
setting: string; setting: string;
@Column({ name: 'project_id', comment: '项目Id' })
projectId: number;
@Column({ @Column({
name: 'create_time', name: 'create_time',
comment: '创建时间', comment: '创建时间',
@@ -37,7 +37,7 @@ export class UserSettingsService extends BaseService<UserSettingsEntity> {
}; };
} }
async getByKey(key: string, userId: number): Promise<UserSettingsEntity | null> { async getByKey(key: string, userId: number, projectId: number): Promise<UserSettingsEntity | null> {
if(!userId){ if(!userId){
throw new Error('userId is required'); throw new Error('userId is required');
} }
@@ -47,16 +47,17 @@ export class UserSettingsService extends BaseService<UserSettingsEntity> {
return await this.repository.findOne({ return await this.repository.findOne({
where: { where: {
key, key,
userId userId,
projectId
} }
}); });
} }
async getSettingByKey(key: string, userId: number): Promise<any | null> { async getSettingByKey(key: string, userId: number, projectId: number): Promise<any | null> {
if(!userId){ if(!userId){
throw new Error('userId is required'); throw new Error('userId is required');
} }
const entity = await this.getByKey(key, userId); const entity = await this.getByKey(key, userId, projectId);
if (!entity) { if (!entity) {
return null; return null;
} }
@@ -67,7 +68,8 @@ export class UserSettingsService extends BaseService<UserSettingsEntity> {
const entity = await this.repository.findOne({ const entity = await this.repository.findOne({
where: { where: {
key: bean.key, key: bean.key,
userId: bean.userId userId: bean.userId,
projectId: bean.projectId
} }
}); });
if (entity) { if (entity) {
@@ -80,12 +82,16 @@ export class UserSettingsService extends BaseService<UserSettingsEntity> {
} }
async getSetting<T>( userId: number,type: any, cache:boolean = false): Promise<T> { async getSetting<T>( userId: number, projectId: number,type: any, cache:boolean = false): Promise<T> {
if(!userId){ if(!userId){
throw new Error('userId is required'); throw new Error('userId is required');
} }
const key = type.__key__; const key = type.__key__;
const cacheKey = key + '_' + userId; let cacheKey = key + '_' + userId ;
if (projectId) {
cacheKey += '_' + projectId;
}
if (cache) { if (cache) {
const settings: T = UserSettingCache.get(cacheKey); const settings: T = UserSettingCache.get(cacheKey);
if (settings) { if (settings) {
@@ -94,7 +100,7 @@ export class UserSettingsService extends BaseService<UserSettingsEntity> {
} }
let newSetting: T = new type(); let newSetting: T = new type();
const savedSettings = await this.getSettingByKey(key, userId); const savedSettings = await this.getSettingByKey(key, userId, projectId);
newSetting = merge(newSetting, savedSettings); newSetting = merge(newSetting, savedSettings);
if (cache) { if (cache) {
@@ -103,11 +109,11 @@ export class UserSettingsService extends BaseService<UserSettingsEntity> {
return newSetting; return newSetting;
} }
async saveSetting<T extends BaseSettings>(userId:number,bean: T) { async saveSetting<T extends BaseSettings>(userId:number, projectId: number,bean: T) {
if(!userId){ if(!userId){
throw new Error('userId is required'); throw new Error('userId is required');
} }
const old = await this.getSetting(userId,bean.constructor) const old = await this.getSetting(userId, projectId,bean.constructor)
bean = merge(old,bean) bean = merge(old,bean)
const type: any = bean.constructor; const type: any = bean.constructor;
@@ -115,7 +121,7 @@ export class UserSettingsService extends BaseService<UserSettingsEntity> {
if(!key){ if(!key){
throw new Error(`${type.name} must have __key__`); throw new Error(`${type.name} must have __key__`);
} }
const entity = await this.getByKey(key,userId); const entity = await this.getByKey(key,userId, projectId);
const newEntity = new UserSettingsEntity(); const newEntity = new UserSettingsEntity();
if (entity) { if (entity) {
newEntity.id = entity.id; newEntity.id = entity.id;
@@ -123,6 +129,7 @@ export class UserSettingsService extends BaseService<UserSettingsEntity> {
newEntity.key = key; newEntity.key = key;
newEntity.title = type.__title__; newEntity.title = type.__title__;
newEntity.userId = userId; newEntity.userId = userId;
newEntity.projectId = projectId;
} }
newEntity.setting = JSON.stringify(bean); newEntity.setting = JSON.stringify(bean);
await this.repository.save(newEntity); await this.repository.save(newEntity);
@@ -17,6 +17,9 @@ export class SubDomainEntity {
@Column({ name: 'disabled', comment: '禁用' }) @Column({ name: 'disabled', comment: '禁用' })
disabled: boolean; disabled: boolean;
@Column({ name: 'project_id', comment: '项目Id' })
projectId: number;
@Column({ @Column({
name: 'create_time', name: 'create_time',
comment: '创建时间', comment: '创建时间',
@@ -3,22 +3,24 @@ import {NotificationService} from "../notification-service.js";
export class NotificationGetter implements INotificationService { export class NotificationGetter implements INotificationService {
userId: number; userId: number;
projectId: number;
notificationService: NotificationService; notificationService: NotificationService;
constructor(userId: number, notificationService: NotificationService) { constructor(userId: number, projectId: number, notificationService: NotificationService) {
this.userId = userId; this.userId = userId;
this.projectId = projectId;
this.notificationService = notificationService; this.notificationService = notificationService;
} }
async getDefault() { async getDefault() {
return await this.notificationService.getDefault(this.userId); return await this.notificationService.getDefault(this.userId, this.projectId);
} }
async getById(id: any) { async getById(id: any) {
return await this.notificationService.getById(id, this.userId); return await this.notificationService.getById(id, this.userId, this.projectId);
} }
async send(req: NotificationSendReq): Promise<void> { async send(req: NotificationSendReq): Promise<void> {
return await this.notificationService.send(req, this.userId); return await this.notificationService.send(req, this.userId, this.projectId);
} }
} }
@@ -15,9 +15,11 @@ const serviceNames = [
] ]
export class TaskServiceGetter implements IServiceGetter{ export class TaskServiceGetter implements IServiceGetter{
private userId: number; private userId: number;
private projectId: number;
private appCtx : IMidwayContainer; private appCtx : IMidwayContainer;
constructor(userId:number,appCtx:IMidwayContainer) { constructor(userId:number,projectId:number,appCtx:IMidwayContainer) {
this.userId = userId; this.userId = userId;
this.projectId = projectId;
this.appCtx = appCtx this.appCtx = appCtx
} }
async get<T>(serviceName: string): Promise<T> { async get<T>(serviceName: string): Promise<T> {
@@ -51,7 +53,7 @@ export class TaskServiceGetter implements IServiceGetter{
async getAccessService(): Promise<AccessGetter> { async getAccessService(): Promise<AccessGetter> {
const accessService:AccessService = await this.appCtx.getAsync("accessService") const accessService:AccessService = await this.appCtx.getAsync("accessService")
return new AccessGetter(this.userId, accessService.getById.bind(accessService)); return new AccessGetter(this.userId, this.projectId, accessService.getById.bind(accessService));
} }
@@ -62,7 +64,7 @@ export class TaskServiceGetter implements IServiceGetter{
async getNotificationService(): Promise<NotificationGetter> { async getNotificationService(): Promise<NotificationGetter> {
const notificationService:NotificationService = await this.appCtx.getAsync("notificationService") const notificationService:NotificationService = await this.appCtx.getAsync("notificationService")
return new NotificationGetter(this.userId, notificationService); return new NotificationGetter(this.userId, this.projectId, notificationService);
} }
async getDomainVerifierGetter(): Promise<DomainVerifierGetter> { async getDomainVerifierGetter(): Promise<DomainVerifierGetter> {
@@ -78,12 +80,14 @@ export class TaskServiceBuilder {
create(req:TaskServiceCreateReq){ create(req:TaskServiceCreateReq){
const userId = req.userId; const userId = req.userId;
return new TaskServiceGetter(userId,this.appCtx) const projectId = req.projectId;
return new TaskServiceGetter(userId,projectId,this.appCtx)
} }
} }
export type TaskServiceCreateReq = { export type TaskServiceCreateReq = {
userId: number; userId: number;
projectId?: number;
} }
@@ -84,7 +84,7 @@ export class NotificationService extends BaseService<NotificationEntity> {
} }
} }
async getById(id: number, userId: number): Promise<NotificationInstanceConfig> { async getById(id: number, userId: number, projectId?: number): Promise<NotificationInstanceConfig> {
if (!id) { if (!id) {
throw new ValidateException('id不能为空'); throw new ValidateException('id不能为空');
} }
@@ -95,6 +95,7 @@ export class NotificationService extends BaseService<NotificationEntity> {
where: { where: {
id, id,
userId, userId,
projectId,
}, },
}); });
if (!res) { if (!res) {
@@ -114,10 +115,11 @@ export class NotificationService extends BaseService<NotificationEntity> {
}; };
} }
async getDefault(userId: number): Promise<NotificationInstanceConfig> { async getDefault(userId: number, projectId?: number): Promise<NotificationInstanceConfig> {
const res = await this.repository.findOne({ const res = await this.repository.findOne({
where: { where: {
userId, userId,
projectId,
}, },
order: { order: {
isDefault: 'DESC', isDefault: 'DESC',
@@ -129,7 +131,7 @@ export class NotificationService extends BaseService<NotificationEntity> {
return this.buildNotificationInstanceConfig(res); return this.buildNotificationInstanceConfig(res);
} }
async setDefault(id: number, userId: number) { async setDefault(id: number, userId: number, projectId?: number) {
if (!id) { if (!id) {
throw new ValidateException('id不能为空'); throw new ValidateException('id不能为空');
} }
@@ -139,6 +141,7 @@ export class NotificationService extends BaseService<NotificationEntity> {
await this.repository.update( await this.repository.update(
{ {
userId, userId,
projectId,
}, },
{ {
isDefault: false, isDefault: false,
@@ -148,6 +151,7 @@ export class NotificationService extends BaseService<NotificationEntity> {
{ {
id, id,
userId, userId,
projectId,
}, },
{ {
isDefault: true, isDefault: true,
@@ -155,8 +159,8 @@ export class NotificationService extends BaseService<NotificationEntity> {
); );
} }
async getOrCreateDefault(email: string, userId: any) { async getOrCreateDefault(email: string, userId: any, projectId?: number) {
const defaultConfig = await this.getDefault(userId); const defaultConfig = await this.getDefault(userId, projectId);
if (defaultConfig) { if (defaultConfig) {
return defaultConfig; return defaultConfig;
} }
@@ -169,21 +173,22 @@ export class NotificationService extends BaseService<NotificationEntity> {
name: '邮件通知', name: '邮件通知',
setting: JSON.stringify(setting), setting: JSON.stringify(setting),
isDefault: true, isDefault: true,
projectId,
}); });
return this.buildNotificationInstanceConfig(res); return this.buildNotificationInstanceConfig(res);
} }
async send(req: NotificationSendReq, userId?: number) { async send(req: NotificationSendReq, userId?: number, projectId?: number) {
const logger = req.logger; const logger = req.logger;
let notifyConfig: NotificationInstanceConfig = null; let notifyConfig: NotificationInstanceConfig = null;
if (req.id && req.id > 0) { if (req.id && req.id > 0) {
notifyConfig = await this.getById(req.id, userId); notifyConfig = await this.getById(req.id, userId, projectId);
if (!notifyConfig) { if (!notifyConfig) {
logger.warn(`未找到通知配置<${req.id}>,请确认是否已被删除`); logger.warn(`未找到通知配置<${req.id}>,请确认是否已被删除`);
} }
} }
if (!notifyConfig) { if (!notifyConfig) {
notifyConfig = await this.getDefault(userId); notifyConfig = await this.getDefault(userId, projectId);
if (!notifyConfig) { if (!notifyConfig) {
logger.warn(`未找到默认通知配置`); logger.warn(`未找到默认通知配置`);
} }