refactor(resourcer): combine middleware class (#825)

* refactor(resourcer): combine middleware class

* refactor(resourcer): move new middleware to plugin instance
This commit is contained in:
Junyi 2022-09-13 23:27:19 +08:00 committed by GitHub
parent b92f3b3b95
commit 1a9cd78eb8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 30 additions and 50 deletions

View File

@ -12,6 +12,7 @@
}
],
"dependencies": {
"@nocobase/utils": "0.7.4-alpha.7",
"deepmerge": "^4.2.2",
"koa-compose": "^4.1.0",
"lodash": "^4.17.21",

View File

@ -1,7 +1,7 @@
import _ from 'lodash';
import compose from 'koa-compose';
import { requireModule } from '@nocobase/utils';
import Resource from './resource';
import { requireModule } from './utils';
import { HandlerType } from './resourcer';
import Middleware, { MiddlewareType } from './middleware';
import { assign, MergeStrategies } from './assign';

View File

@ -1,7 +1,7 @@
import compose from 'koa-compose';
import { requireModule } from '@nocobase/utils';
import { ActionName } from './action';
import { HandlerType } from './resourcer';
import { requireModule } from './utils';
export type MiddlewareType = string | string[] | HandlerType | HandlerType[] | MiddlewareOptions | MiddlewareOptions[];
@ -23,6 +23,7 @@ export interface MiddlewareOptions {
export class Middleware {
protected options: MiddlewareOptions;
private middlewares: HandlerType[] = [];
constructor(options: MiddlewareOptions | Function) {
options = requireModule(options);
@ -38,7 +39,15 @@ export class Middleware {
if (typeof handler !== 'function') {
throw new Error('Handler must be a function!');
}
return handler;
return (ctx, next) => compose([handler, ...this.middlewares])(ctx, next);
}
use(middleware: HandlerType) {
this.middlewares.push(middleware);
}
disuse(middleware: HandlerType) {
this.middlewares.splice(this.middlewares.indexOf(middleware), 1);
}
canAccess(name: ActionName) {
@ -75,22 +84,6 @@ export class Middleware {
export default Middleware;
export class MiddlewareManager {
protected middlewares: HandlerType[] = [];
compose() {
return (ctx, next) => compose(this.middlewares)(ctx, next);
}
use(middleware: HandlerType) {
this.middlewares.push(middleware);
}
unuse(middleware: HandlerType) {
this.middlewares.splice(this.middlewares.indexOf(middleware), 1);
}
}
export function branch(
map: {
[key: string]: HandlerType;

View File

@ -2,9 +2,10 @@ import glob from 'glob';
import compose from 'koa-compose';
import _ from 'lodash';
import { pathToRegexp } from 'path-to-regexp';
import { requireModule } from '@nocobase/utils';
import Action, { ActionName } from './action';
import Resource, { ResourceOptions } from './resource';
import { getNameByParams, ParsedParams, parseQuery, parseRequest, requireModule } from './utils';
import { getNameByParams, ParsedParams, parseQuery, parseRequest } from './utils';
export interface ResourcerContext {
resourcer?: Resourcer;

View File

@ -183,16 +183,6 @@ export function parseRequest(request: ParseRequest, options: ParseOptions = {}):
return params;
}
export function requireModule(module: any) {
if (typeof module === 'string') {
module = require(module);
}
if (typeof module !== 'object') {
return module;
}
return module.__esModule ? module.default : module;
}
export function parseQuery(input: string): any {
// 自带 query 处理的不太给力,需要用 qs 转一下
const query = qs.parse(input, {

View File

@ -1,26 +1,21 @@
import { Context, Next } from '@nocobase/actions';
import { MiddlewareManager } from '@nocobase/resourcer';
import UsersPlugin from '../server';
export function parseToken(options?: { plugin: UsersPlugin }) {
const middleware = new MiddlewareManager();
middleware.use(async function (ctx: Context, next: Next) {
const user = await findUserByToken(ctx, options.plugin);
if (user) {
ctx.state.currentUser = user;
}
return next();
});
return middleware;
}
export async function parseToken(ctx: Context, next: Next) {
const user = await findUserByToken(ctx);
if (user) {
ctx.state.currentUser = user;
}
return next();
};
async function findUserByToken(ctx: Context, plugin: UsersPlugin) {
async function findUserByToken(ctx: Context) {
const token = ctx.getBearerToken();
if (!token) {
return null;
}
const { jwtService } = ctx.app.getPlugin('@nocobase/plugin-users');
try {
const { userId } = await plugin.jwtService.decode(token);
const { userId } = await jwtService.decode(token);
const collection = ctx.db.getCollection('users');
ctx.state.currentUserAppends = ctx.state.currentUserAppends || [];
for (const [, field] of collection.fields) {

View File

@ -4,13 +4,13 @@ import parse from 'json-templates';
import { Collection, Op } from '@nocobase/database';
import { Plugin } from '@nocobase/server';
import { Registry } from '@nocobase/utils';
import { HandlerType, MiddlewareManager } from '@nocobase/resourcer';
import { HandlerType, Middleware } from '@nocobase/resourcer';
import { namespace } from './';
import * as actions from './actions/users';
import { JwtOptions, JwtService } from './jwt-service';
import { enUS, zhCN } from './locale';
import * as middlewares from './middlewares';
import { parseToken } from './middlewares';
import initAuthenticators from './authenticators';
export interface UserPluginConfig {
@ -20,14 +20,14 @@ export interface UserPluginConfig {
export default class UsersPlugin extends Plugin<UserPluginConfig> {
public jwtService: JwtService;
public tokenMiddleware: MiddlewareManager;
public tokenMiddleware: Middleware;
public authenticators: Registry<HandlerType> = new Registry();
constructor(app, options) {
super(app, options);
this.jwtService = new JwtService(options?.jwt || {});
this.tokenMiddleware = middlewares.parseToken({ plugin: this });
this.tokenMiddleware = new Middleware(parseToken);
}
async beforeLoad() {
@ -92,7 +92,7 @@ export default class UsersPlugin extends Plugin<UserPluginConfig> {
this.app.resourcer.registerActionHandler(`users:${key}`, action);
}
this.app.resourcer.use(this.tokenMiddleware.compose());
this.app.resourcer.use(this.tokenMiddleware.getHandler());
const publicActions = ['check', 'signin', 'signup', 'lostpassword', 'resetpassword', 'getUserByResetToken'];
const loggedInActions = ['signout', 'updateProfile', 'changePassword'];