@plumier/jwt
Advanced tools
Comparing version 1.0.0-beta.3 to 1.0.0-beta.4
@@ -1,2 +0,2 @@ | ||
import { ActionResult, Facility, Invocation, Middleware, PlumierApplication } from "@plumier/core"; | ||
import { ActionResult, AuthorizeMetadataInfo, Facility, Invocation, Middleware, PlumierApplication } from "@plumier/core"; | ||
import { ParameterReflection, PropertyReflection } from "tinspector"; | ||
@@ -9,4 +9,4 @@ export declare type RoleField = string | ((value: any) => Promise<string[]>); | ||
} | ||
export declare function checkParameter(path: string[], meta: PropertyReflection | ParameterReflection, value: any, userRole: string[]): string[]; | ||
export declare function checkParameters(path: string[], meta: (PropertyReflection | ParameterReflection)[], value: any[], userRole: string[]): string[]; | ||
export declare function checkParameter(path: string[], meta: PropertyReflection | ParameterReflection, value: any, info: AuthorizeMetadataInfo): Promise<string[]>; | ||
export declare function checkParameters(path: string[], meta: (PropertyReflection | ParameterReflection)[], value: any[], info: AuthorizeMetadataInfo): Promise<string[]>; | ||
export declare class JwtAuthFacility implements Facility { | ||
@@ -13,0 +13,0 @@ private option; |
@@ -11,5 +11,5 @@ "use strict"; | ||
function isAuthDecorator(decorator) { | ||
return decorator.type === "authorize:role" || decorator.type === "authorize:public"; | ||
return decorator.type === "plumier-meta:authorize"; | ||
} | ||
function getGlobalDecorator(globalDecorator) { | ||
function getGlobalDecorators(globalDecorator) { | ||
if (globalDecorator) { | ||
@@ -22,12 +22,17 @@ let DummyClass = class DummyClass { | ||
const meta = tinspector_1.reflect(DummyClass); | ||
const auth = meta.decorators.find((x) => isAuthDecorator(x)); | ||
return auth; | ||
return meta.decorators.filter((x) => isAuthDecorator(x)); | ||
} | ||
else | ||
return []; | ||
} | ||
function getDecorator(info, globalDecorator) { | ||
return info.action.decorators.find((x) => isAuthDecorator(x)) || | ||
info.controller.decorators.find((x) => isAuthDecorator(x)) || | ||
getGlobalDecorator(globalDecorator); | ||
function getAuthorizeDecorators(info, globalDecorator) { | ||
const actionDecs = info.action.decorators.filter((x) => isAuthDecorator(x)); | ||
if (actionDecs.length > 0) | ||
return actionDecs; | ||
const controllerDecs = info.controller.decorators.filter((x) => isAuthDecorator(x)); | ||
if (controllerDecs.length > 0) | ||
return controllerDecs; | ||
return getGlobalDecorators(globalDecorator); | ||
} | ||
function checkParameter(path, meta, value, userRole) { | ||
async function checkParameter(path, meta, value, info) { | ||
if (value === undefined) | ||
@@ -37,4 +42,8 @@ return []; | ||
const newMeta = Object.assign({}, meta, { type: meta.type[0] }); | ||
return value.map((x, i) => checkParameter(path.concat(i.toString()), newMeta, x, userRole)) | ||
.flatten(); | ||
const result = []; | ||
for (let i = 0; i < value.length; i++) { | ||
const val = value[i]; | ||
result.push(...await checkParameter(path.concat(i.toString()), newMeta, val, info)); | ||
} | ||
return result; | ||
} | ||
@@ -44,17 +53,20 @@ else if (core_1.isCustomClass(meta.type)) { | ||
const values = classMeta.properties.map(x => value[x.name]); | ||
return checkParameters(path, classMeta.properties, values, userRole); | ||
return checkParameters(path, classMeta.properties, values, info); | ||
} | ||
else { | ||
const requestRoles = meta.decorators.find((x) => isAuthDecorator(x)); | ||
if (requestRoles && !userRole.some(x => requestRoles.value.some(y => y === x))) | ||
return [path.join(".")]; | ||
const decorators = meta.decorators.filter((x) => isAuthDecorator(x)); | ||
const result = []; | ||
for (const dec of decorators) { | ||
if (!await dec.authorize(Object.assign({}, info, { value }))) | ||
result.push(path.join(".")); | ||
} | ||
return result; | ||
} | ||
return []; | ||
} | ||
exports.checkParameter = checkParameter; | ||
function checkParameters(path, meta, value, userRole) { | ||
async function checkParameters(path, meta, value, info) { | ||
const result = []; | ||
for (let i = 0; i < meta.length; i++) { | ||
const prop = meta[i]; | ||
const issues = checkParameter(path.concat(prop.name), prop, value[i], userRole); | ||
const issues = await checkParameter(path.concat(prop.name), prop, value[i], info); | ||
result.push(...issues); | ||
@@ -93,17 +105,15 @@ } | ||
} | ||
checkUserAccessToRoute(userRoles, decorator) { | ||
//if the access is public | ||
if (decorator && decorator.type === "authorize:public") | ||
async checkUserAccessToRoute(decorators, info) { | ||
if (decorators.some(x => x.tag === "Public")) | ||
return; | ||
//if user not login (all user must have role) | ||
else if (userRoles.length === 0) | ||
throw new core_1.HttpStatusError(403, "Forbidden"); | ||
//if no decorator specific (secured) or decorator match with user role | ||
else if (!decorator || userRoles.some(x => decorator.value.some(y => x === y))) | ||
return; | ||
else | ||
throw new core_1.HttpStatusError(401, "Unauthorized"); | ||
if (info.role.length === 0) | ||
throw new core_1.HttpStatusError(core_1.HttpStatus.Forbidden, "Forbidden"); | ||
const conditions = await Promise.all(decorators.map(x => x.authorize(info))); | ||
//use OR condition | ||
//if ALL condition doesn't authorize user then throw | ||
if (conditions.length > 0 && conditions.every(x => x === false)) | ||
throw new core_1.HttpStatusError(core_1.HttpStatus.Unauthorized, "Lorem ipsum dolor"); | ||
} | ||
checkUserAccessToParameters(meta, values, roles) { | ||
const unauthorizedPaths = checkParameters([], meta, values, roles); | ||
async checkUserAccessToParameters(meta, values, info) { | ||
const unauthorizedPaths = await checkParameters([], meta, values, info); | ||
if (unauthorizedPaths.length > 0) | ||
@@ -115,8 +125,10 @@ throw new core_1.HttpStatusError(401, `Unauthorized to populate parameter paths (${unauthorizedPaths.join(", ")})`); | ||
return invocation.proceed(); | ||
const decorator = getDecorator(invocation.context.route, this.global); | ||
const { route, parameters, state } = invocation.context; | ||
const decorator = getAuthorizeDecorators(invocation.context.route, this.global); | ||
const userRoles = await this.getRole(invocation.context.state.user); | ||
const info = { role: userRoles, parameters, user: state.user, route, ctx: invocation.context }; | ||
//check user access | ||
this.checkUserAccessToRoute(userRoles, decorator); | ||
await this.checkUserAccessToRoute(decorator, info); | ||
//if ok check parameter access | ||
this.checkUserAccessToParameters(invocation.context.route.action.parameters, invocation.context.parameters, userRoles); | ||
await this.checkUserAccessToParameters(invocation.context.route.action.parameters, invocation.context.parameters, info); | ||
//if all above passed then proceed | ||
@@ -123,0 +135,0 @@ return invocation.proceed(); |
{ | ||
"name": "@plumier/jwt", | ||
"version": "1.0.0-beta.3", | ||
"version": "1.0.0-beta.4", | ||
"description": "Plumier authorization module using JWT", | ||
@@ -13,3 +13,3 @@ "main": "lib/index.js", | ||
"dependencies": { | ||
"@plumier/core": "1.0.0-beta.3", | ||
"@plumier/core": "1.0.0-beta.4", | ||
"koa-jwt": "^3.5.1", | ||
@@ -25,3 +25,3 @@ "tslib": "^1.9.3" | ||
}, | ||
"gitHead": "ce2b47b0e9ca50f330741125a90c54b55661c1ad" | ||
"gitHead": "803ec103d9b72a40e53e806182228676a03bb0ce" | ||
} |
8602
156
+ Added@plumier/core@1.0.0-beta.4(transitive)
- Removed@plumier/core@1.0.0-beta.3(transitive)
Updated@plumier/core@1.0.0-beta.4