6067-vnUser_privileges_and_verifyEmail #1764

Merged
alexm merged 15 commits from 6067-vnUser_privileges_and_verifyEmail into dev 2023-10-19 12:13:20 +00:00
8 changed files with 43 additions and 22 deletions
Showing only changes of commit 4545a63214 - Show all commits

View File

@ -32,10 +32,8 @@ module.exports = Self => {
} }
}); });
Self.updateUser = async(ctx, id) => { Self.updateUser = async(ctx, id, name, nickname, email, lang) => {
await Self.userSecurity(ctx, id); await Self.userSecurity(ctx, id);
const user = await Self.app.models.VnUser.findById(id, await Self.upsertWithWhere({id}, {name, nickname, email, lang});
{fields: ['id', 'name', 'nickname', 'email', 'lang', 'password']});
await user.updateAttributes(ctx.args);
}; };
alexm marked this conversation as resolved
Review

En lugar de hacer findById y luego updateAttributes, utilizar upsert.

En lugar de hacer `findById` y luego `updateAttributes`, utilizar `upsert`.
}; };
alexm marked this conversation as resolved
Review

En lugar de utilizar ctx.args listar parámetros en la definición de la función y pasarlos todos excepto el id.

En lugar de utilizar `ctx.args` listar parámetros en la definición de la función y pasarlos todos excepto el `id`.

View File

@ -1,4 +1,5 @@
const models = require('vn-loopback/server/server').models; const models = require('vn-loopback/server/server').models;
const ForbiddenError = require('vn-loopback/util/forbiddenError');
describe('loopback model VnUser', () => { describe('loopback model VnUser', () => {
it('should return true if the user has the given role', async() => { it('should return true if the user has the given role', async() => {
@ -46,7 +47,7 @@ describe('loopback model VnUser', () => {
} catch (error) { } catch (error) {
await tx.rollback(); await tx.rollback();
expect(error.message).toEqual(`You don't have enough privileges`); expect(error).toEqual(new ForbiddenError());
} }
}); });
}); });

View File

