Skip to content

Commit e93a790

Browse files
committed
feat: opt param for auth.
1 parent eecea22 commit e93a790

File tree

7 files changed

+216
-64
lines changed

7 files changed

+216
-64
lines changed

lib/auth/BaseAuth.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ export abstract class BaseAuth extends Service {
1111

1212
export interface RoleMetaInfo {
1313
/** 需要参数名列表 */
14-
params: string[];
14+
params: { name: string, required: boolean }[];
1515
}
1616

1717
const infoSymbol = Symbol('InfoSymbol');
1818
export function getRoleInfo(roleType: typeof BaseAuth): RoleMetaInfo {
1919
const desc = Object.getOwnPropertyDescriptor(roleType, infoSymbol);
2020
if (!desc) {
2121
const info: RoleMetaInfo = {
22-
params: getParameterNames(roleType.prototype.has).map(name => name),
22+
params: getParameterNames(roleType.prototype.has).map(name => ({ name, required: true })),
2323
};
2424
Object.defineProperty(roleType, infoSymbol, {
2525
value: info,
@@ -28,3 +28,10 @@ export function getRoleInfo(roleType: typeof BaseAuth): RoleMetaInfo {
2828
}
2929
return desc.value;
3030
}
31+
32+
export function opt() {
33+
return (target, key, index): any => {
34+
const info = getRoleInfo(target.constructor);
35+
info.params[index].required = false;
36+
};
37+
}

lib/middleware/auth.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ export const authMiddleware = (app: Application, typeInfo: RouteType) => {
1919
(typeInfo.auth || [])
2020
.map(async permRole => {
2121
const params = getRoleInfo(permRole).params.map(p => {
22-
if (paramObj[p] === undefined) {
23-
throw new BadRequestError(`Permission [${permRole.name}] NEED Param [${p}]`);
22+
if (p.required && !(p.name in paramObj)) {
23+
throw new BadRequestError(`Permission [${permRole.name}] NEED Param [${p.name}]`);
2424
}
25-
return paramObj[p];
25+
return paramObj[p.name];
2626
});
2727
if (!(await getInstance<BaseAuth>(permRole, ctx.app, ctx).has(...params))) {
2828
throw new ForbiddenError(

lib/util.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import * as fs from 'fs';
22
import * as path from 'path';
33

4-
const generatorFuncPrototype = Object.getPrototypeOf(function*(): any {});
4+
const generatorFuncPrototype = Object.getPrototypeOf(function* (): any { });
55
export function isGeneratorFunction(fn: any) {
66
return typeof fn === 'function' && Object.getPrototypeOf(fn) === generatorFuncPrototype;
77
}
88

9-
const asyncFuncPrototype = Object.getPrototypeOf(async function() {});
9+
const asyncFuncPrototype = Object.getPrototypeOf(async function () { });
1010
export function isAsyncFunction(fn: any) {
1111
return typeof fn === 'function' && Object.getPrototypeOf(fn) === asyncFuncPrototype;
1212
}
@@ -60,6 +60,10 @@ const DEFAULT_PARAMS = /=[^,]*/gm;
6060
const FAT_ARROWS = /=>.*$/gm;
6161

6262
export function getParameterNames(fn: Function | string) {
63+
if (!fn) {
64+
console.warn('NO fn for getParameterNames!');
65+
return [];
66+
}
6367
let code = typeof fn === 'function' ? fn.toString() : fn;
6468

6569
let right = 0;

test/auth.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,22 @@ describe('auth', () => {
4444
.get('/auth/forbidden')
4545
.expect(403);
4646
});
47+
48+
it('opt param', () => {
49+
return request(app.callback())
50+
.get('/auth/opt')
51+
.expect(204);
52+
});
53+
54+
it('opt param ok', () => {
55+
return request(app.callback())
56+
.get('/auth/opt?id=opt')
57+
.expect(204);
58+
});
59+
60+
it('opt param fail', () => {
61+
return request(app.callback())
62+
.get('/auth/opt?id=fail')
63+
.expect(403);
64+
});
4765
});

test/fixtures/example/app/auth/default.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { BaseAuth } from '../../../../../lib';
22
import { ForbiddenError } from '../../../../../lib/error';
3+
import { opt } from '../../../../../lib/auth/BaseAuth';
34

45
export class DefaultAuth extends BaseAuth {
56
async has(): Promise<boolean> {
@@ -18,3 +19,9 @@ export class ForbiddenAuth extends BaseAuth {
1819
throw new ForbiddenError();
1920
}
2021
}
22+
23+
export class OptParamAuth extends BaseAuth {
24+
async has(@opt() id: string): Promise<boolean> {
25+
return !id || id === 'opt';
26+
}
27+
}
Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
import { Controller } from 'egg';
22
import { route, controller } from '../../../../../lib';
3-
import { DefaultAuth, ForbiddenAuth, NeedParamAuth } from '../auth/default';
3+
import { DefaultAuth, ForbiddenAuth, NeedParamAuth, OptParamAuth } from '../auth/default';
44

55
@controller({ prefix: '/auth' })
66
export class AuthController extends Controller {
77
@route({ auth: [DefaultAuth] })
8-
default() {}
8+
default() { }
99

1010
@route({ auth: [NeedParamAuth] })
11-
needParam() {}
11+
needParam() { }
1212

1313
@route({ auth: [NeedParamAuth] })
14-
needParamOk(id: string) {}
14+
needParamOk(id: string) { }
1515

1616
@route({ auth: [ForbiddenAuth] })
17-
forbidden() {}
17+
forbidden() { }
18+
19+
@route({ auth: [OptParamAuth] })
20+
opt(id?: string) { }
1821
}

0 commit comments

Comments
 (0)