fix(auth): change password issue of basic auth (#2662)

This commit is contained in:
YANG QIA 2023-09-16 13:55:29 +08:00 committed by GitHub
parent ccc238d0d3
commit 3b4cff15b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 140 additions and 5 deletions

View File

@ -26,7 +26,7 @@ const useSaveCurrentUserValues = () => {
return { return {
async run() { async run() {
await form.submit(); await form.submit();
await api.resource('users').changePassword({ await api.resource('auth').changePassword({
values: form.values, values: form.values,
}); });
await form.reset(); await form.reset();

View File

@ -713,4 +713,36 @@ describe('resourcer', () => {
expect(context.arr).toEqual([2, 9, 10, 3]); expect(context.arr).toEqual([2, 9, 10, 3]);
}); });
it('add action', async () => {
const resourcer = new Resourcer();
resourcer.define({
name: 'test',
middleware: require('./middlewares/demo1'),
actions: {
list: {
handler: require('./actions/demo1'),
},
},
});
resourcer.getResource('test').addAction('new', async function (ctx, next) {
ctx.arr.push(100);
await next();
ctx.arr.push(101);
});
const context = {
arr: [],
};
await resourcer.execute(
{
resource: 'test',
action: 'new',
},
context,
);
expect(context.arr).toEqual([2, 100, 101, 3]);
});
}); });

View File

@ -1,7 +1,7 @@
import _ from 'lodash'; import _ from 'lodash';
import Action, { ActionName, ActionType } from './action'; import Action, { ActionName, ActionType } from './action';
import Middleware, { MiddlewareType } from './middleware'; import Middleware, { MiddlewareType } from './middleware';
import { Resourcer } from './resourcer'; import { HandlerType, Resourcer } from './resourcer';
export type ResourceType = 'single' | 'hasOne' | 'hasMany' | 'belongsTo' | 'belongsToMany'; export type ResourceType = 'single' | 'hasOne' | 'hasMany' | 'belongsTo' | 'belongsToMany';
@ -88,6 +88,20 @@ export class Resource {
return this.except; return this.except;
} }
addAction(name: ActionName, handler: HandlerType) {
if (this.except.includes(name)) {
throw new Error(`${name} action is not allowed`);
}
if (this.actions.has(name)) {
throw new Error(`${name} action already exists`);
}
const action = new Action(handler);
action.setName(name);
action.setResource(this);
action.middlewares.unshift(...this.middlewares);
this.actions.set(name, action);
}
getAction(action: ActionName) { getAction(action: ActionName) {
if (this.except.includes(action)) { if (this.except.includes(action)) {
throw new Error(`${action} action is not allowed`); throw new Error(`${action} action is not allowed`);

View File

@ -168,5 +168,36 @@ describe('actions', () => {
const token = data.token; const token = data.token;
expect(token).toBeDefined(); expect(token).toBeDefined();
}); });
it('should change password', async () => {
// Create a user without email
const userRepo = db.getRepository('users');
const user = await userRepo.create({
values: {
username: 'test',
password: '12345',
},
});
const res = await agent.login(user).post('/auth:changePassword').set({ 'X-Authenticator': 'basic' }).send({
oldPassword: '12345',
newPassword: '123456',
confirmPassword: '123456',
});
expect(res.statusCode).toEqual(200);
// Create a user without username
const user1 = await userRepo.create({
values: {
username: 'test2',
password: '12345',
},
});
const res2 = await agent.login(user1).post('/auth:changePassword').set({ 'X-Authenticator': 'basic' }).send({
oldPassword: '12345',
newPassword: '123456',
confirmPassword: '123456',
});
expect(res2.statusCode).toEqual(200);
});
}); });
}); });

View File

@ -124,9 +124,15 @@ export class BasicAuth extends BaseAuth {
if (!currentUser) { if (!currentUser) {
ctx.throw(401); ctx.throw(401);
} }
let key: string;
if (currentUser.username) {
key = 'username';
} else {
key = 'email';
}
const user = await this.userRepository.findOne({ const user = await this.userRepository.findOne({
where: { where: {
email: currentUser.email, [key]: currentUser[key],
}, },
}); });
const pwd = this.userCollection.getField<PasswordField>('password'); const pwd = this.userCollection.getField<PasswordField>('password');

View File

@ -50,8 +50,8 @@ export class AuthPlugin extends Plugin {
title: 'Password', title: 'Password',
}); });
// Register actions // Register actions
Object.entries(authActions).forEach(([action, handler]) => Object.entries(authActions).forEach(
this.app.resourcer.registerAction(`auth:${action}`, handler), ([action, handler]) => this.app.resourcer.getResource('auth')?.addAction(action, handler),
); );
Object.entries(authenticatorsActions).forEach(([action, handler]) => Object.entries(authenticatorsActions).forEach(([action, handler]) =>
this.app.resourcer.registerAction(`authenticators:${action}`, handler), this.app.resourcer.registerAction(`authenticators:${action}`, handler),

View File

@ -318,6 +318,58 @@ export default {
}, },
}, },
}, },
'/auth:changePassword': {
post: {
description: 'Change password',
tags: ['Basic auth'],
security: [],
requestBody: {
content: {
'application/json': {
schema: {
type: 'object',
properties: {
oldPassword: {
type: 'string',
description: '旧密码',
},
newPassword: {
type: 'string',
description: '新密码',
},
confirmPassword: {
type: 'string',
description: '确认密码',
},
},
},
},
},
},
responses: {
200: {
description: 'ok',
content: {
'application/json': {
schema: {
$ref: '#/components/schemas/user',
},
},
},
},
401: {
description: 'Unauthorized',
content: {
'application/json': {
schema: {
$ref: '#/components/schemas/error',
},
},
},
},
},
},
},
'authenticators:listTypes': { 'authenticators:listTypes': {
get: { get: {
description: 'List authenticator types', description: 'List authenticator types',