@ -1,7 +1,7 @@
const vnModel = require('vn-loopback/common/models/vn-model'); const vnModel = require('vn-loopback/common/models/vn-model');
const LoopBackContext = require('loopback-context'); const LoopBackContext = require('loopback-context');
const {Email} = require('vn-print'); const {Email} = require('vn-print');
const UserError = require('vn-loopback/util/user-error'); const ForbiddenError = require('vn-loopback/util/forbiddenError');
module.exports = function(Self) { module.exports = function(Self) {
vnModel(Self); vnModel(Self);
@ -198,11 +198,12 @@ module.exports = function(Self) {
const user = await models.VnUser.findById(userId, {fields: ['id', 'emailVerified']}, myOptions); const user = await models.VnUser.findById(userId, {fields: ['id', 'emailVerified']}, myOptions);
if (!user.emailVerified && hasMediumPrivileges) return; if (!user.emailVerified && hasMediumPrivileges) return;
throw new UserError(`You don't have enough privileges`); throw new ForbiddenError();
alexm marked this conversation as resolved Outdated
Outdated
Review

En lugar de lanzar UserError lanzar ForbiddenError.

En lugar de lanzar `UserError` lanzar `ForbiddenError`.
}; };
Self.observe('after save', async ctx => { Self.observe('after save', async ctx => {
const newEmail = ctx?.instance?.email; const instance = ctx?.instance;
const newEmail = instance?.email;
const oldEmail = ctx?.hookState?.oldInstance?.email; const oldEmail = ctx?.hookState?.oldInstance?.email;
alexm marked this conversation as resolved
Review

Sobre isNewInstance.
Mirar la nota https://redmine.verdnatura.es/issues/5761#note-8

Sobre isNewInstance. Mirar la nota https://redmine.verdnatura.es/issues/5761#note-8
if (!ctx.isNewInstance && (!newEmail || !oldEmail || newEmail == oldEmail)) return; if (!ctx.isNewInstance && (!newEmail || !oldEmail || newEmail == oldEmail)) return;
@ -213,6 +214,21 @@ module.exports = function(Self) {
const origin = headers.origin; const origin = headers.origin;
const url = origin.split(':'); const url = origin.split(':');
const env = process.env.NODE_ENV;
const liliumUrl = await Self.app.models.Url.findOne({
where: {and: [
{appName: 'lilium'},
{environment: env}
]}
});
const hederaUrl = await Self.app.models.Url.findOne({
where: {and: [
{appName: 'hedera'},
{environment: env}
]}
});
const isWorker = instance.isWorker || await Self.app.models.Account.findById(instance.id, null, ctx.options);
class Mailer { class Mailer {
async send(verifyOptions, cb) { async send(verifyOptions, cb) {
const params = { const params = {
alexm marked this conversation as resolved Outdated
Outdated
Review

Redirigir a un (nuevo) subestado verifyEmail del login de Lilium donde, en función de si el usuario tiene account, mostrar "Ir a la tienda" o "Iniciar sesión".

Redirigir a un (nuevo) subestado `verifyEmail` del login de Lilium donde, en función de si el usuario tiene account, mostrar "Ir a la tienda" o "Iniciar sesión".
@ -226,12 +242,11 @@ module.exports = function(Self) {
cb(null, verifyOptions.to); cb(null, verifyOptions.to);
} }
} }
const options = { const options = {
type: 'email', type: 'email',
to: newEmail, to: newEmail,
from: {}, from: {},
redirect: `${origin}/#!/account/${ctx.instance.id}/basic-data?emailConfirmed`, redirect: `${liliumUrl.url}verifyEmail?isWorker=${!!isWorker}&url=${hederaUrl.url}`,
template: false, template: false,
mailer: new Mailer, mailer: new Mailer,
host: url[1].split('/')[2], host: url[1].split('/')[2],
@ -240,6 +255,6 @@ module.exports = function(Self) {
user: Self user: Self
}; };
await ctx.instance.verify(options, ctx.options); await instance.verify(options, ctx.options);
}); });
}; };

View File

@ -0,0 +1,4 @@
INSERT INTO `salix`.`url` (`appName`, `environment`, `url`)
VALUES
('hedera', 'test', 'https://test-shop.verdnatura.es/'),
('hedera', 'production', 'https://shop.verdnatura.es/');

View File

@ -2869,6 +2869,7 @@ INSERT INTO `vn`.`profileType` (`id`, `name`)
INSERT INTO `salix`.`url` (`appName`, `environment`, `url`) INSERT INTO `salix`.`url` (`appName`, `environment`, `url`)
VALUES VALUES
('lilium', 'development', 'http://localhost:9000/#/'), ('lilium', 'development', 'http://localhost:9000/#/'),
('hedera', 'development', 'http://localhost:9090/'),
('salix', 'development', 'http://localhost:5000/#!/'); ('salix', 'development', 'http://localhost:5000/#!/');
INSERT INTO `vn`.`report` (`id`, `name`, `paperSizeFk`, `method`) INSERT INTO `vn`.`report` (`id`, `name`, `paperSizeFk`, `method`)

View File

@ -1,10 +0,0 @@
module.exports = Self => {
Self.observe('before save', async ctx => {
const instance = ctx.currentInstance || ctx.instance;
await Self.app.models.VnUser.userSecurity(ctx, instance.account);
});
Self.observe('before delete', async ctx => {
await Self.app.models.VnUser.userSecurity(ctx, ctx.where.account);
});
};

View File

@ -21,5 +21,16 @@
"model": "VnUser", "model": "VnUser",
"foreignKey": "account" "foreignKey": "account"
} }
} },
"acls": [{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW"
}, {
"accessType": "WRITE",
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW"
}]
} }

View File

@ -155,6 +155,7 @@ module.exports = Self => {
password: randomPassword.password, password: randomPassword.password,
email: args.email, email: args.email,
roleFk: workerConfig.roleFk, roleFk: workerConfig.roleFk,
isWorker: true // to verifyEmail
alexm marked this conversation as resolved Outdated
Outdated
Review

Aço ho he tingut que ficar pq no hi ha forma de si el crees saber que es un treballador no...
Se me ha ocurrit ficarli un paremetre mes que no es gasta per res mes, pero no me acaba la solució.

Tb se podria ficar en el ctx.options algo com isNewWorker o algo

Aço ho he tingut que ficar pq no hi ha forma de si el crees saber que es un treballador no... Se me ha ocurrit ficarli un paremetre mes que no es gasta per res mes, pero no me acaba la solució. Tb se podria ficar en el ctx.options algo com isNewWorker o algo
}, },
myOptions myOptions
); );