feat: refs #7346 #2864
|
@ -118,6 +118,9 @@
|
||||||
"NotificationSubscription": {
|
"NotificationSubscription": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"OrmConfig": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"Province": {
|
"Province": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"name": "OrmConfig",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "ormConfig"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "number",
|
||||||
|
"id": true
|
||||||
|
},
|
||||||
|
"selectLimit": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"acls": [
|
||||||
|
{
|
||||||
|
"accessType": "*",
|
||||||
|
"principalType": "ROLE",
|
||||||
|
"principalId": "$authenticated",
|
||||||
|
"permission": "ALLOW"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -3,4 +3,5 @@ apps:
|
||||||
name: salix-back
|
name: salix-back
|
||||||
instances: 1
|
instances: 1
|
||||||
max_restarts: 0
|
max_restarts: 0
|
||||||
|
autorestart: false
|
||||||
node_args: --tls-min-v1.0 --openssl-legacy-provider
|
node_args: --tls-min-v1.0 --openssl-legacy-provider
|
||||||
|
|
|
@ -21,6 +21,7 @@ BEGIN
|
||||||
AND a.id IS NULL
|
AND a.id IS NULL
|
||||||
AND u.active
|
AND u.active
|
||||||
AND c.created < util.VN_CURDATE() - INTERVAL vMonths MONTH
|
AND c.created < util.VN_CURDATE() - INTERVAL vMonths MONTH
|
||||||
|
AND NOT u.role = (SELECT id FROM `role` WHERE name = 'supplier')
|
||||||
AND u.id NOT IN (
|
AND u.id NOT IN (
|
||||||
SELECT DISTINCT c.id
|
SELECT DISTINCT c.id
|
||||||
FROM client c
|
FROM client c
|
||||||
|
|
|
@ -12,7 +12,7 @@ BEGIN
|
||||||
DECLARE vSaleFk INT;
|
DECLARE vSaleFk INT;
|
||||||
DECLARE vSectorFk INT;
|
DECLARE vSectorFk INT;
|
||||||
DECLARE vSales CURSOR FOR
|
DECLARE vSales CURSOR FOR
|
||||||
SELECT s.id
|
SELECT DISTINCT s.id
|
||||||
FROM sectorCollectionSaleGroup sc
|
FROM sectorCollectionSaleGroup sc
|
||||||
JOIN saleGroupDetail sg ON sg.saleGroupFk = sc.saleGroupFk
|
JOIN saleGroupDetail sg ON sg.saleGroupFk = sc.saleGroupFk
|
||||||
JOIN sale s ON sg.saleFk = s.id
|
JOIN sale s ON sg.saleFk = s.id
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
USE vn;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS ormConfig (
|
||||||
|
id int(5) NOT NULL AUTO_INCREMENT primary key,
|
||||||
|
selectLimit int(5) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT IGNORE INTO ormConfig SET selectLimit = 1000;
|
|
@ -1,28 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('InvoiceIn summary path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('administrative', 'invoiceIn');
|
|
||||||
await page.accessToSearchResult('1');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reach the summary section', async() => {
|
|
||||||
await page.waitForState('invoiceIn.card.summary');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should contain some basic data from the invoice', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.invoiceInSummary.supplierRef, 'innerText');
|
|
||||||
|
|
||||||
expect(result).toEqual('1234');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,52 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('InvoiceIn descriptor path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('administrative', 'invoiceIn');
|
|
||||||
await page.accessToSearchResult('10');
|
|
||||||
await page.accessToSection('invoiceIn.card.basicData');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should clone the invoiceIn using the descriptor more menu', async() => {
|
|
||||||
await page.waitToClick(selectors.invoiceInDescriptor.moreMenu);
|
|
||||||
await page.waitToClick(selectors.invoiceInDescriptor.moreMenuCloneInvoiceIn);
|
|
||||||
await page.waitToClick(selectors.invoiceInDescriptor.acceptButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('InvoiceIn cloned');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have been redirected to the created invoiceIn summary', async() => {
|
|
||||||
await page.waitForState('invoiceIn.card.summary');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should delete the cloned invoiceIn using the descriptor more menu', async() => {
|
|
||||||
await page.waitToClick(selectors.invoiceInDescriptor.moreMenu);
|
|
||||||
await page.waitToClick(selectors.invoiceInDescriptor.moreMenuDeleteInvoiceIn);
|
|
||||||
await page.waitToClick(selectors.invoiceInDescriptor.acceptButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('InvoiceIn deleted');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have been relocated to the invoiceOut index', async() => {
|
|
||||||
await page.waitForState('invoiceIn.index');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should search for the deleted invouceOut to find no results`, async() => {
|
|
||||||
await page.doSearch('10');
|
|
||||||
const nResults = await page.countElement(selectors.invoiceOutIndex.searchResult);
|
|
||||||
|
|
||||||
expect(nResults).toEqual(0);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,196 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('InvoiceIn basic data path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
let newDms;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('administrative', 'invoiceIn');
|
|
||||||
await page.accessToSearchResult('1');
|
|
||||||
await page.accessToSection('invoiceIn.card.basicData');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should edit the invoiceIn basic data`, async() => {
|
|
||||||
const now = Date.vnNew();
|
|
||||||
await page.pickDate(selectors.invoiceInBasicData.issued, now);
|
|
||||||
await page.pickDate(selectors.invoiceInBasicData.operated, now);
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInBasicData.supplier, 'Verdnatura');
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.supplierRef);
|
|
||||||
await page.write(selectors.invoiceInBasicData.supplierRef, '9999');
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.dms);
|
|
||||||
await page.write(selectors.invoiceInBasicData.dms, '2');
|
|
||||||
await page.pickDate(selectors.invoiceInBasicData.bookEntried, now);
|
|
||||||
await page.pickDate(selectors.invoiceInBasicData.booked, now);
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInBasicData.currency, 'USD');
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInBasicData.company, 'ORN');
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.save);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should confirm the invoiceIn supplier was edited`, async() => {
|
|
||||||
await page.reloadSection('invoiceIn.card.basicData');
|
|
||||||
const result = await page.waitToGetProperty(selectors.invoiceInBasicData.supplier, 'value');
|
|
||||||
|
|
||||||
expect(result).toContain('Verdnatura');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should confirm the invoiceIn supplierRef was edited`, async() => {
|
|
||||||
const result = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.supplierRef, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('9999');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should confirm the invoiceIn currency was edited`, async() => {
|
|
||||||
const result = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.currency, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('USD');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should confirm the invoiceIn company was edited`, async() => {
|
|
||||||
const result = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.company, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('ORN');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should confirm the invoiceIn dms was edited`, async() => {
|
|
||||||
const result = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.dms, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('2');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should create a new invoiceIn dms and save the changes`, async() => {
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.dms);
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.create);
|
|
||||||
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.reference);
|
|
||||||
await page.write(selectors.invoiceInBasicData.reference, 'New Dms');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.confirm);
|
|
||||||
let message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.companyId);
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInBasicData.companyId, 'VNL');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.confirm);
|
|
||||||
message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.warehouseId);
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInBasicData.warehouseId, 'Warehouse One');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.confirm);
|
|
||||||
message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.dmsTypeId);
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInBasicData.dmsTypeId, 'Ticket');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.confirm);
|
|
||||||
message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.description);
|
|
||||||
await page.write(selectors.invoiceInBasicData.description, 'Dms without edition.');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.confirm);
|
|
||||||
message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('The files can\'t be empty');
|
|
||||||
|
|
||||||
let currentDir = process.cwd();
|
|
||||||
let filePath = `${currentDir}/e2e/assets/thermograph.jpeg`;
|
|
||||||
|
|
||||||
const [fileChooser] = await Promise.all([
|
|
||||||
page.waitForFileChooser(),
|
|
||||||
page.waitToClick(selectors.invoiceInBasicData.inputFile)
|
|
||||||
]);
|
|
||||||
await fileChooser.accept([filePath]);
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.confirm);
|
|
||||||
message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
|
|
||||||
newDms = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.dms, 'value');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should confirm the invoiceIn was edited with the new dms`, async() => {
|
|
||||||
await page.reloadSection('invoiceIn.card.basicData');
|
|
||||||
const result = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.dms, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual(newDms);
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should edit the invoiceIn`, async() => {
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.edit);
|
|
||||||
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.reference);
|
|
||||||
await page.write(selectors.invoiceInBasicData.reference, 'Dms Edited');
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.companyId);
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInBasicData.companyId, 'CCs');
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.warehouseId);
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInBasicData.warehouseId, 'Algemesi');
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.dmsTypeId);
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInBasicData.dmsTypeId, 'Basura');
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.description);
|
|
||||||
await page.write(selectors.invoiceInBasicData.description, ' Nevermind, now is edited.');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.confirm);
|
|
||||||
let message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should confirm the new dms has been edited`, async() => {
|
|
||||||
await page.reloadSection('invoiceIn.card.basicData');
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.edit);
|
|
||||||
|
|
||||||
const reference = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.reference, 'value');
|
|
||||||
const companyId = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.companyId, 'value');
|
|
||||||
const warehouseId = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.warehouseId, 'value');
|
|
||||||
const dmsTypeId = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.dmsTypeId, 'value');
|
|
||||||
const description = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.description, 'value');
|
|
||||||
|
|
||||||
expect(reference).toEqual('Dms Edited');
|
|
||||||
expect(companyId).toEqual('CCs');
|
|
||||||
expect(warehouseId).toEqual('Algemesi');
|
|
||||||
expect(dmsTypeId).toEqual('Basura');
|
|
||||||
expect(description).toEqual('Dms without edition. Nevermind, now is edited.');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.confirm);
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should disable edit and download if dms doesn't exists, and set back the original dms`, async() => {
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.dms);
|
|
||||||
await page.write(selectors.invoiceInBasicData.dms, '9999');
|
|
||||||
|
|
||||||
await page.waitForSelector(`${selectors.invoiceInBasicData.download}.disabled`);
|
|
||||||
await page.waitForSelector(`${selectors.invoiceInBasicData.edit}.disabled`);
|
|
||||||
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.dms);
|
|
||||||
await page.write(selectors.invoiceInBasicData.dms, '1');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.save);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,59 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('InvoiceIn tax path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('developer', 'invoiceIn');
|
|
||||||
await page.accessToSearchResult('2');
|
|
||||||
await page.accessToSection('invoiceIn.card.tax');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should add a new tax and check it', async() => {
|
|
||||||
await page.waitToClick(selectors.invoiceInTax.addTaxButton);
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInTax.thirdExpense, '6210000567');
|
|
||||||
await page.write(selectors.invoiceInTax.thirdTaxableBase, '100');
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInTax.thirdTaxType, 'H.P. IVA');
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInTax.thirdTransactionType, 'Operaciones exentas');
|
|
||||||
await page.waitToClick(selectors.invoiceInTax.saveButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInDescriptor.summaryIcon);
|
|
||||||
await page.waitForState('invoiceIn.card.summary');
|
|
||||||
const total = await page.waitToGetProperty(selectors.invoiceInSummary.totalTaxableBase, 'innerText');
|
|
||||||
|
|
||||||
await page.accessToSection('invoiceIn.card.tax');
|
|
||||||
|
|
||||||
const thirdExpense = await page.waitToGetProperty(selectors.invoiceInTax.thirdExpense, 'value');
|
|
||||||
const thirdTaxableBase = await page.waitToGetProperty(selectors.invoiceInTax.thirdTaxableBase, 'value');
|
|
||||||
const thirdTaxType = await page.waitToGetProperty(selectors.invoiceInTax.thirdTaxType, 'value');
|
|
||||||
const thirdTransactionType = await page.waitToGetProperty(selectors.invoiceInTax.thirdTransactionType, 'value');
|
|
||||||
const thirdRate = await page.waitToGetProperty(selectors.invoiceInTax.thirdRate, 'value');
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
|
|
||||||
expect(total).toEqual('Taxable base €1,323.16');
|
|
||||||
|
|
||||||
expect(thirdExpense).toEqual('6210000567');
|
|
||||||
expect(thirdTaxableBase).toEqual('100');
|
|
||||||
expect(thirdTaxType).toEqual('H.P. IVA 4% CEE');
|
|
||||||
expect(thirdTransactionType).toEqual('Operaciones exentas');
|
|
||||||
expect(thirdRate).toEqual('€4.00');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should delete the added line', async() => {
|
|
||||||
await page.waitToClick(selectors.invoiceInTax.thirdDeleteButton);
|
|
||||||
await page.waitToClick(selectors.invoiceInTax.saveButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,48 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('InvoiceIn serial path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
let httpRequest;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('administrative', 'invoiceIn');
|
|
||||||
await page.accessToSection('invoiceIn.serial');
|
|
||||||
page.on('request', req => {
|
|
||||||
if (req.url().includes(`InvoiceIns/getSerial`))
|
|
||||||
httpRequest = req.url();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should check that passes the correct params to back', async() => {
|
|
||||||
await page.overwrite(selectors.invoiceInSerial.daysAgo, '30');
|
|
||||||
await page.keyboard.press('Enter');
|
|
||||||
|
|
||||||
expect(httpRequest).toContain('daysAgo=30');
|
|
||||||
|
|
||||||
await page.overwrite(selectors.invoiceInSerial.serial, 'R');
|
|
||||||
await page.keyboard.press('Enter');
|
|
||||||
|
|
||||||
expect(httpRequest).toContain('serial=R');
|
|
||||||
await page.click(selectors.invoiceInSerial.chip);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should go to index and check if the search-panel has the correct params', async() => {
|
|
||||||
await page.waitToClick(selectors.invoiceInSerial.goToIndex);
|
|
||||||
const params = await page.$$(selectors.invoiceInIndex.topbarSearchParams);
|
|
||||||
const serial = await params[0].getProperty('title');
|
|
||||||
const isBooked = await params[1].getProperty('title');
|
|
||||||
const from = await params[2].getProperty('title');
|
|
||||||
|
|
||||||
expect(await serial.jsonValue()).toContain('serial');
|
|
||||||
expect(await isBooked.jsonValue()).toContain('not isBooked');
|
|
||||||
expect(await from.jsonValue()).toContain('from');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,164 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Account create and basic data path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('itManagement', 'account');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should open the new account form by clicking the add button', async() => {
|
|
||||||
await page.waitToClick(selectors.accountIndex.addAccount);
|
|
||||||
await page.waitForState('account.create');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fill the form and then save it by clicking the create button', async() => {
|
|
||||||
await page.write(selectors.accountIndex.newName, 'remy');
|
|
||||||
await page.write(selectors.accountIndex.newNickname, 'Gambit');
|
|
||||||
await page.write(selectors.accountIndex.newEmail, 'RemyEtienneLeBeau@verdnatura.es');
|
|
||||||
await page.autocompleteSearch(selectors.accountIndex.newRole, 'Trainee');
|
|
||||||
await page.write(selectors.accountIndex.newPassword, 'cestlavie');
|
|
||||||
await page.waitToClick(selectors.accountIndex.createAccountButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should redirect the user to the created account basic data section', async() => {
|
|
||||||
await page.waitForState('account.card.basicData');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should check the name is as expected', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.accountBasicData.name, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('remy');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should check the nickname is as expected', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.accountBasicData.nickname, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('Gambit');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should check the email is as expected', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.accountBasicData.email, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('RemyEtienneLeBeau@verdnatura.es');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should navigate to the roles section to check the roles are correct', async() => {
|
|
||||||
await page.accessToSection('account.card.roles');
|
|
||||||
const rolesCount = await page.countElement(selectors.accountRoles.anyResult);
|
|
||||||
|
|
||||||
expect(rolesCount).toEqual(3);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Descriptor option', () => {
|
|
||||||
describe('activate account', () => {
|
|
||||||
it(`should check the active account icon isn't present in the descriptor`, async() => {
|
|
||||||
await page.waitForNumberOfElements(selectors.accountDescriptor.activeAccountIcon, 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should activate the account using the descriptor menu', async() => {
|
|
||||||
await page.waitToClick(selectors.accountDescriptor.menuButton);
|
|
||||||
await page.waitToClick(selectors.accountDescriptor.activateAccount);
|
|
||||||
await page.waitToClick(selectors.accountDescriptor.acceptButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Account enabled!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should check the active account icon is now present in the descriptor', async() => {
|
|
||||||
await page.waitForSelector(selectors.accountDescriptor.activeAccountIcon, {visible: false});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('deactivate user', () => {
|
|
||||||
it(`should check the inactive user icon isn't present in the descriptor just yet`, async() => {
|
|
||||||
await page.waitForNumberOfElements(selectors.accountDescriptor.activeUserIcon, 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should deactivate the user using the descriptor menu', async() => {
|
|
||||||
await page.waitToClick(selectors.accountDescriptor.menuButton);
|
|
||||||
await page.waitToClick(selectors.accountDescriptor.deactivateUser);
|
|
||||||
await page.waitToClick(selectors.accountDescriptor.acceptButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('User deactivated!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should check the inactive user icon is now present', async() => {
|
|
||||||
await page.waitForNumberOfElements(selectors.accountDescriptor.activeUserIcon, 1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('activate user', () => {
|
|
||||||
it('should activate the user using the descriptor menu', async() => {
|
|
||||||
await page.waitToClick(selectors.accountDescriptor.menuButton);
|
|
||||||
await page.waitToClick(selectors.accountDescriptor.activateUser);
|
|
||||||
await page.waitToClick(selectors.accountDescriptor.acceptButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('User activated!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should check the inactive user icon is not present anymore', async() => {
|
|
||||||
await page.waitForNumberOfElements(selectors.accountDescriptor.activeUserIcon, 0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('mail forwarding', () => {
|
|
||||||
it('should activate the mail forwarding and set the recipent email', async() => {
|
|
||||||
await page.accessToSection('account.card.mailForwarding');
|
|
||||||
await page.waitToClick(selectors.accountMailForwarding.mailForwardingCheckbox);
|
|
||||||
await page.write(selectors.accountMailForwarding.email, 'someEmail@someDomain.es');
|
|
||||||
await page.waitToClick(selectors.accountMailForwarding.save);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Set password', () => {
|
|
||||||
it('should set the password using the descriptor menu', async() => {
|
|
||||||
const newPassword = 'quantum.12345';
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.accountDescriptor.menuButton);
|
|
||||||
await page.waitToClick(selectors.accountDescriptor.setPassword);
|
|
||||||
await page.write(selectors.accountDescriptor.newPassword, newPassword);
|
|
||||||
await page.write(selectors.accountDescriptor.repeatPassword, newPassword);
|
|
||||||
await page.waitToClick(selectors.accountDescriptor.acceptButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Password changed succesfully!');
|
|
||||||
});
|
|
||||||
|
|
||||||
// cant log into created account for unknown reasons
|
|
||||||
// it('should login into the created account with the new password', async() => {
|
|
||||||
// await page.loginAndModule('Remy', 'quantum.crypt0graphy');
|
|
||||||
// });
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('delete account', () => {
|
|
||||||
// it('should navigate to the account basic data section', async() => {
|
|
||||||
// });
|
|
||||||
|
|
||||||
it('should delete the account using the descriptor menu', async() => {
|
|
||||||
await page.waitToClick(selectors.accountDescriptor.menuButton);
|
|
||||||
await page.waitToClick(selectors.accountDescriptor.deleteAccount);
|
|
||||||
await page.waitToClick(selectors.accountDescriptor.acceptButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('User removed');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,66 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Account Alias create and basic data path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('itManagement', 'account');
|
|
||||||
await page.accessToSection('account.alias');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should open the new account alias form by clicking the add button', async() => {
|
|
||||||
await page.waitToClick(selectors.accountAliasIndex.addAlias);
|
|
||||||
await page.waitForState('account.alias.create');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fill the form and then save it by clicking the create alias button', async() => {
|
|
||||||
await page.write(selectors.accountAliasIndex.newName, 'Boring alias');
|
|
||||||
await page.write(selectors.accountAliasIndex.newDescription, 'Boring description');
|
|
||||||
await page.waitToClick(selectors.accountAliasIndex.createAliasButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should redirect the user to the created account alias basic data section', async() => {
|
|
||||||
await page.waitForState('account.alias.card.basicData');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should edit the alias basic data', async() => {
|
|
||||||
await page.overwrite(selectors.accountAliasBasicData.name, 'Psykers');
|
|
||||||
await page.overwrite(selectors.accountAliasBasicData.description, 'Email group for psykers');
|
|
||||||
await page.waitToClick(selectors.accountAliasBasicData.save);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reload the basicData section and check the name was edited successfully', async() => {
|
|
||||||
await page.reloadSection('account.alias.card.basicData');
|
|
||||||
const result = await page.waitToGetProperty(selectors.accountAliasBasicData.name, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('Psykers');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should check the alias description was edited successfully', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.accountAliasBasicData.description, 'value');
|
|
||||||
|
|
||||||
expect(result).toContain('psykers');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should search IT alias then access the user section to check the role listed is the expected one', async() => {
|
|
||||||
await page.accessToSearchResult('IT');
|
|
||||||
await page.accessToSection('account.alias.card.users');
|
|
||||||
const rolesCount = await page.countElement(selectors.accountAliasUsers.anyResult);
|
|
||||||
|
|
||||||
expect(rolesCount).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,86 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Account Role create and basic data path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('it', 'account');
|
|
||||||
await page.accessToSection('account.role');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should open the new account role form by clicking the add button', async() => {
|
|
||||||
await page.waitToClick(selectors.accountRoleIndex.addRole);
|
|
||||||
await page.waitForState('account.role.create');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fill the form and then save it by clicking the create role button', async() => {
|
|
||||||
await page.write(selectors.accountRoleIndex.newName, 'boringRole');
|
|
||||||
await page.write(selectors.accountRoleIndex.newDescription, 'Boring description');
|
|
||||||
await page.waitToClick(selectors.accountRoleIndex.createRoleButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should redirect the user to the created role basic data section', async() => {
|
|
||||||
await page.waitForState('account.role.card.basicData');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should edit the role basic data', async() => {
|
|
||||||
await page.overwrite(selectors.accountRoleBasicData.name, 'psyker');
|
|
||||||
await page.overwrite(selectors.accountRoleBasicData.description, 'A role just for psykers');
|
|
||||||
await page.waitToClick(selectors.accountRoleBasicData.save);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reload the role basicData section and check the name was edited successfully', async() => {
|
|
||||||
await page.reloadSection('account.role.card.basicData');
|
|
||||||
const result = await page.waitToGetProperty(selectors.accountRoleBasicData.name, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('psyker');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should check the role description was edited successfully', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.accountRoleBasicData.description, 'value');
|
|
||||||
|
|
||||||
expect(result).toContain('psykers');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should navigate to the subroles section', async() => {
|
|
||||||
await page.accessToSection('account.role.card.subroles');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should asign a subrole', async() => {
|
|
||||||
await page.waitToClick(selectors.accountSubroles.addSubrole);
|
|
||||||
await page.autocompleteSearch(selectors.accountSubroles.role, 'teamManager');
|
|
||||||
await page.waitToClick(selectors.accountSubroles.save);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Role added!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reload the subroles section and check a role was added', async() => {
|
|
||||||
await page.reloadSection('account.role.card.subroles');
|
|
||||||
const subrolesCount = await page.countElement(selectors.accountSubroles.anyResult);
|
|
||||||
|
|
||||||
expect(subrolesCount).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should access the employee roles inheritance then check the roles listed are the expected ones', async() => {
|
|
||||||
await page.accessToSearchResult('employee');
|
|
||||||
await page.accessToSection('account.role.card.inherited');
|
|
||||||
const rolesCount = await page.countElement(selectors.accountRoleInheritance.anyResult);
|
|
||||||
|
|
||||||
expect(rolesCount).toEqual(7);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,60 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Account ACL path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('developer', 'account');
|
|
||||||
await page.accessToSection('account.acl');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should go to create new acl', async() => {
|
|
||||||
await page.waitToClick(selectors.accountAcl.addAcl);
|
|
||||||
await page.waitForState('account.acl.create');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create new acl', async() => {
|
|
||||||
await page.autocompleteSearch(selectors.accountAcl.role, 'sysadmin');
|
|
||||||
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);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should navigate to edit', async() => {
|
|
||||||
await page.doSearch();
|
|
||||||
await page.waitToClick(selectors.accountAcl.thirdAcl);
|
|
||||||
await page.waitForState('account.acl.edit');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should edit the third acl', async() => {
|
|
||||||
await page.autocompleteSearch(selectors.accountAcl.model, 'Supplier');
|
|
||||||
await page.autocompleteSearch(selectors.accountAcl.accessType, 'READ');
|
|
||||||
await page.waitToClick(selectors.accountAcl.save);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should delete the third result', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.accountAcl.thirdAcl, 'innerText');
|
|
||||||
await page.waitToClick(selectors.accountAcl.deleteThirdAcl);
|
|
||||||
await page.waitToClick(selectors.globalItems.acceptButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
const newResult = await page.waitToGetProperty(selectors.accountAcl.thirdAcl, 'innerText');
|
|
||||||
|
|
||||||
expect(message.text).toContain('ACL removed');
|
|
||||||
expect(result).not.toEqual(newResult);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,25 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Account Connections path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
const account = 'sysadmin';
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule(account, 'account');
|
|
||||||
await page.accessToSection('account.connections');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should check this is the last connection', async() => {
|
|
||||||
const firstResult = await page.waitToGetProperty(selectors.accountConnections.firstConnection, 'innerText');
|
|
||||||
|
|
||||||
expect(firstResult).toContain(account);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,37 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Account Accounts path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('sysadmin', 'account');
|
|
||||||
await page.accessToSection('account.accounts');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should sync roles', async() => {
|
|
||||||
await page.waitToClick(selectors.accountAccounts.syncRoles);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Roles synchronized!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should relogin', async() => {
|
|
||||||
await page.loginAndModule('sysadmin', 'account');
|
|
||||||
await page.accessToSection('account.accounts');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should sync all', async() => {
|
|
||||||
await page.waitToClick(selectors.accountAccounts.syncAll);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Synchronizing in the background');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,41 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Account LDAP path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('sysadmin', 'account');
|
|
||||||
await page.accessToSection('account.ldap');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set data and save', async() => {
|
|
||||||
await page.waitToClick(selectors.accountLdap.checkEnable);
|
|
||||||
await page.write(selectors.accountLdap.server, '1234');
|
|
||||||
await page.write(selectors.accountLdap.rdn, '1234');
|
|
||||||
await page.write(selectors.accountLdap.password, 'nightmare');
|
|
||||||
await page.write(selectors.accountLdap.userDn, 'sysadmin');
|
|
||||||
await page.write(selectors.accountLdap.groupDn, '1234');
|
|
||||||
await page.waitToClick(selectors.accountLdap.save);
|
|
||||||
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reset data', async() => {
|
|
||||||
await page.waitToClick(selectors.accountLdap.checkEnable);
|
|
||||||
await page.waitToClick(selectors.accountLdap.save);
|
|
||||||
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,42 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Account Samba path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('sysadmin', 'account');
|
|
||||||
await page.accessToSection('account.samba');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set data and save', async() => {
|
|
||||||
await page.waitToClick(selectors.accountSamba.checkEnable);
|
|
||||||
await page.write(selectors.accountSamba.adDomain, '1234');
|
|
||||||
await page.write(selectors.accountSamba.adController, '1234');
|
|
||||||
await page.write(selectors.accountSamba.adUser, 'sysadmin');
|
|
||||||
await page.write(selectors.accountSamba.adPassword, 'nightmare');
|
|
||||||
await page.write(selectors.accountSamba.userDn, 'testDn');
|
|
||||||
await page.waitToClick(selectors.accountSamba.verifyCert);
|
|
||||||
await page.waitToClick(selectors.accountSamba.save);
|
|
||||||
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reset data', async() => {
|
|
||||||
await page.waitToClick(selectors.accountSamba.checkEnable);
|
|
||||||
await page.waitToClick(selectors.accountSamba.save);
|
|
||||||
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,112 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Account privileges path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('developer', 'account');
|
|
||||||
await page.accessToSearchResult('1101');
|
|
||||||
await page.accessToSection('account.card.privileges');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('as developer', () => {
|
|
||||||
it('should throw error when give privileges', async() => {
|
|
||||||
await page.waitToClick(selectors.accountPrivileges.checkHasGrant);
|
|
||||||
await page.waitToClick(selectors.accountPrivileges.save);
|
|
||||||
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain(`You don't have grant privilege`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw error when change role', async() => {
|
|
||||||
await page.autocompleteSearch(selectors.accountPrivileges.role, 'employee');
|
|
||||||
await page.waitToClick(selectors.accountPrivileges.save);
|
|
||||||
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain(`You don't have grant privilege`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('as sysadmin', () => {
|
|
||||||
beforeAll(async() => {
|
|
||||||
await page.loginAndModule('sysadmin', 'account');
|
|
||||||
await page.accessToSearchResult('9');
|
|
||||||
await page.accessToSection('account.card.privileges');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should give privileges', async() => {
|
|
||||||
await page.waitToClick(selectors.accountPrivileges.checkHasGrant);
|
|
||||||
await page.waitToClick(selectors.accountPrivileges.save);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
await page.reloadSection('account.card.privileges');
|
|
||||||
const result = await page.checkboxState(selectors.accountPrivileges.checkHasGrant);
|
|
||||||
|
|
||||||
expect(message.text).toContain(`Data saved!`);
|
|
||||||
expect(result).toBe('checked');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw error when change role and not own role', async() => {
|
|
||||||
await page.autocompleteSearch(selectors.accountPrivileges.role, 'itBoss');
|
|
||||||
await page.waitToClick(selectors.accountPrivileges.save);
|
|
||||||
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain(`You don't own the role and you can't assign it to another user`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should change role to employee', async() => {
|
|
||||||
await page.autocompleteSearch(selectors.accountPrivileges.role, 'employee');
|
|
||||||
await page.waitToClick(selectors.accountPrivileges.save);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
await page.reloadSection('account.card.privileges');
|
|
||||||
const result = await page.waitToGetProperty(selectors.accountPrivileges.role, 'value');
|
|
||||||
|
|
||||||
expect(message.text).toContain(`Data saved!`);
|
|
||||||
expect(result).toContain('employee');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return role to developer', async() => {
|
|
||||||
await page.autocompleteSearch(selectors.accountPrivileges.role, 'developer');
|
|
||||||
await page.waitToClick(selectors.accountPrivileges.save);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
await page.reloadSection('account.card.privileges');
|
|
||||||
const result = await page.waitToGetProperty(selectors.accountPrivileges.role, 'value');
|
|
||||||
|
|
||||||
expect(message.text).toContain(`Data saved!`);
|
|
||||||
expect(result).toContain('developer');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('as developer again', () => {
|
|
||||||
it('should remove privileges', async() => {
|
|
||||||
await page.accessToSearchResult('9');
|
|
||||||
await page.accessToSection('account.card.privileges');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.accountPrivileges.checkHasGrant);
|
|
||||||
await page.waitToClick(selectors.accountPrivileges.save);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain(`Data saved!`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should logIn in developer', async() => {
|
|
||||||
await page.reloadSection('account.card.privileges');
|
|
||||||
const result = await page.checkboxState(selectors.accountPrivileges.checkHasGrant);
|
|
||||||
|
|
||||||
expect(result).toBe('unchecked');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -38,7 +38,7 @@
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
</div>
|
</div>
|
||||||
<a
|
<a
|
||||||
ui-sref="worker.card.summary({id: $root.user.id})"
|
ng-click="$ctrl.redirect($root.user.id)"
|
||||||
class="vn-button colored"
|
class="vn-button colored"
|
||||||
translate>
|
translate>
|
||||||
My account
|
My account
|
||||||
|
|
|
@ -82,6 +82,9 @@ class Controller {
|
||||||
? {id: $search}
|
? {id: $search}
|
||||||
: {bank: {like: '%' + $search + '%'}};
|
: {bank: {like: '%' + $search + '%'}};
|
||||||
}
|
}
|
||||||
|
async redirect(id) {
|
||||||
|
window.location.href = await this.vnConfig.vnApp.getUrl(`worker/${id}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Controller.$inject = ['$scope', '$translate', 'vnConfig', 'vnAuth', 'vnToken'];
|
Controller.$inject = ['$scope', '$translate', 'vnConfig', 'vnAuth', 'vnToken'];
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@ module.exports = function(Self) {
|
||||||
Object.assign(Self, {
|
Object.assign(Self, {
|
||||||
setup() {
|
setup() {
|
||||||
Self.super_.setup.call(this);
|
Self.super_.setup.call(this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setting a global transaction timeout to find out if the service
|
* Setting a global transaction timeout to find out if the service
|
||||||
* is blocked because the connection pool is empty.
|
* is blocked because the connection pool is empty.
|
||||||
|
@ -28,6 +27,26 @@ module.exports = function(Self) {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.beforeRemote('**', async ctx => {
|
||||||
|
if (!this.hasFilter(ctx)) return;
|
||||||
|
|
||||||
|
const defaultLimit = this.app.orm.selectLimit;
|
||||||
|
const filter = ctx.args.filter || {limit: defaultLimit};
|
||||||
|
|
||||||
|
if (filter.limit > defaultLimit) {
|
||||||
|
filter.limit = defaultLimit;
|
||||||
|
ctx.args.filter = filter;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.afterRemote('**', async ctx => {
|
||||||
|
if (!this.hasFilter(ctx)) return;
|
||||||
|
|
||||||
|
const {result} = ctx;
|
||||||
|
const length = Array.isArray(result) ? result.length : result ? 1 : 0;
|
||||||
|
if (length >= this.app.orm.selectLimit) throw new UserError('Too many records');
|
||||||
|
});
|
||||||
|
|
||||||
// Register field ACL validation
|
// Register field ACL validation
|
||||||
/*
|
/*
|
||||||
this.beforeRemote('prototype.patchAttributes', ctx => this.checkUpdateAcls(ctx));
|
this.beforeRemote('prototype.patchAttributes', ctx => this.checkUpdateAcls(ctx));
|
||||||
|
@ -327,6 +346,12 @@ module.exports = function(Self) {
|
||||||
|
|
||||||
checkInsertAcls(ctx) {
|
checkInsertAcls(ctx) {
|
||||||
return this.checkAcls(ctx, 'insert');
|
return this.checkAcls(ctx, 'insert');
|
||||||
|
},
|
||||||
|
|
||||||
|
hasFilter(ctx) {
|
||||||
|
return ctx.req.method.toUpperCase() === 'GET' &&
|
||||||
|
ctx.method.accepts.some(x => x.arg === 'filter' && x.type.toLowerCase() === 'object');
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -369,5 +369,6 @@
|
||||||
"Cannot send mail": "Não é possível enviar o email",
|
"Cannot send mail": "Não é possível enviar o email",
|
||||||
"CONSTRAINT `supplierAccountTooShort` failed for `vn`.`supplier`": "La cuenta debe tener exactamente 10 dígitos",
|
"CONSTRAINT `supplierAccountTooShort` failed for `vn`.`supplier`": "La cuenta debe tener exactamente 10 dígitos",
|
||||||
"The sale not exists in the item shelving": "La venta no existe en la estantería del artículo",
|
"The sale not exists in the item shelving": "La venta no existe en la estantería del artículo",
|
||||||
"The entry not have stickers": "La entrada no tiene etiquetas"
|
"The entry not have stickers": "La entrada no tiene etiquetas",
|
||||||
|
"Too many records": "Demasiados registros"
|
||||||
}
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
module.exports = async function(app) {
|
||||||
|
if (!app.orm) {
|
||||||
|
const ormConfig = await app.models.OrmConfig.findOne();
|
||||||
|
app.orm = ormConfig;
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,75 +0,0 @@
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
url="AccountConfigs"
|
|
||||||
data="$ctrl.config"
|
|
||||||
id-value="1"
|
|
||||||
form="form">
|
|
||||||
</vn-watcher>
|
|
||||||
<form
|
|
||||||
name="form"
|
|
||||||
ng-submit="watcher.submit()"
|
|
||||||
class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg" vn-focus>
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-textfield
|
|
||||||
label="Homedir base"
|
|
||||||
ng-model="$ctrl.config.homedir"
|
|
||||||
rule="AccountConfig">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
label="Shell"
|
|
||||||
ng-model="$ctrl.config.shell"
|
|
||||||
rule="AccountConfig">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-input-number
|
|
||||||
label="User and role base id"
|
|
||||||
ng-model="$ctrl.config.idBase"
|
|
||||||
rule="AccountConfig">
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-number
|
|
||||||
label="Min"
|
|
||||||
ng-model="$ctrl.config.min"
|
|
||||||
rule="AccountConfig">
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-input-number
|
|
||||||
label="Max"
|
|
||||||
ng-model="$ctrl.config.max"
|
|
||||||
rule="AccountConfig">
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-number
|
|
||||||
label="Warn"
|
|
||||||
ng-model="$ctrl.config.warn"
|
|
||||||
rule="AccountConfig">
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-input-number
|
|
||||||
label="Inact"
|
|
||||||
ng-model="$ctrl.config.inact"
|
|
||||||
rule="AccountConfig">
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
label="Synchronize all"
|
|
||||||
ng-click="$ctrl.onSynchronizeAll()">
|
|
||||||
</vn-button>
|
|
||||||
<vn-button
|
|
||||||
label="Synchronize roles"
|
|
||||||
ng-click="$ctrl.onSynchronizeRoles()">
|
|
||||||
</vn-button>
|
|
||||||
<vn-button
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
class="cancel"
|
|
||||||
label="Undo changes"
|
|
||||||
ng-click="watcher.loadOriginalData()">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,19 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
onSynchronizeAll() {
|
|
||||||
this.vnApp.showSuccess(this.$t('Synchronizing in the background'));
|
|
||||||
this.$http.patch(`Accounts/syncAll`);
|
|
||||||
}
|
|
||||||
|
|
||||||
onSynchronizeRoles() {
|
|
||||||
this.$http.patch(`RoleInherits/sync`)
|
|
||||||
.then(() => this.vnApp.showSuccess(this.$t('Roles synchronized!')));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnAccountAccounts', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,14 +0,0 @@
|
||||||
Accounts: Cuentas
|
|
||||||
Homedir base: Directorio base para carpetas de usuario
|
|
||||||
Shell: Intérprete de línea de comandos
|
|
||||||
User and role base id: Id base usuarios y roles
|
|
||||||
Synchronize all: Sincronizar todo
|
|
||||||
Synchronize roles: Sincronizar roles
|
|
||||||
If password is not specified, just user attributes are synchronized: >-
|
|
||||||
Si la contraseña no se especifica solo se sincronizarán lo atributos del usuario
|
|
||||||
Synchronizing in the background: Sincronizando en segundo plano
|
|
||||||
Users synchronized!: ¡Usuarios sincronizados!
|
|
||||||
Username: Nombre de usuario
|
|
||||||
Synchronize: Sincronizar
|
|
||||||
Please enter the username: Por favor introduce el nombre de usuario
|
|
||||||
Roles synchronized!: ¡Roles sincronizados!
|
|
|
@ -1,70 +0,0 @@
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
url="ACLs"
|
|
||||||
data="$ctrl.acl"
|
|
||||||
id-value="$ctrl.$params.id"
|
|
||||||
insert-mode="!$ctrl.$params.id"
|
|
||||||
form="form">
|
|
||||||
</vn-watcher>
|
|
||||||
<form
|
|
||||||
name="form"
|
|
||||||
vn-http-submit="watcher.submitGo('account.acl')"
|
|
||||||
class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Role"
|
|
||||||
ng-model="$ctrl.acl.principalId"
|
|
||||||
url="VnRoles"
|
|
||||||
id-field="name"
|
|
||||||
value-field="name"
|
|
||||||
vn-focus>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Model"
|
|
||||||
ng-model="$ctrl.acl.model"
|
|
||||||
data="$ctrl.models"
|
|
||||||
id-field="name"
|
|
||||||
value-field="name">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
label="Property"
|
|
||||||
ng-model="$ctrl.acl.property"
|
|
||||||
info="Use * to match all properties">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Access type"
|
|
||||||
ng-model="$ctrl.acl.accessType"
|
|
||||||
data="$ctrl.accessTypes"
|
|
||||||
id-field="name"
|
|
||||||
value-field="name">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Permission"
|
|
||||||
ng-model="$ctrl.acl.permission"
|
|
||||||
data="$ctrl.permissions"
|
|
||||||
id-field="name"
|
|
||||||
value-field="name">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Cancel"
|
|
||||||
ui-sref="account.acl">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,33 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
constructor(...args) {
|
|
||||||
super(...args);
|
|
||||||
this.accessTypes = [
|
|
||||||
{name: '*'},
|
|
||||||
{name: 'READ'},
|
|
||||||
{name: 'WRITE'}
|
|
||||||
];
|
|
||||||
this.permissions = [
|
|
||||||
{name: 'ALLOW'},
|
|
||||||
{name: 'DENY'}
|
|
||||||
];
|
|
||||||
|
|
||||||
this.models = [];
|
|
||||||
for (let model in window.validations)
|
|
||||||
this.models.push({name: model});
|
|
||||||
|
|
||||||
this.acl = {
|
|
||||||
property: '*',
|
|
||||||
principalType: 'ROLE',
|
|
||||||
accessType: 'READ',
|
|
||||||
permission: 'ALLOW'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnAclCreate', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,4 +0,0 @@
|
||||||
import './main';
|
|
||||||
import './index/';
|
|
||||||
import './create';
|
|
||||||
import './search-panel';
|
|
|
@ -1,51 +0,0 @@
|
||||||
<vn-auto-search
|
|
||||||
model="model">
|
|
||||||
</vn-auto-search>
|
|
||||||
<vn-data-viewer
|
|
||||||
model="model"
|
|
||||||
class="vn-w-sm">
|
|
||||||
<vn-card>
|
|
||||||
<vn-list class="separated">
|
|
||||||
<a
|
|
||||||
ng-repeat="row in model.data track by row.id"
|
|
||||||
ui-sref="account.acl.edit(::{id: row.id})"
|
|
||||||
translate-attr="{title: 'Edit ACL'}"
|
|
||||||
class="vn-item search-result">
|
|
||||||
<vn-item-section>
|
|
||||||
<h6>{{::row.model}}.{{::row.property}}</h6>
|
|
||||||
<vn-label-value
|
|
||||||
label="Role"
|
|
||||||
value="{{::row.principalId}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Access type"
|
|
||||||
value="{{::row.accessType}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Permission"
|
|
||||||
value="{{::row.permission}}">
|
|
||||||
</vn-label-value>
|
|
||||||
</vn-item-section>
|
|
||||||
<vn-item-section side>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-click-stop="deleteAcl.show(row)"
|
|
||||||
vn-tooltip="Delete"
|
|
||||||
icon="delete">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-item-section>
|
|
||||||
</a>
|
|
||||||
</vn-list>
|
|
||||||
</vn-card>
|
|
||||||
</vn-data-viewer>
|
|
||||||
<a ui-sref="account.acl.create"
|
|
||||||
vn-tooltip="New ACL"
|
|
||||||
vn-bind="+"
|
|
||||||
fixed-bottom-right>
|
|
||||||
<vn-float-button icon="add"></vn-float-button>
|
|
||||||
</a>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="deleteAcl"
|
|
||||||
on-accept="$ctrl.onDelete($data)"
|
|
||||||
question="Are you sure you want to continue?"
|
|
||||||
message="ACL will be removed">
|
|
||||||
</vn-confirm>
|
|
|
@ -1,15 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
onDelete(row) {
|
|
||||||
return this.$http.delete(`ACLs/${row.id}`)
|
|
||||||
.then(() => this.$.model.refresh())
|
|
||||||
.then(() => this.vnApp.showSuccess(this.$t('ACL removed')));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnAclIndex', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,4 +0,0 @@
|
||||||
New ACL: Nuevo ACL
|
|
||||||
Edit ACL: Editar ACL
|
|
||||||
ACL will be removed: El ACL será eliminado
|
|
||||||
ACL removed: ACL eliminado
|
|
|
@ -1,4 +0,0 @@
|
||||||
Model: Modelo
|
|
||||||
Property: Propiedad
|
|
||||||
Access type: Tipo de acceso
|
|
||||||
Permission: Permiso
|
|
|
@ -1,20 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="ACLs"
|
|
||||||
limit="20"
|
|
||||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
|
||||||
auto-save="true">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-portal slot="topbar">
|
|
||||||
<vn-searchbar
|
|
||||||
info="Search ACL by model name"
|
|
||||||
panel="vn-acl-search-panel"
|
|
||||||
model="model"
|
|
||||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
|
||||||
base-state="account.acl"
|
|
||||||
entity-state="edit">
|
|
||||||
</vn-searchbar>
|
|
||||||
</vn-portal>
|
|
||||||
<ui-view>
|
|
||||||
<vn-acl-index></vn-acl-index>
|
|
||||||
</ui-view>
|
|
|
@ -1,18 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import ModuleMain from 'salix/components/module-main';
|
|
||||||
|
|
||||||
export default class ACL extends ModuleMain {
|
|
||||||
exprBuilder(param, value) {
|
|
||||||
switch (param) {
|
|
||||||
case 'search':
|
|
||||||
return {model: {like: `%${value}%`}};
|
|
||||||
default:
|
|
||||||
return {[param]: value};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnAclComponent', {
|
|
||||||
controller: ACL,
|
|
||||||
template: require('./index.html')
|
|
||||||
});
|
|
|
@ -1,39 +0,0 @@
|
||||||
<div class="search-panel">
|
|
||||||
<form ng-submit="$ctrl.onSearch()">
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Role"
|
|
||||||
ng-model="filter.principalId"
|
|
||||||
url="VnRoles"
|
|
||||||
value-field="name">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Model"
|
|
||||||
ng-model="filter.model"
|
|
||||||
data="$ctrl.models"
|
|
||||||
id-field="name"
|
|
||||||
value-field="name">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-textfield
|
|
||||||
label="Property"
|
|
||||||
ng-model="filter.property">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Access type"
|
|
||||||
ng-model="filter.accessType"
|
|
||||||
data="$ctrl.accessTypes"
|
|
||||||
value-field="name">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Permission"
|
|
||||||
ng-model="$ctrl.acl.permission"
|
|
||||||
data="$ctrl.permissions"
|
|
||||||
value-field="name">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-submit
|
|
||||||
label="Search"
|
|
||||||
class="vn-mt-lg">
|
|
||||||
</vn-submit>
|
|
||||||
</vn-vertical>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
|
@ -1,26 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import SearchPanel from 'core/components/searchbar/search-panel';
|
|
||||||
|
|
||||||
export default class Controller extends SearchPanel {
|
|
||||||
constructor(...args) {
|
|
||||||
super(...args);
|
|
||||||
this.accessTypes = [
|
|
||||||
{name: '*'},
|
|
||||||
{name: 'READ'},
|
|
||||||
{name: 'WRITE'}
|
|
||||||
];
|
|
||||||
this.permissions = [
|
|
||||||
{name: 'ALLOW'},
|
|
||||||
{name: 'DENY'}
|
|
||||||
];
|
|
||||||
|
|
||||||
this.models = [];
|
|
||||||
for (let model in window.validations)
|
|
||||||
this.models.push({name: model});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnAclSearchPanel', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,43 +0,0 @@
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
url="MailAliases"
|
|
||||||
data="$ctrl.alias"
|
|
||||||
form="form">
|
|
||||||
</vn-watcher>
|
|
||||||
<form
|
|
||||||
name="form"
|
|
||||||
ng-submit="watcher.submit()"
|
|
||||||
class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-textfield
|
|
||||||
label="Name"
|
|
||||||
ng-model="$ctrl.alias.alias"
|
|
||||||
rule="MailAlias"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
label="Description"
|
|
||||||
ng-model="$ctrl.alias.description"
|
|
||||||
rule="MailAlias">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-check
|
|
||||||
label="Public"
|
|
||||||
ng-model="$ctrl.alias.isPublic"
|
|
||||||
rule="MailAlias">
|
|
||||||
</vn-check>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Undo changes"
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
ng-click="watcher.loadOriginalData()">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,12 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {}
|
|
||||||
|
|
||||||
ngModule.component('vnAliasBasicData', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
alias: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,5 +0,0 @@
|
||||||
<vn-portal slot="menu">
|
|
||||||
<vn-alias-descriptor alias="$ctrl.alias"></vn-alias-descriptor>
|
|
||||||
<vn-left-menu source="alias"></vn-left-menu>
|
|
||||||
</vn-portal>
|
|
||||||
<ui-view></ui-view>
|
|
|
@ -1,14 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import ModuleCard from 'salix/components/module-card';
|
|
||||||
|
|
||||||
class Controller extends ModuleCard {
|
|
||||||
reload() {
|
|
||||||
this.$http.get(`MailAliases/${this.$params.id}`)
|
|
||||||
.then(res => this.alias = res.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnAliasCard', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,38 +0,0 @@
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
url="MailAliases"
|
|
||||||
data="$ctrl.alias"
|
|
||||||
insert-mode="true"
|
|
||||||
form="form">
|
|
||||||
</vn-watcher>
|
|
||||||
<form
|
|
||||||
name="form"
|
|
||||||
vn-http-submit="$ctrl.onSubmit()"
|
|
||||||
class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-textfield
|
|
||||||
label="Name"
|
|
||||||
ng-model="$ctrl.alias.alias"
|
|
||||||
rule="MailAlias"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
label="Description"
|
|
||||||
ng-model="$ctrl.alias.description"
|
|
||||||
rule="MailAlias">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Create">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Cancel"
|
|
||||||
ui-sref="account.alias">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,15 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
onSubmit() {
|
|
||||||
return this.$.watcher.submit().then(res =>
|
|
||||||
this.$state.go('account.alias.card.basicData', {id: res.data.id})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnAliasCreate', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,27 +0,0 @@
|
||||||
<vn-descriptor-content
|
|
||||||
module="account"
|
|
||||||
base-state="account.alias"
|
|
||||||
description="$ctrl.alias.alias">
|
|
||||||
<slot-menu>
|
|
||||||
<vn-item
|
|
||||||
ng-click="deleteAlias.show()"
|
|
||||||
name="deleteAlias"
|
|
||||||
translate>
|
|
||||||
Delete
|
|
||||||
</vn-item>
|
|
||||||
</slot-menu>
|
|
||||||
<slot-body>
|
|
||||||
<div class="attributes">
|
|
||||||
<vn-label-value
|
|
||||||
label="Description"
|
|
||||||
value="{{$ctrl.alias.description}}">
|
|
||||||
</vn-label-value>
|
|
||||||
</div>
|
|
||||||
</slot-body>
|
|
||||||
</vn-descriptor-content>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="delete-alias"
|
|
||||||
on-accept="$ctrl.onDelete()"
|
|
||||||
question="Are you sure you want to continue?"
|
|
||||||
message="Alias will be removed">
|
|
||||||
</vn-confirm>
|
|
|
@ -1,26 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Descriptor from 'salix/components/descriptor';
|
|
||||||
|
|
||||||
class Controller extends Descriptor {
|
|
||||||
get alias() {
|
|
||||||
return this.entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
set alias(value) {
|
|
||||||
this.entity = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
onDelete() {
|
|
||||||
return this.$http.delete(`MailAliases/${this.id}`)
|
|
||||||
.then(() => this.$state.go('account.alias'))
|
|
||||||
.then(() => this.vnApp.showSuccess(this.$t('Alias removed')));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnAliasDescriptor', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
alias: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,2 +0,0 @@
|
||||||
Alias will be removed: El alias será eliminado
|
|
||||||
Alias removed: Alias eliminado
|
|
|
@ -1,9 +0,0 @@
|
||||||
import './main';
|
|
||||||
import './index/';
|
|
||||||
import './create';
|
|
||||||
import './summary';
|
|
||||||
import './card';
|
|
||||||
import './descriptor';
|
|
||||||
import './create';
|
|
||||||
import './basic-data';
|
|
||||||
import './users';
|
|
|
@ -1,39 +0,0 @@
|
||||||
<vn-auto-search
|
|
||||||
model="model">
|
|
||||||
</vn-auto-search>
|
|
||||||
<vn-data-viewer
|
|
||||||
model="model"
|
|
||||||
class="vn-w-sm">
|
|
||||||
<vn-card>
|
|
||||||
<vn-list class="separated">
|
|
||||||
<a
|
|
||||||
ng-repeat="alias in model.data track by alias.id"
|
|
||||||
ui-sref="account.alias.card.summary(::{id: alias.id})"
|
|
||||||
ui-sref-opts="{inherit: false}"
|
|
||||||
translate-attr="{title: 'View alias'}"
|
|
||||||
class="vn-item search-result">
|
|
||||||
<vn-item-section>
|
|
||||||
<h6>{{::alias.alias}}</h6>
|
|
||||||
<div>{{::alias.description}}</div>
|
|
||||||
</vn-item-section>
|
|
||||||
<vn-item-section side>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-click-stop="$ctrl.preview(alias)"
|
|
||||||
vn-tooltip="Preview"
|
|
||||||
icon="preview">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-item-section>
|
|
||||||
</a>
|
|
||||||
</vn-list>
|
|
||||||
</vn-card>
|
|
||||||
</vn-data-viewer>
|
|
||||||
<vn-popup vn-id="summary">
|
|
||||||
<vn-alias-summary alias="$ctrl.selectedAlias"></vn-alias-summary>
|
|
||||||
</vn-popup>
|
|
||||||
<a ui-sref="account.alias.create"
|
|
||||||
ui-sref-opts="{inherit: false}"
|
|
||||||
vn-tooltip="New alias"
|
|
||||||
vn-bind="+"
|
|
||||||
fixed-bottom-right>
|
|
||||||
<vn-float-button icon="add"></vn-float-button>
|
|
||||||
</a>
|
|
|
@ -1,14 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
preview(alias) {
|
|
||||||
this.selectedAlias = alias;
|
|
||||||
this.$.summary.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnAliasIndex', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,2 +0,0 @@
|
||||||
New alias: Nuevo alias
|
|
||||||
View alias: Ver alias
|
|
|
@ -1 +0,0 @@
|
||||||
Public: Público
|
|
|
@ -1,17 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="MailAliases"
|
|
||||||
limit="20"
|
|
||||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-portal slot="topbar">
|
|
||||||
<vn-searchbar
|
|
||||||
info="Search alias by id or name"
|
|
||||||
model="model"
|
|
||||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
|
||||||
base-state="account.alias">
|
|
||||||
</vn-searchbar>
|
|
||||||
</vn-portal>
|
|
||||||
<ui-view>
|
|
||||||
<vn-alias-index></vn-alias-index>
|
|
||||||
</ui-view>
|
|
|
@ -1,18 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import ModuleMain from 'salix/components/module-main';
|
|
||||||
|
|
||||||
export default class Alias extends ModuleMain {
|
|
||||||
exprBuilder(param, value) {
|
|
||||||
switch (param) {
|
|
||||||
case 'search':
|
|
||||||
return /^\d+$/.test(value)
|
|
||||||
? {id: value}
|
|
||||||
: {alias: {like: `%${value}%`}};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnAlias', {
|
|
||||||
controller: Alias,
|
|
||||||
template: require('./index.html')
|
|
||||||
});
|
|
|
@ -1,16 +0,0 @@
|
||||||
<vn-card class="summary">
|
|
||||||
<h5>{{summary.alias}}</h5>
|
|
||||||
<vn-horizontal class="vn-pa-md">
|
|
||||||
<vn-one>
|
|
||||||
<h4 translate>Basic data</h4>
|
|
||||||
<vn-label-value
|
|
||||||
label="Id"
|
|
||||||
value="{{summary.id}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Description"
|
|
||||||
value="{{summary.description}}">
|
|
||||||
</vn-label-value>
|
|
||||||
</vn-one>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
|
@ -1,25 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Component from 'core/lib/component';
|
|
||||||
|
|
||||||
class Controller extends Component {
|
|
||||||
set alias(value) {
|
|
||||||
this._alias = value;
|
|
||||||
this.$.summary = null;
|
|
||||||
if (!value) return;
|
|
||||||
|
|
||||||
this.$http.get(`MailAliases/${value.id}`)
|
|
||||||
.then(res => this.$.summary = res.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
get alias() {
|
|
||||||
return this._alias;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnAliasSummary', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
alias: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,26 +0,0 @@
|
||||||
<vn-data-viewer
|
|
||||||
data="data"
|
|
||||||
class="vn-w-xs">
|
|
||||||
<vn-card>
|
|
||||||
<vn-table>
|
|
||||||
<vn-tbody>
|
|
||||||
<vn-tr ng-repeat="row in data | orderBy:'user.name'">
|
|
||||||
<vn-td>{{::row.user.name}}</vn-td>
|
|
||||||
<vn-td shrink>
|
|
||||||
<vn-icon-button
|
|
||||||
icon="delete"
|
|
||||||
translate-attr="{title: 'Remove'}"
|
|
||||||
ng-click="removeConfirm.show(row)">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-td>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-tbody>
|
|
||||||
</vn-table>
|
|
||||||
</vn-card>
|
|
||||||
</vn-data-viewer>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="removeConfirm"
|
|
||||||
message="User will be removed from alias"
|
|
||||||
question="Are you sure you want to continue?"
|
|
||||||
on-accept="$ctrl.onRemove($data)">
|
|
||||||
</vn-confirm>
|
|
|
@ -1,31 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
$onInit() {
|
|
||||||
let filter = {
|
|
||||||
include: {
|
|
||||||
relation: 'user',
|
|
||||||
scope: {
|
|
||||||
fields: ['id', 'name']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.$http.get(`MailAliases/${this.$params.id}/accounts`, {filter})
|
|
||||||
.then(res => this.$.data = res.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
onRemove(row) {
|
|
||||||
return this.$http.delete(`MailAliases/${this.$params.id}/accounts/${row.id}`)
|
|
||||||
.then(() => {
|
|
||||||
let index = this.$.data.indexOf(row);
|
|
||||||
if (index !== -1) this.$.data.splice(index, 1);
|
|
||||||
this.vnApp.showSuccess(this.$t('User removed'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnAliasUsers', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,42 +0,0 @@
|
||||||
import './index';
|
|
||||||
|
|
||||||
describe('component vnAliasUsers', () => {
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(ngModule('account'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
controller = $componentController('vnAliasUsers', {$element: null});
|
|
||||||
controller.$params.id = 1;
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('$onInit()', () => {
|
|
||||||
it('should delete entity and go to index', () => {
|
|
||||||
$httpBackend.expectGET('MailAliases/1/accounts').respond('foo');
|
|
||||||
controller.$onInit();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.$.data).toBe('foo');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onRemove()', () => {
|
|
||||||
it('should call backend method to change role', () => {
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
|
|
||||||
controller.$.data = [
|
|
||||||
{id: 1, alias: 'foo'},
|
|
||||||
{id: 2, alias: 'bar'}
|
|
||||||
];
|
|
||||||
|
|
||||||
$httpBackend.expectDELETE('MailAliases/1/accounts/1').respond();
|
|
||||||
controller.onRemove(controller.$.data[0]);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.$.data).toEqual([{id: 2, alias: 'bar'}]);
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,2 +0,0 @@
|
||||||
User will be removed from alias: El usuario será borrado del alias
|
|
||||||
User removed: Usuario borrado
|
|
|
@ -1,64 +0,0 @@
|
||||||
<div ng-if="$ctrl.card.hasAccount">
|
|
||||||
<vn-data-viewer
|
|
||||||
data="data"
|
|
||||||
class="vn-w-xs">
|
|
||||||
<vn-card>
|
|
||||||
<vn-list class="separated">
|
|
||||||
<vn-item ng-repeat="row in data | orderBy:'alias.alias'">
|
|
||||||
<vn-item-section>
|
|
||||||
<div>
|
|
||||||
{{::row.alias.alias}}
|
|
||||||
</div>
|
|
||||||
<div class="text-caption text-secondary">
|
|
||||||
{{::row.alias.description}}
|
|
||||||
</div>
|
|
||||||
</vn-item-section>
|
|
||||||
<vn-item-section side>
|
|
||||||
<vn-icon-button
|
|
||||||
icon="delete"
|
|
||||||
translate-attr="{title: 'Unsubscribe'}"
|
|
||||||
ng-click="removeConfirm.show(row)">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-item-section>
|
|
||||||
</vn-item>
|
|
||||||
</vn-list>
|
|
||||||
</vn-table>
|
|
||||||
</vn-card>
|
|
||||||
</vn-data-viewer>
|
|
||||||
<vn-float-button
|
|
||||||
icon="add"
|
|
||||||
translate-attr="{title: 'Add'}"
|
|
||||||
vn-bind="+"
|
|
||||||
ng-click="$ctrl.onAddClick()"
|
|
||||||
fixed-bottom-right>
|
|
||||||
</vn-float-button>
|
|
||||||
<vn-dialog
|
|
||||||
vn-id="dialog"
|
|
||||||
on-accept="$ctrl.onAddSave()">
|
|
||||||
<tpl-body>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Alias"
|
|
||||||
ng-model="$ctrl.addData.mailAlias"
|
|
||||||
url="MailAliases"
|
|
||||||
show-field="alias"
|
|
||||||
vn-focus>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</tpl-body>
|
|
||||||
<tpl-buttons>
|
|
||||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
|
||||||
<button response="accept" translate>Save</button>
|
|
||||||
</tpl-buttons>
|
|
||||||
</vn-dialog>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="removeConfirm"
|
|
||||||
message="User will be removed from alias"
|
|
||||||
question="Are you sure you want to continue?"
|
|
||||||
on-accept="$ctrl.onRemove($data)">
|
|
||||||
</vn-confirm>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
ng-if="!$ctrl.card.hasAccount"
|
|
||||||
class="bg-title"
|
|
||||||
translate>
|
|
||||||
Account not enabled
|
|
||||||
</div>
|
|
|
@ -1,51 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
$onInit() {
|
|
||||||
this.refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh() {
|
|
||||||
let filter = {
|
|
||||||
where: {account: this.$params.id},
|
|
||||||
include: {
|
|
||||||
relation: 'alias',
|
|
||||||
scope: {
|
|
||||||
fields: ['id', 'alias', 'description']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return this.$http.get(`MailAliasAccounts`, {filter})
|
|
||||||
.then(res => this.$.data = res.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
onAddClick() {
|
|
||||||
this.addData = {account: this.$params.id};
|
|
||||||
this.$.dialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
onAddSave() {
|
|
||||||
return this.$http.post(`MailAliasAccounts`, this.addData)
|
|
||||||
.then(() => this.refresh())
|
|
||||||
.then(() => this.vnApp.showSuccess(
|
|
||||||
this.$t('Subscribed to alias!'))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
onRemove(row) {
|
|
||||||
return this.$http.delete(`MailAliasAccounts/${row.id}`)
|
|
||||||
.then(() => {
|
|
||||||
this.$.data.splice(this.$.data.indexOf(row), 1);
|
|
||||||
this.vnApp.showSuccess(this.$t('Unsubscribed from alias!'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnUserAliases', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
require: {
|
|
||||||
card: '^vnUserCard'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,53 +0,0 @@
|
||||||
import './index';
|
|
||||||
|
|
||||||
describe('component vnUserAliases', () => {
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(ngModule('account'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
controller = $componentController('vnUserAliases', {$element: null});
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('refresh()', () => {
|
|
||||||
it('should refresh the controller data', () => {
|
|
||||||
$httpBackend.expectGET('MailAliasAccounts').respond('foo');
|
|
||||||
controller.refresh();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.$.data).toBe('foo');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onAddSave()', () => {
|
|
||||||
it('should add the new row', () => {
|
|
||||||
controller.addData = {account: 1};
|
|
||||||
|
|
||||||
$httpBackend.expectPOST('MailAliasAccounts').respond();
|
|
||||||
$httpBackend.expectGET('MailAliasAccounts').respond('foo');
|
|
||||||
controller.onAddSave();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onRemove()', () => {
|
|
||||||
it('shoud remove the passed row remote and locally', () => {
|
|
||||||
controller.$.data = [
|
|
||||||
{id: 1, alias: 'foo'},
|
|
||||||
{id: 2, alias: 'bar'}
|
|
||||||
];
|
|
||||||
|
|
||||||
$httpBackend.expectDELETE('MailAliasAccounts/1').respond();
|
|
||||||
controller.onRemove(controller.$.data[0]);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.$.data).toEqual([{id: 2, alias: 'bar'}]);
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,3 +0,0 @@
|
||||||
Unsubscribe: Desuscribir
|
|
||||||
Subscribed to alias!: ¡Suscrito al alias!
|
|
||||||
Unsubscribed from alias!: ¡Desuscrito del alias!
|
|
|
@ -1,51 +0,0 @@
|
||||||
<mg-ajax path="VnUsers/{{patch.params.id}}/update-user" options="vnPatch"></mg-ajax>
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
data="$ctrl.user"
|
|
||||||
form="form"
|
|
||||||
save="patch">
|
|
||||||
</vn-watcher>
|
|
||||||
<form
|
|
||||||
name="form"
|
|
||||||
ng-submit="$ctrl.onSubmit()"
|
|
||||||
class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-textfield
|
|
||||||
label="User"
|
|
||||||
ng-model="$ctrl.user.name"
|
|
||||||
rule="VnUser"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
label="Nickname"
|
|
||||||
ng-model="$ctrl.user.nickname"
|
|
||||||
rule="VnUser">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
label="Personal email"
|
|
||||||
ng-model="$ctrl.user.email"
|
|
||||||
rule="VnUser">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Language"
|
|
||||||
ng-model="$ctrl.user.lang"
|
|
||||||
url="Languages"
|
|
||||||
value-field="code"
|
|
||||||
rule="VnUser">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Undo changes"
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
ng-click="watcher.loadOriginalData()">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,25 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
$onInit() {
|
|
||||||
if (this.$params.emailConfirmed)
|
|
||||||
this.vnApp.showSuccess(this.$t('Email verified successfully!'));
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
this.$.watcher.submit()
|
|
||||||
.then(() => this.card.reload());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnUserBasicData', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
require: {
|
|
||||||
card: '^vnUserCard'
|
|
||||||
},
|
|
||||||
bindings: {
|
|
||||||
user: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1 +0,0 @@
|
||||||
Email verified successfully!: Correo verificado correctamente!
|
|
|
@ -1,8 +0,0 @@
|
||||||
<vn-portal slot="menu">
|
|
||||||
<vn-user-descriptor
|
|
||||||
user="$ctrl.user"
|
|
||||||
on-change="$ctrl.reload()">
|
|
||||||
</vn-user-descriptor>
|
|
||||||
<vn-left-menu source="card"></vn-left-menu>
|
|
||||||
</vn-portal>
|
|
||||||
<ui-view></ui-view>
|
|
|
@ -1,32 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import ModuleCard from 'salix/components/module-card';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends ModuleCard {
|
|
||||||
reload() {
|
|
||||||
const filter = {
|
|
||||||
where: {id: this.$params.id},
|
|
||||||
include: {
|
|
||||||
relation: 'role',
|
|
||||||
scope: {
|
|
||||||
fields: ['id', 'name']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return Promise.all([
|
|
||||||
this.$http.get(`VnUsers/preview`, {filter})
|
|
||||||
.then(res => {
|
|
||||||
const [user] = res.data;
|
|
||||||
this.user = user;
|
|
||||||
}),
|
|
||||||
this.$http.get(`Accounts/${this.$params.id}/exists`)
|
|
||||||
.then(res => this.hasAccount = res.data.exists)
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnUserCard', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,27 +0,0 @@
|
||||||
import './index';
|
|
||||||
|
|
||||||
describe('component vnUserCard', () => {
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(ngModule('account'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
controller = $componentController('vnUserCard', {$element: null});
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('reload()', () => {
|
|
||||||
it('should reload the controller data', () => {
|
|
||||||
controller.$params.id = 1;
|
|
||||||
|
|
||||||
$httpBackend.expectGET('VnUsers/preview').respond('foo');
|
|
||||||
$httpBackend.expectGET('Accounts/1/exists').respond({exists: true});
|
|
||||||
controller.reload();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.user).toBe('f');
|
|
||||||
expect(controller.hasAccount).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,10 +0,0 @@
|
||||||
@import "variables";
|
|
||||||
|
|
||||||
.bg-title {
|
|
||||||
display: block;
|
|
||||||
text-align: center;
|
|
||||||
padding: 24px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
color: $color-font-secondary;
|
|
||||||
font-size: 1.375rem;
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="AccessTokens"
|
|
||||||
filter="::$ctrl.filter"
|
|
||||||
limit="20"
|
|
||||||
auto-load="true">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-data-viewer
|
|
||||||
model="model"
|
|
||||||
class="vn-w-sm">
|
|
||||||
<vn-card>
|
|
||||||
<vn-list class="separated">
|
|
||||||
<a
|
|
||||||
ng-repeat="row in model.data"
|
|
||||||
ui-sref="account.card.summary(::{id: row.user.id})"
|
|
||||||
translate-attr="{title: 'Go to user'}"
|
|
||||||
class="vn-item search-result">
|
|
||||||
<vn-item-section>
|
|
||||||
<h6>{{::row.user.username}}</h6>
|
|
||||||
<div>{{::row.created | date:'dd/MM HH:mm'}}</div>
|
|
||||||
</vn-item-section>
|
|
||||||
<vn-item-section side>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-click-stop="disconnect.show(row)"
|
|
||||||
vn-tooltip="Kill session"
|
|
||||||
icon="exit_to_app">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-item-section>
|
|
||||||
</a>
|
|
||||||
</vn-list>
|
|
||||||
</vn-card>
|
|
||||||
</vn-data-viewer>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="disconnect"
|
|
||||||
on-accept="$ctrl.onDisconnect($data)"
|
|
||||||
question="Are you sure you want to continue?"
|
|
||||||
message="Session will be killed">
|
|
||||||
</vn-confirm>
|
|
||||||
<vn-float-button
|
|
||||||
vn-tooltip="Refresh"
|
|
||||||
icon="refresh"
|
|
||||||
ng-click="model.refresh()"
|
|
||||||
vn-bind="r"
|
|
||||||
fixed-bottom-right>
|
|
||||||
</vn-float-button>
|
|
|
@ -1,29 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
constructor(...args) {
|
|
||||||
super(...args);
|
|
||||||
this.filter = {
|
|
||||||
fields: ['id', 'created', 'userId'],
|
|
||||||
include: {
|
|
||||||
relation: 'user',
|
|
||||||
scope: {
|
|
||||||
fields: ['username']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
order: 'created DESC'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
onDisconnect(row) {
|
|
||||||
return this.$http.delete(`AccessTokens/${row.id}`)
|
|
||||||
.then(() => this.$.model.refresh())
|
|
||||||
.then(() => this.vnApp.showSuccess(this.$t('Session killed')));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnConnections', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,5 +0,0 @@
|
||||||
Go to user: Ir al usuario
|
|
||||||
Refresh: Actualizar
|
|
||||||
Session will be killed: Se va a matar la sesión
|
|
||||||
Kill session: Matar sesión
|
|
||||||
Session killed: Sesión matada
|
|
|
@ -1,57 +0,0 @@
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
url="VnUsers"
|
|
||||||
data="$ctrl.user"
|
|
||||||
insert-mode="true"
|
|
||||||
form="form">
|
|
||||||
</vn-watcher>
|
|
||||||
<form
|
|
||||||
name="form"
|
|
||||||
vn-http-submit="$ctrl.onSubmit()"
|
|
||||||
class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-textfield
|
|
||||||
label="Name"
|
|
||||||
ng-model="$ctrl.user.name"
|
|
||||||
rule="VnUser"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
label="Nickname"
|
|
||||||
ng-model="$ctrl.user.nickname"
|
|
||||||
rule="VnUser">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
label="Email"
|
|
||||||
ng-model="$ctrl.user.email"
|
|
||||||
rule="VnUser">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Role"
|
|
||||||
ng-model="$ctrl.user.roleFk"
|
|
||||||
url="VnRoles"
|
|
||||||
rule="VnUser">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-textfield
|
|
||||||
label="Password"
|
|
||||||
ng-model="$ctrl.user.password"
|
|
||||||
type="password">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-check
|
|
||||||
label="Active"
|
|
||||||
ng-model="$ctrl.user.active">
|
|
||||||
</vn-check>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
label="Create">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Cancel"
|
|
||||||
ui-sref="account.index">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,20 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
constructor($element, $) {
|
|
||||||
super($element, $);
|
|
||||||
this.user = {active: true};
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
return this.$.watcher.submit().then(res => {
|
|
||||||
this.$state.go('account.card.basicData', {id: res.data.id});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnUserCreate', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,5 +0,0 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`component vnUserDescriptor onPassChange() should throw an error when password is empty 1`] = `"You must enter a new password"`;
|
|
||||||
|
|
||||||
exports[`component vnUserDescriptor onPassChange() should throw an error when repeat password not matches new password 1`] = `"Passwords don't match"`;
|
|
|
@ -1,97 +0,0 @@
|
||||||
import './index';
|
|
||||||
|
|
||||||
describe('component vnUserDescriptor', () => {
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
let user = {id: 1, name: 'foo'};
|
|
||||||
|
|
||||||
beforeEach(ngModule('account'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$httpBackend.whenGET('Accounts/1/exists').respond({exists: true});
|
|
||||||
|
|
||||||
controller = $componentController('vnUserDescriptor', {$element: null}, {user});
|
|
||||||
jest.spyOn(controller, 'emit');
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('onDelete()', () => {
|
|
||||||
it('should delete entity and go to index', () => {
|
|
||||||
controller.$state.go = jest.fn();
|
|
||||||
|
|
||||||
$httpBackend.expectDELETE('VnUsers/1').respond();
|
|
||||||
controller.onDelete();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.$state.go).toHaveBeenCalledWith('account.index');
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onPassChange()', () => {
|
|
||||||
it('should throw an error when password is empty', () => {
|
|
||||||
expect(() => {
|
|
||||||
controller.onPassChange();
|
|
||||||
}).toThrowErrorMatchingSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error when repeat password not matches new password', () => {
|
|
||||||
controller.newPassword = 'foo';
|
|
||||||
controller.repeatPassword = 'bar';
|
|
||||||
|
|
||||||
expect(() => {
|
|
||||||
controller.onPassChange();
|
|
||||||
}).toThrowErrorMatchingSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should make a request when password checks passes', () => {
|
|
||||||
controller.newPassword = 'foo';
|
|
||||||
controller.repeatPassword = 'foo';
|
|
||||||
|
|
||||||
$httpBackend.expectPATCH('Accounts/1/setPassword').respond();
|
|
||||||
controller.onPassChange();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
expect(controller.emit).toHaveBeenCalledWith('change');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onEnableAccount()', () => {
|
|
||||||
it('should make request to enable account', () => {
|
|
||||||
$httpBackend.expectPOST('Accounts', {id: 1}).respond();
|
|
||||||
controller.onEnableAccount();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.hasAccount).toBeTruthy();
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
expect(controller.emit).toHaveBeenCalledWith('change');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onDisableAccount()', () => {
|
|
||||||
it('should make request to disable account', () => {
|
|
||||||
$httpBackend.expectDELETE('Accounts/1').respond();
|
|
||||||
controller.onDisableAccount();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.hasAccount).toBeFalsy();
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
expect(controller.emit).toHaveBeenCalledWith('change');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onSetActive()', () => {
|
|
||||||
it('should make request to activate/deactivate the user', () => {
|
|
||||||
$httpBackend.expectPATCH('VnUsers/1', {active: true}).respond();
|
|
||||||
controller.onSetActive(true);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.user.active).toBeTruthy();
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
expect(controller.emit).toHaveBeenCalledWith('change');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,24 +1,6 @@
|
||||||
export * from './module';
|
export * from './module';
|
||||||
|
|
||||||
import './main';
|
import './main';
|
||||||
import './index/';
|
|
||||||
import './role';
|
|
||||||
import './alias';
|
|
||||||
import './connections';
|
|
||||||
import './acl';
|
|
||||||
import './summary';
|
|
||||||
import './card';
|
|
||||||
import './descriptor';
|
import './descriptor';
|
||||||
import './descriptor-popover';
|
import './descriptor-popover';
|
||||||
import './search-panel';
|
import './summary';
|
||||||
import './create';
|
|
||||||
import './basic-data';
|
|
||||||
import './mail-forwarding';
|
|
||||||
import './aliases';
|
|
||||||
import './roles';
|
|
||||||
import './ldap';
|
|
||||||
import './samba';
|
|
||||||
import './accounts';
|
|
||||||
import './privileges';
|
|
||||||
import './user-log';
|
|
||||||
import './role-log';
|
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
<vn-auto-search
|
|
||||||
model="model">
|
|
||||||
</vn-auto-search>
|
|
||||||
<vn-data-viewer
|
|
||||||
model="model"
|
|
||||||
class="vn-w-sm">
|
|
||||||
<vn-card>
|
|
||||||
<div class="vn-list separated">
|
|
||||||
<a
|
|
||||||
ng-repeat="user in model.data track by user.id"
|
|
||||||
ui-sref="account.card.summary(::{id: user.id})"
|
|
||||||
translate-attr="{title: 'View user'}"
|
|
||||||
class="vn-item search-result">
|
|
||||||
<vn-item-section>
|
|
||||||
<h6>{{::user.nickname}}</h6>
|
|
||||||
<vn-label-value
|
|
||||||
label="Id"
|
|
||||||
value="{{::user.id}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="User"
|
|
||||||
value="{{::user.name}}">
|
|
||||||
</vn-label-value>
|
|
||||||
</vn-item-section>
|
|
||||||
<vn-item-section side>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-click-stop="$ctrl.preview(user)"
|
|
||||||
vn-tooltip="Preview"
|
|
||||||
icon="preview">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-item-section>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</vn-card>
|
|
||||||
</vn-data-viewer>
|
|
||||||
<vn-popup vn-id="summary">
|
|
||||||
<vn-user-summary user="$ctrl.selectedUser"></vn-user-summary>
|
|
||||||
</vn-popup>
|
|
||||||
<a
|
|
||||||
fixed-bottom-right
|
|
||||||
ui-sref="account.create"
|
|
||||||
vn-tooltip="New user"
|
|
||||||
vn-bind="+"
|
|
||||||
vn-acl="itManagement"
|
|
||||||
vn-acl-action="remove">
|
|
||||||
<vn-float-button icon="add"></vn-float-button>
|
|
||||||
</a>
|
|
|
@ -1,14 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
preview(user) {
|
|
||||||
this.selectedUser = user;
|
|
||||||
this.$.summary.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnUserIndex', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,2 +0,0 @@
|
||||||
New user: Nuevo usuario
|
|
||||||
View user: Ver usuario
|
|
|
@ -1,66 +0,0 @@
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
url="LdapConfigs"
|
|
||||||
data="$ctrl.config"
|
|
||||||
id-value="1"
|
|
||||||
form="form">
|
|
||||||
</vn-watcher>
|
|
||||||
<form
|
|
||||||
name="form"
|
|
||||||
ng-submit="watcher.submit()"
|
|
||||||
class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg" vn-focus>
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-check
|
|
||||||
label="Enable synchronization"
|
|
||||||
ng-model="watcher.hasData">
|
|
||||||
</vn-check>
|
|
||||||
</vn-vertical>
|
|
||||||
<vn-vertical
|
|
||||||
ng-if="watcher.hasData"
|
|
||||||
class="vn-mt-md">
|
|
||||||
<vn-textfield
|
|
||||||
label="Server"
|
|
||||||
ng-model="$ctrl.config.server"
|
|
||||||
rule="LdapConfig">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
label="RDN"
|
|
||||||
ng-model="$ctrl.config.rdn"
|
|
||||||
rule="LdapConfig">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
label="Password"
|
|
||||||
ng-model="$ctrl.config.password"
|
|
||||||
type="password"
|
|
||||||
rule="LdapConfig">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
label="User DN"
|
|
||||||
ng-model="$ctrl.config.userDn"
|
|
||||||
rule="LdapConfig">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
label="Group DN"
|
|
||||||
ng-model="$ctrl.config.groupDn"
|
|
||||||
rule="LdapConfig">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
label="Test connection"
|
|
||||||
ng-click="$ctrl.onTestConection()">
|
|
||||||
</vn-button>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Undo changes"
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
ng-click="watcher.loadOriginalData()">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,14 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
onTestConection() {
|
|
||||||
this.$http.get(`LdapConfigs/test`)
|
|
||||||
.then(() => this.vnApp.showSuccess(this.$t('LDAP connection established!')));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnAccountLdap', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,8 +0,0 @@
|
||||||
Enable synchronization: Habilitar sincronización
|
|
||||||
Server: Servidor
|
|
||||||
RDN: RDN
|
|
||||||
User DN: DN usuarios
|
|
||||||
Filter: Filtro
|
|
||||||
Group DN: DN grupos
|
|
||||||
Test connection: Probar conexión
|
|
||||||
LDAP connection established!: ¡Conexión con LDAP establecida!
|
|
|
@ -1,49 +0,0 @@
|
||||||
<div ng-if="$ctrl.card.hasAccount">
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
url="MailForwards"
|
|
||||||
id-field="account"
|
|
||||||
id-value="$ctrl.$params.id"
|
|
||||||
data="data"
|
|
||||||
form="form">
|
|
||||||
</vn-watcher>
|
|
||||||
<form
|
|
||||||
name="form"
|
|
||||||
ng-submit="watcher.submit()"
|
|
||||||
class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-check
|
|
||||||
label="Enable mail forwarding"
|
|
||||||
ng-model="watcher.hasData">
|
|
||||||
</vn-check>
|
|
||||||
<vn-textfield
|
|
||||||
ng-if="watcher.hasData"
|
|
||||||
label="Forward email"
|
|
||||||
ng-model="data.forwardTo"
|
|
||||||
info="All emails will be forwarded to the specified address."
|
|
||||||
rule="MailForward"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Undo changes"
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
ng-click="watcher.loadOriginalData()">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
ng-if="!$ctrl.card.hasAccount"
|
|
||||||
class="bg-title"
|
|
||||||
translate>
|
|
||||||
Account not enabled
|
|
||||||
</div>
|
|
|
@ -1,12 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {}
|
|
||||||
|
|
||||||
ngModule.component('vnUserMailForwarding', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
require: {
|
|
||||||
card: '^vnUserCard'
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,7 +0,0 @@
|
||||||
Mail forwarding: Reenvío de correo
|
|
||||||
Forward email: Dirección de reenvío
|
|
||||||
Enable mail forwarding: Habilitar redirección de correo
|
|
||||||
All emails will be forwarded to the specified address.: >
|
|
||||||
Todos los correos serán reenviados a la dirección especificada, no se
|
|
||||||
mantendrá copia de los mismos en el buzón del usuario.
|
|
||||||
You don't have enough privileges: No tienes suficientes permisos
|
|
|
@ -1,19 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="VnUsers/preview"
|
|
||||||
filter="::$ctrl.filter"
|
|
||||||
limit="20">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-portal slot="topbar">
|
|
||||||
<vn-searchbar
|
|
||||||
vn-focus
|
|
||||||
panel="vn-user-search-panel"
|
|
||||||
info="Search user by id, name or nickname"
|
|
||||||
model="model"
|
|
||||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
|
||||||
</vn-searchbar>
|
|
||||||
</vn-portal>
|
|
||||||
<vn-portal slot="menu">
|
|
||||||
<vn-left-menu></vn-left-menu>
|
|
||||||
</vn-portal>
|
|
||||||
<ui-view></ui-view>
|
|
|
@ -4,32 +4,10 @@ import ModuleMain from 'salix/components/module-main';
|
||||||
export default class User extends ModuleMain {
|
export default class User extends ModuleMain {
|
||||||
constructor($element, $) {
|
constructor($element, $) {
|
||||||
super($element, $);
|
super($element, $);
|
||||||
this.filter = {
|
|
||||||
fields: ['id', 'nickname', 'name', 'role'],
|
|
||||||
include: {
|
|
||||||
relation: 'role',
|
|
||||||
scope: {
|
|
||||||
fields: ['id', 'name']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
exprBuilder(param, value) {
|
|
||||||
switch (param) {
|
|
||||||
case 'search':
|
|
||||||
return /^\d+$/.test(value)
|
|
||||||
? {id: value}
|
|
||||||
: {or: [
|
|
||||||
{name: {like: `%${value}%`}},
|
|
||||||
{nickname: {like: `%${value}%`}}
|
|
||||||
]};
|
|
||||||
case 'name':
|
|
||||||
case 'nickname':
|
|
||||||
return {[param]: {like: `%${value}%`}};
|
|
||||||
case 'roleFk':
|
|
||||||
return {[param]: value};
|
|
||||||
}
|
}
|
||||||
|
async $onInit() {
|
||||||
|
this.$state.go('home');
|
||||||
|
window.location.href = await this.vnApp.getUrl(`account/`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
import './index';
|
|
||||||
|
|
||||||
describe('component vnUser', () => {
|
|
||||||
let controller;
|
|
||||||
|
|
||||||
beforeEach(ngModule('account'));
|
|
||||||
|
|
||||||
beforeEach(inject($componentController => {
|
|
||||||
controller = $componentController('vnUser', {$element: null});
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('exprBuilder()', () => {
|
|
||||||
it('should search by id when only digits string is passed', () => {
|
|
||||||
let expr = controller.exprBuilder('search', '1');
|
|
||||||
|
|
||||||
expect(expr).toEqual({id: '1'});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should search by name when non-only digits string is passed', () => {
|
|
||||||
let expr = controller.exprBuilder('search', '1foo');
|
|
||||||
|
|
||||||
expect(expr).toEqual({or: [
|
|
||||||
{name: {like: '%1foo%'}},
|
|
||||||
{nickname: {like: '%1foo%'}}
|
|
||||||
]});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,41 +0,0 @@
|
||||||
<mg-ajax path="VnUsers/{{post.params.id}}/privileges" options="vnPost"></mg-ajax>
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
data="$ctrl.user"
|
|
||||||
form="form"
|
|
||||||
save="post">
|
|
||||||
</vn-watcher>
|
|
||||||
<form
|
|
||||||
name="form"
|
|
||||||
ng-submit="watcher.submit()"
|
|
||||||
class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-check
|
|
||||||
label="Has grant"
|
|
||||||
ng-model="$ctrl.user.hasGrant">
|
|
||||||
</vn-check>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-card>
|
|
||||||
<vn-card class="vn-pa-lg vn-mt-md">
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Role"
|
|
||||||
ng-model="$ctrl.user.roleFk"
|
|
||||||
url="VnRoles">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Undo changes"
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
ng-click="watcher.loadOriginalData()">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,21 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
get user() {
|
|
||||||
return this._user;
|
|
||||||
}
|
|
||||||
|
|
||||||
set user(value) {
|
|
||||||
this._user = value;
|
|
||||||
if (!value) return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnUserPrivileges', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
user: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,2 +0,0 @@
|
||||||
Privileges: Privilegios
|
|
||||||
Has grant: Puede delegar privilegios
|
|
|
@ -1 +0,0 @@
|
||||||
<vn-log url="RoleLogs" origin-id="$ctrl.$params.id"></vn-log>
|
|
|
@ -1,7 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRoleLog', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Section,
|
|
||||||
});
|
|
|
@ -1,40 +0,0 @@
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
url="VnRoles"
|
|
||||||
data="$ctrl.role"
|
|
||||||
form="form">
|
|
||||||
</vn-watcher>
|
|
||||||
<form
|
|
||||||
name="form"
|
|
||||||
ng-submit="watcher.submit()"
|
|
||||||
|
|
||||||
class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-textfield
|
|
||||||
label="Name"
|
|
||||||
ng-model="$ctrl.role.name"
|
|
||||||
rule="VnRole.name"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
label="Description"
|
|
||||||
ng-model="$ctrl.role.description"
|
|
||||||
rule="VnRole.description"
|
|
||||||
>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Undo changes"
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
ng-click="watcher.loadOriginalData()">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,12 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {}
|
|
||||||
|
|
||||||
ngModule.component('vnRoleBasicData', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
role: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,5 +0,0 @@
|
||||||
<vn-portal slot="menu">
|
|
||||||
<vn-role-descriptor role="$ctrl.role"></vn-role-descriptor>
|
|
||||||
<vn-left-menu source="role"></vn-left-menu>
|
|
||||||
</vn-portal>
|
|
||||||
<ui-view></ui-view>
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue