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
10 changed files with 113 additions and 34 deletions
Showing only changes of commit fcf46ade7d - Show all commits

View File

@ -1,26 +1,20 @@
const path = require('path'); const LoopBackContext = require('loopback-context');
const {Email} = require('vn-print');
module.exports = function(Self) { module.exports = function(Self) {
function getUrl() {
return Self.app.get('rootUrl') || app.get('url');
}
function getFrom() {
return Self.dataSources.email.settings.transports[0].auth.from;
}
Self.on('resetPasswordRequest', async function(info) { Self.on('resetPasswordRequest', async function(info) {
const renderer = loopback.template(path.resolve(__dirname, '../../views/reset-password.ejs')); const loopBackContext = LoopBackContext.getCurrentContext();
const html = renderer({ const httpCtx = {req: loopBackContext.active};
url: `${getUrl()}#/reset-password?access_token=${info.accessToken.id}` const httpRequest = httpCtx.req.http.req;
}); const headers = httpRequest.headers;
const origin = headers.origin;
await app.models.Email.send({ const params = {
to: info.email, url: `${origin}/#!/login/reset-password?access_token=${info.accessToken.id}`
from: getFrom(), };
subject: 'Password reset',
html const sendEmail = new Email('recover-password', params);
});
console.log('> Sending password reset email to:', info.email); return sendEmail.send();
}); });
}; };

View File

@ -7,7 +7,7 @@ import UserError from 'core/lib/user-error';
* @property {Boolean} loggedIn Whether the user is currently logged * @property {Boolean} loggedIn Whether the user is currently logged
*/ */
export default class Auth { export default class Auth {
constructor($http, $q, $state, $transitions, $window, vnToken, vnModules, aclService, $location) { constructor($http, $q, $state, $transitions, $window, vnToken, vnModules, aclService) {
Object.assign(this, { Object.assign(this, {
$http, $http,
$q, $q,
@ -17,8 +17,7 @@ export default class Auth {
vnToken, vnToken,
vnModules, vnModules,
aclService, aclService,
loggedIn: false, loggedIn: false
$location
}); });
} }
@ -26,10 +25,6 @@ export default class Auth {
let criteria = { let criteria = {
to: state => !state.name.includes('login') to: state => !state.name.includes('login')
}; };
if (this.$location.$$search.access_token)
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;
@ -103,6 +98,6 @@ export default class Auth {
}); });
} }
} }
Auth.$inject = ['$http', '$q', '$state', '$transitions', '$window', 'vnToken', 'vnModules', 'aclService', '$location']; Auth.$inject = ['$http', '$q', '$state', '$transitions', '$window', 'vnToken', 'vnModules', 'aclService'];
ngModule.service('vnAuth', Auth); ngModule.service('vnAuth', Auth);

View File

@ -3,11 +3,15 @@
</vn-layout> </vn-layout>
<ui-view <ui-view
name="login" name="login"
ng-if="!$ctrl.showLayout && !$ctrl.isRecover"> ng-if="!$ctrl.showLayout && !$ctrl.isRecover && !$ctrl.isRecover2">
</ui-view> </ui-view>
<ui-view <ui-view
name="recover-password" name="recover-password"
ng-if="!$ctrl.showLayout && $ctrl.isRecover"> ng-if="!$ctrl.showLayout && $ctrl.isRecover">
</ui-view> </ui-view>
<ui-view
name="reset-password"
ng-if="!$ctrl.showLayout && $ctrl.isReset">
</ui-view>
<vn-snackbar vn-id="snackbar"></vn-snackbar> <vn-snackbar vn-id="snackbar"></vn-snackbar>
<vn-debug-info></vn-debug-info> <vn-debug-info></vn-debug-info>

View File

