4077-login_recover-password & account_verifyEmail #1063

Merged
alexm merged 52 commits from 4077-login_recover-password into dev 2022-11-28 11:34:03 +00:00
9 changed files with 78 additions and 12 deletions
Showing only changes of commit c79f884526 - Show all commits

View File

@ -20,6 +20,7 @@ module.exports = Self => {
Self.recoverPassword = async function(ctx, email) { Self.recoverPassword = async function(ctx, email) {
const models = Self.app.models; const models = Self.app.models;
const origin = ctx.req.headers.origin; const origin = ctx.req.headers.origin;
const $t = ctx.req.__; // $translate
const ttl = 1209600; const ttl = 1209600;
const user = await models.Account.findOne({ const user = await models.Account.findOne({
@ -37,7 +38,13 @@ module.exports = Self => {
userId: user.id userId: user.id
}); });
return await Self.rawSql(`CALL vn.mail_insert(?,?,?,?)`, await Self.rawSql(`CALL vn.mail_insert(?,?,?,?)`, [
[email, null, 'Recovery Password', `${origin}/#!/account/${user.id}/basic-data?access_token=${token.id}`]); email,
null,
$t('Recovery password'),
`${origin}/#!/account/${user.id}/basic-data?access_token=${token.id}`
]);
return;
}; };
}; };

View File

@ -0,0 +1,36 @@
const models = require('vn-loopback/server/server').models;
describe('account recoverPassword()', () => {
const ctx = {
req: {
headers: {origin: 'http://localhost:5000'}
}
};
ctx.req.__ = value => {
return value;
};
it('should throw an error when email does not belong to a user', async() => {
let error;
try {
await models.Account.recoverPassword(ctx, 'thor@mydomain.com');
} catch (e) {
error = e;
}
expect(error.message).toEqual('This email does not belong to a user');
});
it('should update password when it passes requirements', async() => {
const user = await models.Account.findById(1107);
await models.Account.recoverPassword(ctx, user.email);
const [result] = await models.AccessToken.find({
where: {
userId: user.id
}
});
expect(result).toBeDefined();
});
});

View File

@ -1,6 +1,6 @@
const app = require('vn-loopback/server/server'); const app = require('vn-loopback/server/server');
describe('account changePassword()', () => { describe('account setPassword()', () => {
it('should throw an error when password does not meet requirements', async() => { it('should throw an error when password does not meet requirements', async() => {
let req = app.models.Account.setPassword(1, 'insecurePass'); let req = app.models.Account.setPassword(1, 'insecurePass');

View File

@ -27,14 +27,15 @@ export default class Auth {
to: state => !state.name.includes('login') to: state => !state.name.includes('login')
}; };
this.vnToken.set(this.$location.$$search.access_token, false); if (this.$location.$$search.access_token)
console.log(this.$location.$$search.access_token, false); this.vnToken.set(this.$location.$$search.access_token, false);
this.$transitions.onStart(criteria, transition => { this.$transitions.onStart(criteria, transition => {
if (this.loggedIn) if (this.loggedIn)
return true; return true;
let redirectToLogin = () => { let redirectToLogin = () => {
// return transition.router.stateService.target('login'); return transition.router.stateService.target('login');
}; };
if (this.vnToken.token || this) { if (this.vnToken.token || this) {
@ -63,7 +64,6 @@ export default class Auth {
} }
onLoginOk(json, remember) { onLoginOk(json, remember) {
console.log(json.data.token);
this.vnToken.set(json.data.token, remember); this.vnToken.set(json.data.token, remember);
return this.loadAcls().then(() => { return this.loadAcls().then(() => {
@ -84,7 +84,7 @@ export default class Auth {
this.loggedIn = false; this.loggedIn = false;
this.vnModules.reset(); this.vnModules.reset();
this.aclService.reset(); this.aclService.reset();
// this.$state.go('login'); this.$state.go('login');
return promise; return promise;
} }

View File

@ -11,7 +11,6 @@ function interceptor($q, vnApp, vnToken, $translate) {
}, },
request(config) { request(config) {
vnApp.pushLoader(); vnApp.pushLoader();
console.log(vnToken.token);
if (config.url.charAt(0) !== '/' && apiPath) if (config.url.charAt(0) !== '/' && apiPath)
config.url = `${apiPath}${config.url}`; config.url = `${apiPath}${config.url}`;
if (vnToken.token) if (vnToken.token)

View File

@ -115,7 +115,7 @@ function $exceptionHandler(vnApp, $window, $state, $injector) {
if (!$state.current.name.includes('login')) { if (!$state.current.name.includes('login')) {
messageT = 'Session has expired'; messageT = 'Session has expired';
let params = {continue: $window.location.hash}; let params = {continue: $window.location.hash};
// $state.go('login', params); $state.go('login', params);
} else } else
messageT = 'Invalid login'; messageT = 'Invalid login';
break; break;

View File

@ -233,5 +233,6 @@
"Descanso diario 12h.": "Descanso diario 12h.", "Descanso diario 12h.": "Descanso diario 12h.",
"Descanso semanal 36h. / 72h.": "Descanso semanal 36h. / 72h.", "Descanso semanal 36h. / 72h.": "Descanso semanal 36h. / 72h.",
"Dirección incorrecta": "Dirección incorrecta", "Dirección incorrecta": "Dirección incorrecta",
"This email does not belong to a user": "This email does not belong to a user" "This email does not belong to a user": "Este correo electrónico no pertenece a un usuario.",
} "Recovery password": "Recuperar contraseña"
}

View File

@ -3,6 +3,11 @@ import Descriptor from 'salix/components/descriptor';
import UserError from 'core/lib/user-error'; import UserError from 'core/lib/user-error';
class Controller extends Descriptor { class Controller extends Descriptor {
constructor($element, $scope, $location) {
super($element, $scope);
this.$location = $location;
}
get user() { get user() {
return this.entity; return this.entity;
} }
@ -24,6 +29,11 @@ class Controller extends Descriptor {
.then(res => this.hasAccount = res.data.exists); .then(res => this.hasAccount = res.data.exists);
} }
$onInit() {
if (this.$location.$$search.access_token)
this.onChangePassClick(false);
}
onDelete() { onDelete() {
return this.$http.delete(`Accounts/${this.id}`) return this.$http.delete(`Accounts/${this.id}`)
.then(() => this.$state.go('account.index')) .then(() => this.$state.go('account.index'))
@ -114,6 +124,8 @@ class Controller extends Descriptor {
} }
} }
Controller.$inject = ['$element', '$scope', '$location'];
ngModule.component('vnUserDescriptor', { ngModule.component('vnUserDescriptor', {
template: require('./index.html'), template: require('./index.html'),
controller: Controller, controller: Controller,

View File

@ -105,4 +105,15 @@ describe('component vnUserDescriptor', () => {
expect(controller.emit).toHaveBeenCalledWith('change'); expect(controller.emit).toHaveBeenCalledWith('change');
}); });
}); });
describe('onInit()', () => {
it('should open onChangePassClick popup', () => {
controller.$location = {$$search: {access_token: 'RANDOM_TOKEN'}};
jest.spyOn(controller, 'onChangePassClick');
controller.$onInit();
expect(controller.onChangePassClick).toHaveBeenCalled();
});
});
}); });