From f355b4e441f369eebd91e945268f092beb2185cf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 7 Nov 2025 16:33:31 +0000 Subject: [PATCH] Add user-scoped data filtering for env operations Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> --- back/api/env.ts | 28 +++++++++++++-------------- back/services/env.ts | 45 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 51 insertions(+), 22 deletions(-) diff --git a/back/api/env.ts b/back/api/env.ts index 845b5df5..51fdc631 100644 --- a/back/api/env.ts +++ b/back/api/env.ts @@ -26,7 +26,7 @@ export default (app: Router) => { const logger: Logger = Container.get('logger'); try { const envService = Container.get(EnvService); - const data = await envService.envs(req.query.searchValue as string); + const data = await envService.envs(req.query.searchValue as string, {}, req.user?.userId); return res.send({ code: 200, data }); } catch (e) { logger.error('🔥 error: %o', e); @@ -54,7 +54,7 @@ export default (app: Router) => { if (!req.body?.length) { return res.send({ code: 400, message: '参数不正确' }); } - const data = await envService.create(req.body); + const data = await envService.create(req.body, req.user?.userId); return res.send({ code: 200, data }); } catch (e) { return next(e); @@ -93,10 +93,10 @@ export default (app: Router) => { const logger: Logger = Container.get('logger'); try { const envService = Container.get(EnvService); - const data = await envService.remove(req.body); + const data = await envService.remove(req.body, req.user?.userId); return res.send({ code: 200, data }); - } catch (e) { - return next(e); + } catch (e: any) { + return res.send({ code: 400, message: e.message }); } }, ); @@ -132,10 +132,10 @@ export default (app: Router) => { const logger: Logger = Container.get('logger'); try { const envService = Container.get(EnvService); - const data = await envService.disabled(req.body); + const data = await envService.disabled(req.body, req.user?.userId); return res.send({ code: 200, data }); - } catch (e) { - return next(e); + } catch (e: any) { + return res.send({ code: 400, message: e.message }); } }, ); @@ -149,10 +149,10 @@ export default (app: Router) => { const logger: Logger = Container.get('logger'); try { const envService = Container.get(EnvService); - const data = await envService.enabled(req.body); + const data = await envService.enabled(req.body, req.user?.userId); return res.send({ code: 200, data }); - } catch (e) { - return next(e); + } catch (e: any) { + return res.send({ code: 400, message: e.message }); } }, ); @@ -169,10 +169,10 @@ export default (app: Router) => { const logger: Logger = Container.get('logger'); try { const envService = Container.get(EnvService); - const data = await envService.updateNames(req.body); + const data = await envService.updateNames(req.body, req.user?.userId); return res.send({ code: 200, data }); - } catch (e) { - return next(e); + } catch (e: any) { + return res.send({ code: 400, message: e.message }); } }, ); diff --git a/back/services/env.ts b/back/services/env.ts index be89cc86..ea5590ce 100644 --- a/back/services/env.ts +++ b/back/services/env.ts @@ -19,8 +19,32 @@ import { writeFileWithLock } from '../shared/utils'; export default class EnvService { constructor(@Inject('logger') private logger: winston.Logger) {} - public async create(payloads: Env[]): Promise { - const envs = await this.envs(); + private addUserIdFilter(query: any, userId?: number) { + if (userId !== undefined) { + query.userId = userId; + } + return query; + } + + private async checkOwnership(ids: number[], userId?: number): Promise { + if (userId === undefined) { + // Admin can access all envs + return; + } + const envs = await EnvModel.findAll({ + where: { id: ids }, + attributes: ['id', 'userId'], + }); + const unauthorized = envs.filter( + (env) => env.userId !== userId && env.userId !== undefined + ); + if (unauthorized.length > 0) { + throw new Error('无权限操作该环境变量'); + } + } + + public async create(payloads: Env[], userId?: number): Promise { + const envs = await this.envs('', {}, userId); let position = initPosition; if ( envs && @@ -31,7 +55,7 @@ export default class EnvService { } const tabs = payloads.map((x) => { position = position - stepPosition; - const tab = new Env({ ...x, position }); + const tab = new Env({ ...x, position, userId }); return tab; }); const docs = await this.insert(tabs); @@ -62,7 +86,8 @@ export default class EnvService { return await this.getDb({ id: payload.id }); } - public async remove(ids: number[]) { + public async remove(ids: number[], userId?: number) { + await this.checkOwnership(ids, userId); await EnvModel.destroy({ where: { id: ids } }); await this.set_envs(); } @@ -119,8 +144,9 @@ export default class EnvService { return parseFloat(position.toPrecision(16)); } - public async envs(searchText: string = '', query: any = {}): Promise { + public async envs(searchText: string = '', query: any = {}, userId?: number): Promise { let condition = { ...query }; + this.addUserIdFilter(condition, userId); if (searchText) { const encodeText = encodeURI(searchText); const reg = { @@ -172,7 +198,8 @@ export default class EnvService { return doc.get({ plain: true }); } - public async disabled(ids: number[]) { + public async disabled(ids: number[], userId?: number) { + await this.checkOwnership(ids, userId); await EnvModel.update( { status: EnvStatus.disabled }, { where: { id: ids } }, @@ -180,12 +207,14 @@ export default class EnvService { await this.set_envs(); } - public async enabled(ids: number[]) { + public async enabled(ids: number[], userId?: number) { + await this.checkOwnership(ids, userId); await EnvModel.update({ status: EnvStatus.normal }, { where: { id: ids } }); await this.set_envs(); } - public async updateNames({ ids, name }: { ids: number[]; name: string }) { + public async updateNames({ ids, name }: { ids: number[]; name: string }, userId?: number) { + await this.checkOwnership(ids, userId); await EnvModel.update({ name }, { where: { id: ids } }); await this.set_envs(); }