@ -15,12 +15,15 @@ export default class App extends Component {
get showLayout() { get showLayout() {
let state = this.$state.current.name; let state = this.$state.current.name;
return state && state != 'login' && !this.isRecover; return state && state != 'login' && !this.isRecover && !this.isReset;
} }
get isRecover() { get isRecover() {
let state = this.$state.current.name; return this.$state.current.name == 'login.recover-password';
return state == 'login.recover-password'; }
get isReset() {
return this.$state.current.name == 'login.reset-password';
} }
$onDestroy() { $onDestroy() {

View File

@ -7,6 +7,7 @@ import './layout';
import './left-menu/left-menu'; import './left-menu/left-menu';
import './login/login'; import './login/login';
import './login/recover-password'; import './login/recover-password';
import './login/reset-password';
import './module-card'; import './module-card';
import './module-main'; import './module-main';
import './side-menu/side-menu'; import './side-menu/side-menu';

View File

@ -18,7 +18,7 @@ export default class Controller {
email: this.email email: this.email
}; };
this.$http.post('Accounts/recoverPassword', params) this.$http.post('users/reset', params)
.then(() => { .then(() => {
this.vnApp.showSuccess(this.$translate.instant('Notification sent!')); this.vnApp.showSuccess(this.$translate.instant('Notification sent!'));
this.$state.go('login'); this.$state.go('login');

View File

@ -0,0 +1,23 @@
<div class="box">
<form name="form" ng-submit="$ctrl.submit()">
<h5 class="vn-mb-lg" translate>Reset password</h5>
<vn-textfield
label="New password"
ng-model="$ctrl.newPassword"
type="password"
info="{{'Password requirements' | translate:$ctrl.passRequirements}}"
vn-focus>
</vn-textfield>
<vn-textfield
label="Repeat password"
ng-model="$ctrl.repeatPassword"
type="password">
</vn-textfield>
<div class="footer">
<vn-submit label="Change password"></vn-submit>
<div class="spinner-wrapper">
<vn-spinner enable="$ctrl.loading"></vn-spinner>
</div>
</div>
</form>
</div>

View File

@ -0,0 +1,53 @@
import ngModule from '../../module';
import './style.scss';
const axios = require('axios');
alexm marked this conversation as resolved
Review

Perque gastes axios y no el servei $http?

Perque gastes axios y no el servei $http?
export default class Controller {
constructor($scope, $element, $http, vnApp, $translate, $state, $location) {
Object.assign(this, {
$scope,
$element,
$http,
vnApp,
$translate,
$state,
$location
});
}
$onInit() {
const headers = {
Authorization: this.$location.$$search.access_token
};
axios.post('api/UserPasswords/findOne', null, {headers})
.then(res => {
this.passRequirements = res.data;
});
}
submit() {
if (!this.newPassword)
throw new UserError(`You must enter a new password`);
if (this.newPassword != this.repeatPassword)
throw new UserError(`Passwords don't match`);
const headers = {
Authorization: this.$location.$$search.access_token
};
const newPassword = this.newPassword;
axios.post('api/users/reset-password', {newPassword}, {headers})
.then(() => {
this.vnApp.showSuccess(this.$translate.instant('Password changed!'));
this.$state.go('login');
});
}
}
Controller.$inject = ['$scope', '$element', '$http', 'vnApp', '$translate', '$state', '$location'];
ngModule.vnComponent('vnResetPassword', {
template: require('./reset-password.html'),
controller: Controller
});

View File

@ -1,6 +1,7 @@
@import "variables"; @import "variables";
vn-login, vn-login,
vn-reset-password,
vn-recover-password{ vn-recover-password{
position: absolute; position: absolute;
height: 100%; height: 100%;

View File

@ -11,13 +11,18 @@ function config($stateProvider, $urlRouterProvider) {
description: 'Login', description: 'Login',
views: { views: {
'login': {template: '<vn-login></vn-login>'}, 'login': {template: '<vn-login></vn-login>'},
'recover-password': {template: '<vn-recover-password></vn-recover-password>'} 'recover-password': {template: '<vn-recover-password></vn-recover-password>'},
'reset-password': {template: '<vn-reset-password></vn-reset-password>'}
} }
}) })
.state('login.recover-password', { .state('login.recover-password', {
url: '/recover-password', url: '/recover-password',
description: 'Recover-password' description: 'Recover-password'
}) })
.state('login.reset-password', {
url: '/reset-password',
description: 'Reset-password'
})
.state('home', { .state('home', {
url: '/', url: '/',
description: 'Home', description: 'Home',