mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
fix: welcome-email should not include password-link when disabled (#1302)
This commit is contained in:
parent
26f66c4f93
commit
1cad01b97e
@ -10,6 +10,9 @@ import ResetTokenService from '../../services/reset-token-service';
|
||||
import { IUnleashServices } from '../../types/services';
|
||||
import SessionService from '../../services/session-service';
|
||||
import { IAuthRequest } from '../unleash-types';
|
||||
import SettingService from '../../services/setting-service';
|
||||
import { SimpleAuthSettings } from '../../server-impl';
|
||||
import { simpleAuthKey } from '../../types/settings/simple-auth-settings';
|
||||
|
||||
interface ICreateUserBody {
|
||||
username: string;
|
||||
@ -32,6 +35,10 @@ export default class UserAdminController extends Controller {
|
||||
|
||||
private sessionService: SessionService;
|
||||
|
||||
private settingService: SettingService;
|
||||
|
||||
readonly unleashUrl: string;
|
||||
|
||||
constructor(
|
||||
config: IUnleashConfig,
|
||||
{
|
||||
@ -40,6 +47,7 @@ export default class UserAdminController extends Controller {
|
||||
emailService,
|
||||
resetTokenService,
|
||||
sessionService,
|
||||
settingService,
|
||||
}: Pick<
|
||||
IUnleashServices,
|
||||
| 'userService'
|
||||
@ -47,15 +55,18 @@ export default class UserAdminController extends Controller {
|
||||
| 'emailService'
|
||||
| 'resetTokenService'
|
||||
| 'sessionService'
|
||||
| 'settingService'
|
||||
>,
|
||||
) {
|
||||
super(config);
|
||||
this.userService = userService;
|
||||
this.accessService = accessService;
|
||||
this.emailService = emailService;
|
||||
this.logger = config.getLogger('routes/user-controller.ts');
|
||||
this.resetTokenService = resetTokenService;
|
||||
this.sessionService = sessionService;
|
||||
this.settingService = settingService;
|
||||
this.logger = config.getLogger('routes/user-controller.ts');
|
||||
this.unleashUrl = config.server.unleashUrl;
|
||||
|
||||
this.get('/', this.getUsers, ADMIN);
|
||||
this.get('/search', this.search);
|
||||
@ -69,8 +80,7 @@ export default class UserAdminController extends Controller {
|
||||
this.get('/active-sessions', this.getActiveSessions, ADMIN);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
async resetPassword(req, res): Promise<void> {
|
||||
async resetPassword(req: IAuthRequest, res: Response): Promise<void> {
|
||||
const { user } = req;
|
||||
const receiver = req.body.id;
|
||||
const resetPasswordUrl =
|
||||
@ -78,24 +88,17 @@ export default class UserAdminController extends Controller {
|
||||
res.json({ resetPasswordUrl });
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
async getUsers(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const users = await this.userService.getAll();
|
||||
const rootRoles = await this.accessService.getRootRoles();
|
||||
const inviteLinks =
|
||||
await this.resetTokenService.getActiveInvitations();
|
||||
const users = await this.userService.getAll();
|
||||
const rootRoles = await this.accessService.getRootRoles();
|
||||
const inviteLinks = await this.resetTokenService.getActiveInvitations();
|
||||
|
||||
const usersWithInviteLinks = users.map((user) => {
|
||||
const inviteLink = inviteLinks[user.id] || '';
|
||||
return { ...user, inviteLink };
|
||||
});
|
||||
const usersWithInviteLinks = users.map((user) => {
|
||||
const inviteLink = inviteLinks[user.id] || '';
|
||||
return { ...user, inviteLink };
|
||||
});
|
||||
|
||||
res.json({ users: usersWithInviteLinks, rootRoles });
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
res.status(500).send({ msg: 'server errors' });
|
||||
}
|
||||
res.json({ users: usersWithInviteLinks, rootRoles });
|
||||
}
|
||||
|
||||
async getActiveSessions(req: Request, res: Response): Promise<void> {
|
||||
@ -103,7 +106,6 @@ export default class UserAdminController extends Controller {
|
||||
res.json(sessions);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
async search(req: Request, res: Response): Promise<void> {
|
||||
const { q } = req.query as any;
|
||||
try {
|
||||
@ -122,7 +124,6 @@ export default class UserAdminController extends Controller {
|
||||
res.json(user);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
async createUser(
|
||||
req: IAuthRequest<any, any, ICreateUserBody, any>,
|
||||
res: Response,
|
||||
@ -140,10 +141,20 @@ export default class UserAdminController extends Controller {
|
||||
},
|
||||
user,
|
||||
);
|
||||
const inviteLink = await this.resetTokenService.createNewUserUrl(
|
||||
createdUser.id,
|
||||
user.email,
|
||||
);
|
||||
|
||||
const passwordAuthSettings =
|
||||
await this.settingService.get<SimpleAuthSettings>(
|
||||
simpleAuthKey,
|
||||
);
|
||||
|
||||
let inviteLink: string;
|
||||
if (!passwordAuthSettings?.disabled) {
|
||||
const inviteUrl = await this.resetTokenService.createNewUserUrl(
|
||||
createdUser.id,
|
||||
user.email,
|
||||
);
|
||||
inviteLink = inviteUrl.toString();
|
||||
}
|
||||
|
||||
let emailSent = false;
|
||||
const emailConfigured = this.emailService.configured();
|
||||
@ -154,7 +165,8 @@ export default class UserAdminController extends Controller {
|
||||
await this.emailService.sendGettingStartedMail(
|
||||
createdUser.name,
|
||||
createdUser.email,
|
||||
inviteLink.toString(),
|
||||
this.unleashUrl,
|
||||
inviteLink,
|
||||
);
|
||||
emailSent = true;
|
||||
} catch (e) {
|
||||
@ -171,7 +183,7 @@ export default class UserAdminController extends Controller {
|
||||
|
||||
res.status(201).send({
|
||||
...createdUser,
|
||||
inviteLink,
|
||||
inviteLink: inviteLink || this.unleashUrl,
|
||||
emailSent,
|
||||
rootRole,
|
||||
});
|
||||
@ -227,5 +239,3 @@ export default class UserAdminController extends Controller {
|
||||
res.status(200).send();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = UserAdminController;
|
||||
|
@ -1,27 +0,0 @@
|
||||
const Controller = require('../controller');
|
||||
|
||||
class PasswordProvider extends Controller {
|
||||
constructor(config, { userService }) {
|
||||
super(config);
|
||||
this.logger = config.getLogger('/auth/password-provider.js');
|
||||
this.userService = userService;
|
||||
|
||||
this.post('/login', this.login);
|
||||
}
|
||||
|
||||
async login(req, res) {
|
||||
const { username, password } = req.body;
|
||||
|
||||
if (!username || !password) {
|
||||
return res.status(400).json({
|
||||
message: 'You must provide username and password',
|
||||
});
|
||||
}
|
||||
|
||||
const user = await this.userService.loginUser(username, password);
|
||||
req.session.user = user;
|
||||
return res.status(200).json(user);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PasswordProvider;
|
@ -9,6 +9,7 @@ test('Should require password', async () => {
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
const userService = () => {};
|
||||
// @ts-ignore
|
||||
const ctr = new PasswordProvider({ getLogger }, { userService });
|
||||
|
||||
//@ts-ignore
|
||||
@ -41,6 +42,7 @@ test('Should login user', async () => {
|
||||
throw new Error('Wrong password');
|
||||
},
|
||||
};
|
||||
// @ts-ignore
|
||||
const ctr = new PasswordProvider({ getLogger }, { userService });
|
||||
|
||||
//@ts-ignore
|
||||
@ -74,6 +76,7 @@ test('Should not login user with wrong password', async () => {
|
||||
throw new PasswordMismatchError();
|
||||
},
|
||||
};
|
||||
// @ts-ignore
|
||||
const ctr = new PasswordProvider({ getLogger }, { userService });
|
||||
|
||||
//@ts-ignore
|
||||
|
42
src/lib/routes/auth/simple-password-provider.ts
Normal file
42
src/lib/routes/auth/simple-password-provider.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { Response } from 'express';
|
||||
import { Logger } from '../../logger';
|
||||
import { IUnleashConfig } from '../../server-impl';
|
||||
import UserService from '../../services/user-service';
|
||||
import { IUnleashServices } from '../../types';
|
||||
import { NONE } from '../../types/permissions';
|
||||
import Controller from '../controller';
|
||||
import { IAuthRequest } from '../unleash-types';
|
||||
|
||||
class PasswordProvider extends Controller {
|
||||
private userService: UserService;
|
||||
|
||||
private logger: Logger;
|
||||
|
||||
constructor(
|
||||
config: IUnleashConfig,
|
||||
{ userService }: Pick<IUnleashServices, 'userService'>,
|
||||
) {
|
||||
super(config);
|
||||
this.logger = config.getLogger('/auth/password-provider.js');
|
||||
this.userService = userService;
|
||||
|
||||
this.post('/login', this.login, NONE);
|
||||
}
|
||||
|
||||
async login(req: IAuthRequest, res: Response): Promise<void> {
|
||||
const { username, password } = req.body;
|
||||
|
||||
if (!username || !password) {
|
||||
res.status(400).json({
|
||||
message: 'You must provide username and password',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const user = await this.userService.loginUser(username, password);
|
||||
req.session.user = user;
|
||||
res.status(200).json(user);
|
||||
}
|
||||
}
|
||||
|
||||
export default PasswordProvider;
|
@ -1,6 +1,7 @@
|
||||
import { Request, Response } from 'express';
|
||||
import { BackstageController } from './backstage';
|
||||
import ResetPasswordController from './auth/reset-password-controller';
|
||||
import SimplePasswordProvider from './auth/simple-password-provider';
|
||||
import { IUnleashConfig } from '../types/option';
|
||||
import { IUnleashServices } from '../types/services';
|
||||
import { api } from './api-def';
|
||||
@ -10,7 +11,6 @@ const ClientApi = require('./client-api');
|
||||
const Controller = require('./controller');
|
||||
const HealthCheckController = require('./health-check');
|
||||
const LogoutController = require('./logout');
|
||||
const SimplePasswordProvider = require('./auth/simple-password-provider');
|
||||
|
||||
class IndexRouter extends Controller {
|
||||
constructor(config: IUnleashConfig, services: IUnleashServices) {
|
||||
|
@ -136,11 +136,12 @@ export class EmailService {
|
||||
async sendGettingStartedMail(
|
||||
name: string,
|
||||
recipient: string,
|
||||
passwordLink: string,
|
||||
unleashUrl: string,
|
||||
passwordLink?: string,
|
||||
): Promise<IEmailEnvelope> {
|
||||
if (this.configured()) {
|
||||
const year = new Date().getFullYear();
|
||||
const context = { passwordLink, name, year };
|
||||
const context = { passwordLink, name, year, unleashUrl };
|
||||
const bodyHtml = await this.compileTemplate(
|
||||
'getting-started',
|
||||
TemplateFormat.HTML,
|
||||
|
@ -484,10 +484,18 @@
|
||||
|
||||
<p>You have been invited to your organization's Unleash account - the new way of delivering software.</p>
|
||||
|
||||
{{# passwordLink }}
|
||||
<p>Below is your magic sign-in link. Just click the button and follow the steps provided to update your password and get started using Unleash.</p>
|
||||
|
||||
<br />
|
||||
<a class="resetPasswordLink" href="{{{ passwordLink }}}" target="_blank" rel="noopener noreferrer">Setup account<a/>
|
||||
{{/ passwordLink }}
|
||||
{{^ passwordLink }}
|
||||
<p>Use the link below to access your Unleash instance.</p>
|
||||
|
||||
<br />
|
||||
<a class="resetPasswordLink" href="{{{ unleashUrl }}}" target="_blank" rel="noopener noreferrer">Login<a/>
|
||||
{{/ passwordLink }}
|
||||
<br />
|
||||
<br />
|
||||
<p>By the way - did you know we have built Unleash on best practice when releasing new features. Our solution removes pressure from developers, allowing you to focus on delivering value through experimentation.</p>
|
||||
|
@ -2,9 +2,19 @@ Welcome to Unleash {{ name }}!
|
||||
|
||||
You have been invited to your organization's Unleash account - the new way of delivering software.
|
||||
|
||||
{{# passwordLink }}
|
||||
|
||||
Below is your magic sign-in link. Just click the button and follow the steps provided to update your password and get started using Unleash.
|
||||
|
||||
Visit {{{ passwordLink }}} to get started.
|
||||
{{/ passwordLink }}
|
||||
{{^ passwordLink }}
|
||||
|
||||
Use the link below to access your Unleash instance:
|
||||
|
||||
{{{ unleashUrl }}}
|
||||
|
||||
{{/ passwordLink }}
|
||||
|
||||
By the way - did you know we have built Unleash on best practice when releasing new features. Our solution removes pressure from developers, allowing you to focus on delivering value through experimentation.
|
||||
Looking forward to having a lot of fun together.
|
||||
|
Loading…
Reference in New Issue
Block a user