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) {
const models = Self.app.models;
const origin = ctx.req.headers.origin;
const $t = ctx.req.__; // $translate
const ttl = 1209600;
const user = await models.Account.findOne({
@ -37,7 +38,13 @@ module.exports = Self => {
userId: user.id
});
return await Self.rawSql(`CALL vn.mail_insert(?,?,?,?)`,
[email, null, 'Recovery Password', `${origin}/#!/account/${user.id}/basic-data?access_token=${token.id}`]);
await Self.rawSql(`CALL vn.mail_insert(?,?,?,?)`, [
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');
describe('account changePassword()', () => {
describe('account setPassword()', () => {
it('should throw an error when password does not meet requirements', async() => {
let req = app.models.Account.setPassword(1, 'insecurePass');

View File

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

View File

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

View File

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

View File

@ -233,5 +233,6 @@
"Descanso diario 12h.": "Descanso diario 12h.",
"Descanso semanal 36h. / 72h.": "Descanso semanal 36h. / 72h.",
"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';
class Controller extends Descriptor {
constructor($element, $scope, $location) {
super($element, $scope);
this.$location = $location;
}
get user() {
return this.entity;
}
@ -24,6 +29,11 @@ class Controller extends Descriptor {
.then(res => this.hasAccount = res.data.exists);
}
$onInit() {
if (this.$location.$$search.access_token)
this.onChangePassClick(false);
}
onDelete() {
return this.$http.delete(`Accounts/${this.id}`)
.then(() => this.$state.go('account.index'))
@ -114,6 +124,8 @@ class Controller extends Descriptor {
}
}
Controller.$inject = ['$element', '$scope', '$location'];
ngModule.component('vnUserDescriptor', {
template: require('./index.html'),
controller: Controller,

View File

@ -105,4 +105,15 @@ describe('component vnUserDescriptor', () => {
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();
});
});
});