mirror of
https://github.com/laurent22/joplin.git
synced 2025-04-04 21:35:03 +02:00
Server: Allow sending reset password email from admin UI
This commit is contained in:
parent
6ae0e84a1a
commit
479237d16f
packages/server/src
@ -225,16 +225,19 @@ export default class UserModel extends BaseModel<User> {
|
|||||||
await this.save({ id: user.id, email_confirmed: 1 });
|
await this.save({ id: user.id, email_confirmed: 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
// public async saveWithAccountType(accountType:AccountType, user: User, options: SaveOptions = {}): Promise<User> {
|
public async sendAccountConfirmationEmail(user: User) {
|
||||||
// if (accountType !== AccountType.Default) {
|
const validationToken = await this.models().token().generate(user.id);
|
||||||
// user = {
|
const confirmUrl = encodeURI(this.confirmUrl(user.id, validationToken));
|
||||||
// ...user,
|
|
||||||
// ...accountTypeProperties(accountType),
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return this.save(user, options);
|
await this.models().email().push({
|
||||||
// }
|
sender_id: EmailSender.NoReply,
|
||||||
|
recipient_id: user.id,
|
||||||
|
recipient_email: user.email,
|
||||||
|
recipient_name: user.full_name || '',
|
||||||
|
subject: `Please setup your ${this.appName} account`,
|
||||||
|
body: `Your new ${this.appName} account is almost ready to use!\n\nPlease click on the following link to finish setting up your account:\n\n[Complete your account](${confirmUrl})`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Note that when the "password" property is provided, it is going to be
|
// Note that when the "password" property is provided, it is going to be
|
||||||
// hashed automatically. It means that it is not safe to do:
|
// hashed automatically. It means that it is not safe to do:
|
||||||
@ -254,17 +257,7 @@ export default class UserModel extends BaseModel<User> {
|
|||||||
const savedUser = await super.save(user, options);
|
const savedUser = await super.save(user, options);
|
||||||
|
|
||||||
if (isNew) {
|
if (isNew) {
|
||||||
const validationToken = await this.models().token().generate(savedUser.id);
|
await this.sendAccountConfirmationEmail(savedUser);
|
||||||
const confirmUrl = encodeURI(this.confirmUrl(savedUser.id, validationToken));
|
|
||||||
|
|
||||||
await this.models().email().push({
|
|
||||||
sender_id: EmailSender.NoReply,
|
|
||||||
recipient_id: savedUser.id,
|
|
||||||
recipient_email: savedUser.email,
|
|
||||||
recipient_name: savedUser.full_name || '',
|
|
||||||
subject: `Please setup your ${this.appName} account`,
|
|
||||||
body: `Your new ${this.appName} account has been created!\n\nPlease click on the following link to complete the creation of your account:\n\n[Complete your account](${confirmUrl})`,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UserModel.eventEmitter.emit('created');
|
UserModel.eventEmitter.emit('created');
|
||||||
|
@ -4,7 +4,7 @@ import { RouteType } from '../../utils/types';
|
|||||||
import { AppContext, HttpMethod } from '../../utils/types';
|
import { AppContext, HttpMethod } from '../../utils/types';
|
||||||
import { bodyFields, formParse } from '../../utils/requestUtils';
|
import { bodyFields, formParse } from '../../utils/requestUtils';
|
||||||
import { ErrorForbidden, ErrorUnprocessableEntity } from '../../utils/errors';
|
import { ErrorForbidden, ErrorUnprocessableEntity } from '../../utils/errors';
|
||||||
import { User } from '../../db';
|
import { User, Uuid } from '../../db';
|
||||||
import config from '../../config';
|
import config from '../../config';
|
||||||
import { View } from '../../services/MustacheService';
|
import { View } from '../../services/MustacheService';
|
||||||
import defaultView from '../../utils/defaultView';
|
import defaultView from '../../utils/defaultView';
|
||||||
@ -200,13 +200,20 @@ router.post('users/:id/confirm', async (path: SubPath, ctx: AppContext) => {
|
|||||||
|
|
||||||
router.alias(HttpMethod.POST, 'users/:id', 'users');
|
router.alias(HttpMethod.POST, 'users/:id', 'users');
|
||||||
|
|
||||||
|
interface FormFields {
|
||||||
|
id: Uuid;
|
||||||
|
post_button: string;
|
||||||
|
delete_button: string;
|
||||||
|
send_reset_password_email: string;
|
||||||
|
}
|
||||||
|
|
||||||
router.post('users', async (path: SubPath, ctx: AppContext) => {
|
router.post('users', async (path: SubPath, ctx: AppContext) => {
|
||||||
let user: User = {};
|
let user: User = {};
|
||||||
const userId = userIsMe(path) ? ctx.owner.id : path.id;
|
const userId = userIsMe(path) ? ctx.owner.id : path.id;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const body = await formParse(ctx.req);
|
const body = await formParse(ctx.req);
|
||||||
const fields = body.fields;
|
const fields = body.fields as FormFields;
|
||||||
const isNew = userIsNew(path);
|
const isNew = userIsNew(path);
|
||||||
if (userIsMe(path)) fields.id = userId;
|
if (userIsMe(path)) fields.id = userId;
|
||||||
user = makeUser(isNew, fields);
|
user = makeUser(isNew, fields);
|
||||||
@ -226,6 +233,10 @@ router.post('users', async (path: SubPath, ctx: AppContext) => {
|
|||||||
const user = await userModel.load(path.id);
|
const user = await userModel.load(path.id);
|
||||||
await userModel.checkIfAllowed(ctx.owner, AclAction.Delete, user);
|
await userModel.checkIfAllowed(ctx.owner, AclAction.Delete, user);
|
||||||
await userModel.delete(path.id);
|
await userModel.delete(path.id);
|
||||||
|
} else if (fields.send_reset_password_email) {
|
||||||
|
const user = await userModel.load(path.id);
|
||||||
|
await userModel.save({ id: user.id, must_set_password: 1 });
|
||||||
|
await userModel.sendAccountConfirmationEmail(user);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Invalid form button');
|
throw new Error('Invalid form button');
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<input type="submit" name="post_button" class="button is-primary" value="{{buttonTitle}}" />
|
<input type="submit" name="post_button" class="button is-primary" value="{{buttonTitle}}" />
|
||||||
|
{{#global.owner.is_admin}}
|
||||||
|
<input type="submit" name="send_reset_password_email" class="button is-warning" value="Send reset password email" />
|
||||||
|
{{/global.owner.is_admin}}
|
||||||
{{#showDeleteButton}}
|
{{#showDeleteButton}}
|
||||||
<input type="submit" name="delete_button" class="button is-danger" value="Delete" />
|
<input type="submit" name="delete_button" class="button is-danger" value="Delete" />
|
||||||
{{/showDeleteButton}}
|
{{/showDeleteButton}}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user