5488-use_checkAccessAcl #1482

Merged
alexm merged 32 commits from 5488-use_checkAccessAcl into dev 2023-05-29 05:20:29 +00:00
175 changed files with 6998 additions and 2739 deletions
Showing only changes of commit bde81e685f - Show all commits

View File

@ -8,13 +8,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [2316.01] - 2023-05-04 ## [2316.01] - 2023-05-04
### Added ### Added
-
### Changed
- -
### Changed
- (Artículo -> Precio fijado) Modificado el buscador superior por uno lateral
### Fixed ### Fixed
- -
## [2314.01] - 2023-04-20 ## [2314.01] - 2023-04-20

View File

@ -1,9 +1,9 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('campaign latest()', () => { describe('campaign latest()', () => {
it('should return the campaigns from the last year', async() => { it('should return the campaigns from the last year', async() => {
const now = Date.vnNew(); const now = Date.vnNew();
const result = await app.models.Campaign.latest(); const result = await models.Campaign.latest();
const randomIndex = Math.floor(Math.random() * result.length); const randomIndex = Math.floor(Math.random() * result.length);
const campaignDated = result[randomIndex].dated; const campaignDated = result[randomIndex].dated;
@ -14,7 +14,7 @@ describe('campaign latest()', () => {
it('should return the campaigns from the current year', async() => { it('should return the campaigns from the current year', async() => {
const now = Date.vnNew(); const now = Date.vnNew();
const currentYear = now.getFullYear(); const currentYear = now.getFullYear();
const result = await app.models.Campaign.latest({ const result = await models.Campaign.latest({
where: {dated: {like: `%${currentYear}%`}} where: {dated: {like: `%${currentYear}%`}}
}); });

View File

@ -1,8 +1,8 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
describe('campaign upcoming()', () => { describe('campaign upcoming()', () => {
it('should return the upcoming campaign but from the last year', async() => { it('should return the upcoming campaign but from the last year', async() => {
const response = await app.models.Campaign.upcoming(); const response = await models.Campaign.upcoming();
const campaignDated = response.dated; const campaignDated = response.dated;
const now = Date.vnNew(); const now = Date.vnNew();

View File

@ -26,7 +26,7 @@ module.exports = Self => {
Self.send = async(ctx, to, message) => { Self.send = async(ctx, to, message) => {
const models = Self.app.models; const models = Self.app.models;
const accessToken = ctx.req.accessToken; const accessToken = ctx.req.accessToken;
const sender = await models.Account.findById(accessToken.userId); const sender = await models.VnUser.findById(accessToken.userId);
const recipient = to.replace('@', ''); const recipient = to.replace('@', '');
if (sender.name != recipient) { if (sender.name != recipient) {

View File

@ -29,8 +29,8 @@ module.exports = Self => {
const models = Self.app.models; const models = Self.app.models;
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
const sender = await models.Account.findById(userId, {fields: ['id']}); const sender = await models.VnUser.findById(userId, {fields: ['id']});
const recipient = await models.Account.findById(recipientId, null); const recipient = await models.VnUser.findById(recipientId, null);
// Prevent sending messages to yourself // Prevent sending messages to yourself
if (recipientId == userId) return false; if (recipientId == userId) return false;

View File

@ -58,7 +58,7 @@ module.exports = Self => {
const models = Self.app.models; const models = Self.app.models;
const recipientName = chat.recipient.slice(1); const recipientName = chat.recipient.slice(1);
const recipient = await models.Account.findOne({ const recipient = await models.VnUser.findOne({
where: { where: {
name: recipientName name: recipientName
} }
@ -104,7 +104,7 @@ module.exports = Self => {
} }
const models = Self.app.models; const models = Self.app.models;
const sender = await models.Account.findById(senderFk); const sender = await models.VnUser.findById(senderFk);
const login = await Self.getServiceAuth(); const login = await Self.getServiceAuth();
const avatar = `${login.host}/avatar/${sender.name}`; const avatar = `${login.host}/avatar/${sender.name}`;

View File

@ -1,12 +1,12 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
describe('Chat notifyIssue()', () => { describe('Chat notifyIssue()', () => {
const ctx = {req: {accessToken: {userId: 1}}}; const ctx = {req: {accessToken: {userId: 1}}};
ctx.req.__ = value => { ctx.req.__ = value => {
return value; return value;
}; };
const chatModel = app.models.Chat; const chatModel = models.Chat;
const osTicketModel = app.models.OsTicket; const osTicketModel = models.OsTicket;
const departmentId = 31; const departmentId = 31;
it(`should not call to the send() method and neither return a response`, async() => { it(`should not call to the send() method and neither return a response`, async() => {
@ -29,7 +29,7 @@ describe('Chat notifyIssue()', () => {
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
const expectedMessage = `@all ➔ There's a new urgent ticket:\r\n[ID: 00001 - Issue title @batman](https://cau.verdnatura.es/scp/tickets.php?id=1)`; const expectedMessage = `@all ➔ There's a new urgent ticket:\r\n[ID: 00001 - Issue title @batman](https://cau.verdnatura.es/scp/tickets.php?id=1)`;
const department = await app.models.Department.findById(departmentId); const department = await models.Department.findById(departmentId);
let orgChatName = department.chatName; let orgChatName = department.chatName;
await department.updateAttribute('chatName', 'IT'); await department.updateAttribute('chatName', 'IT');

View File

@ -1,16 +1,16 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
describe('Chat send()', () => { describe('Chat send()', () => {
it('should return true as response', async() => { it('should return true as response', async() => {
let ctx = {req: {accessToken: {userId: 1}}}; let ctx = {req: {accessToken: {userId: 1}}};
let response = await app.models.Chat.send(ctx, '@salesPerson', 'I changed something'); let response = await models.Chat.send(ctx, '@salesPerson', 'I changed something');
expect(response).toEqual(true); expect(response).toEqual(true);
}); });
it('should return false as response', async() => { it('should return false as response', async() => {
let ctx = {req: {accessToken: {userId: 18}}}; let ctx = {req: {accessToken: {userId: 18}}};
let response = await app.models.Chat.send(ctx, '@salesPerson', 'I changed something'); let response = await models.Chat.send(ctx, '@salesPerson', 'I changed something');
expect(response).toEqual(false); expect(response).toEqual(false);
}); });

View File

@ -1,8 +1,8 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
describe('getSectors()', () => { describe('getSectors()', () => {
it('return list of sectors', async() => { it('return list of sectors', async() => {
let response = await app.models.Collection.getSectors(); let response = await models.Collection.getSectors();
expect(response.length).toBeGreaterThan(0); expect(response.length).toBeGreaterThan(0);
expect(response[0].id).toEqual(1); expect(response[0].id).toEqual(1);

View File

@ -1,10 +1,10 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
describe('newCollection()', () => { describe('newCollection()', () => {
it('should return a new collection', async() => { it('should return a new collection', async() => {
pending('#3400 analizar que hacer con rutas de back collection'); pending('#3400 analizar que hacer con rutas de back collection');
let ctx = {req: {accessToken: {userId: 1106}}}; let ctx = {req: {accessToken: {userId: 1106}}};
let response = await app.models.Collection.newCollection(ctx, 1, 1, 1); let response = await models.Collection.newCollection(ctx, 1, 1, 1);
expect(response.length).toBeGreaterThan(0); expect(response.length).toBeGreaterThan(0);
expect(response[0].ticketFk).toEqual(2); expect(response[0].ticketFk).toEqual(2);

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
describe('dms downloadFile()', () => { describe('dms downloadFile()', () => {
let dmsId = 1; let dmsId = 1;
@ -6,7 +6,7 @@ describe('dms downloadFile()', () => {
it('should return a response for an employee with text content-type', async() => { it('should return a response for an employee with text content-type', async() => {
let workerId = 1107; let workerId = 1107;
let ctx = {req: {accessToken: {userId: workerId}}}; let ctx = {req: {accessToken: {userId: workerId}}};
const result = await app.models.Dms.downloadFile(ctx, dmsId); const result = await models.Dms.downloadFile(ctx, dmsId);
expect(result[1]).toEqual('text/plain'); expect(result[1]).toEqual('text/plain');
}); });
@ -16,7 +16,7 @@ describe('dms downloadFile()', () => {
let ctx = {req: {accessToken: {userId: clientId}}}; let ctx = {req: {accessToken: {userId: clientId}}};
let error; let error;
await app.models.Dms.downloadFile(ctx, dmsId).catch(e => { await models.Dms.downloadFile(ctx, dmsId).catch(e => {
error = e; error = e;
}).finally(() => { }).finally(() => {
expect(error.message).toEqual(`You don't have enough privileges`); expect(error.message).toEqual(`You don't have enough privileges`);

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
describe('dms removeFile()', () => { describe('dms removeFile()', () => {
let dmsId = 1; let dmsId = 1;
@ -8,7 +8,7 @@ describe('dms removeFile()', () => {
let ctx = {req: {accessToken: {userId: clientId}}}; let ctx = {req: {accessToken: {userId: clientId}}};
let error; let error;
await app.models.Dms.removeFile(ctx, dmsId).catch(e => { await models.Dms.removeFile(ctx, dmsId).catch(e => {
error = e; error = e;
}).finally(() => { }).finally(() => {
expect(error.message).toEqual(`You don't have enough privileges`); expect(error.message).toEqual(`You don't have enough privileges`);

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
describe('dms updateFile()', () => { describe('dms updateFile()', () => {
it(`should return an error for a user without enough privileges`, async() => { it(`should return an error for a user without enough privileges`, async() => {
@ -11,7 +11,7 @@ describe('dms updateFile()', () => {
let ctx = {req: {accessToken: {userId: clientId}}, args: {dmsTypeId: dmsTypeId}}; let ctx = {req: {accessToken: {userId: clientId}}, args: {dmsTypeId: dmsTypeId}};
let error; let error;
await app.models.Dms.updateFile(ctx, dmsId, warehouseId, companyId, dmsTypeId).catch(e => { await models.Dms.updateFile(ctx, dmsId, warehouseId, companyId, dmsTypeId).catch(e => {
error = e; error = e;
}).finally(() => { }).finally(() => {
expect(error.message).toEqual(`You don't have enough privileges`); expect(error.message).toEqual(`You don't have enough privileges`);

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
describe('dms uploadFile()', () => { describe('dms uploadFile()', () => {
it(`should return an error for a user without enough privileges`, async() => { it(`should return an error for a user without enough privileges`, async() => {
@ -7,7 +7,7 @@ describe('dms uploadFile()', () => {
let ctx = {req: {accessToken: {userId: clientId}}, args: {dmsTypeId: ticketDmsTypeId}}; let ctx = {req: {accessToken: {userId: clientId}}, args: {dmsTypeId: ticketDmsTypeId}};
let error; let error;
await app.models.Dms.uploadFile(ctx).catch(e => { await models.Dms.uploadFile(ctx).catch(e => {
error = e; error = e;
}).finally(() => { }).finally(() => {
expect(error.message).toEqual(`You don't have enough privileges`); expect(error.message).toEqual(`You don't have enough privileges`);

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
describe('image download()', () => { describe('image download()', () => {
const collection = 'user'; const collection = 'user';
@ -8,7 +8,7 @@ describe('image download()', () => {
it('should return the image content-type of the user', async() => { it('should return the image content-type of the user', async() => {
const userId = 9; const userId = 9;
const image = await app.models.Image.download(ctx, collection, size, userId); const image = await models.Image.download(ctx, collection, size, userId);
const contentType = image[1]; const contentType = image[1];
expect(contentType).toEqual('image/png'); expect(contentType).toEqual('image/png');
@ -16,7 +16,7 @@ describe('image download()', () => {
it(`should return false if the user doesn't have image`, async() => { it(`should return false if the user doesn't have image`, async() => {
const userId = 1110; const userId = 1110;
const image = await app.models.Image.download(ctx, collection, size, userId); const image = await models.Image.download(ctx, collection, size, userId);
expect(image).toBeFalse(); expect(image).toBeFalse();
}); });

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
describe('image upload()', () => { describe('image upload()', () => {
describe('as buyer', () => { describe('as buyer', () => {
@ -16,7 +16,7 @@ describe('image upload()', () => {
let error; let error;
try { try {
await app.models.Image.upload(ctx); await models.Image.upload(ctx);
} catch (err) { } catch (err) {
error = err; error = err;
} }
@ -25,7 +25,7 @@ describe('image upload()', () => {
}); });
it('should call to the TempContainer upload method for the collection "catalog"', async() => { it('should call to the TempContainer upload method for the collection "catalog"', async() => {
const containerModel = app.models.TempContainer; const containerModel = models.TempContainer;
spyOn(containerModel, 'upload'); spyOn(containerModel, 'upload');
const ctx = {req: {accessToken: {userId: buyerId}}, const ctx = {req: {accessToken: {userId: buyerId}},
@ -36,7 +36,7 @@ describe('image upload()', () => {
}; };
try { try {
await app.models.Image.upload(ctx); await models.Image.upload(ctx);
} catch (err) { } } catch (err) { }
expect(containerModel.upload).toHaveBeenCalled(); expect(containerModel.upload).toHaveBeenCalled();
@ -49,7 +49,7 @@ describe('image upload()', () => {
const itemId = 4; const itemId = 4;
it('should be able to call to the TempContainer upload method for the collection "user"', async() => { it('should be able to call to the TempContainer upload method for the collection "user"', async() => {
const containerModel = app.models.TempContainer; const containerModel = models.TempContainer;
spyOn(containerModel, 'upload'); spyOn(containerModel, 'upload');
const ctx = {req: {accessToken: {userId: marketingId}}, const ctx = {req: {accessToken: {userId: marketingId}},
@ -60,14 +60,14 @@ describe('image upload()', () => {
}; };
try { try {
await app.models.Image.upload(ctx); await models.Image.upload(ctx);
} catch (err) { } } catch (err) { }
expect(containerModel.upload).toHaveBeenCalled(); expect(containerModel.upload).toHaveBeenCalled();
}); });
it('should be able to call to the TempContainer upload method for the collection "catalog"', async() => { it('should be able to call to the TempContainer upload method for the collection "catalog"', async() => {
const containerModel = app.models.TempContainer; const containerModel = models.TempContainer;
spyOn(containerModel, 'upload'); spyOn(containerModel, 'upload');
const ctx = {req: {accessToken: {userId: marketingId}}, const ctx = {req: {accessToken: {userId: marketingId}},
@ -78,7 +78,7 @@ describe('image upload()', () => {
}; };
try { try {
await app.models.Image.upload(ctx); await models.Image.upload(ctx);
} catch (err) { } } catch (err) { }
expect(containerModel.upload).toHaveBeenCalled(); expect(containerModel.upload).toHaveBeenCalled();
@ -91,7 +91,7 @@ describe('image upload()', () => {
const itemId = 4; const itemId = 4;
it('should upload a file for the collection "user" and call to the TempContainer upload method', async() => { it('should upload a file for the collection "user" and call to the TempContainer upload method', async() => {
const containerModel = app.models.TempContainer; const containerModel = models.TempContainer;
spyOn(containerModel, 'upload'); spyOn(containerModel, 'upload');
const ctx = {req: {accessToken: {userId: hhrrId}}, const ctx = {req: {accessToken: {userId: hhrrId}},
@ -102,7 +102,7 @@ describe('image upload()', () => {
}; };
try { try {
await app.models.Image.upload(ctx); await models.Image.upload(ctx);
} catch (err) { } } catch (err) { }
expect(containerModel.upload).toHaveBeenCalled(); expect(containerModel.upload).toHaveBeenCalled();
@ -118,7 +118,7 @@ describe('image upload()', () => {
let error; let error;
try { try {
await app.models.Image.upload(ctx); await models.Image.upload(ctx);
} catch (err) { } catch (err) {
error = err; error = err;
} }

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
const LoopBackContext = require('loopback-context'); const LoopBackContext = require('loopback-context');
describe('getStarredModules()', () => { describe('getStarredModules()', () => {
@ -19,13 +19,13 @@ describe('getStarredModules()', () => {
}); });
it(`should return the starred modules for a given user`, async() => { it(`should return the starred modules for a given user`, async() => {
const newStarred = await app.models.StarredModule.create({workerFk: 9, moduleFk: 'customer', position: 1}); const newStarred = await models.StarredModule.create({workerFk: 9, moduleFk: 'customer', position: 1});
const starredModules = await app.models.StarredModule.getStarredModules(ctx); const starredModules = await models.StarredModule.getStarredModules(ctx);
expect(starredModules.length).toEqual(1); expect(starredModules.length).toEqual(1);
expect(starredModules[0].moduleFk).toEqual('customer'); expect(starredModules[0].moduleFk).toEqual('customer');
// restores // restores
await app.models.StarredModule.destroyById(newStarred.id); await models.StarredModule.destroyById(newStarred.id);
}); });
}); });

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
const LoopBackContext = require('loopback-context'); const LoopBackContext = require('loopback-context');
describe('setPosition()', () => { describe('setPosition()', () => {
@ -21,7 +21,7 @@ describe('setPosition()', () => {
}); });
it('should increase the orders module position by replacing it with clients and vice versa', async() => { it('should increase the orders module position by replacing it with clients and vice versa', async() => {
const tx = await app.models.StarredModule.beginTransaction({}); const tx = await models.StarredModule.beginTransaction({});
const filter = { const filter = {
where: { where: {
@ -32,24 +32,24 @@ describe('setPosition()', () => {
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
await app.models.StarredModule.toggleStarredModule(ctx, 'order', options); await models.StarredModule.toggleStarredModule(ctx, 'order', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options); await models.StarredModule.toggleStarredModule(ctx, 'customer', options);
let orders = await app.models.StarredModule.findOne(filter, options); let orders = await models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'customer'; filter.where.moduleFk = 'customer';
let clients = await app.models.StarredModule.findOne(filter, options); let clients = await models.StarredModule.findOne(filter, options);
expect(orders.position).toEqual(1); expect(orders.position).toEqual(1);
expect(clients.position).toEqual(2); expect(clients.position).toEqual(2);
await app.models.StarredModule.setPosition(ctx, 'customer', 'left', options); await models.StarredModule.setPosition(ctx, 'customer', 'left', options);
filter.where.moduleFk = 'customer'; filter.where.moduleFk = 'customer';
clients = await app.models.StarredModule.findOne(filter, options); clients = await models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'order'; filter.where.moduleFk = 'order';
orders = await app.models.StarredModule.findOne(filter, options); orders = await models.StarredModule.findOne(filter, options);
expect(clients.position).toEqual(1); expect(clients.position).toEqual(1);
expect(orders.position).toEqual(2); expect(orders.position).toEqual(2);
@ -62,7 +62,7 @@ describe('setPosition()', () => {
}); });
it('should decrease the orders module position by replacing it with clients and vice versa', async() => { it('should decrease the orders module position by replacing it with clients and vice versa', async() => {
const tx = await app.models.StarredModule.beginTransaction({}); const tx = await models.StarredModule.beginTransaction({});
const filter = { const filter = {
where: { where: {
@ -73,24 +73,24 @@ describe('setPosition()', () => {
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
await app.models.StarredModule.toggleStarredModule(ctx, 'order', options); await models.StarredModule.toggleStarredModule(ctx, 'order', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options); await models.StarredModule.toggleStarredModule(ctx, 'customer', options);
let orders = await app.models.StarredModule.findOne(filter, options); let orders = await models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'customer'; filter.where.moduleFk = 'customer';
let clients = await app.models.StarredModule.findOne(filter, options); let clients = await models.StarredModule.findOne(filter, options);
expect(orders.position).toEqual(1); expect(orders.position).toEqual(1);
expect(clients.position).toEqual(2); expect(clients.position).toEqual(2);
await app.models.StarredModule.setPosition(ctx, 'order', 'right', options); await models.StarredModule.setPosition(ctx, 'order', 'right', options);
filter.where.moduleFk = 'order'; filter.where.moduleFk = 'order';
orders = await app.models.StarredModule.findOne(filter, options); orders = await models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'customer'; filter.where.moduleFk = 'customer';
clients = await app.models.StarredModule.findOne(filter, options); clients = await models.StarredModule.findOne(filter, options);
expect(orders.position).toEqual(2); expect(orders.position).toEqual(2);
expect(clients.position).toEqual(1); expect(clients.position).toEqual(1);
@ -103,7 +103,7 @@ describe('setPosition()', () => {
}); });
it('should switch two modules after adding and deleting several modules', async() => { it('should switch two modules after adding and deleting several modules', async() => {
const tx = await app.models.StarredModule.beginTransaction({}); const tx = await models.StarredModule.beginTransaction({});
const filter = { const filter = {
where: { where: {
@ -115,29 +115,29 @@ describe('setPosition()', () => {
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options); await models.StarredModule.toggleStarredModule(ctx, 'customer', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'order', options); await models.StarredModule.toggleStarredModule(ctx, 'order', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options); await models.StarredModule.toggleStarredModule(ctx, 'customer', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'order', options); await models.StarredModule.toggleStarredModule(ctx, 'order', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'item', options); await models.StarredModule.toggleStarredModule(ctx, 'item', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'claim', options); await models.StarredModule.toggleStarredModule(ctx, 'claim', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options); await models.StarredModule.toggleStarredModule(ctx, 'customer', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'order', options); await models.StarredModule.toggleStarredModule(ctx, 'order', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'zone', options); await models.StarredModule.toggleStarredModule(ctx, 'zone', options);
const items = await app.models.StarredModule.findOne(filter, options); const items = await models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'claim'; filter.where.moduleFk = 'claim';
const claims = await app.models.StarredModule.findOne(filter, options); const claims = await models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'customer'; filter.where.moduleFk = 'customer';
let clients = await app.models.StarredModule.findOne(filter, options); let clients = await models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'order'; filter.where.moduleFk = 'order';
let orders = await app.models.StarredModule.findOne(filter, options); let orders = await models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'zone'; filter.where.moduleFk = 'zone';
const zones = await app.models.StarredModule.findOne(filter, options); const zones = await models.StarredModule.findOne(filter, options);
expect(items.position).toEqual(1); expect(items.position).toEqual(1);
expect(claims.position).toEqual(2); expect(claims.position).toEqual(2);
@ -145,13 +145,13 @@ describe('setPosition()', () => {
expect(orders.position).toEqual(4); expect(orders.position).toEqual(4);
expect(zones.position).toEqual(5); expect(zones.position).toEqual(5);
await app.models.StarredModule.setPosition(ctx, 'customer', 'right', options); await models.StarredModule.setPosition(ctx, 'customer', 'right', options);
filter.where.moduleFk = 'order'; filter.where.moduleFk = 'order';
orders = await app.models.StarredModule.findOne(filter, options); orders = await models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'customer'; filter.where.moduleFk = 'customer';
clients = await app.models.StarredModule.findOne(filter, options); clients = await models.StarredModule.findOne(filter, options);
expect(orders.position).toEqual(3); expect(orders.position).toEqual(3);
expect(clients.position).toEqual(4); expect(clients.position).toEqual(4);
@ -164,7 +164,7 @@ describe('setPosition()', () => {
}); });
it('should switch two modules after adding and deleting a module between them', async() => { it('should switch two modules after adding and deleting a module between them', async() => {
const tx = await app.models.StarredModule.beginTransaction({}); const tx = await models.StarredModule.beginTransaction({});
const filter = { const filter = {
where: { where: {
@ -176,25 +176,25 @@ describe('setPosition()', () => {
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
await app.models.StarredModule.toggleStarredModule(ctx, 'item', options); await models.StarredModule.toggleStarredModule(ctx, 'item', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options); await models.StarredModule.toggleStarredModule(ctx, 'customer', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'claim', options); await models.StarredModule.toggleStarredModule(ctx, 'claim', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'order', options); await models.StarredModule.toggleStarredModule(ctx, 'order', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'zone', options); await models.StarredModule.toggleStarredModule(ctx, 'zone', options);
const items = await app.models.StarredModule.findOne(filter, options); const items = await models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'customer'; filter.where.moduleFk = 'customer';
let clients = await app.models.StarredModule.findOne(filter, options); let clients = await models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'claim'; filter.where.moduleFk = 'claim';
const claims = await app.models.StarredModule.findOne(filter, options); const claims = await models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'order'; filter.where.moduleFk = 'order';
let orders = await app.models.StarredModule.findOne(filter, options); let orders = await models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'zone'; filter.where.moduleFk = 'zone';
const zones = await app.models.StarredModule.findOne(filter, options); const zones = await models.StarredModule.findOne(filter, options);
expect(items.position).toEqual(1); expect(items.position).toEqual(1);
expect(clients.position).toEqual(2); expect(clients.position).toEqual(2);
@ -202,14 +202,14 @@ describe('setPosition()', () => {
expect(orders.position).toEqual(4); expect(orders.position).toEqual(4);
expect(zones.position).toEqual(5); expect(zones.position).toEqual(5);
await app.models.StarredModule.toggleStarredModule(ctx, 'claim', options); await models.StarredModule.toggleStarredModule(ctx, 'claim', options);
await app.models.StarredModule.setPosition(ctx, 'customer', 'right', options); await models.StarredModule.setPosition(ctx, 'customer', 'right', options);
filter.where.moduleFk = 'customer'; filter.where.moduleFk = 'customer';
clients = await app.models.StarredModule.findOne(filter, options); clients = await models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'order'; filter.where.moduleFk = 'order';
orders = await app.models.StarredModule.findOne(filter, options); orders = await models.StarredModule.findOne(filter, options);
expect(orders.position).toEqual(2); expect(orders.position).toEqual(2);
expect(clients.position).toEqual(4); expect(clients.position).toEqual(4);

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
const LoopBackContext = require('loopback-context'); const LoopBackContext = require('loopback-context');
describe('toggleStarredModule()', () => { describe('toggleStarredModule()', () => {
@ -21,16 +21,16 @@ describe('toggleStarredModule()', () => {
}); });
it('should create a new starred module and then remove it by calling the method again with same args', async() => { it('should create a new starred module and then remove it by calling the method again with same args', async() => {
const starredModule = await app.models.StarredModule.toggleStarredModule(ctx, 'order'); const starredModule = await models.StarredModule.toggleStarredModule(ctx, 'order');
let starredModules = await app.models.StarredModule.getStarredModules(ctx); let starredModules = await models.StarredModule.getStarredModules(ctx);
expect(starredModules.length).toEqual(1); expect(starredModules.length).toEqual(1);
expect(starredModule.moduleFk).toEqual('order'); expect(starredModule.moduleFk).toEqual('order');
expect(starredModule.workerFk).toEqual(activeCtx.accessToken.userId); expect(starredModule.workerFk).toEqual(activeCtx.accessToken.userId);
expect(starredModule.position).toEqual(starredModules.length); expect(starredModule.position).toEqual(starredModules.length);
await app.models.StarredModule.toggleStarredModule(ctx, 'order'); await models.StarredModule.toggleStarredModule(ctx, 'order');
starredModules = await app.models.StarredModule.getStarredModules(ctx); starredModules = await models.StarredModule.getStarredModules(ctx);
expect(starredModules.length).toEqual(0); expect(starredModules.length).toEqual(0);
}); });

View File

@ -22,7 +22,7 @@ module.exports = Self => {
let userId = ctx.req.accessToken.userId; let userId = ctx.req.accessToken.userId;
let models = Self.app.models; let models = Self.app.models;
let user = await models.Account.findById(userId, { let user = await Self.findById(userId, {
fields: ['id', 'name', 'nickname', 'email', 'lang'], fields: ['id', 'name', 'nickname', 'email', 'lang'],
include: { include: {
relation: 'userConfig', relation: 'userConfig',

View File

@ -1,9 +1,14 @@
const UserError = require('vn-loopback/util/user-error'); const UserError = require('vn-loopback/util/user-error');
module.exports = Self => { module.exports = Self => {
Self.remoteMethodCtx('privileges', { Self.remoteMethod('privileges', {
description: 'Change role and hasGrant if user has privileges', description: 'Change role and hasGrant if user has privileges',
accepts: [ accepts: [
{
arg: 'ctx',
type: 'Object',
http: {source: 'context'}
},
{ {
arg: 'id', arg: 'id',
type: 'number', type: 'number',
@ -39,9 +44,9 @@ module.exports = Self => {
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
const user = await models.Account.findById(userId, {fields: ['hasGrant']}, myOptions); const user = await Self.findById(userId, {fields: ['hasGrant']}, myOptions);
const userToUpdate = await models.Account.findById(id, { const userToUpdate = await Self.findById(id, {
fields: ['id', 'name', 'hasGrant', 'roleFk', 'password'], fields: ['id', 'name', 'hasGrant', 'roleFk', 'password'],
include: { include: {
relation: 'role', relation: 'role',
@ -54,7 +59,7 @@ module.exports = Self => {
if (!user.hasGrant) if (!user.hasGrant)
throw new UserError(`You don't have grant privilege`); throw new UserError(`You don't have grant privilege`);
const hasRoleFromUser = await models.Account.hasRole(userId, userToUpdate.role().name, myOptions); const hasRoleFromUser = await Self.hasRole(userId, userToUpdate.role().name, myOptions);
if (!hasRoleFromUser) if (!hasRoleFromUser)
throw new UserError(`You don't own the role and you can't assign it to another user`); throw new UserError(`You don't own the role and you can't assign it to another user`);
@ -64,7 +69,7 @@ module.exports = Self => {
if (roleFk) { if (roleFk) {
const role = await models.Role.findById(roleFk, {fields: ['name']}, myOptions); const role = await models.Role.findById(roleFk, {fields: ['name']}, myOptions);
const hasRole = await models.Account.hasRole(userId, role.name, myOptions); const hasRole = await Self.hasRole(userId, role.name, myOptions);
if (!hasRole) if (!hasRole)
throw new UserError(`You don't own the role and you can't assign it to another user`); throw new UserError(`You don't own the role and you can't assign it to another user`);
@ -73,6 +78,6 @@ module.exports = Self => {
} }
await userToUpdate.save(userToUpdate); await userToUpdate.save(userToUpdate);
await models.UserAccount.sync(userToUpdate.name); await models.Account.sync(userToUpdate.name);
}; };
}; };

View File

@ -20,7 +20,7 @@ module.exports = Self => {
const usesEmail = user.indexOf('@') !== -1; const usesEmail = user.indexOf('@') !== -1;
if (!usesEmail) { if (!usesEmail) {
const account = await models.Account.findOne({ const account = await models.VnUser.findOne({
fields: ['email'], fields: ['email'],
where: {name: user} where: {name: user}
}); });
@ -28,7 +28,7 @@ module.exports = Self => {
} }
try { try {
await models.user.resetPassword({email: user, emailTemplate: 'recover-password'}); await Self.resetPassword({email: user, emailTemplate: 'recover-password'});
} catch (err) { } catch (err) {
if (err.code === 'EMAIL_NOT_FOUND') if (err.code === 'EMAIL_NOT_FOUND')
return; return;

View File

@ -1,14 +1,14 @@
const md5 = require('md5');
const UserError = require('vn-loopback/util/user-error'); const UserError = require('vn-loopback/util/user-error');
module.exports = Self => { module.exports = Self => {
Self.remoteMethod('login', { Self.remoteMethod('signIn', {
description: 'Login a user with username/email and password', description: 'Login a user with username/email and password',
accepts: [ accepts: [
{ {
arg: 'user', arg: 'user',
type: 'String', type: 'String',
description: 'The user name or email', description: 'The user name or email',
http: {source: 'form'},
required: true required: true
}, { }, {
arg: 'password', arg: 'password',
@ -21,20 +21,20 @@ module.exports = Self => {
root: true root: true
}, },
http: { http: {
path: `/login`, path: `/signIn`,
verb: 'POST' verb: 'POST'
} }
}); });
Self.login = async function(user, password) { Self.signIn = async function(user, password) {
let $ = Self.app.models; let models = Self.app.models;
let token; let token;
let usesEmail = user.indexOf('@') !== -1; let usesEmail = user.indexOf('@') !== -1;
let userInfo = usesEmail let userInfo = usesEmail
? {email: user} ? {email: user}
: {username: user}; : {username: user};
let instance = await $.User.findOne({ let instance = await Self.findOne({
fields: ['username', 'password'], fields: ['username', 'password'],
where: userInfo where: userInfo
}); });
@ -42,29 +42,27 @@ module.exports = Self => {
let where = usesEmail let where = usesEmail
? {email: user} ? {email: user}
: {name: user}; : {name: user};
let account = await Self.findOne({ let vnUser = await Self.findOne({
fields: ['active', 'password'], fields: ['active'],
where where
}); });
let validCredentials = instance && ( let validCredentials = instance
await instance.hasPassword(password) || && await instance.hasPassword(password);
account.password == md5(password || '')
);
if (validCredentials) { if (validCredentials) {
if (!account.active) if (!vnUser.active)
throw new UserError('User disabled'); throw new UserError('User disabled');
try { try {
await $.UserAccount.sync(instance.username, password); await models.Account.sync(instance.username, password);
} catch (err) { } catch (err) {
console.warn(err); console.warn(err);
} }
} }
let loginInfo = Object.assign({password}, userInfo); let loginInfo = Object.assign({password}, userInfo);
token = await $.User.login(loginInfo, 'user'); token = await Self.login(loginInfo, 'user');
return {token: token.id}; return {token: token.id};
}; };
}; };

View File

@ -1,6 +1,6 @@
const models = require('vn-loopback/server/server').models; const models = require('vn-loopback/server/server').models;
describe('account privileges()', () => { describe('VnUser privileges()', () => {
const employeeId = 1; const employeeId = 1;
const developerId = 9; const developerId = 9;
const sysadminId = 66; const sysadminId = 66;
@ -10,13 +10,13 @@ describe('account privileges()', () => {
it('should throw an error when user not has privileges', async() => { it('should throw an error when user not has privileges', async() => {
const ctx = {req: {accessToken: {userId: developerId}}}; const ctx = {req: {accessToken: {userId: developerId}}};
const tx = await models.Account.beginTransaction({}); const tx = await models.VnUser.beginTransaction({});
let error; let error;
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
await models.Account.privileges(ctx, employeeId, null, true, options); await models.VnUser.privileges(ctx, employeeId, null, true, options);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
@ -29,13 +29,13 @@ describe('account privileges()', () => {
it('should throw an error when user has privileges but not has the role', async() => { it('should throw an error when user has privileges but not has the role', async() => {
const ctx = {req: {accessToken: {userId: sysadminId}}}; const ctx = {req: {accessToken: {userId: sysadminId}}};
const tx = await models.Account.beginTransaction({}); const tx = await models.VnUser.beginTransaction({});
let error; let error;
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
await models.Account.privileges(ctx, employeeId, rootId, null, options); await models.VnUser.privileges(ctx, employeeId, rootId, null, options);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
@ -48,13 +48,13 @@ describe('account privileges()', () => {
it('should throw an error when user has privileges but not has the role from user', async() => { it('should throw an error when user has privileges but not has the role from user', async() => {
const ctx = {req: {accessToken: {userId: sysadminId}}}; const ctx = {req: {accessToken: {userId: sysadminId}}};
const tx = await models.Account.beginTransaction({}); const tx = await models.VnUser.beginTransaction({});
let error; let error;
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
await models.Account.privileges(ctx, itBossId, developerId, null, options); await models.VnUser.privileges(ctx, itBossId, developerId, null, options);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
@ -67,7 +67,7 @@ describe('account privileges()', () => {
it('should change role', async() => { it('should change role', async() => {
const ctx = {req: {accessToken: {userId: sysadminId}}}; const ctx = {req: {accessToken: {userId: sysadminId}}};
const tx = await models.Account.beginTransaction({}); const tx = await models.VnUser.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
const agency = await models.Role.findOne({ const agency = await models.Role.findOne({
@ -79,8 +79,8 @@ describe('account privileges()', () => {
let error; let error;
let result; let result;
try { try {
await models.Account.privileges(ctx, clarkKent, agency.id, null, options); await models.VnUser.privileges(ctx, clarkKent, agency.id, null, options);
result = await models.Account.findById(clarkKent, null, options); result = await models.VnUser.findById(clarkKent, null, options);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
@ -94,14 +94,14 @@ describe('account privileges()', () => {
it('should change hasGrant', async() => { it('should change hasGrant', async() => {
const ctx = {req: {accessToken: {userId: sysadminId}}}; const ctx = {req: {accessToken: {userId: sysadminId}}};
const tx = await models.Account.beginTransaction({}); const tx = await models.VnUser.beginTransaction({});
let error; let error;
let result; let result;
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
await models.Account.privileges(ctx, clarkKent, null, true, options); await models.VnUser.privileges(ctx, clarkKent, null, true, options);
result = await models.Account.findById(clarkKent, null, options); result = await models.VnUser.findById(clarkKent, null, options);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -1,25 +1,25 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
describe('account login()', () => { describe('VnUser signIn()', () => {
describe('when credentials are correct', () => { describe('when credentials are correct', () => {
it('should return the token', async() => { it('should return the token', async() => {
let login = await app.models.Account.login('salesAssistant', 'nightmare'); let login = await models.VnUser.signIn('salesAssistant', 'nightmare');
let accessToken = await app.models.AccessToken.findById(login.token); let accessToken = await models.AccessToken.findById(login.token);
let ctx = {req: {accessToken: accessToken}}; let ctx = {req: {accessToken: accessToken}};
expect(login.token).toBeDefined(); expect(login.token).toBeDefined();
await app.models.Account.logout(ctx); await models.VnUser.signOut(ctx);
}); });
it('should return the token if the user doesnt exist but the client does', async() => { it('should return the token if the user doesnt exist but the client does', async() => {
let login = await app.models.Account.login('PetterParker', 'nightmare'); let login = await models.VnUser.signIn('PetterParker', 'nightmare');
let accessToken = await app.models.AccessToken.findById(login.token); let accessToken = await models.AccessToken.findById(login.token);
let ctx = {req: {accessToken: accessToken}}; let ctx = {req: {accessToken: accessToken}};
expect(login.token).toBeDefined(); expect(login.token).toBeDefined();
await app.models.Account.logout(ctx); await models.VnUser.signOut(ctx);
}); });
}); });
@ -28,7 +28,7 @@ describe('account login()', () => {
let error; let error;
try { try {
await app.models.Account.login('IDontExist', 'TotallyWrongPassword'); await models.VnUser.signIn('IDontExist', 'TotallyWrongPassword');
} catch (e) { } catch (e) {
error = e; error = e;
} }

View File

@ -1,13 +1,13 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
describe('account logout()', () => { describe('VnUser signOut()', () => {
it('should logout and remove token after valid login', async() => { it('should logout and remove token after valid login', async() => {
let loginResponse = await app.models.Account.login('buyer', 'nightmare'); let loginResponse = await models.VnUser.signOut('buyer', 'nightmare');
let accessToken = await app.models.AccessToken.findById(loginResponse.token); let accessToken = await models.AccessToken.findById(loginResponse.token);
let ctx = {req: {accessToken: accessToken}}; let ctx = {req: {accessToken: accessToken}};
let logoutResponse = await app.models.Account.logout(ctx); let logoutResponse = await models.VnUser.signOut(ctx);
let tokenAfterLogout = await app.models.AccessToken.findById(loginResponse.token); let tokenAfterLogout = await models.AccessToken.findById(loginResponse.token);
expect(logoutResponse).toBeTrue(); expect(logoutResponse).toBeTrue();
expect(tokenAfterLogout).toBeNull(); expect(tokenAfterLogout).toBeNull();
@ -18,7 +18,7 @@ describe('account logout()', () => {
let ctx = {req: {accessToken: {id: 'invalidToken'}}}; let ctx = {req: {accessToken: {id: 'invalidToken'}}};
try { try {
response = await app.models.Account.logout(ctx); response = await models.VnUser.signOut(ctx);
} catch (e) { } catch (e) {
error = e; error = e;
} }
@ -32,7 +32,7 @@ describe('account logout()', () => {
let ctx = {req: {accessToken: null}}; let ctx = {req: {accessToken: null}};
try { try {
response = await app.models.Account.logout(ctx); response = await models.VnUser.signOut(ctx);
} catch (e) { } catch (e) {
error = e; error = e;
} }

View File

@ -1,7 +1,4 @@
{ {
"Account": {
"dataSource": "vn"
},
"AccountingType": { "AccountingType": {
"dataSource": "vn" "dataSource": "vn"
}, },
@ -125,10 +122,10 @@
"UserConfigView": { "UserConfigView": {
"dataSource": "vn" "dataSource": "vn"
}, },
"UserLog": { "Warehouse": {
"dataSource": "vn" "dataSource": "vn"
}, },
"Warehouse": { "VnUser": {
"dataSource": "vn" "dataSource": "vn"
}, },
"OsTicket": { "OsTicket": {

View File

@ -1,139 +0,0 @@
/* eslint max-len: ["error", { "code": 150 }]*/
const md5 = require('md5');
const LoopBackContext = require('loopback-context');
const {Email} = require('vn-print');
module.exports = Self => {
require('../methods/account/login')(Self);
require('../methods/account/logout')(Self);
require('../methods/account/acl')(Self);
require('../methods/account/change-password')(Self);
require('../methods/account/set-password')(Self);
require('../methods/account/recover-password')(Self);
require('../methods/account/validate-token')(Self);
require('../methods/account/privileges')(Self);
// Validations
Self.validatesFormatOf('email', {
message: 'Invalid email',
allowNull: true,
allowBlank: true,
with: /^[\w|.|-]+@[\w|-]+(\.[\w|-]+)*(,[\w|.|-]+@[\w|-]+(\.[\w|-]+)*)*$/
});
Self.validatesUniquenessOf('name', {
message: `A client with that Web User name already exists`
});
Self.observe('before save', async function(ctx) {
if (ctx.currentInstance && ctx.currentInstance.id && ctx.data && ctx.data.password)
ctx.data.password = md5(ctx.data.password);
});
Self.afterRemote('prototype.patchAttributes', async(ctx, instance) => {
if (!ctx.args || !ctx.args.data.email) return;
const models = Self.app.models;
const loopBackContext = LoopBackContext.getCurrentContext();
const httpCtx = {req: loopBackContext.active};
const httpRequest = httpCtx.req.http.req;
const headers = httpRequest.headers;
const origin = headers.origin;
const url = origin.split(':');
const userId = ctx.instance.id;
const user = await models.user.findById(userId);
class Mailer {
async send(verifyOptions, cb) {
const params = {
url: verifyOptions.verifyHref,
recipient: verifyOptions.to,
lang: ctx.req.getLocale()
};
const email = new Email('email-verify', params);
email.send();
cb(null, verifyOptions.to);
}
}
const options = {
type: 'email',
to: instance.email,
from: {},
redirect: `${origin}/#!/account/${instance.id}/basic-data?emailConfirmed`,
template: false,
mailer: new Mailer,
host: url[1].split('/')[2],
port: url[2],
protocol: url[0],
user: Self
};
await user.verify(options);
});
Self.remoteMethod('getCurrentUserData', {
description: 'Gets the current user data',
accepts: [
{
arg: 'ctx',
type: 'object',
http: {source: 'context'}
}
],
returns: {
type: 'object',
root: true
},
http: {
verb: 'GET',
path: '/getCurrentUserData'
}
});
Self.getCurrentUserData = async function(ctx) {
let userId = ctx.req.accessToken.userId;
return await Self.findById(userId, {
fields: ['id', 'name', 'nickname']
});
};
/**
* Checks if user has a role.
*
* @param {Integer} userId The user id
* @param {String} name The role name
* @param {object} options Options
* @return {Boolean} %true if user has the role, %false otherwise
*/
Self.hasRole = async function(userId, name, options) {
let roles = await Self.getRoles(userId, options);
return roles.some(role => role == name);
};
/**
* Get all user roles.
*
* @param {Integer} userId The user id
* @param {object} options Options
* @return {object} User role list
*/
Self.getRoles = async(userId, options) => {
let result = await Self.rawSql(
`SELECT r.name
FROM account.user u
JOIN account.roleRole rr ON rr.role = u.role
JOIN account.role r ON r.id = rr.inheritsFrom
WHERE u.id = ?`, [userId], options);
let roles = [];
for (const role of result)
roles.push(role.name);
return roles;
};
};

View File

@ -54,8 +54,8 @@ module.exports = Self => {
const writeRole = dmsType.writeRole() && dmsType.writeRole().name; const writeRole = dmsType.writeRole() && dmsType.writeRole().name;
const requiredRole = readRole || writeRole; const requiredRole = readRole || writeRole;
const hasRequiredRole = await models.Account.hasRole(myUserId, requiredRole, options); const hasRequiredRole = await models.VnUser.hasRole(myUserId, requiredRole, options);
const isRoot = await models.Account.hasRole(myUserId, 'root', options); const isRoot = await models.VnUser.hasRole(myUserId, 'root', options);
if (isRoot || hasRequiredRole) if (isRoot || hasRequiredRole)
return true; return true;

View File

@ -20,7 +20,7 @@
"relations": { "relations": {
"user": { "user": {
"type": "belongsTo", "type": "belongsTo",
"model": "Account", "model": "VnUser",
"foreignKey": "userFk" "foreignKey": "userFk"
} }
}, },

View File

@ -53,8 +53,8 @@ module.exports = Self => {
const writeRole = collection.writeRole() && collection.writeRole().name; const writeRole = collection.writeRole() && collection.writeRole().name;
const requiredRole = readRole || writeRole; const requiredRole = readRole || writeRole;
const hasRequiredRole = await models.Account.hasRole(myUserId, requiredRole, options); const hasRequiredRole = await models.VnUser.hasRole(myUserId, requiredRole, options);
const isRoot = await models.Account.hasRole(myUserId, 'root', options); const isRoot = await models.VnUser.hasRole(myUserId, 'root', options);
if (isRoot || hasRequiredRole) if (isRoot || hasRequiredRole)
return true; return true;

View File

@ -31,7 +31,7 @@
}, },
"author": { "author": {
"type": "belongsTo", "type": "belongsTo",
"model": "Account", "model": "VnUser",
"foreignKey": "authorFk" "foreignKey": "authorFk"
} }
} }

View File

@ -29,7 +29,7 @@
}, },
"user": { "user": {
"type": "belongsTo", "type": "belongsTo",
"model": "Account", "model": "VnUser",
"foreignKey": "userFk" "foreignKey": "userFk"
} }
} }

View File

@ -1,8 +1,8 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
describe('loopback model Company', () => { describe('loopback model Company', () => {
it('should check that the company FTH doesnt exists', async() => { it('should check that the company FTH doesnt exists', async() => {
let result = await app.models.Company.findOne({where: {code: 'FTH'}}); let result = await models.Company.findOne({where: {code: 'FTH'}});
expect(result).toBeFalsy(); expect(result).toBeFalsy();
}); });

View File

@ -1,6 +1,6 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
describe('Dms', () => { describe('Dms', () => {
const Dms = app.models.Dms; const Dms = models.Dms;
describe('getFile()', () => { describe('getFile()', () => {
it('should return a response with text content-type', async() => { it('should return a response with text content-type', async() => {
@ -23,7 +23,7 @@ describe('Dms', () => {
it('should return an error for a record does not exists', async() => { it('should return an error for a record does not exists', async() => {
let error = {}; let error = {};
try { try {
await app.models.Dms.getFile('NotExistentId'); await models.Dms.getFile('NotExistentId');
} catch (e) { } catch (e) {
error = e; error = e;
} }

View File

@ -1,7 +1,7 @@
const models = require('vn-loopback/server/server').models; const models = require('vn-loopback/server/server').models;
const LoopBackContext = require('loopback-context'); const LoopBackContext = require('loopback-context');
describe('account recoverPassword()', () => { describe('VnUser recoverPassword()', () => {
const userId = 1107; const userId = 1107;
const activeCtx = { const activeCtx = {
@ -21,9 +21,9 @@ describe('account recoverPassword()', () => {
it('should send email with token', async() => { it('should send email with token', async() => {
const userId = 1107; const userId = 1107;
const user = await models.Account.findById(userId); const user = await models.VnUser.findById(userId);
await models.Account.recoverPassword(user.email); await models.VnUser.recoverPassword(user.email);
const result = await models.AccessToken.findOne({where: {userId: userId}}); const result = await models.AccessToken.findOne({where: {userId: userId}});

View File

@ -1,14 +1,14 @@
const models = require('vn-loopback/server/server').models; const models = require('vn-loopback/server/server').models;
describe('loopback model Account', () => { 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() => {
let result = await models.Account.hasRole(1, 'employee'); let result = await models.VnUser.hasRole(1, 'employee');
expect(result).toBeTruthy(); expect(result).toBeTruthy();
}); });
it('should return false if the user doesnt have the given role', async() => { it('should return false if the user doesnt have the given role', async() => {
let result = await models.Account.hasRole(1, 'administrator'); let result = await models.VnUser.hasRole(1, 'administrator');
expect(result).toBeFalsy(); expect(result).toBeFalsy();
}); });

View File

@ -26,7 +26,7 @@
"relations": { "relations": {
"user": { "user": {
"type": "belongsTo", "type": "belongsTo",
"model": "Account", "model": "VnUser",
"foreignKey": "userFk" "foreignKey": "userFk"
} }
} }

View File

@ -39,9 +39,9 @@
"model": "Company", "model": "Company",
"foreignKey": "companyFk" "foreignKey": "companyFk"
}, },
"account": { "VnUser": {
"type": "belongsTo", "type": "belongsTo",
"model": "Account", "model": "VnUser",
"foreignKey": "userFk" "foreignKey": "userFk"
} }
} }

View File

@ -1,27 +0,0 @@
const LoopBackContext = require('loopback-context');
const {Email} = require('vn-print');
module.exports = function(Self) {
Self.on('resetPasswordRequest', async function(info) {
const loopBackContext = LoopBackContext.getCurrentContext();
const httpCtx = {req: loopBackContext.active};
const httpRequest = httpCtx.req.http.req;
const headers = httpRequest.headers;
const origin = headers.origin;
const user = await Self.app.models.Account.findById(info.user.id);
const params = {
recipient: info.email,
lang: user.lang,
url: `${origin}/#!/reset-password?access_token=${info.accessToken.id}`
};
const options = Object.assign({}, info.options);
for (const param in options)
params[param] = options[param];
const email = new Email(options.emailTemplate, params);
return email.send();
});
};

View File

@ -1,20 +0,0 @@
{
"name": "user",
"base": "User",
"options": {
"mysql": {
"table": "salix.User"
},
"resetPasswordTokenTTL": "604800"
},
"properties": {
"id": {
"id": true,
"type": "number",
"forceId": false
},
"username":{
"type": "string"
}
}
}

110
back/models/vn-user.js Normal file
View File

@ -0,0 +1,110 @@
const vnModel = require('vn-loopback/common/models/vn-model');
const LoopBackContext = require('loopback-context');
const {Email} = require('vn-print');
module.exports = function(Self) {
vnModel(Self);
require('../methods/vn-user/signIn')(Self);
require('../methods/vn-user/acl')(Self);
require('../methods/vn-user/recover-password')(Self);
require('../methods/vn-user/validate-token')(Self);
require('../methods/vn-user/privileges')(Self);
// Validations
Self.validatesFormatOf('email', {
message: 'Invalid email',
allowNull: true,
allowBlank: true,
with: /^[\w|.|-]+@[\w|-]+(\.[\w|-]+)*(,[\w|.|-]+@[\w|-]+(\.[\w|-]+)*)*$/
});
Self.validatesUniquenessOf('name', {
message: `A client with that Web User name already exists`
});
Self.remoteMethod('getCurrentUserData', {
description: 'Gets the current user data',
accepts: [
{
arg: 'ctx',
type: 'Object',
http: {source: 'context'}
}
],
returns: {
type: 'Object',
root: true
},
http: {
verb: 'GET',
path: '/getCurrentUserData'
}
});
Self.getCurrentUserData = async function(ctx) {
let userId = ctx.req.accessToken.userId;
return await Self.findById(userId, {
fields: ['id', 'name', 'nickname']
});
};
/**
* Checks if user has a role.
*
* @param {Integer} userId The user id
* @param {String} name The role name
* @param {Object} options Options
* @return {Boolean} %true if user has the role, %false otherwise
*/
Self.hasRole = async function(userId, name, options) {
const roles = await Self.getRoles(userId, options);
return roles.some(role => role == name);
};
/**
* Get all user roles.
*
* @param {Integer} userId The user id
* @param {Object} options Options
* @return {Object} User role list
*/
Self.getRoles = async(userId, options) => {
const result = await Self.rawSql(
`SELECT r.name
FROM account.user u
JOIN account.roleRole rr ON rr.role = u.role
JOIN account.role r ON r.id = rr.inheritsFrom
WHERE u.id = ?`, [userId], options);
const roles = [];
for (const role of result)
roles.push(role.name);
return roles;
};
Self.on('resetPasswordRequest', async function(info) {
const loopBackContext = LoopBackContext.getCurrentContext();
const httpCtx = {req: loopBackContext.active};
const httpRequest = httpCtx.req.http.req;
const headers = httpRequest.headers;
const origin = headers.origin;
const user = await Self.app.models.VnUser.findById(info.user.id);
const params = {
recipient: info.email,
lang: user.lang,
url: `${origin}/#!/reset-password?access_token=${info.accessToken.id}`
};
const options = Object.assign({}, info.options);
for (const param in options)
params[param] = options[param];
const email = new Email(options.emailTemplate, params);
return email.send();
});
};

View File

@ -1,11 +1,13 @@
{ {
"name": "Account", "name": "VnUser",
"base": "VnModel", "base": "User",
"validateUpsert": true,
"options": { "options": {
"mysql": { "mysql": {
"table": "account.user" "table": "account.user"
} }
}, },
"resetPasswordTokenTTL": "604800",
"properties": { "properties": {
"id": { "id": {
"type": "number", "type": "number",
@ -15,6 +17,19 @@
"type": "string", "type": "string",
"required": true "required": true
}, },
"username": {
"type": "string",
"mysql": {
"columnName": "name"
}
},
"password": {
"type": "string",
"required": true,
"mysql": {
"columnName": "bcryptPassword"
}
},
"roleFk": { "roleFk": {
"type": "number", "type": "number",
"mysql": { "mysql": {
@ -27,10 +42,6 @@
"lang": { "lang": {
"type": "string" "type": "string"
}, },
"password": {
"type": "string",
"required": true
},
"bcryptPassword": { "bcryptPassword": {
"type": "string" "type": "string"
}, },
@ -40,9 +51,6 @@
"email": { "email": {
"type": "string" "type": "string"
}, },
"emailVerified": {
"type": "boolean"
},
"created": { "created": {
"type": "date" "type": "date"
}, },
@ -86,7 +94,7 @@
}, },
"acls": [ "acls": [
{ {
"property": "login", "property": "signIn",
"accessType": "EXECUTE", "accessType": "EXECUTE",
"principalType": "ROLE", "principalType": "ROLE",
"principalId": "$everyone", "principalId": "$everyone",
@ -100,13 +108,6 @@
"permission": "ALLOW" "permission": "ALLOW"
}, },
{ {
"property": "logout",
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW"
},
{
"property": "validateToken", "property": "validateToken",
"accessType": "EXECUTE", "accessType": "EXECUTE",
"principalType": "ROLE", "principalType": "ROLE",

View File

@ -0,0 +1,18 @@
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
VALUES ('VnUser', '*', '*', 'ALLOW', 'ROLE', 'employee');
INSERT INTO `salix`.`ACL` (id, model, property, accessType, permission, principalType, principalId)
VALUES ('VnUser', 'acl', 'READ', 'ALLOW', 'ROLE', 'account');
INSERT INTO `salix`.`ACL` (id, model, property, accessType, permission, principalType, principalId)
VALUES ('VnUser', 'getCurrentUserData', 'READ', 'ALLOW', 'ROLE', 'account');
INSERT INTO `salix`.`ACL` (id, model, property, accessType, permission, principalType, principalId)
VALUES ('VnUser', 'changePassword', '*', 'ALLOW', 'ROLE', 'account');
UPDATE `hedera`.`imageCollection` t
SET t.model = 'VnUser'
WHERE t.id = 6;

View File

@ -0,0 +1,21 @@
create or replace definer = root@localhost view User as
select `account`.`user`.`id` AS `id`,
`account`.`user`.`realm` AS `realm`,
`account`.`user`.`name` AS `name`,
`account`.`user`.`nickname` AS `nickname`,
`account`.`user`.`bcryptPassword` AS `password`,
`account`.`user`.`role` AS `role`,
`account`.`user`.`active` AS `active`,
`account`.`user`.`email` AS `email`,
`account`.`user`.`emailVerified` AS `emailVerified`,
`account`.`user`.`verificationToken` AS `verificationToken`,
`account`.`user`.`lang` AS `lang`,
`account`.`user`.`lastPassChange` AS `lastPassChange`,
`account`.`user`.`created` AS `created`,
`account`.`user`.`updated` AS `updated`,
`account`.`user`.`image` AS `image`,
`account`.`user`.`recoverPass` AS `recoverPass`,
`account`.`user`.`sync` AS `sync`,
`account`.`user`.`hasGrant` AS `hasGrant`
from `account`.`user`;

View File

@ -0,0 +1,21 @@
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
VALUES
('VnUser', '*', '*', 'ALLOW', 'ROLE', 'employee'),
('VnUser','acl','READ','ALLOW','ROLE','account'),
('VnUser','getCurrentUserData','READ','ALLOW','ROLE','account'),
('VnUser','changePassword', 'WRITE', 'ALLOW', 'ROLE', 'account'),
('Account','exists','READ','ALLOW','ROLE','account');
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
VALUES
('Account','exists','READ','ALLOW','ROLE','account');
DELETE FROM `salix`.`ACL` WHERE (model, property) = ('Account', 'acl');
DELETE FROM `salix`.`ACL` WHERE (model, property) = ('Account', 'getCurrentUserData');
DELETE FROM `salix`.`ACL` WHERE (model, property) = ('Account', 'changePassword');
DELETE FROM `salix`.`ACL` WHERE model = 'UserAccount';
UPDATE `hedera`.`imageCollection` t
SET t.model = 'VnUser'
WHERE t.id = 6;

View File

@ -0,0 +1,4 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('UserLog', '*', 'READ', 'ALLOW', 'ROLE', 'employee'),
('RoleLog', '*', 'READ', 'ALLOW', 'ROLE', 'employee');

View File

@ -98,20 +98,20 @@ INSERT INTO `hedera`.`tpvConfig`(`id`, `currency`, `terminal`, `transactionType`
VALUES VALUES
(1, 978, 1, 0, 2000, 9, 0); (1, 978, 1, 0, 2000, 9, 0);
INSERT INTO `account`.`user`(`id`,`name`,`nickname`, `password`,`role`,`active`,`email`,`lang`, `image`) INSERT INTO `account`.`user`(`id`,`name`,`nickname`, `bcryptPassword`, `password`,`role`,`active`,`email`,`lang`, `image`)
VALUES VALUES
(1101, 'BruceWayne', 'Bruce Wayne', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'BruceWayne@mydomain.com', 'es', 'e7723f0b24ff05b32ed09d95196f2f29'), (1101, 'BruceWayne', 'Bruce Wayne', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'BruceWayne@mydomain.com', 'es', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1102, 'PetterParker', 'Petter Parker', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'PetterParker@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'), (1102, 'PetterParker', 'Petter Parker', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'PetterParker@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1103, 'ClarkKent', 'Clark Kent', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'ClarkKent@mydomain.com', 'fr', 'e7723f0b24ff05b32ed09d95196f2f29'), (1103, 'ClarkKent', 'Clark Kent', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'ClarkKent@mydomain.com', 'fr', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1104, 'TonyStark', 'Tony Stark', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'TonyStark@mydomain.com', 'es', 'e7723f0b24ff05b32ed09d95196f2f29'), (1104, 'TonyStark', 'Tony Stark', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'TonyStark@mydomain.com', 'es', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1105, 'MaxEisenhardt', 'Max Eisenhardt', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'MaxEisenhardt@mydomain.com', 'pt', 'e7723f0b24ff05b32ed09d95196f2f29'), (1105, 'MaxEisenhardt', 'Max Eisenhardt', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'MaxEisenhardt@mydomain.com', 'pt', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1106, 'DavidCharlesHaller', 'David Charles Haller', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'DavidCharlesHaller@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'), (1106, 'DavidCharlesHaller', 'David Charles Haller', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'DavidCharlesHaller@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1107, 'HankPym', 'Hank Pym', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'HankPym@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'), (1107, 'HankPym', 'Hank Pym', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'HankPym@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1108, 'CharlesXavier', 'Charles Xavier', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'CharlesXavier@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'), (1108, 'CharlesXavier', 'Charles Xavier', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'CharlesXavier@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1109, 'BruceBanner', 'Bruce Banner', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'BruceBanner@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'), (1109, 'BruceBanner', 'Bruce Banner', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'BruceBanner@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1110, 'JessicaJones', 'Jessica Jones', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'JessicaJones@mydomain.com', 'en', NULL), (1110, 'JessicaJones', 'Jessica Jones', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'JessicaJones@mydomain.com', 'en', NULL),
(1111, 'Missing', 'Missing', 'ac754a330530832ba1bf7687f577da91', 2, 0, NULL, 'en', NULL), (1111, 'Missing', 'Missing', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 0, NULL, 'en', NULL),
(1112, 'Trash', 'Trash', 'ac754a330530832ba1bf7687f577da91', 2, 0, NULL, 'en', NULL); (1112, 'Trash', 'Trash', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 0, NULL, 'en', NULL);
INSERT INTO `account`.`mailAlias`(`id`, `alias`, `description`, `isPublic`) INSERT INTO `account`.`mailAlias`(`id`, `alias`, `description`, `isPublic`)
VALUES VALUES

View File

@ -414,7 +414,7 @@ export default {
saveFieldsButton: '.vn-popover.shown vn-button[label="Save"] > button' saveFieldsButton: '.vn-popover.shown vn-button[label="Save"] > button'
}, },
itemFixedPrice: { itemFixedPrice: {
add: 'vn-fixed-price vn-icon-button[icon="add_circle"]', add: 'vn-fixed-price vn-icon-button[vn-tooltip="Add fixed price"]',
firstItemID: 'vn-fixed-price tr:nth-child(2) vn-autocomplete[ng-model="price.itemFk"]', firstItemID: 'vn-fixed-price tr:nth-child(2) vn-autocomplete[ng-model="price.itemFk"]',
fourthFixedPrice: 'vn-fixed-price tr:nth-child(5)', fourthFixedPrice: 'vn-fixed-price tr:nth-child(5)',
fourthItemID: 'vn-fixed-price tr:nth-child(5) vn-autocomplete[ng-model="price.itemFk"]', fourthItemID: 'vn-fixed-price tr:nth-child(5) vn-autocomplete[ng-model="price.itemFk"]',
@ -427,7 +427,18 @@ export default {
fourthEnded: 'vn-fixed-price tr:nth-child(5) vn-date-picker[ng-model="price.ended"]', fourthEnded: 'vn-fixed-price tr:nth-child(5) vn-date-picker[ng-model="price.ended"]',
fourthDeleteIcon: 'vn-fixed-price tr:nth-child(5) > td:nth-child(9) > vn-icon-button[icon="delete"]', fourthDeleteIcon: 'vn-fixed-price tr:nth-child(5) > td:nth-child(9) > vn-icon-button[icon="delete"]',
orderColumnId: 'vn-fixed-price th[field="itemFk"]', orderColumnId: 'vn-fixed-price th[field="itemFk"]',
removeWarehouseFilter: 'vn-searchbar > form > vn-textfield > div.container > div.prepend > prepend > div > span:nth-child(1) > vn-icon > i' removeWarehouseFilter: 'vn-searchbar > form > vn-textfield > div.container > div.prepend > prepend > div > span:nth-child(1) > vn-icon > i',
generalSearchFilter: 'vn-fixed-price-search-panel vn-textfield[ng-model="$ctrl.filter.search"]',
reignFilter: 'vn-fixed-price-search-panel vn-horizontal.item-category vn-one',
typeFilter: 'vn-fixed-price-search-panel vn-autocomplete[ng-model="$ctrl.filter.typeFk"]',
buyerFilter: 'vn-fixed-price-search-panel vn-autocomplete[ng-model="$ctrl.filter.buyerFk"]',
warehouseFilter: 'vn-fixed-price-search-panel vn-autocomplete[ng-model="$ctrl.filter.warehouseFk"]',
mineFilter: 'vn-fixed-price-search-panel vn-check[ng-model="$ctrl.filter.mine"]',
hasMinPriceFilter: 'vn-fixed-price-search-panel vn-check[ng-model="$ctrl.filter.hasMinPrice"]',
addTag: 'vn-fixed-price-search-panel vn-icon-button[icon="add_circle"]',
tagFilter: 'vn-fixed-price-search-panel vn-autocomplete[ng-model="itemTag.tagFk"]',
tagValueFilter: 'vn-fixed-price-search-panel vn-autocomplete[ng-model="itemTag.value"]',
chip: 'vn-fixed-price-search-panel vn-chip > vn-icon'
}, },
itemCreateView: { itemCreateView: {
temporalName: 'vn-item-create vn-textfield[ng-model="$ctrl.item.provisionalName"]', temporalName: 'vn-item-create vn-textfield[ng-model="$ctrl.item.provisionalName"]',

View File

@ -4,20 +4,69 @@ import getBrowser from '../../helpers/puppeteer';
describe('Item fixed prices path', () => { describe('Item fixed prices path', () => {
let browser; let browser;
let page; let page;
let httpRequest;
beforeAll(async() => { beforeAll(async() => {
browser = await getBrowser(); browser = await getBrowser();
page = browser.page; page = browser.page;
await page.loginAndModule('buyer', 'item'); await page.loginAndModule('buyer', 'item');
await page.accessToSection('item.fixedPrice'); await page.accessToSection('item.fixedPrice');
page.on('request', req => {
if (req.url().includes(`FixedPrices/filter`))
httpRequest = req.url();
});
}); });
afterAll(async() => { afterAll(async() => {
await browser.close(); await browser.close();
}); });
it('should filter using all the fields', async() => {
await page.write(selectors.itemFixedPrice.generalSearchFilter, 'item');
await page.keyboard.press('Enter');
expect(httpRequest).toContain('search=item');
await page.click(selectors.itemFixedPrice.chip);
await page.click(selectors.itemFixedPrice.reignFilter);
expect(httpRequest).toContain('categoryFk');
await page.autocompleteSearch(selectors.itemFixedPrice.typeFilter, 'Alstroemeria');
expect(httpRequest).toContain('typeFk');
await page.click(selectors.itemFixedPrice.chip);
await page.autocompleteSearch(selectors.itemFixedPrice.buyerFilter, 'buyerNick');
expect(httpRequest).toContain('buyerFk');
await page.click(selectors.itemFixedPrice.chip);
await page.autocompleteSearch(selectors.itemFixedPrice.warehouseFilter, 'Algemesi');
expect(httpRequest).toContain('warehouseFk');
await page.click(selectors.itemFixedPrice.chip);
await page.click(selectors.itemFixedPrice.mineFilter);
expect(httpRequest).toContain('mine=true');
await page.click(selectors.itemFixedPrice.chip);
await page.click(selectors.itemFixedPrice.hasMinPriceFilter);
expect(httpRequest).toContain('hasMinPrice=true');
await page.click(selectors.itemFixedPrice.chip);
await page.click(selectors.itemFixedPrice.addTag);
await page.autocompleteSearch(selectors.itemFixedPrice.tagFilter, 'Color');
await page.autocompleteSearch(selectors.itemFixedPrice.tagValueFilter, 'Brown');
expect(httpRequest).toContain('tags');
await page.click(selectors.itemFixedPrice.chip);
});
it('should click on the add new fixed price button', async() => { it('should click on the add new fixed price button', async() => {
await page.waitToClick(selectors.itemFixedPrice.removeWarehouseFilter);
await page.waitForSpinnerLoad();
await page.waitToClick(selectors.itemFixedPrice.add); await page.waitToClick(selectors.itemFixedPrice.add);
await page.waitForSelector(selectors.itemFixedPrice.fourthFixedPrice); await page.waitForSelector(selectors.itemFixedPrice.fourthFixedPrice);
}); });
@ -36,10 +85,7 @@ describe('Item fixed prices path', () => {
}); });
it('should reload the section and check the created price has the expected ID', async() => { it('should reload the section and check the created price has the expected ID', async() => {
await page.accessToSection('item.index'); await page.goto(`http://localhost:5000/#!/item/fixed-price`);
await page.accessToSection('item.fixedPrice');
await page.waitToClick(selectors.itemFixedPrice.removeWarehouseFilter);
await page.waitForSpinnerLoad();
const result = await page.waitToGetProperty(selectors.itemFixedPrice.fourthItemID, 'value'); const result = await page.waitToGetProperty(selectors.itemFixedPrice.fourthItemID, 'value');

View File

@ -23,7 +23,7 @@ describe('Account ACL path', () => {
it('should create new acl', async() => { it('should create new acl', async() => {
await page.autocompleteSearch(selectors.accountAcl.role, 'sysadmin'); await page.autocompleteSearch(selectors.accountAcl.role, 'sysadmin');
await page.autocompleteSearch(selectors.accountAcl.model, 'UserAccount'); await page.autocompleteSearch(selectors.accountAcl.model, 'Account');
await page.autocompleteSearch(selectors.accountAcl.accessType, '*'); await page.autocompleteSearch(selectors.accountAcl.accessType, '*');
await page.autocompleteSearch(selectors.accountAcl.permission, 'ALLOW'); await page.autocompleteSearch(selectors.accountAcl.permission, 'ALLOW');
await page.waitToClick(selectors.accountAcl.save); await page.waitToClick(selectors.accountAcl.save);

View File

@ -7,7 +7,7 @@ describe('Directive acl', () => {
beforeEach(ngModule('vnCore')); beforeEach(ngModule('vnCore'));
beforeEach(inject(($httpBackend, aclService) => { beforeEach(inject(($httpBackend, aclService) => {
$httpBackend.whenGET('Accounts/acl') $httpBackend.whenGET('VnUsers/acl')
.respond({ .respond({
user: {id: 1, name: 'myUser'}, user: {id: 1, name: 'myUser'},
roles: [ roles: [

View File

@ -4,7 +4,7 @@ describe('Service acl', () => {
beforeEach(ngModule('vnCore')); beforeEach(ngModule('vnCore'));
beforeEach(inject((_aclService_, $httpBackend) => { beforeEach(inject((_aclService_, $httpBackend) => {
$httpBackend.when('GET', `Accounts/acl`).respond({ $httpBackend.when('GET', `VnUsers/acl`).respond({
roles: [ roles: [
{role: {name: 'foo'}}, {role: {name: 'foo'}},
{role: {name: 'bar'}}, {role: {name: 'bar'}},

View File

@ -11,7 +11,7 @@ class AclService {
} }
load() { load() {
return this.$http.get('Accounts/acl').then(res => { return this.$http.get('VnUsers/acl').then(res => {
this.user = res.data.user; this.user = res.data.user;
this.roles = {}; this.roles = {};

View File

@ -59,7 +59,7 @@ export default class Auth {
password: password || undefined password: password || undefined
}; };
return this.$http.post('Accounts/login', params).then( return this.$http.post('VnUsers/signIn', params).then(
json => this.onLoginOk(json, remember)); json => this.onLoginOk(json, remember));
} }
@ -76,7 +76,7 @@ export default class Auth {
} }
logout() { logout() {
let promise = this.$http.post('Accounts/logout', null, { let promise = this.$http.post('VnUsers/logout', null, {
headers: {Authorization: this.vnToken.token} headers: {Authorization: this.vnToken.token}
}).catch(() => {}); }).catch(() => {});

View File

@ -13,7 +13,7 @@ export class Layout extends Component {
} }
getUserData() { getUserData() {
this.$http.get('Accounts/getCurrentUserData').then(json => { this.$http.get('VnUsers/getCurrentUserData').then(json => {
this.$.$root.user = json.data; this.$.$root.user = json.data;
window.localStorage.currentUserWorkerId = json.data.id; window.localStorage.currentUserWorkerId = json.data.id;
}); });

View File

@ -15,7 +15,7 @@ describe('Component vnLayout', () => {
describe('getUserData()', () => { describe('getUserData()', () => {
it(`should set the user name property in the controller`, () => { it(`should set the user name property in the controller`, () => {
$httpBackend.expect('GET', `Accounts/getCurrentUserData`).respond({name: 'batman'}); $httpBackend.expect('GET', `VnUsers/getCurrentUserData`).respond({name: 'batman'});
controller.getUserData(); controller.getUserData();
$httpBackend.flush(); $httpBackend.flush();

View File

@ -23,7 +23,7 @@ export default class Controller {
user: this.user user: this.user
}; };
this.$http.post('Accounts/recoverPassword', params) this.$http.post('VnUsers/recoverPassword', params)
.then(() => { .then(() => {
this.goToLogin(); this.goToLogin();
}); });

View File

@ -229,7 +229,7 @@ module.exports = function(Self) {
async checkAcls(ctx, actionType) { async checkAcls(ctx, actionType) {
let userId = ctx.req.accessToken.userId; let userId = ctx.req.accessToken.userId;
let models = this.app.models; let models = this.app.models;
let userRoles = await models.Account.getRoles(userId); let userRoles = await models.VnUser.getRoles(userId);
let data = ctx.args.data; let data = ctx.args.data;
let modelAcls; let modelAcls;

View File

@ -155,5 +155,7 @@
"Warehouse inventory not set": "Almacén inventario no está establecido", "Warehouse inventory not set": "Almacén inventario no está establecido",
"Component cost not set": "Componente coste no está estabecido", "Component cost not set": "Componente coste no está estabecido",
"Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2", "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2",
"Description cannot be blank": "Description cannot be blank" "Description cannot be blank": "Description cannot be blank",
"Added observation": "Added observation",
"Comment added to client": "Comment added to client"
} }

View File

@ -293,7 +293,7 @@ class VnMySQL extends MySQL {
try { try {
const userId = opts.httpCtx && opts.httpCtx.active.accessToken.userId; const userId = opts.httpCtx && opts.httpCtx.active.accessToken.userId;
if (userId) { if (userId) {
const user = await Model.app.models.Account.findById(userId, {fields: ['name']}, opts); const user = await Model.app.models.VnUser.findById(userId, {fields: ['name']}, opts);
await this.executeP(`CALL account.myUser_loginWithName(?)`, [user.name], opts); await this.executeP(`CALL account.myUser_loginWithName(?)`, [user.name], opts);
} }

View File

@ -28,7 +28,11 @@
}, },
"session": {}, "session": {},
"auth": { "auth": {
"loopback#token": {} "loopback#token": {
"params": {
"currentUserLiteral": "me"
}
}
}, },
"auth:after": { "auth:after": {
"./middleware/current-user": {}, "./middleware/current-user": {},

View File

@ -9,7 +9,7 @@
"relations": { "relations": {
"user": { "user": {
"type": "belongsTo", "type": "belongsTo",
"model": "user", "model": "VnUser",
"foreignKey": "userId" "foreignKey": "userId"
} }
} }
@ -41,9 +41,6 @@
} }
} }
}, },
"user": {
"dataSource": "vn"
},
"Schema": { "Schema": {
"dataSource": "vn" "dataSource": "vn"
}, },

View File

@ -30,6 +30,6 @@ module.exports = Self => {
Self.changePassword = async function(id, oldPassword, newPassword) { Self.changePassword = async function(id, oldPassword, newPassword) {
await Self.rawSql(`CALL account.user_changePassword(?, ?, ?)`, await Self.rawSql(`CALL account.user_changePassword(?, ?, ?)`,
[id, oldPassword, newPassword]); [id, oldPassword, newPassword]);
await Self.app.models.UserAccount.syncById(id, newPassword); await Self.app.models.Account.syncById(id, newPassword);
}; };
}; };

View File

@ -0,0 +1,27 @@
module.exports = Self => {
Self.remoteMethod('login', {
description: 'Login a user with username/email and password',
accepts: [
{
arg: 'user',
type: 'String',
description: 'The user name or email',
required: true
}, {
arg: 'password',
type: 'String',
description: 'The password'
}
],
returns: {
type: 'object',
root: true
},
http: {
path: `/login`,
verb: 'POST'
}
});
Self.login = async(user, password) => Self.app.models.VnUser.signIn(user, password);
};

View File

@ -18,8 +18,5 @@ module.exports = Self => {
} }
}); });
Self.logout = async function(ctx) { Self.logout = async ctx => Self.app.models.VnUser.logout(ctx.req.accessToken.id);
await Self.app.models.User.logout(ctx.req.accessToken.id);
return true;
};
}; };

View File

@ -24,6 +24,6 @@ module.exports = Self => {
Self.setPassword = async function(id, newPassword) { Self.setPassword = async function(id, newPassword) {
await Self.rawSql(`CALL account.user_setPassword(?, ?)`, await Self.rawSql(`CALL account.user_setPassword(?, ?)`,
[id, newPassword]); [id, newPassword]);
await Self.app.models.UserAccount.syncById(id, newPassword); await Self.app.models.Account.syncById(id, newPassword);
}; };
}; };

View File

@ -1,14 +1,14 @@
const app = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
describe('account setPassword()', () => { 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 = models.Account.setPassword(1, 'insecurePass');
await expectAsync(req).toBeRejected(); await expectAsync(req).toBeRejected();
}); });
it('should update password when it passes requirements', async() => { it('should update password when it passes requirements', async() => {
let req = app.models.Account.setPassword(1, 'Very$ecurePa22.'); let req = models.Account.setPassword(1, 'Very$ecurePa22.');
await expectAsync(req).toBeResolved(); await expectAsync(req).toBeResolved();
}); });

View File

@ -25,7 +25,7 @@ module.exports = Self => {
}); });
Self.syncById = async function(id, password, force) { Self.syncById = async function(id, password, force) {
let user = await Self.app.models.Account.findById(id, {fields: ['name']}); let user = await Self.app.models.VnUser.findById(id, {fields: ['name']});
await Self.sync(user.name, password, force); await Self.sync(user.name, password, force);
}; };
}; };

View File

@ -25,16 +25,16 @@ module.exports = Self => {
}); });
Self.sync = async function(userName, password, force) { Self.sync = async function(userName, password, force) {
let $ = Self.app.models; const models = Self.app.models;
let user = await $.Account.findOne({ const user = await models.VnUser.findOne({
fields: ['id'], fields: ['id'],
where: {name: userName} where: {name: userName}
}); });
let isSync = !await $.UserSync.exists(userName); const isSync = !await models.UserSync.exists(userName);
if (!force && isSync && user) return; if (!force && isSync && user) return;
await $.AccountConfig.syncUser(userName, password); await models.AccountConfig.syncUser(userName, password);
await $.UserSync.destroyById(userName); await models.UserSync.destroyById(userName);
}; };
}; };

View File

@ -23,6 +23,9 @@
"RoleConfig": { "RoleConfig": {
"dataSource": "vn" "dataSource": "vn"
}, },
"RoleLog": {
"dataSource": "vn"
},
"RoleInherit": { "RoleInherit": {
"dataSource": "vn" "dataSource": "vn"
}, },
@ -38,7 +41,10 @@
"SipConfig": { "SipConfig": {
"dataSource": "vn" "dataSource": "vn"
}, },
"UserAccount": { "Account": {
"dataSource": "vn"
},
"UserLog": {
"dataSource": "vn" "dataSource": "vn"
}, },
"UserPassword": { "UserPassword": {
@ -47,4 +53,4 @@
"UserSync": { "UserSync": {
"dataSource": "vn" "dataSource": "vn"
} }
} }

View File

@ -100,7 +100,7 @@ module.exports = Self => {
if (['administrator', 'root'].indexOf(userName) >= 0) if (['administrator', 'root'].indexOf(userName) >= 0)
return; return;
let user = await $.Account.findOne({ let user = await $.VnUser.findOne({
where: {name: userName}, where: {name: userName},
fields: [ fields: [
'id', 'id',
@ -138,7 +138,7 @@ module.exports = Self => {
}; };
if (user) { if (user) {
let exists = await $.UserAccount.exists(user.id); let exists = await $.Account.exists(user.id);
Object.assign(info, { Object.assign(info, {
hasAccount: user.active && exists, hasAccount: user.active && exists,
corporateMail: `${userName}@${this.domain}`, corporateMail: `${userName}@${this.domain}`,
@ -177,11 +177,11 @@ module.exports = Self => {
async syncUser(userName, info, password) { async syncUser(userName, info, password) {
if (info.user && password) if (info.user && password)
await app.models.user.setPassword(info.user.id, password); await app.models.VnUser.setPassword(info.user.id, password);
}, },
async getUsers(usersToSync) { async getUsers(usersToSync) {
let accounts = await app.models.UserAccount.find({ let accounts = await app.models.Account.find({
fields: ['id'], fields: ['id'],
include: { include: {
relation: 'user', relation: 'user',

View File

@ -0,0 +1,10 @@
module.exports = Self => {
require('../methods/account/sync')(Self);
require('../methods/account/sync-by-id')(Self);
require('../methods/account/sync-all')(Self);
require('../methods/account/login')(Self);
require('../methods/account/logout')(Self);
require('../methods/account/change-password')(Self);
require('../methods/account/set-password')(Self);
};

View File

@ -0,0 +1,42 @@
{
"name": "Account",
"base": "VnModel",
"options": {
"mysql": {
"table": "account.account"
}
},
"properties": {
"id": {
"id": true
}
},
"relations": {
"user": {
"type": "belongsTo",
"model": "VnUser",
"foreignKey": "id"
},
"aliases": {
"type": "hasMany",
"model": "MailAliasAccount",
"foreignKey": "account"
}
},
"acls": [
{
"property": "login",
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
},
{
"property": "logout",
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW"
}
]
}

View File

@ -5,7 +5,7 @@ const crypto = require('crypto');
const nthash = require('smbhash').nthash; const nthash = require('smbhash').nthash;
module.exports = Self => { module.exports = Self => {
const shouldSync = process.env.NODE_ENV !== 'test'; const shouldSync = process.env.NODE_ENV === 'production';
Self.getSynchronizer = async function() { Self.getSynchronizer = async function() {
return await Self.findOne({ return await Self.findOne({
@ -32,7 +32,6 @@ module.exports = Self => {
}, },
async syncUser(userName, info, password) { async syncUser(userName, info, password) {
let { let {
client, client,
accountConfig accountConfig
@ -212,7 +211,7 @@ module.exports = Self => {
} }
} }
} }
await applyOperations(deleteGroups, 'delete'); await applyOperations(deleteGroups, 'delete');
await applyOperations(addGroups, 'add'); await applyOperations(addGroups, 'add');
}, },
@ -248,7 +247,7 @@ module.exports = Self => {
return {key: e.inheritsFrom, val: e.role}; return {key: e.inheritsFrom, val: e.role};
}); });
let accounts = await $.UserAccount.find({ let accounts = await $.Account.find({
fields: ['id'], fields: ['id'],
include: { include: {
relation: 'user', relation: 'user',

View File

@ -20,7 +20,7 @@
}, },
"user": { "user": {
"type": "belongsTo", "type": "belongsTo",
"model": "Account", "model": "VnUser",
"foreignKey": "account" "foreignKey": "account"
} }
} }

View File

@ -18,7 +18,7 @@
"relations": { "relations": {
"user": { "user": {
"type": "belongsTo", "type": "belongsTo",
"model": "Account", "model": "VnUser",
"foreignKey": "account" "foreignKey": "account"
} }
} }

View File

@ -0,0 +1,58 @@
{
"name": "RoleLog",
"base": "VnModel",
"options": {
"mysql": {
"table": "account.roleLog"
}
},
"properties": {
"id": {
"id": true,
"type": "number",
"forceId": false
},
"originFk": {
"type": "number",
"required": true
},
"userFk": {
"type": "number"
},
"action": {
"type": "string",
"required": true
},
"changedModel": {
"type": "string"
},
"oldInstance": {
"type": "object"
},
"newInstance": {
"type": "object"
},
"creationDate": {
"type": "date"
},
"changedModelId": {
"type": "number"
},
"changedModelValue": {
"type": "string"
},
"description": {
"type": "string"
}
},
"relations": {
"user": {
"type": "belongsTo",
"model": "Account",
"foreignKey": "userFk"
}
},
"scope": {
"order": ["creationDate DESC", "id DESC"]
}
}

View File

@ -10,7 +10,7 @@ module.exports = Self => {
async syncUser(userName, info, password) { async syncUser(userName, info, password) {
if (!info.hasAccount || !password) return; if (!info.hasAccount || !password) return;
await app.models.Account.rawSql('CALL pbx.sip_setPassword(?, ?)', await app.models.VnUser.rawSql('CALL pbx.sip_setPassword(?, ?)',
[info.user.id, password] [info.user.id, password]
); );
} }

View File

@ -23,7 +23,7 @@
"relations": { "relations": {
"user": { "user": {
"type": "belongsTo", "type": "belongsTo",
"model": "Account", "model": "VnUser",
"foreignKey": "user_id" "foreignKey": "user_id"
} }
} }

View File

@ -1,6 +0,0 @@
module.exports = Self => {
require('../methods/user-account/sync')(Self);
require('../methods/user-account/sync-by-id')(Self);
require('../methods/user-account/sync-all')(Self);
};

View File

@ -1,26 +0,0 @@
{
"name": "UserAccount",
"base": "VnModel",
"options": {
"mysql": {
"table": "account.account"
}
},
"properties": {
"id": {
"id": true
}
},
"relations": {
"user": {
"type": "belongsTo",
"model": "Account",
"foreignKey": "id"
},
"aliases": {
"type": "hasMany",
"model": "MailAliasAccount",
"foreignKey": "account"
}
}
}

View File

@ -3,7 +3,7 @@
"base": "VnModel", "base": "VnModel",
"options": { "options": {
"mysql": { "mysql": {
"table": "userLog" "table": "account.userLog"
} }
}, },
"properties": { "properties": {
@ -16,7 +16,7 @@
"type": "number", "type": "number",
"required": true "required": true
}, },
"userFk": { "userFk": {
"type": "number" "type": "number"
}, },
"action": { "action": {
@ -48,9 +48,9 @@
"relations": { "relations": {
"user": { "user": {
"type": "belongsTo", "type": "belongsTo",
"model": "Account", "model": "VnUser",
"foreignKey": "userFk" "foreignKey": "userFk"
} }
}, },
"scope": { "scope": {
"order": ["creationDate DESC", "id DESC"] "order": ["creationDate DESC", "id DESC"]

View File

@ -5,7 +5,7 @@ import UserError from 'core/lib/user-error';
export default class Controller extends Section { export default class Controller extends Section {
onSynchronizeAll() { onSynchronizeAll() {
this.vnApp.showSuccess(this.$t('Synchronizing in the background')); this.vnApp.showSuccess(this.$t('Synchronizing in the background'));
this.$http.patch(`UserAccounts/syncAll`) this.$http.patch(`Accounts/syncAll`)
.then(() => this.vnApp.showSuccess(this.$t('Users synchronized!'))); .then(() => this.vnApp.showSuccess(this.$t('Users synchronized!')));
} }
@ -17,7 +17,7 @@ export default class Controller extends Section {
password: this.syncPassword, password: this.syncPassword,
force: true force: true
}; };
return this.$http.patch(`UserAccounts/${this.syncUser}/sync`, params) return this.$http.patch(`Accounts/${this.syncUser}/sync`, params)
.then(() => this.vnApp.showSuccess(this.$t('User synchronized!'))); .then(() => this.vnApp.showSuccess(this.$t('User synchronized!')));
} }

View File

@ -1,6 +1,6 @@
<vn-watcher <vn-watcher
vn-id="watcher" vn-id="watcher"
url="Accounts" url="VnUsers"
data="$ctrl.user" data="$ctrl.user"
id-value="$ctrl.$params.id" id-value="$ctrl.$params.id"
form="form"> form="form">
@ -14,25 +14,25 @@
<vn-textfield <vn-textfield
label="User" label="User"
ng-model="$ctrl.user.name" ng-model="$ctrl.user.name"
rule rule="VnUser"
vn-focus> vn-focus>
</vn-textfield> </vn-textfield>
<vn-textfield <vn-textfield
label="Nickname" label="Nickname"
ng-model="$ctrl.user.nickname" ng-model="$ctrl.user.nickname"
rule> rule="VnUser">
</vn-textfield> </vn-textfield>
<vn-textfield <vn-textfield
label="Personal email" label="Personal email"
ng-model="$ctrl.user.email" ng-model="$ctrl.user.email"
rule> rule="VnUser">
</vn-textfield> </vn-textfield>
<vn-autocomplete <vn-autocomplete
label="Language" label="Language"
ng-model="$ctrl.user.lang" ng-model="$ctrl.user.lang"
url="Languages" url="Languages"
value-field="code" value-field="code"
rule> rule="VnUser">
</vn-autocomplete> </vn-autocomplete>
</vn-vertical> </vn-vertical>
</vn-card> </vn-card>

View File

@ -14,9 +14,9 @@ class Controller extends ModuleCard {
}; };
return Promise.all([ return Promise.all([
this.$http.get(`Accounts/${this.$params.id}`, {filter}) this.$http.get(`VnUsers/${this.$params.id}`, {filter})
.then(res => this.user = res.data), .then(res => this.user = res.data),
this.$http.get(`UserAccounts/${this.$params.id}/exists`) this.$http.get(`Accounts/${this.$params.id}/exists`)
.then(res => this.hasAccount = res.data.exists) .then(res => this.hasAccount = res.data.exists)
]); ]);
} }

View File

@ -15,8 +15,8 @@ describe('component vnUserCard', () => {
it('should reload the controller data', () => { it('should reload the controller data', () => {
controller.$params.id = 1; controller.$params.id = 1;
$httpBackend.expectGET('Accounts/1').respond('foo'); $httpBackend.expectGET('VnUsers/1').respond('foo');
$httpBackend.expectGET('UserAccounts/1/exists').respond({exists: true}); $httpBackend.expectGET('Accounts/1/exists').respond({exists: true});
controller.reload(); controller.reload();
$httpBackend.flush(); $httpBackend.flush();

View File

@ -1,6 +1,6 @@
<vn-watcher <vn-watcher
vn-id="watcher" vn-id="watcher"
url="Accounts" url="VnUsers"
data="$ctrl.user" data="$ctrl.user"
insert-mode="true" insert-mode="true"
form="form"> form="form">
@ -14,24 +14,24 @@
<vn-textfield <vn-textfield
label="Name" label="Name"
ng-model="$ctrl.user.name" ng-model="$ctrl.user.name"
rule rule="VnUser"
vn-focus> vn-focus>
</vn-textfield> </vn-textfield>
<vn-textfield <vn-textfield
label="Nickname" label="Nickname"
ng-model="$ctrl.user.nickname" ng-model="$ctrl.user.nickname"
rule> rule="VnUser">
</vn-textfield> </vn-textfield>
<vn-textfield <vn-textfield
label="Email" label="Email"
ng-model="$ctrl.user.email" ng-model="$ctrl.user.email"
rule> rule="VnUser">
</vn-textfield> </vn-textfield>
<vn-autocomplete <vn-autocomplete
label="Role" label="Role"
ng-model="$ctrl.user.roleFk" ng-model="$ctrl.user.roleFk"
url="Roles" url="Roles"
rule> rule="VnUser">
</vn-autocomplete> </vn-autocomplete>
<vn-textfield <vn-textfield
label="Password" label="Password"

View File

@ -20,12 +20,12 @@ class Controller extends Descriptor {
this.hasAccount = null; this.hasAccount = null;
if (!value) return; if (!value) return;
this.$http.get(`UserAccounts/${value.id}/exists`) this.$http.get(`Accounts/${value.id}/exists`)
.then(res => this.hasAccount = res.data.exists); .then(res => this.hasAccount = res.data.exists);
} }
onDelete() { onDelete() {
return this.$http.delete(`Accounts/${this.id}`) return this.$http.delete(`VnUsers/${this.id}`)
.then(() => this.$state.go('account.index')) .then(() => this.$state.go('account.index'))
.then(() => this.vnApp.showSuccess(this.$t('User removed'))); .then(() => this.vnApp.showSuccess(this.$t('User removed')));
} }
@ -69,12 +69,12 @@ class Controller extends Descriptor {
} }
onEnableAccount() { onEnableAccount() {
return this.$http.post(`UserAccounts`, {id: this.id}) return this.$http.post(`Accounts`, {id: this.id})
.then(() => this.onSwitchAccount(true)); .then(() => this.onSwitchAccount(true));
} }
onDisableAccount() { onDisableAccount() {
return this.$http.delete(`UserAccounts/${this.id}`) return this.$http.delete(`Accounts/${this.id}`)
.then(() => this.onSwitchAccount(false)); .then(() => this.onSwitchAccount(false));
} }
@ -88,7 +88,7 @@ class Controller extends Descriptor {
} }
onSetActive(active) { onSetActive(active) {
return this.$http.patch(`Accounts/${this.id}`, {active}) return this.$http.patch(`VnUsers/${this.id}`, {active})
.then(() => { .then(() => {
this.user.active = active; this.user.active = active;
const message = active const message = active

View File

@ -10,7 +10,7 @@ describe('component vnUserDescriptor', () => {
beforeEach(inject(($componentController, _$httpBackend_) => { beforeEach(inject(($componentController, _$httpBackend_) => {
$httpBackend = _$httpBackend_; $httpBackend = _$httpBackend_;
$httpBackend.whenGET('UserAccounts/1/exists').respond({exists: true}); $httpBackend.whenGET('Accounts/1/exists').respond({exists: true});
controller = $componentController('vnUserDescriptor', {$element: null}, {user}); controller = $componentController('vnUserDescriptor', {$element: null}, {user});
jest.spyOn(controller, 'emit'); jest.spyOn(controller, 'emit');
@ -21,7 +21,7 @@ describe('component vnUserDescriptor', () => {
it('should delete entity and go to index', () => { it('should delete entity and go to index', () => {
controller.$state.go = jest.fn(); controller.$state.go = jest.fn();
$httpBackend.expectDELETE('Accounts/1').respond(); $httpBackend.expectDELETE('VnUsers/1').respond();
controller.onDelete(); controller.onDelete();
$httpBackend.flush(); $httpBackend.flush();
@ -61,7 +61,7 @@ describe('component vnUserDescriptor', () => {
describe('onEnableAccount()', () => { describe('onEnableAccount()', () => {
it('should make request to enable account', () => { it('should make request to enable account', () => {
$httpBackend.expectPOST('UserAccounts', {id: 1}).respond(); $httpBackend.expectPOST('Accounts', {id: 1}).respond();
controller.onEnableAccount(); controller.onEnableAccount();
$httpBackend.flush(); $httpBackend.flush();
@ -73,7 +73,7 @@ describe('component vnUserDescriptor', () => {
describe('onDisableAccount()', () => { describe('onDisableAccount()', () => {
it('should make request to disable account', () => { it('should make request to disable account', () => {
$httpBackend.expectDELETE('UserAccounts/1').respond(); $httpBackend.expectDELETE('Accounts/1').respond();
controller.onDisableAccount(); controller.onDisableAccount();
$httpBackend.flush(); $httpBackend.flush();
@ -85,7 +85,7 @@ describe('component vnUserDescriptor', () => {
describe('onSetActive()', () => { describe('onSetActive()', () => {
it('should make request to activate/deactivate the user', () => { it('should make request to activate/deactivate the user', () => {
$httpBackend.expectPATCH('Accounts/1', {active: true}).respond(); $httpBackend.expectPATCH('VnUsers/1', {active: true}).respond();
controller.onSetActive(true); controller.onSetActive(true);
$httpBackend.flush(); $httpBackend.flush();

View File

@ -19,3 +19,5 @@ import './ldap';
import './samba'; import './samba';
import './accounts'; import './accounts';
import './privileges'; import './privileges';
import './user-log';
import './role-log';

View File

@ -8,4 +8,5 @@ Role: Rol
Mail aliases: Alias de correo Mail aliases: Alias de correo
Account not enabled: Cuenta no habilitada Account not enabled: Cuenta no habilitada
Inherited roles: Roles heredados Inherited roles: Roles heredados
Go to the user: Ir al usuario Go to the user: Ir al usuario
Log: Histórico

View File

@ -1,6 +1,6 @@
<vn-crud-model <vn-crud-model
vn-id="model" vn-id="model"
url="Accounts" url="VnUsers"
filter="::$ctrl.filter" filter="::$ctrl.filter"
limit="20"> limit="20">
</vn-crud-model> </vn-crud-model>

View File

@ -1,7 +1,7 @@
<mg-ajax path="Accounts/{{post.params.id}}/privileges" options="vnPost"></mg-ajax> <mg-ajax path="VnUsers/{{post.params.id}}/privileges" options="vnPost"></mg-ajax>
<vn-watcher <vn-watcher
vn-id="watcher" vn-id="watcher"
url="Accounts" url="VnUsers"
data="$ctrl.user" data="$ctrl.user"
id-value="$ctrl.$params.id" id-value="$ctrl.$params.id"
form="form" form="form"

View File

@ -0,0 +1 @@
<vn-log url="RoleLogs" origin-id="$ctrl.$params.id"></vn-log>

View File

@ -0,0 +1,7 @@
import ngModule from '../module';
import Section from 'salix/components/section';
ngModule.vnComponent('vnRoleLog', {
template: require('./index.html'),
controller: Section,
});

Some files were not shown because too many files have changed in this diff Show More