Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 084200-footerAlbaranReport

This commit is contained in:
Carlos Satorres 2023-04-26 09:03:37 +02:00
commit 57ec0f8587
266 changed files with 9871 additions and 2025 deletions

View File

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

View File

@ -1,9 +1,9 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('campaign latest()', () => {
it('should return the campaigns from the last year', async() => {
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 campaignDated = result[randomIndex].dated;
@ -14,7 +14,7 @@ describe('campaign latest()', () => {
it('should return the campaigns from the current year', async() => {
const now = Date.vnNew();
const currentYear = now.getFullYear();
const result = await app.models.Campaign.latest({
const result = await models.Campaign.latest({
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()', () => {
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 now = Date.vnNew();

View File

@ -26,7 +26,7 @@ module.exports = Self => {
Self.send = async(ctx, to, message) => {
const models = Self.app.models;
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('@', '');
if (sender.name != recipient) {

View File

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

View File

@ -58,7 +58,7 @@ module.exports = Self => {
const models = Self.app.models;
const recipientName = chat.recipient.slice(1);
const recipient = await models.Account.findOne({
const recipient = await models.VnUser.findOne({
where: {
name: recipientName
}
@ -104,7 +104,7 @@ module.exports = Self => {
}
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 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()', () => {
const ctx = {req: {accessToken: {userId: 1}}};
ctx.req.__ = value => {
return value;
};
const chatModel = app.models.Chat;
const osTicketModel = app.models.OsTicket;
const chatModel = models.Chat;
const osTicketModel = models.OsTicket;
const departmentId = 31;
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
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;
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()', () => {
it('should return true as response', async() => {
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);
});
it('should return false as response', async() => {
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);
});

View File

@ -1,8 +1,8 @@
const app = require('vn-loopback/server/server');
const {models} = require('vn-loopback/server/server');
describe('getSectors()', () => {
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[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()', () => {
it('should return a new collection', async() => {
pending('#3400 analizar que hacer con rutas de back collection');
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[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()', () => {
let dmsId = 1;
@ -6,7 +6,7 @@ describe('dms downloadFile()', () => {
it('should return a response for an employee with text content-type', async() => {
let workerId = 1107;
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');
});
@ -16,7 +16,7 @@ describe('dms downloadFile()', () => {
let ctx = {req: {accessToken: {userId: clientId}}};
let error;
await app.models.Dms.downloadFile(ctx, dmsId).catch(e => {
await models.Dms.downloadFile(ctx, dmsId).catch(e => {
error = e;
}).finally(() => {
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()', () => {
let dmsId = 1;
@ -8,7 +8,7 @@ describe('dms removeFile()', () => {
let ctx = {req: {accessToken: {userId: clientId}}};
let error;
await app.models.Dms.removeFile(ctx, dmsId).catch(e => {
await models.Dms.removeFile(ctx, dmsId).catch(e => {
error = e;
}).finally(() => {
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()', () => {
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 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;
}).finally(() => {
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()', () => {
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 error;
await app.models.Dms.uploadFile(ctx).catch(e => {
await models.Dms.uploadFile(ctx).catch(e => {
error = e;
}).finally(() => {
expect(error.message).toEqual(`You don't have enough privileges`);

130
back/methods/image/scrub.js Normal file
View File

@ -0,0 +1,130 @@
const fs = require('fs-extra');
const path = require('path');
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethod('scrub', {
description: 'Deletes images without database reference',
accessType: 'WRITE',
accepts: [
{
arg: 'collection',
type: 'string',
description: 'The collection name',
required: true
}, {
arg: 'remove',
type: 'boolean',
description: 'Delete instead of move images to trash'
}, {
arg: 'limit',
type: 'integer',
description: 'Maximum number of images to clean'
}, {
arg: 'dryRun',
type: 'boolean',
description: 'Simulate actions'
}, {
arg: 'skipLock',
type: 'boolean',
description: 'Wether to skip exclusive lock'
}
],
returns: {
type: 'integer',
root: true
},
http: {
path: `/scrub`,
verb: 'POST'
}
});
Self.scrub = async function(collection, remove, limit, dryRun, skipLock) {
const $ = Self.app.models;
const env = process.env.NODE_ENV;
dryRun = dryRun || (env && env !== 'production');
const instance = await $.ImageCollection.findOne({
fields: ['id'],
where: {name: collection}
});
if (!instance)
throw new UserError('Collection does not exist');
const container = await $.ImageContainer.container(collection);
const rootPath = container.client.root;
let tx;
let opts;
const lockName = 'salix.Image.scrub';
if (!skipLock) {
tx = await Self.beginTransaction({timeout: null});
opts = {transaction: tx};
const [row] = await Self.rawSql(
`SELECT GET_LOCK(?, 10) hasLock`, [lockName], opts);
if (!row.hasLock)
throw new UserError('Cannot obtain exclusive lock');
}
try {
const now = Date.vnNew().toJSON();
const scrubDir = path.join(rootPath, '.scrub', now);
const collectionDir = path.join(rootPath, collection);
const sizes = await fs.readdir(collectionDir);
let cleanCount = 0;
mainLoop: for (const size of sizes) {
const sizeDir = path.join(collectionDir, size);
const scrubSizeDir = path.join(scrubDir, collection, size);
const images = await fs.readdir(sizeDir);
for (const image of images) {
const imageName = path.parse(image).name;
const count = await Self.count({
collectionFk: collection,
name: imageName
}, opts);
const exists = count > 0;
let scrubDirCreated = false;
if (!exists) {
const srcFile = path.join(sizeDir, image);
if (remove !== true) {
if (!scrubDirCreated) {
if (!dryRun)
await fs.mkdir(scrubSizeDir, {recursive: true});
scrubDirCreated = true;
}
const dstFile = path.join(scrubSizeDir, image);
if (!dryRun) await fs.rename(srcFile, dstFile);
} else {
try {
if (!dryRun) await fs.unlink(srcFile);
} catch (err) {
console.error(err.message);
}
}
cleanCount++;
if (limit && cleanCount == limit)
break mainLoop;
}
}
}
return cleanCount;
} finally {
if (!skipLock) {
try {
await Self.rawSql(`DO RELEASE_LOCK(?)`, [lockName], opts);
await tx.rollback();
} catch (err) {
console.error(err.message);
}
}
}
};
};

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server');
const {models} = require('vn-loopback/server/server');
describe('image download()', () => {
const collection = 'user';
@ -8,7 +8,7 @@ describe('image download()', () => {
it('should return the image content-type of the user', async() => {
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];
expect(contentType).toEqual('image/png');
@ -16,7 +16,7 @@ describe('image download()', () => {
it(`should return false if the user doesn't have image`, async() => {
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();
});

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server');
const {models} = require('vn-loopback/server/server');
describe('image upload()', () => {
describe('as buyer', () => {
@ -16,7 +16,7 @@ describe('image upload()', () => {
let error;
try {
await app.models.Image.upload(ctx);
await models.Image.upload(ctx);
} catch (err) {
error = err;
}
@ -25,7 +25,7 @@ describe('image upload()', () => {
});
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');
const ctx = {req: {accessToken: {userId: buyerId}},
@ -36,7 +36,7 @@ describe('image upload()', () => {
};
try {
await app.models.Image.upload(ctx);
await models.Image.upload(ctx);
} catch (err) { }
expect(containerModel.upload).toHaveBeenCalled();
@ -49,7 +49,7 @@ describe('image upload()', () => {
const itemId = 4;
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');
const ctx = {req: {accessToken: {userId: marketingId}},
@ -60,14 +60,14 @@ describe('image upload()', () => {
};
try {
await app.models.Image.upload(ctx);
await models.Image.upload(ctx);
} catch (err) { }
expect(containerModel.upload).toHaveBeenCalled();
});
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');
const ctx = {req: {accessToken: {userId: marketingId}},
@ -78,7 +78,7 @@ describe('image upload()', () => {
};
try {
await app.models.Image.upload(ctx);
await models.Image.upload(ctx);
} catch (err) { }
expect(containerModel.upload).toHaveBeenCalled();
@ -91,7 +91,7 @@ describe('image upload()', () => {
const itemId = 4;
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');
const ctx = {req: {accessToken: {userId: hhrrId}},
@ -102,7 +102,7 @@ describe('image upload()', () => {
};
try {
await app.models.Image.upload(ctx);
await models.Image.upload(ctx);
} catch (err) { }
expect(containerModel.upload).toHaveBeenCalled();
@ -118,7 +118,7 @@ describe('image upload()', () => {
let error;
try {
await app.models.Image.upload(ctx);
await models.Image.upload(ctx);
} catch (err) {
error = err;
}

View File

@ -12,13 +12,13 @@ module.exports = Self => {
type: 'Number',
description: 'The entity id',
required: true
},
{
}, {
arg: 'collection',
type: 'string',
description: 'The collection name',
required: true
}],
}
],
returns: {
type: 'Object',
root: true

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');
describe('getStarredModules()', () => {
@ -19,13 +19,13 @@ describe('getStarredModules()', () => {
});
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 starredModules = await app.models.StarredModule.getStarredModules(ctx);
const newStarred = await models.StarredModule.create({workerFk: 9, moduleFk: 'customer', position: 1});
const starredModules = await models.StarredModule.getStarredModules(ctx);
expect(starredModules.length).toEqual(1);
expect(starredModules[0].moduleFk).toEqual('customer');
// 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');
describe('setPosition()', () => {
@ -21,7 +21,7 @@ describe('setPosition()', () => {
});
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 = {
where: {
@ -32,24 +32,24 @@ describe('setPosition()', () => {
try {
const options = {transaction: tx};
await app.models.StarredModule.toggleStarredModule(ctx, 'order', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options);
await models.StarredModule.toggleStarredModule(ctx, 'order', 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';
let clients = await app.models.StarredModule.findOne(filter, options);
let clients = await models.StarredModule.findOne(filter, options);
expect(orders.position).toEqual(1);
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';
clients = await app.models.StarredModule.findOne(filter, options);
clients = await models.StarredModule.findOne(filter, options);
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(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() => {
const tx = await app.models.StarredModule.beginTransaction({});
const tx = await models.StarredModule.beginTransaction({});
const filter = {
where: {
@ -73,24 +73,24 @@ describe('setPosition()', () => {
try {
const options = {transaction: tx};
await app.models.StarredModule.toggleStarredModule(ctx, 'order', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options);
await models.StarredModule.toggleStarredModule(ctx, 'order', 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';
let clients = await app.models.StarredModule.findOne(filter, options);
let clients = await models.StarredModule.findOne(filter, options);
expect(orders.position).toEqual(1);
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';
orders = await app.models.StarredModule.findOne(filter, options);
orders = await models.StarredModule.findOne(filter, options);
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(clients.position).toEqual(1);
@ -103,7 +103,7 @@ describe('setPosition()', () => {
});
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 = {
where: {
@ -115,29 +115,29 @@ describe('setPosition()', () => {
try {
const options = {transaction: tx};
await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'order', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'order', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'item', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'claim', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'order', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'zone', options);
await models.StarredModule.toggleStarredModule(ctx, 'customer', options);
await models.StarredModule.toggleStarredModule(ctx, 'order', options);
await models.StarredModule.toggleStarredModule(ctx, 'customer', options);
await models.StarredModule.toggleStarredModule(ctx, 'order', options);
await models.StarredModule.toggleStarredModule(ctx, 'item', options);
await models.StarredModule.toggleStarredModule(ctx, 'claim', options);
await models.StarredModule.toggleStarredModule(ctx, 'customer', options);
await models.StarredModule.toggleStarredModule(ctx, 'order', 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';
const claims = await app.models.StarredModule.findOne(filter, options);
const claims = await models.StarredModule.findOne(filter, options);
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';
let orders = await app.models.StarredModule.findOne(filter, options);
let orders = await models.StarredModule.findOne(filter, options);
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(claims.position).toEqual(2);
@ -145,13 +145,13 @@ describe('setPosition()', () => {
expect(orders.position).toEqual(4);
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';
orders = await app.models.StarredModule.findOne(filter, options);
orders = await models.StarredModule.findOne(filter, options);
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(clients.position).toEqual(4);
@ -164,7 +164,7 @@ describe('setPosition()', () => {
});
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 = {
where: {
@ -176,25 +176,25 @@ describe('setPosition()', () => {
try {
const options = {transaction: tx};
await app.models.StarredModule.toggleStarredModule(ctx, 'item', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'claim', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'order', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'zone', options);
await models.StarredModule.toggleStarredModule(ctx, 'item', options);
await models.StarredModule.toggleStarredModule(ctx, 'customer', options);
await models.StarredModule.toggleStarredModule(ctx, 'claim', options);
await models.StarredModule.toggleStarredModule(ctx, 'order', 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';
let clients = await app.models.StarredModule.findOne(filter, options);
let clients = await models.StarredModule.findOne(filter, options);
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';
let orders = await app.models.StarredModule.findOne(filter, options);
let orders = await models.StarredModule.findOne(filter, options);
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(clients.position).toEqual(2);
@ -202,14 +202,14 @@ describe('setPosition()', () => {
expect(orders.position).toEqual(4);
expect(zones.position).toEqual(5);
await app.models.StarredModule.toggleStarredModule(ctx, 'claim', options);
await app.models.StarredModule.setPosition(ctx, 'customer', 'right', options);
await models.StarredModule.toggleStarredModule(ctx, 'claim', options);
await models.StarredModule.setPosition(ctx, 'customer', 'right', options);
filter.where.moduleFk = 'customer';
clients = await app.models.StarredModule.findOne(filter, options);
clients = await models.StarredModule.findOne(filter, options);
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(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');
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() => {
const starredModule = await app.models.StarredModule.toggleStarredModule(ctx, 'order');
let starredModules = await app.models.StarredModule.getStarredModules(ctx);
const starredModule = await models.StarredModule.toggleStarredModule(ctx, 'order');
let starredModules = await models.StarredModule.getStarredModules(ctx);
expect(starredModules.length).toEqual(1);
expect(starredModule.moduleFk).toEqual('order');
expect(starredModule.workerFk).toEqual(activeCtx.accessToken.userId);
expect(starredModule.position).toEqual(starredModules.length);
await app.models.StarredModule.toggleStarredModule(ctx, 'order');
starredModules = await app.models.StarredModule.getStarredModules(ctx);
await models.StarredModule.toggleStarredModule(ctx, 'order');
starredModules = await models.StarredModule.getStarredModules(ctx);
expect(starredModules.length).toEqual(0);
});

View File

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

View File

@ -1,9 +1,14 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('privileges', {
Self.remoteMethod('privileges', {
description: 'Change role and hasGrant if user has privileges',
accepts: [
{
arg: 'ctx',
type: 'Object',
http: {source: 'context'}
},
{
arg: 'id',
type: 'number',
@ -39,9 +44,9 @@ module.exports = Self => {
if (typeof options == 'object')
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'],
include: {
relation: 'role',
@ -54,7 +59,7 @@ module.exports = Self => {
if (!user.hasGrant)
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)
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) {
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)
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 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;
if (!usesEmail) {
const account = await models.Account.findOne({
const account = await models.VnUser.findOne({
fields: ['email'],
where: {name: user}
});
@ -28,7 +28,7 @@ module.exports = Self => {
}
try {
await models.user.resetPassword({email: user, emailTemplate: 'recover-password'});
await Self.resetPassword({email: user, emailTemplate: 'recover-password'});
} catch (err) {
if (err.code === 'EMAIL_NOT_FOUND')
return;

View File

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

View File

@ -1,6 +1,6 @@
const models = require('vn-loopback/server/server').models;
describe('account privileges()', () => {
describe('VnUser privileges()', () => {
const employeeId = 1;
const developerId = 9;
const sysadminId = 66;
@ -10,13 +10,13 @@ describe('account privileges()', () => {
it('should throw an error when user not has privileges', async() => {
const ctx = {req: {accessToken: {userId: developerId}}};
const tx = await models.Account.beginTransaction({});
const tx = await models.VnUser.beginTransaction({});
let error;
try {
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();
} catch (e) {
@ -29,13 +29,13 @@ describe('account privileges()', () => {
it('should throw an error when user has privileges but not has the role', async() => {
const ctx = {req: {accessToken: {userId: sysadminId}}};
const tx = await models.Account.beginTransaction({});
const tx = await models.VnUser.beginTransaction({});
let error;
try {
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();
} 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() => {
const ctx = {req: {accessToken: {userId: sysadminId}}};
const tx = await models.Account.beginTransaction({});
const tx = await models.VnUser.beginTransaction({});
let error;
try {
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();
} catch (e) {
@ -67,7 +67,7 @@ describe('account privileges()', () => {
it('should change role', async() => {
const ctx = {req: {accessToken: {userId: sysadminId}}};
const tx = await models.Account.beginTransaction({});
const tx = await models.VnUser.beginTransaction({});
const options = {transaction: tx};
const agency = await models.Role.findOne({
@ -79,8 +79,8 @@ describe('account privileges()', () => {
let error;
let result;
try {
await models.Account.privileges(ctx, clarkKent, agency.id, null, options);
result = await models.Account.findById(clarkKent, null, options);
await models.VnUser.privileges(ctx, clarkKent, agency.id, null, options);
result = await models.VnUser.findById(clarkKent, null, options);
await tx.rollback();
} catch (e) {
@ -94,14 +94,14 @@ describe('account privileges()', () => {
it('should change hasGrant', async() => {
const ctx = {req: {accessToken: {userId: sysadminId}}};
const tx = await models.Account.beginTransaction({});
const tx = await models.VnUser.beginTransaction({});
let error;
let result;
try {
const options = {transaction: tx};
await models.Account.privileges(ctx, clarkKent, null, true, options);
result = await models.Account.findById(clarkKent, null, options);
await models.VnUser.privileges(ctx, clarkKent, null, true, options);
result = await models.VnUser.findById(clarkKent, null, options);
await tx.rollback();
} 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', () => {
it('should return the token', async() => {
let login = await app.models.Account.login('salesAssistant', 'nightmare');
let accessToken = await app.models.AccessToken.findById(login.token);
let login = await models.VnUser.signIn('salesAssistant', 'nightmare');
let accessToken = await models.AccessToken.findById(login.token);
let ctx = {req: {accessToken: accessToken}};
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() => {
let login = await app.models.Account.login('PetterParker', 'nightmare');
let accessToken = await app.models.AccessToken.findById(login.token);
let login = await models.VnUser.signIn('PetterParker', 'nightmare');
let accessToken = await models.AccessToken.findById(login.token);
let ctx = {req: {accessToken: accessToken}};
expect(login.token).toBeDefined();
await app.models.Account.logout(ctx);
await models.VnUser.signOut(ctx);
});
});
@ -28,7 +28,7 @@ describe('account login()', () => {
let error;
try {
await app.models.Account.login('IDontExist', 'TotallyWrongPassword');
await models.VnUser.signIn('IDontExist', 'TotallyWrongPassword');
} catch (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() => {
let loginResponse = await app.models.Account.login('buyer', 'nightmare');
let accessToken = await app.models.AccessToken.findById(loginResponse.token);
let loginResponse = await models.VnUser.signOut('buyer', 'nightmare');
let accessToken = await models.AccessToken.findById(loginResponse.token);
let ctx = {req: {accessToken: accessToken}};
let logoutResponse = await app.models.Account.logout(ctx);
let tokenAfterLogout = await app.models.AccessToken.findById(loginResponse.token);
let logoutResponse = await models.VnUser.signOut(ctx);
let tokenAfterLogout = await models.AccessToken.findById(loginResponse.token);
expect(logoutResponse).toBeTrue();
expect(tokenAfterLogout).toBeNull();
@ -18,7 +18,7 @@ describe('account logout()', () => {
let ctx = {req: {accessToken: {id: 'invalidToken'}}};
try {
response = await app.models.Account.logout(ctx);
response = await models.VnUser.signOut(ctx);
} catch (e) {
error = e;
}
@ -32,7 +32,7 @@ describe('account logout()', () => {
let ctx = {req: {accessToken: null}};
try {
response = await app.models.Account.logout(ctx);
response = await models.VnUser.signOut(ctx);
} catch (e) {
error = e;
}

View File

@ -1,7 +1,4 @@
{
"Account": {
"dataSource": "vn"
},
"AccountingType": {
"dataSource": "vn"
},
@ -125,10 +122,10 @@
"UserConfigView": {
"dataSource": "vn"
},
"UserLog": {
"Warehouse": {
"dataSource": "vn"
},
"Warehouse": {
"VnUser": {
"dataSource": "vn"
},
"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 requiredRole = readRole || writeRole;
const hasRequiredRole = await models.Account.hasRole(myUserId, requiredRole, options);
const isRoot = await models.Account.hasRole(myUserId, 'root', options);
const hasRequiredRole = await models.VnUser.hasRole(myUserId, requiredRole, options);
const isRoot = await models.VnUser.hasRole(myUserId, 'root', options);
if (isRoot || hasRequiredRole)
return true;

View File

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

View File

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

View File

@ -5,6 +5,7 @@ const gm = require('gm');
module.exports = Self => {
require('../methods/image/download')(Self);
require('../methods/image/upload')(Self);
require('../methods/image/scrub')(Self);
Self.resize = async function({collectionName, srcFile, fileName, entityId}) {
const models = Self.app.models;
@ -29,13 +30,14 @@ module.exports = Self => {
);
// Insert image row
const imageName = path.parse(fileName).name;
await models.Image.upsertWithWhere(
{
name: fileName,
name: imageName,
collectionFk: collectionName
},
{
name: fileName,
name: imageName,
collectionFk: collectionName,
updated: Date.vnNow() / 1000,
}
@ -49,7 +51,7 @@ module.exports = Self => {
if (entity) {
await entity.updateAttribute(
collection.property,
fileName
imageName
);
}

View File

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

View File

@ -29,7 +29,7 @@
},
"user": {
"type": "belongsTo",
"model": "Account",
"model": "VnUser",
"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', () => {
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();
});

View File

@ -1,6 +1,6 @@
const app = require('vn-loopback/server/server');
const {models} = require('vn-loopback/server/server');
describe('Dms', () => {
const Dms = app.models.Dms;
const Dms = models.Dms;
describe('getFile()', () => {
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() => {
let error = {};
try {
await app.models.Dms.getFile('NotExistentId');
await models.Dms.getFile('NotExistentId');
} catch (e) {
error = e;
}

View File

@ -1,7 +1,7 @@
const models = require('vn-loopback/server/server').models;
const LoopBackContext = require('loopback-context');
describe('account recoverPassword()', () => {
describe('VnUser recoverPassword()', () => {
const userId = 1107;
const activeCtx = {
@ -21,9 +21,9 @@ describe('account recoverPassword()', () => {
it('should send email with token', async() => {
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}});

View File

@ -1,14 +1,14 @@
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() => {
let result = await models.Account.hasRole(1, 'employee');
let result = await models.VnUser.hasRole(1, 'employee');
expect(result).toBeTruthy();
});
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();
});

View File

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

View File

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

View File

@ -53,7 +53,7 @@ async function test() {
const JunitReporter = require('jasmine-reporters');
jasmine.addReporter(new JunitReporter.JUnitXmlReporter());
jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;
jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;
jasmine.exitOnCompletion = true;
}

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,3 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('Receipt', 'receiptEmail', '*', 'ALLOW', 'ROLE', 'salesAssistant');

View File

@ -0,0 +1 @@
ALTER TABLE `vn`.`printQueueArgs` MODIFY COLUMN value varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL;

View File

@ -0,0 +1,5 @@
DROP TRIGGER `vn`.`deviceProduction_afterInsert`;
DROP TRIGGER `vn`.`deviceProduction_afterUpdate`;
DROP TRIGGER `vn`.`deviceProductionUser_afterDelete`;

View File

@ -1,12 +1,5 @@
DROP TABLE IF EXISTS `vn`.`dmsRecover`;
ALTER TABLE `vn`.`delivery` DROP COLUMN addressFk;
ALTER TABLE `vn`.`delivery` DROP CONSTRAINT delivery_ticketFk_FK;
ALTER TABLE `vn`.`delivery` DROP COLUMN ticketFk;
ALTER TABLE `vn`.`delivery` ADD ticketFk INT DEFAULT NULL;
ALTER TABLE `vn`.`delivery` ADD CONSTRAINT delivery_ticketFk_FK FOREIGN KEY (`ticketFk`) REFERENCES `vn`.`ticket`(`id`);
DROP PROCEDURE IF EXISTS vn.route_getTickets;
DROP PROCEDURE IF EXISTS `vn`.`route_getTickets`;
DELIMITER $$
$$
@ -17,14 +10,14 @@ BEGIN
* de sus tickets.
*
* @param vRouteFk
*
* @select Información de los tickets
*/
SELECT
t.id Id,
SELECT *
FROM (
SELECT t.id Id,
t.clientFk Client,
a.id Address,
a.nickname ClientName,
t.packages Packages,
a.street AddressName,
a.postalCode PostalCode,
@ -37,34 +30,48 @@ BEGIN
d.longitude Longitude,
d.latitude Latitude,
wm.mediaValue SalePersonPhone,
tob.Note Note,
t.isSigned Signed
tob.description Note,
t.isSigned Signed,
t.priority
FROM ticket t
JOIN client c ON t.clientFk = c.id
JOIN address a ON t.addressFk = a.id
LEFT JOIN delivery d ON t.id = d.ticketFk
LEFT JOIN delivery d ON d.ticketFk = t.id
LEFT JOIN workerMedia wm ON wm.workerFk = c.salesPersonFk
LEFT JOIN
(SELECT tob.description Note, t.id
LEFT JOIN(
SELECT tob.description, t.id
FROM ticketObservation tob
JOIN ticket t ON tob.ticketFk = t.id
JOIN observationType ot ON ot.id = tob.observationTypeFk
WHERE t.routeFk = vRouteFk
AND ot.code = 'delivery'
)tob ON tob.id = t.id
LEFT JOIN
(SELECT sub.ticketFk,
CONCAT('(', GROUP_CONCAT(DISTINCT sub.itemPackingTypeFk ORDER BY sub.items DESC SEPARATOR ','), ') ') itemPackingTypeFk
FROM (SELECT s.ticketFk , i.itemPackingTypeFk, COUNT(*) items
LEFT JOIN(
SELECT sub.ticketFk,
CONCAT('(',
GROUP_CONCAT(DISTINCT sub.itemPackingTypeFk
ORDER BY sub.items DESC SEPARATOR ','),
') ') itemPackingTypeFk
FROM (
SELECT s.ticketFk, i.itemPackingTypeFk, COUNT(*) items
FROM ticket t
JOIN sale s ON s.ticketFk = t.id
JOIN item i ON i.id = s.itemFk
WHERE t.routeFk = vRouteFk
GROUP BY t.id,i.itemPackingTypeFk)sub
GROUP BY t.id, i.itemPackingTypeFk
)sub
GROUP BY sub.ticketFk
)sub2 ON sub2.ticketFk = t.id
WHERE t.routeFk = vRouteFk
GROUP BY t.id
ORDER BY t.priority;
ORDER BY d.id DESC
LIMIT 10000000000000000000
)sub3
GROUP BY sub3.id
ORDER BY sub3.priority;
END$$
DELIMITER ;
ALTER TABLE `vn`.`delivery` DROP FOREIGN KEY delivery_ticketFk_FK;
ALTER TABLE `vn`.`delivery` DROP COLUMN ticketFk;
ALTER TABLE `vn`.`delivery` ADD ticketFk INT DEFAULT NULL;
ALTER TABLE `vn`.`delivery` ADD CONSTRAINT delivery_ticketFk_FK FOREIGN KEY (`ticketFk`) REFERENCES `vn`.`ticket`(`id`);

View File

@ -0,0 +1,3 @@
UPDATE `salix`.`ACL`
SET model = 'InvoiceOut'
WHERE property IN ('negativeBases', 'negativeBasesCsv');

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,3 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES ('ClientInforma', '*', 'READ', 'ALLOW', 'ROLE', 'employee'),
('ClientInforma', '*', 'WRITE', 'ALLOW', 'ROLE', 'financial');

View File

@ -0,0 +1,16 @@
ALTER TABLE `vn`.`client` ADD rating INT UNSIGNED DEFAULT NULL NULL COMMENT 'información proporcionada por Informa';
ALTER TABLE `vn`.`client` ADD recommendedCredit INT UNSIGNED DEFAULT NULL NULL COMMENT 'información proporcionada por Informa';
CREATE TABLE `vn`.`clientInforma` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`clientFk` int(11) NOT NULL,
`rating` int(10) unsigned DEFAULT NULL,
`recommendedCredit` int(10) unsigned DEFAULT NULL,
`workerFk` int(10) unsigned NOT NULL,
`created` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
KEY `informaWorkers_fk_idx` (`workerFk`),
KEY `informaClientFk` (`clientFk`),
CONSTRAINT `informa_ClienteFk` FOREIGN KEY (`clientFk`) REFERENCES `client` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `informa_workers_fk` FOREIGN KEY (`workerFk`) REFERENCES `worker` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='información proporcionada por Informa, se actualiza desde el hook de client (salix)';

View File

@ -0,0 +1,64 @@
DELETE FROM `salix`.`ACL` WHERE id=7;
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
VALUES
('Client', 'setRating', 'WRITE', 'ALLOW', 'ROLE', 'financial');
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
VALUES
('Client', '*', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Client', 'addressesPropagateRe', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'canBeInvoiced', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'canCreateTicket', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'consumption', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'createAddress', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'createWithUser', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'extendedListFilter', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'getAverageInvoiced', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'getCard', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'getDebt', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'getMana', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'transactions', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'hasCustomerRole', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'isValidClient', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'lastActiveTickets', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'sendSms', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'setPassword', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'summary', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'updateAddress', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'updateFiscalData', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'updateUser', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'uploadFile', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'campaignMetricsPdf', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'campaignMetricsEmail', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'clientWelcomeHtml', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'clientWelcomeEmail', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'printerSetupHtml', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'printerSetupEmail', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'sepaCoreEmail', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'letterDebtorPdf', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'letterDebtorStHtml', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'letterDebtorStEmail', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'letterDebtorNdHtml', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'letterDebtorNdEmail', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'clientDebtStatementPdf', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'clientDebtStatementHtml', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'clientDebtStatementEmail', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'creditRequestPdf', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'creditRequestHtml', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'creditRequestEmail', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'incotermsAuthorizationPdf', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'incotermsAuthorizationHtml', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'incotermsAuthorizationEmail', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'consumptionSendQueued', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'filter', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'getClientOrSupplierReference', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'upsert', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'create', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'replaceById', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'updateAttributes', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'updateAttributes', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'deleteById', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'replaceOrCreate', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'updateAll', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'upsertWithWhere', '*', 'ALLOW', 'ROLE', 'employee');

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
(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
(1101, 'BruceWayne', 'Bruce Wayne', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'BruceWayne@mydomain.com', 'es', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1102, 'PetterParker', 'Petter Parker', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'PetterParker@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1103, 'ClarkKent', 'Clark Kent', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'ClarkKent@mydomain.com', 'fr', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1104, 'TonyStark', 'Tony Stark', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'TonyStark@mydomain.com', 'es', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1105, 'MaxEisenhardt', 'Max Eisenhardt', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'MaxEisenhardt@mydomain.com', 'pt', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1106, 'DavidCharlesHaller', 'David Charles Haller', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'DavidCharlesHaller@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1107, 'HankPym', 'Hank Pym', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'HankPym@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1108, 'CharlesXavier', 'Charles Xavier', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'CharlesXavier@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1109, 'BruceBanner', 'Bruce Banner', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'BruceBanner@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1110, 'JessicaJones', 'Jessica Jones', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'JessicaJones@mydomain.com', 'en', NULL),
(1111, 'Missing', 'Missing', 'ac754a330530832ba1bf7687f577da91', 2, 0, NULL, 'en', NULL),
(1112, 'Trash', 'Trash', 'ac754a330530832ba1bf7687f577da91', 2, 0, NULL, 'en', NULL);
(1101, 'BruceWayne', 'Bruce Wayne', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'BruceWayne@mydomain.com', 'es', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1102, 'PetterParker', 'Petter Parker', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'PetterParker@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1103, 'ClarkKent', 'Clark Kent', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'ClarkKent@mydomain.com', 'fr', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1104, 'TonyStark', 'Tony Stark', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'TonyStark@mydomain.com', 'es', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1105, 'MaxEisenhardt', 'Max Eisenhardt', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'MaxEisenhardt@mydomain.com', 'pt', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1106, 'DavidCharlesHaller', 'David Charles Haller', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'DavidCharlesHaller@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1107, 'HankPym', 'Hank Pym', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'HankPym@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1108, 'CharlesXavier', 'Charles Xavier', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'CharlesXavier@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1109, 'BruceBanner', 'Bruce Banner', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'BruceBanner@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
(1110, 'JessicaJones', 'Jessica Jones', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'JessicaJones@mydomain.com', 'en', NULL),
(1111, 'Missing', 'Missing', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', '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`)
VALUES
@ -173,10 +173,6 @@ INSERT INTO `vn`.`sector`(`id`, `description`, `warehouseFk`, `isPreviousPrepare
(1, 'First sector', 1, 1, 'FIRST'),
(2, 'Second sector', 2, 0, 'SECOND');
INSERT INTO `vn`.`operator` (`workerFk`, `numberOfWagons`, `trainFk`, `itemPackingTypeFk`, `warehouseFk`, `sectorFk`, `labelerFk`)
VALUES ('1106', '1', '1', 'H', '1', '1', '1'),
('1107', '1', '1', 'V', '1', '2', '1');
INSERT INTO `vn`.`printer` (`id`, `name`, `path`, `isLabeler`, `sectorFk`, `ipAddress`)
VALUES
(1, 'printer1', 'path1', 0, 1 , NULL),
@ -1201,6 +1197,11 @@ INSERT INTO `vn`.`train`(`id`, `name`)
(1, 'Train1'),
(2, 'Train2');
INSERT INTO `vn`.`operator` (`workerFk`, `numberOfWagons`, `trainFk`, `itemPackingTypeFk`, `warehouseFk`, `sectorFk`, `labelerFk`)
VALUES
('1106', '1', '1', 'H', '1', '1', '1'),
('1107', '1', '1', 'V', '1', '1', '1');
INSERT INTO `vn`.`collection`(`id`, `workerFk`, `stateFk`, `created`, `trainFk`)
VALUES
(1, 1106, 5, DATE_ADD(util.VN_CURDATE(),INTERVAL +1 DAY), 1),
@ -2789,7 +2790,7 @@ INSERT INTO `vn`.`profileType` (`id`, `name`)
INSERT INTO `salix`.`url` (`appName`, `environment`, `url`)
VALUES
('lilium', 'dev', 'http://localhost:8080/#/'),
('lilium', 'dev', 'http://localhost:9000/#/'),
('salix', 'dev', 'http://localhost:5000/#!/');
INSERT INTO `vn`.`report` (`id`, `name`, `paperSizeFk`, `method`)

View File

@ -156,14 +156,14 @@ let actions = {
await this.waitForSpinnerLoad();
},
accessToSection: async function(state) {
accessToSection: async function(state, name = 'Others') {
await this.waitForSelector('vn-left-menu');
let nested = await this.evaluate(state => {
return document.querySelector(`vn-left-menu li li > a[ui-sref="${state}"]`) != null;
}, state);
if (nested) {
let selector = 'vn-left-menu vn-item-section > vn-icon[icon=keyboard_arrow_down]';
let selector = `vn-left-menu li[name="${name}"]`;
await this.evaluate(selector => {
document.querySelector(selector).scrollIntoViewIfNeeded();
}, selector);

View File

@ -414,7 +414,7 @@ export default {
saveFieldsButton: '.vn-popover.shown vn-button[label="Save"] > button'
},
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"]',
fourthFixedPrice: 'vn-fixed-price tr:nth-child(5)',
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"]',
fourthDeleteIcon: 'vn-fixed-price tr:nth-child(5) > td:nth-child(9) > vn-icon-button[icon="delete"]',
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: {
temporalName: 'vn-item-create vn-textfield[ng-model="$ctrl.item.provisionalName"]',
@ -989,9 +1000,9 @@ export default {
saveButton: 'vn-worker-basic-data button[type=submit]'
},
workerNotes: {
addNoteFloatButton: 'vn-worker-note vn-float-button',
note: 'vn-textarea[ng-model="$ctrl.note.text"]',
saveButton: 'button[type=submit]',
addNoteFloatButton: 'vn-worker-note vn-icon[icon="add"]',
note: 'vn-note-worker-create vn-textarea[ng-model="$ctrl.note.text"]',
saveButton: 'vn-note-worker-create button[type=submit]',
firstNoteText: 'vn-worker-note .text'
},
workerPbx: {

View File

@ -79,27 +79,21 @@ describe('SmartTable SearchBar integration', () => {
it('should order by first id', async() => {
await page.loginAndModule('developer', 'item');
await page.accessToSection('item.fixedPrice');
await page.doSearch();
await page.keyboard.press('Enter');
const result = await page.waitToGetProperty(selectors.itemFixedPrice.firstItemID, 'value');
expect(result).toEqual('1');
});
it('should order by last id', async() => {
it('should order by last id, reload page and have same order', async() => {
await page.waitToClick(selectors.itemFixedPrice.orderColumnId);
const result = await page.waitToGetProperty(selectors.itemFixedPrice.firstItemID, 'value');
expect(result).toEqual('3');
});
it('should reload page and have same order', async() => {
await page.reload({
waitUntil: 'networkidle2'
});
const result = await page.waitToGetProperty(selectors.itemFixedPrice.firstItemID, 'value');
expect(result).toEqual('3');
expect(result).toEqual('13');
});
});
});

View File

@ -4,20 +4,69 @@ import getBrowser from '../../helpers/puppeteer';
describe('Item fixed prices path', () => {
let browser;
let page;
let httpRequest;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('buyer', 'item');
await page.accessToSection('item.fixedPrice');
page.on('request', req => {
if (req.url().includes(`FixedPrices/filter`))
httpRequest = req.url();
});
});
afterAll(async() => {
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() => {
await page.waitToClick(selectors.itemFixedPrice.removeWarehouseFilter);
await page.waitForSpinnerLoad();
await page.waitToClick(selectors.itemFixedPrice.add);
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() => {
await page.accessToSection('item.index');
await page.accessToSection('item.fixedPrice');
await page.waitToClick(selectors.itemFixedPrice.removeWarehouseFilter);
await page.waitForSpinnerLoad();
await page.goto(`http://localhost:5000/#!/item/fixed-price`);
const result = await page.waitToGetProperty(selectors.itemFixedPrice.fourthItemID, 'value');

View File

@ -1,6 +1,6 @@
import getBrowser from '../../helpers/puppeteer';
describe('InvoiceIn negative bases path', () => {
describe('InvoiceOut negative bases path', () => {
let browser;
let page;
const httpRequests = [];
@ -9,11 +9,11 @@ describe('InvoiceIn negative bases path', () => {
browser = await getBrowser();
page = browser.page;
page.on('request', req => {
if (req.url().includes(`InvoiceIns/negativeBases`))
if (req.url().includes(`InvoiceOuts/negativeBases`))
httpRequests.push(req.url());
});
await page.loginAndModule('administrative', 'invoiceIn');
await page.accessToSection('invoiceIn.negative-bases');
await page.loginAndModule('administrative', 'invoiceOut');
await page.accessToSection('invoiceOut.negative-bases');
});
afterAll(async() => {

View File

@ -23,7 +23,7 @@ describe('Account ACL path', () => {
it('should create new acl', async() => {
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.permission, 'ALLOW');
await page.waitToClick(selectors.accountAcl.save);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -15,7 +15,7 @@ describe('Component vnLayout', () => {
describe('getUserData()', () => {
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();
$httpBackend.flush();

View File

@ -66,7 +66,6 @@
</vn-tr>
</vn-tbody>
</vn-table>
<vn-pagination model="model"></vn-pagination>
</vn-card>
</vn-data-viewer>
<vn-worker-descriptor-popover vn-id="workerDescriptor">

View File

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

View File

@ -21,8 +21,8 @@ module.exports = function(Self) {
let orgBeginTransaction = this.beginTransaction;
this.beginTransaction = function(options, cb) {
options = options || {};
if (!options.timeout)
options.timeout = 120000;
if (options.timeout === undefined)
options.timeout = 120 * 1000;
return orgBeginTransaction.call(this, options, cb);
};
});
@ -229,7 +229,7 @@ module.exports = function(Self) {
async checkAcls(ctx, actionType) {
let userId = ctx.req.accessToken.userId;
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 modelAcls;

View File

@ -154,5 +154,20 @@
"Valid priorities: 1,2,3": "Valid priorities: 1,2,3",
"Warehouse inventory not set": "Almacén inventario no está establecido",
"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",
"company": "Company",
"country": "Country",
"clientId": "Id client",
"clientSocialName": "Client",
"amount": "Amount",
"taxableBase": "Taxable base",
"ticketFk": "Id ticket",
"isActive": "Active",
"hasToInvoice": "Invoice",
"isTaxDataChecked": "Data checked",
"comercialId": "Id Comercial",
"comercialName": "Comercial",
"Added observation": "Added observation",
"Comment added to client": "Comment added to client"
}

View File

@ -272,8 +272,22 @@
"Tickets with associated refunds": "No se pueden borrar tickets con abonos asociados. Este ticket está asociado al abono Nº {{id}}",
"Not exist this branch": "La rama no existe",
"This ticket cannot be signed because it has not been boxed": "Este ticket no puede firmarse porque no ha sido encajado",
"Collection does not exist": "La colección no existe",
"Cannot obtain exclusive lock": "No se puede obtener un bloqueo exclusivo",
"Insert a date range": "Inserte un rango de fechas",
"Added observation": "{{user}} añadió esta observacion: {{text}}",
"Comment added to client": "Observación añadida al cliente {{clientFk}}",
"Cannot create a new claimBeginning from a different ticket": "No se puede crear una línea de reclamación de un ticket diferente al origen"
"Cannot create a new claimBeginning from a different ticket": "No se puede crear una línea de reclamación de un ticket diferente al origen",
"company": "Compañía",
"country": "País",
"clientId": "Id cliente",
"clientSocialName": "Cliente",
"amount": "Importe",
"taxableBase": "Base",
"ticketFk": "Id ticket",
"isActive": "Activo",
"hasToInvoice": "Facturar",
"isTaxDataChecked": "Datos comprobados",
"comercialId": "Id comercial",
"comercialName": "Comercial"
}

View File

@ -293,7 +293,7 @@ class VnMySQL extends MySQL {
try {
const userId = opts.httpCtx && opts.httpCtx.active.accessToken.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);
}

View File

@ -15,7 +15,7 @@
"legacyUtcDateProcessing": false,
"timezone": "local",
"connectTimeout": 40000,
"acquireTimeout": 60000,
"acquireTimeout": 90000,
"waitForConnections": true
},
"osticket": {

View File

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

View File

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

View File

@ -30,6 +30,6 @@ module.exports = Self => {
Self.changePassword = async function(id, oldPassword, newPassword) {
await Self.rawSql(`CALL account.user_changePassword(?, ?, ?)`,
[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) {
await Self.app.models.User.logout(ctx.req.accessToken.id);
return true;
};
Self.logout = async ctx => Self.app.models.VnUser.logout(ctx.req.accessToken.id);
};

View File

@ -24,6 +24,6 @@ module.exports = Self => {
Self.setPassword = async function(id, newPassword) {
await Self.rawSql(`CALL account.user_setPassword(?, ?)`,
[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() => {
let req = app.models.Account.setPassword(1, 'insecurePass');
let req = models.Account.setPassword(1, 'insecurePass');
await expectAsync(req).toBeRejected();
});
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();
});

View File

@ -25,7 +25,7 @@ module.exports = Self => {
});
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);
};
};

View File

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

View File

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

View File

@ -100,7 +100,7 @@ module.exports = Self => {
if (['administrator', 'root'].indexOf(userName) >= 0)
return;
let user = await $.Account.findOne({
let user = await $.VnUser.findOne({
where: {name: userName},
fields: [
'id',
@ -138,7 +138,7 @@ module.exports = Self => {
};
if (user) {
let exists = await $.UserAccount.exists(user.id);
let exists = await $.Account.exists(user.id);
Object.assign(info, {
hasAccount: user.active && exists,
corporateMail: `${userName}@${this.domain}`,
@ -177,11 +177,11 @@ module.exports = Self => {
async syncUser(userName, info, 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) {
let accounts = await app.models.UserAccount.find({
let accounts = await app.models.Account.find({
fields: ['id'],
include: {
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;
module.exports = Self => {
const shouldSync = process.env.NODE_ENV !== 'test';
const shouldSync = process.env.NODE_ENV === 'production';
Self.getSynchronizer = async function() {
return await Self.findOne({
@ -32,7 +32,6 @@ module.exports = Self => {
},
async syncUser(userName, info, password) {
let {
client,
accountConfig
@ -248,7 +247,7 @@ module.exports = Self => {
return {key: e.inheritsFrom, val: e.role};
});
let accounts = await $.UserAccount.find({
let accounts = await $.Account.find({
fields: ['id'],
include: {
relation: 'user',

View File

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

View File

@ -18,7 +18,7 @@
"relations": {
"user": {
"type": "belongsTo",
"model": "Account",
"model": "VnUser",
"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"]
}
}

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