chore: stash

This commit is contained in:
Zeke Zhang 2025-04-01 10:14:37 +08:00
parent a1748e1da1
commit 69423adafa
4 changed files with 107 additions and 6 deletions

View File

@ -0,0 +1,42 @@
/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { parsedValue } from "../parsedValue";
describe('parsedValue', () => {
it('should correctly parse simple templates', () => {
const value = '{{name}} is {{age}} years old';
const variables = { name: 'Zhang San', age: 18 };
expect(parsedValue(value, variables)).toBe('Zhang San is 18 years old');
});
it('should correctly parse that the template has just one variable', () => {
const value = '{{name}}';
const variables = { name: 'Zhang San' };
expect(parsedValue(value, variables)).toBe('Zhang San');
});
it('should handle nested objects', () => {
const value = "{{user.name}}'s email is {{user.email}}";
const variables = { user: { name: 'Li Si', email: 'lisi@example.com' } };
expect(parsedValue(value, variables)).toBe("Li Si's email is lisi@example.com");
});
it('should handle arrays', () => {
const value = '{{fruits.0}} and {{fruits.1}}';
const variables = { fruits: ['apple', 'banana'] };
expect(parsedValue(value, variables)).toBe('apple and banana');
});
it('should handle undefined variables', () => {
const value = '{{name}} and {{undefinedVar}}';
const variables = { name: 'Wang Wu' };
expect(parsedValue(value, variables)).toBe('Wang Wu and ');
});
});

View File

@ -39,4 +39,5 @@ export * from './url';
export * from './i18n';
export * from './wrap-middleware';
export * from './object-to-cli-args';
export * from './parsedValue';
export { Schema } from '@formily/json-schema';

View File

@ -0,0 +1,22 @@
import { parse } from "./json-templates";
function appendArrayColumn(scope, key) {
const paths = key.split('.');
let data = scope;
for (let p = 0; p < paths.length && data != null; p++) {
const path = paths[p];
const isIndex = path.match(/^\d+$/);
if (Array.isArray(data) && !isIndex && !data[path]) {
data[path] = data.map((item) => item[path]).flat();
}
data = data?.[path];
}
}
export const parsedValue = (value, variables) => {
const template = parse(value);
template.parameters.forEach(({ key }) => {
appendArrayColumn(variables, key);
});
return template(variables);
};

View File

@ -9,9 +9,9 @@
import { AuthConfig, BaseAuth } from '@nocobase/auth';
import { PasswordField } from '@nocobase/database';
import crypto from 'crypto';
import { namespace } from '../preset';
import _ from 'lodash';
import { namespace } from '../preset';
import { getDateVars, parsedValue } from '@nocobase/utils';
export class BasicAuth extends BaseAuth {
constructor(config: AuthConfig) {
@ -33,8 +33,8 @@ export class BasicAuth extends BaseAuth {
const filter = email
? { email }
: {
$or: [{ username: account }, { email: account }],
};
$or: [{ username: account }, { email: account }],
};
const user = await this.userRepository.findOne({
filter,
});
@ -139,19 +139,55 @@ export class BasicAuth extends BaseAuth {
const {
values: { email },
} = ctx.action.params;
if (!email) {
ctx.throw(400, ctx.t('Please fill in your email address', { ns: namespace }));
}
const user = await this.userRepository.findOne({
where: {
email,
},
});
if (!user) {
ctx.throw(401, ctx.t('The email is incorrect, please re-enter', { ns: namespace }));
}
user.resetToken = crypto.randomBytes(20).toString('hex');
await user.save();
// 通过用户认证的接口获取邮件渠道、主题、内容等
const { emailChannel, subject, contentType, content, expiresIn } = this.getEmailConfig();
// 生成重置密码的 token
const resetToken = await ctx.app.authManager.jwt.sign({
resetPasswordUserId: user.id,
}, {
expiresIn, // 配置的过期时间
});
// 通过通知管理插件发送邮件
const notificationManager = ctx.app.getPlugin('notification-manager');
if (notificationManager) {
const emailer = notificationManager.getChannel(emailChannel);
if (emailer) {
await emailer.send({
to: email,
subject,
content: parsedValue(content, {
$user: user,
$resetLink: `${ctx.request.protocol}://${ctx.request.host}/reset-password?token=${resetToken}`,
$date: getDateVars(),
$env: ctx.app.environment.getVariables(),
}),
});
} else {
ctx.throw(400, ctx.t('Email channel not found', { ns: namespace }));
}
} else {
ctx.throw(500, ctx.t('Notification manager plugin not found', { ns: namespace }));
}
ctx.logger.info(`Password reset email sent to ${email}`);
return user;
}