Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 2378-imap
This commit is contained in:
commit
ce1c4e6f60
|
@ -0,0 +1,34 @@
|
|||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('changePassword', {
|
||||
description: 'Changes the user password',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'id',
|
||||
type: 'Number',
|
||||
description: 'The user id',
|
||||
http: {source: 'path'}
|
||||
}, {
|
||||
arg: 'oldPassword',
|
||||
type: 'String',
|
||||
description: 'The old password',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'newPassword',
|
||||
type: 'String',
|
||||
description: 'The new password',
|
||||
required: true
|
||||
}
|
||||
],
|
||||
http: {
|
||||
path: `/:id/changePassword`,
|
||||
verb: 'PATCH'
|
||||
}
|
||||
});
|
||||
|
||||
Self.changePassword = async function(id, oldPassword, newPassword) {
|
||||
await Self.rawSql(`CALL account.user_changePassword(?, ?, ?)`,
|
||||
[id, oldPassword, newPassword]);
|
||||
await Self.app.models.UserAccount.syncById(id, newPassword);
|
||||
};
|
||||
};
|
|
@ -26,9 +26,9 @@ module.exports = Self => {
|
|||
});
|
||||
|
||||
Self.login = async function(user, password) {
|
||||
let $ = Self.app.models;
|
||||
let token;
|
||||
let usesEmail = user.indexOf('@') !== -1;
|
||||
let User = Self.app.models.User;
|
||||
|
||||
let loginInfo = {password};
|
||||
|
||||
|
@ -38,7 +38,7 @@ module.exports = Self => {
|
|||
loginInfo.username = user;
|
||||
|
||||
try {
|
||||
token = await User.login(loginInfo, 'user');
|
||||
token = await $.User.login(loginInfo, 'user');
|
||||
} catch (err) {
|
||||
if (err.code != 'LOGIN_FAILED' || usesEmail)
|
||||
throw err;
|
||||
|
@ -49,17 +49,8 @@ module.exports = Self => {
|
|||
if (!instance || instance.password !== md5(password || ''))
|
||||
throw err;
|
||||
|
||||
let where = {id: instance.id};
|
||||
let userData = {
|
||||
id: instance.id,
|
||||
username: user,
|
||||
password: password,
|
||||
email: instance.email,
|
||||
created: instance.created,
|
||||
updated: instance.updated
|
||||
};
|
||||
await User.upsertWithWhere(where, userData);
|
||||
token = await User.login(loginInfo, 'user');
|
||||
await $.UserAccount.sync(user, password);
|
||||
token = await $.User.login(loginInfo, 'user');
|
||||
}
|
||||
|
||||
return {token: token.id};
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('setPassword', {
|
||||
description: 'Sets the user password',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'id',
|
||||
type: 'Number',
|
||||
description: 'The user id',
|
||||
http: {source: 'path'}
|
||||
}, {
|
||||
arg: 'newPassword',
|
||||
type: 'String',
|
||||
description: 'The new password',
|
||||
required: true
|
||||
}
|
||||
],
|
||||
http: {
|
||||
path: `/:id/setPassword`,
|
||||
verb: 'PATCH'
|
||||
}
|
||||
});
|
||||
|
||||
Self.setPassword = async function(id, newPassword) {
|
||||
await Self.rawSql(`CALL account.user_setPassword(?, ?)`,
|
||||
[id, newPassword]);
|
||||
await Self.app.models.UserAccount.syncById(id, newPassword);
|
||||
};
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('account changePassword()', () => {
|
||||
it('should throw an error when old password is wrong', async() => {
|
||||
let req = app.models.Account.changePassword(null, 1, 'wrongOldPass', 'newPass');
|
||||
|
||||
await expectAsync(req).toBeRejected();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,15 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('account changePassword()', () => {
|
||||
it('should throw an error when password does not meet requirements', async() => {
|
||||
let req = app.models.Account.setPassword(1, 'insecurePass');
|
||||
|
||||
await expectAsync(req).toBeRejected();
|
||||
});
|
||||
|
||||
it('should update password when it passes requirements', async() => {
|
||||
let req = app.models.Account.setPassword(1, 'Very$ecurePa22.');
|
||||
|
||||
await expectAsync(req).toBeResolved();
|
||||
});
|
||||
});
|
|
@ -38,6 +38,9 @@
|
|||
"ImageCollectionSize": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Language": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Province": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
|
|
|
@ -4,6 +4,8 @@ module.exports = Self => {
|
|||
require('../methods/account/login')(Self);
|
||||
require('../methods/account/logout')(Self);
|
||||
require('../methods/account/acl')(Self);
|
||||
require('../methods/account/change-password')(Self);
|
||||
require('../methods/account/set-password')(Self);
|
||||
require('../methods/account/validate-token')(Self);
|
||||
|
||||
// Validations
|
||||
|
@ -38,17 +40,9 @@ module.exports = Self => {
|
|||
|
||||
Self.getCurrentUserData = async function(ctx) {
|
||||
let userId = ctx.req.accessToken.userId;
|
||||
|
||||
let account = await Self.findById(userId, {
|
||||
return await Self.findById(userId, {
|
||||
fields: ['id', 'name', 'nickname']
|
||||
});
|
||||
|
||||
let worker = await Self.app.models.Worker.findOne({
|
||||
fields: ['id'],
|
||||
where: {userFk: userId}
|
||||
});
|
||||
|
||||
return Object.assign(account, {workerId: worker.id});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"mysql": {
|
||||
"table": "account.user"
|
||||
}
|
||||
},
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
|
@ -24,10 +24,16 @@
|
|||
"nickname": {
|
||||
"type": "string"
|
||||
},
|
||||
"lang": {
|
||||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"bcryptPassword": {
|
||||
"type": "string"
|
||||
},
|
||||
"active": {
|
||||
"type": "boolean"
|
||||
},
|
||||
|
@ -41,44 +47,47 @@
|
|||
"type": "date"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
"role": {
|
||||
"type": "belongsTo",
|
||||
"model": "Role",
|
||||
"foreignKey": "roleFk"
|
||||
},
|
||||
"emailUser": {
|
||||
"type": "hasOne",
|
||||
"model": "EmailUser",
|
||||
"foreignKey": "userFk"
|
||||
"relations": {
|
||||
"role": {
|
||||
"type": "belongsTo",
|
||||
"model": "Role",
|
||||
"foreignKey": "roleFk"
|
||||
},
|
||||
"roles": {
|
||||
"type": "hasMany",
|
||||
"model": "RoleRole",
|
||||
"foreignKey": "role"
|
||||
},
|
||||
"emailUser": {
|
||||
"type": "hasOne",
|
||||
"model": "EmailUser",
|
||||
"foreignKey": "userFk"
|
||||
},
|
||||
"worker": {
|
||||
"type": "hasOne",
|
||||
"model": "Worker",
|
||||
"foreignKey": "userFk"
|
||||
}
|
||||
},
|
||||
"acls": [
|
||||
{
|
||||
}
|
||||
},
|
||||
"acls": [
|
||||
{
|
||||
"property": "login",
|
||||
"accessType": "EXECUTE",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
},
|
||||
{
|
||||
}, {
|
||||
"property": "logout",
|
||||
"accessType": "EXECUTE",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$authenticated",
|
||||
"permission": "ALLOW"
|
||||
},
|
||||
{
|
||||
}, {
|
||||
"property": "validateToken",
|
||||
"accessType": "EXECUTE",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$authenticated",
|
||||
"permission": "ALLOW"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"name": "Language",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "hedera.language"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "string",
|
||||
"id": true
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"orgName": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"isActive": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"acls": [
|
||||
{
|
||||
"accessType": "READ",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
UPDATE `salix`.`ACL` SET `model` = 'Calendar' WHERE (`id` = '155');
|
||||
UPDATE `salix`.`ACL` SET `model` = 'Calendar' WHERE (`id` = '157');
|
|
@ -1,44 +0,0 @@
|
|||
|
||||
USE `vn`;
|
||||
DROP procedure IF EXISTS `vn`.`itemLastEntries`;
|
||||
|
||||
DELIMITER $$
|
||||
USE `vn`$$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `itemLastEntries__`(IN `vItem` INT, IN `vDays` DATE)
|
||||
BEGIN
|
||||
SELECT
|
||||
w.id AS warehouseFk,
|
||||
w.name AS warehouse,
|
||||
tr.landed,
|
||||
b.entryFk,
|
||||
b.isIgnored,
|
||||
b.price2,
|
||||
b.price3,
|
||||
b.stickers,
|
||||
b.packing,
|
||||
b.`grouping`,
|
||||
b.groupingMode,
|
||||
b.weight,
|
||||
i.stems,
|
||||
b.quantity,
|
||||
b.buyingValue,
|
||||
b.packageFk ,
|
||||
s.id AS supplierFk,
|
||||
s.name AS supplier
|
||||
FROM itemType it
|
||||
RIGHT JOIN (entry e
|
||||
LEFT JOIN supplier s ON s.id = e.supplierFk
|
||||
RIGHT JOIN buy b ON b.entryFk = e.id
|
||||
LEFT JOIN item i ON i.id = b.itemFk
|
||||
LEFT JOIN ink ON ink.id = i.inkFk
|
||||
LEFT JOIN travel tr ON tr.id = e.travelFk
|
||||
LEFT JOIN warehouse w ON w.id = tr.warehouseInFk
|
||||
LEFT JOIN origin o ON o.id = i.originFk
|
||||
) ON it.id = i.typeFk
|
||||
LEFT JOIN edi.ekt ek ON b.ektFk = ek.id
|
||||
WHERE b.itemFk = vItem And tr.shipped BETWEEN vDays AND DATE_ADD(CURDATE(), INTERVAl + 10 DAY)
|
||||
ORDER BY tr.landed DESC , b.id DESC;
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
||||
;
|
|
@ -1,47 +0,0 @@
|
|||
USE `vn`;
|
||||
CREATE
|
||||
OR REPLACE ALGORITHM = UNDEFINED
|
||||
DEFINER = `root`@`%`
|
||||
SQL SECURITY DEFINER
|
||||
VIEW `vn`.`zoneEstimatedDelivery` AS
|
||||
SELECT
|
||||
`t`.`zoneFk` AS `zoneFk`,
|
||||
CAST((CURDATE() + INTERVAL ((HOUR(`zc`.`hour`) * 60) + MINUTE(`zc`.`hour`)) MINUTE)
|
||||
AS TIME) AS `hourTheoretical`,
|
||||
CAST(SUM(`sv`.`volume`) AS DECIMAL (5 , 1 )) AS `totalVolume`,
|
||||
CAST(SUM(IF((`s`.`alertLevel` < 2),
|
||||
`sv`.`volume`,
|
||||
0))
|
||||
AS DECIMAL (5 , 1 )) AS `remainingVolume`,
|
||||
GREATEST(IFNULL(`lhp`.`m3`, 0),
|
||||
IFNULL(`dl`.`minSpeed`, 0)) AS `speed`,
|
||||
CAST((`zc`.`hour` + INTERVAL ((-(SUM(IF((`s`.`alertLevel` < 2),
|
||||
`sv`.`volume`,
|
||||
0))) * 60) / GREATEST(IFNULL(`lhp`.`m3`, 0),
|
||||
IFNULL(`dl`.`minSpeed`, 0))) MINUTE)
|
||||
AS TIME) AS `hourEffective`,
|
||||
FLOOR(((-(SUM(IF((`s`.`alertLevel` < 2),
|
||||
`sv`.`volume`,
|
||||
0))) * 60) / GREATEST(IFNULL(`lhp`.`m3`, 0),
|
||||
IFNULL(`dl`.`minSpeed`, 0)))) AS `minutesLess`,
|
||||
CAST((`zc`.`hour` + INTERVAL ((-(SUM(IF((`s`.`alertLevel` < 2),
|
||||
`sv`.`volume`,
|
||||
0))) * 60) / GREATEST(IFNULL(`lhp`.`m3`, 0),
|
||||
IFNULL(`dl`.`minSpeed`, 0))) MINUTE)
|
||||
AS TIME) AS `etc`
|
||||
FROM
|
||||
((((((((`ticket` `t`
|
||||
JOIN `ticketStateToday` `tst` ON ((`tst`.`ticket` = `t`.`id`)))
|
||||
JOIN `state` `s` ON ((`s`.`id` = `tst`.`state`)))
|
||||
JOIN `saleVolume` `sv` ON ((`sv`.`ticketFk` = `t`.`id`)))
|
||||
LEFT JOIN `lastHourProduction` `lhp` ON ((`lhp`.`warehouseFk` = `t`.`warehouseFk`)))
|
||||
JOIN `warehouse` `w` ON ((`w`.`id` = `t`.`warehouseFk`)))
|
||||
JOIN `warehouseAlias` `wa` ON ((`wa`.`id` = `w`.`aliasFk`)))
|
||||
LEFT JOIN `zoneClosure` `zc` ON (((`zc`.`zoneFk` = `t`.`zoneFk`)
|
||||
AND (`zc`.`dated` = CURDATE()))))
|
||||
LEFT JOIN `cache`.`departure_limit` `dl` ON (((`dl`.`warehouse_id` = `t`.`warehouseFk`)
|
||||
AND (`dl`.`fecha` = CURDATE()))))
|
||||
WHERE
|
||||
((`wa`.`name` = 'Silla')
|
||||
AND (CAST(`t`.`shipped` AS DATE) = CURDATE()))
|
||||
GROUP BY `t`.`zoneFk`;
|
|
@ -1,16 +0,0 @@
|
|||
CREATE
|
||||
OR REPLACE ALGORITHM = UNDEFINED
|
||||
DEFINER = `root`@`%`
|
||||
SQL SECURITY DEFINER
|
||||
VIEW `vn`.`zone_ETD` AS
|
||||
SELECT
|
||||
`zed`.`zoneFk` AS `zoneFk`,
|
||||
`zed`.`hourTheoretical` AS `HoraTeórica`,
|
||||
`zed`.`totalVolume` AS `volumenTotal`,
|
||||
`zed`.`remainingVolume` AS `volumenPendiente`,
|
||||
`zed`.`speed` AS `velocidad`,
|
||||
`zed`.`hourEffective` AS `HoraPráctica`,
|
||||
`zed`.`minutesLess` AS `minutesLess`,
|
||||
`zed`.`etc` AS `etc`
|
||||
FROM
|
||||
`vn`.`zoneEstimatedDelivery` `zed`
|
|
@ -0,0 +1,6 @@
|
|||
ALTER TABLE `vn`.`entryLog`
|
||||
ADD COLUMN `changedModel` varchar(45) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
ADD COLUMN `oldInstance` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
|
||||
ADD COLUMN `newInstance` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
|
||||
ADD COLUMN `changedModelId` int(11) DEFAULT NULL,
|
||||
ADD COLUMN `changedModelValue` varchar(45) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL;
|
|
@ -0,0 +1,127 @@
|
|||
|
||||
ALTER TABLE `account`.`role`
|
||||
MODIFY COLUMN `hasLogin` tinyint(3) unsigned DEFAULT 1 NOT NULL;
|
||||
|
||||
ALTER TABLE `account`.`roleInherit`
|
||||
ADD UNIQUE( `role`, `inheritsFrom`);
|
||||
|
||||
ALTER TABLE `account`.`roleInherit`
|
||||
DROP PRIMARY KEY;
|
||||
|
||||
ALTER TABLE `account`.`roleInherit`
|
||||
ADD `id` INT UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
ALTER TABLE `account`.`mailAlias`
|
||||
ADD `description` VARCHAR(255) NULL AFTER `alias`;
|
||||
|
||||
ALTER TABLE `account`.`mailAliasAccount`
|
||||
ADD UNIQUE( `mailAlias`, `account`);
|
||||
|
||||
ALTER TABLE `account`.`mailAliasAccount`
|
||||
DROP PRIMARY KEY;
|
||||
|
||||
ALTER TABLE `account`.`mailAliasAccount`
|
||||
ADD `id` INT UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
ALTER TABLE account.ldapConfig
|
||||
ADD groupDn varchar(255) NULL;
|
||||
|
||||
UPDATE account.ldapConfig SET groupDn = 'ou=groups,dc=verdnatura,dc=es';
|
||||
|
||||
DROP PROCEDURE IF EXISTS account.user_syncPassword;
|
||||
|
||||
ALTER TABLE account.`user`
|
||||
MODIFY COLUMN sync tinyint(4) DEFAULT 0 NOT NULL COMMENT 'Deprecated';
|
||||
|
||||
CREATE TABLE account.userSync (
|
||||
name varchar(30) NOT NULL,
|
||||
CONSTRAINT userSync_PK PRIMARY KEY (name)
|
||||
)
|
||||
ENGINE=InnoDB
|
||||
DEFAULT CHARSET=utf8
|
||||
COLLATE=utf8_general_ci;
|
||||
|
||||
USE account;
|
||||
|
||||
DELIMITER $$
|
||||
|
||||
DROP TRIGGER IF EXISTS account.user_beforeUpdate$$
|
||||
CREATE DEFINER=`root`@`%` TRIGGER `user_beforeUpdate`
|
||||
BEFORE UPDATE ON `user` FOR EACH ROW
|
||||
BEGIN
|
||||
IF !(NEW.`name` <=> OLD.`name`) THEN
|
||||
CALL user_checkName (NEW.`name`);
|
||||
END IF;
|
||||
|
||||
IF !(NEW.`password` <=> OLD.`password`) THEN
|
||||
SET NEW.bcryptPassword = NULL;
|
||||
SET NEW.lastPassChange = NOW();
|
||||
END IF;
|
||||
END$$
|
||||
|
||||
DROP TRIGGER IF EXISTS account.user_afterUpdate$$
|
||||
CREATE DEFINER=`root`@`%` TRIGGER `user_afterUpdate`
|
||||
AFTER UPDATE ON `user` FOR EACH ROW
|
||||
BEGIN
|
||||
INSERT IGNORE INTO userSync SET `name` = NEW.`name`;
|
||||
|
||||
IF !(OLD.`name` <=> NEW.`name`) THEN
|
||||
INSERT IGNORE INTO userSync SET `name` = OLD.`name`;
|
||||
END IF;
|
||||
|
||||
IF !(NEW.`role` <=> OLD.`role`)
|
||||
THEN
|
||||
INSERT INTO vn.mail SET
|
||||
`sender` = 'jgallego@verdnatura.es',
|
||||
`replyTo` = 'jgallego@verdnatura.es',
|
||||
`subject` = 'Rol modificado',
|
||||
`body` = CONCAT(myUserGetName(), ' ha modificado el rol del usuario ',
|
||||
NEW.`name`, ' de ', OLD.role, ' a ', NEW.role);
|
||||
END IF;
|
||||
END$$
|
||||
|
||||
CREATE DEFINER=`root`@`%` TRIGGER `user_afterInsert`
|
||||
AFTER INSERT ON `user` FOR EACH ROW
|
||||
BEGIN
|
||||
INSERT IGNORE INTO userSync SET `name` = NEW.`name`;
|
||||
END$$
|
||||
|
||||
CREATE DEFINER=`root`@`%` TRIGGER `user_afterDelete`
|
||||
AFTER DELETE ON `user` FOR EACH ROW
|
||||
BEGIN
|
||||
INSERT IGNORE INTO userSync SET `name` = OLD.`name`;
|
||||
END$$
|
||||
|
||||
DROP TRIGGER IF EXISTS account.account_afterInsert$$
|
||||
CREATE DEFINER=`root`@`%` TRIGGER `account_afterInsert`
|
||||
AFTER INSERT ON `account` FOR EACH ROW
|
||||
BEGIN
|
||||
INSERT IGNORE INTO userSync (`name`)
|
||||
SELECT `name` FROM `user` WHERE id = NEW.id;
|
||||
END$$
|
||||
|
||||
DROP TRIGGER IF EXISTS account.account_afterDelete$$
|
||||
CREATE DEFINER=`root`@`%` TRIGGER `account_afterDelete`
|
||||
AFTER DELETE ON `account` FOR EACH ROW
|
||||
BEGIN
|
||||
INSERT IGNORE INTO userSync (`name`)
|
||||
SELECT `name` FROM `user` WHERE id = OLD.id;
|
||||
END$$
|
||||
|
||||
CREATE TRIGGER role_beforeInsert
|
||||
BEFORE INSERT ON `role` FOR EACH ROW
|
||||
BEGIN
|
||||
CALL role_checkName(NEW.`name`);
|
||||
END$$
|
||||
|
||||
CREATE TRIGGER role_beforeUpdate
|
||||
BEFORE UPDATE ON `role` FOR EACH ROW
|
||||
BEGIN
|
||||
IF !(NEW.`name` <=> OLD.`name`) THEN
|
||||
CALL role_checkName (NEW.`name`);
|
||||
END IF;
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
|
@ -0,0 +1,13 @@
|
|||
DROP PROCEDURE IF EXISTS account.myUserChangePassword;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `account`.`myUserChangePassword`(vOldPassword VARCHAR(255), vPassword VARCHAR(255))
|
||||
BEGIN
|
||||
/**
|
||||
* @deprecated Use myUser_changePassword()
|
||||
*/
|
||||
CALL myUser_changePassword(vOldPassword, vPassword);
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON PROCEDURE account.myUserChangePassword TO account@localhost;
|
|
@ -0,0 +1,15 @@
|
|||
DROP FUNCTION IF EXISTS account.myUserCheckLogin;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`myUserCheckLogin`() RETURNS tinyint(1)
|
||||
READS SQL DATA
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
/**
|
||||
* @deprecated Use myUser_checkLogin()
|
||||
*/
|
||||
RETURN myUser_checkLogin();
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION account.myUserCheckLogin TO guest@localhost;
|
|
@ -0,0 +1,15 @@
|
|||
DROP FUNCTION IF EXISTS account.myUserGetId;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`myUserGetId`() RETURNS int(11)
|
||||
READS SQL DATA
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
/**
|
||||
* @deprecated Use myUser_getId()
|
||||
*/
|
||||
RETURN myUser_getId();
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION account.myUserGetId TO guest@localhost;
|
|
@ -0,0 +1,15 @@
|
|||
DROP FUNCTION IF EXISTS account.myUserGetName;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`myUserGetName`() RETURNS varchar(30) CHARSET utf8
|
||||
NO SQL
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
/**
|
||||
* @deprecated Use myUser_getName()
|
||||
*/
|
||||
RETURN myUser_getName();
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION account.myUserGetName TO guest@localhost;
|
|
@ -0,0 +1,14 @@
|
|||
DROP FUNCTION IF EXISTS account.myUserHasRole;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`myUserHasRole`(vRoleName VARCHAR(255)) RETURNS tinyint(1)
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
/**
|
||||
* @deprecated Use myUser_hasRole()
|
||||
*/
|
||||
RETURN myUser_hasRole(vRoleName);
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION account.myUserHasRole TO guest@localhost;
|
|
@ -0,0 +1,14 @@
|
|||
DROP FUNCTION IF EXISTS account.myUserHasRoleId;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`myUserHasRoleId`(vRoleId INT) RETURNS tinyint(1)
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
/**
|
||||
* @deprecated Use myUser_hasRoleId()
|
||||
*/
|
||||
RETURN myUser_hasRoleId(vRoleId);
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION account.myUserHasRoleId TO guest@localhost;
|
|
@ -0,0 +1,17 @@
|
|||
DROP PROCEDURE IF EXISTS account.myUser_changePassword;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `account`.`myUser_changePassword`(vOldPassword VARCHAR(255), vPassword VARCHAR(255))
|
||||
BEGIN
|
||||
/**
|
||||
* Changes the current user password, if user is in recovery mode ignores the
|
||||
* current password.
|
||||
*
|
||||
* @param vOldPassword The current password
|
||||
* @param vPassword The new password
|
||||
*/
|
||||
CALL user_changePassword(myUser_getId(), vOldPassword, vPassword);
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON PROCEDURE account.myUser_changePassword TO account@localhost;
|
|
@ -0,0 +1,29 @@
|
|||
DROP FUNCTION IF EXISTS account.myUser_checkLogin;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`myUser_checkLogin`() RETURNS tinyint(1)
|
||||
READS SQL DATA
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
/**
|
||||
* Checks that variables @userId and @userName haven't been altered.
|
||||
*
|
||||
* @return %TRUE if they are unaltered or unset, otherwise %FALSE
|
||||
*/
|
||||
DECLARE vSignature VARCHAR(128);
|
||||
DECLARE vKey VARCHAR(255);
|
||||
|
||||
IF @userId IS NOT NULL
|
||||
AND @userName IS NOT NULL
|
||||
AND @userSignature IS NOT NULL
|
||||
THEN
|
||||
SELECT loginKey INTO vKey FROM userConfig;
|
||||
SET vSignature = util.hmacSha2(256, CONCAT_WS('/', @userId, @userName), vKey);
|
||||
RETURN vSignature = @userSignature;
|
||||
END IF;
|
||||
|
||||
RETURN FALSE;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION account.myUser_checkLogin TO guest@localhost;
|
|
@ -0,0 +1,27 @@
|
|||
DROP FUNCTION IF EXISTS account.myUser_getId;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`myUser_getId`() RETURNS int(11)
|
||||
READS SQL DATA
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
/**
|
||||
* Returns the current user id.
|
||||
*
|
||||
* @return The user id
|
||||
*/
|
||||
DECLARE vUser INT DEFAULT NULL;
|
||||
|
||||
IF myUser_checkLogin()
|
||||
THEN
|
||||
SET vUser = @userId;
|
||||
ELSE
|
||||
SELECT id INTO vUser FROM user
|
||||
WHERE name = LEFT(USER(), INSTR(USER(), '@') - 1);
|
||||
END IF;
|
||||
|
||||
RETURN vUser;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION account.myUser_getId TO guest@localhost;
|
|
@ -0,0 +1,27 @@
|
|||
DROP FUNCTION IF EXISTS account.myUser_getName;
|
||||
|
||||
DELIMITER $$
|
||||
$$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`myUser_getName`() RETURNS varchar(30) CHARSET utf8
|
||||
NO SQL
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
/**
|
||||
* Returns the current user name.
|
||||
*
|
||||
* @return The user name
|
||||
*/
|
||||
DECLARE vUser VARCHAR(30) DEFAULT NULL;
|
||||
|
||||
IF myUser_checkLogin()
|
||||
THEN
|
||||
SET vUser = @userName;
|
||||
ELSE
|
||||
SET vUser = LEFT(USER(), INSTR(USER(), '@') - 1);
|
||||
END IF;
|
||||
|
||||
RETURN vUser;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION account.myUser_getName TO guest@localhost;
|
|
@ -0,0 +1,17 @@
|
|||
DROP FUNCTION IF EXISTS account.myUser_hasRole;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`myUser_hasRole`(vRoleName VARCHAR(255)) RETURNS tinyint(1)
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
/**
|
||||
* Checks if current user has/inherits a role.
|
||||
*
|
||||
* @param vRoleName Role to check
|
||||
* @return %TRUE if it has role, %FALSE otherwise
|
||||
*/
|
||||
RETURN user_hasRole(myUser_getName(), vRoleName);
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION account.myUser_hasRole TO guest@localhost;
|
|
@ -0,0 +1,17 @@
|
|||
DROP FUNCTION IF EXISTS account.myUser_hasRoleId;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`myUser_hasRoleId`(vRoleId INT) RETURNS tinyint(1)
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
/**
|
||||
* Checks if current user has/inherits a role.
|
||||
*
|
||||
* @param vRoleName Role id to check
|
||||
* @return %TRUE if it has role, %FALSE otherwise
|
||||
*/
|
||||
RETURN user_hasRoleId(myUserGetName(), vRoleId);
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION account.myUser_hasRoleId TO guest@localhost;
|
|
@ -0,0 +1,29 @@
|
|||
DROP PROCEDURE IF EXISTS account.myUser_login;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `account`.`myUser_login`(vUserName VARCHAR(255), vPassword VARCHAR(255))
|
||||
READS SQL DATA
|
||||
BEGIN
|
||||
/**
|
||||
* Logs in using the user credentials.
|
||||
*
|
||||
* @param vUserName The user name
|
||||
* @param vPassword The user password
|
||||
*/
|
||||
DECLARE vAuthIsOk BOOLEAN DEFAULT FALSE;
|
||||
|
||||
SELECT COUNT(*) = 1 INTO vAuthIsOk FROM user
|
||||
WHERE name = vUserName
|
||||
AND password = MD5(vPassword)
|
||||
AND active;
|
||||
|
||||
IF vAuthIsOk
|
||||
THEN
|
||||
CALL myUser_loginWithName (vUserName);
|
||||
ELSE
|
||||
CALL util.throw ('INVALID_CREDENTIALS');
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON PROCEDURE account.myUser_login TO guest@localhost;
|
|
@ -0,0 +1,25 @@
|
|||
DROP PROCEDURE IF EXISTS account.myUser_loginWithKey;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `account`.`myUser_loginWithKey`(vUserName VARCHAR(255), vKey VARCHAR(255))
|
||||
READS SQL DATA
|
||||
BEGIN
|
||||
/**
|
||||
* Logs in using the user name and MySQL master key.
|
||||
*
|
||||
* @param vUserName The user name
|
||||
* @param vKey The MySQL master key
|
||||
*/
|
||||
DECLARE vLoginKey VARCHAR(255);
|
||||
|
||||
SELECT loginKey INTO vLoginKey FROM userConfig;
|
||||
|
||||
IF vLoginKey = vKey THEN
|
||||
CALL user_loginWithName(vUserName);
|
||||
ELSE
|
||||
CALL util.throw('INVALID_KEY');
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON PROCEDURE account.myUser_loginWithKey TO guest@localhost;
|
|
@ -0,0 +1,26 @@
|
|||
DROP PROCEDURE IF EXISTS account.myUser_loginWithName;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `account`.`myUser_loginWithName`(vUserName VARCHAR(255))
|
||||
READS SQL DATA
|
||||
BEGIN
|
||||
/**
|
||||
* Logs in using only the user name. This procedure is intended to be executed
|
||||
* by users with a high level of privileges so that normal users should not have
|
||||
* execute permissions on it.
|
||||
*
|
||||
* @param vUserName The user name
|
||||
*/
|
||||
DECLARE vUserId INT DEFAULT NULL;
|
||||
DECLARE vKey VARCHAR(255);
|
||||
|
||||
SELECT id INTO vUserId FROM user
|
||||
WHERE name = vUserName;
|
||||
|
||||
SELECT loginKey INTO vKey FROM userConfig;
|
||||
|
||||
SET @userId = vUserId;
|
||||
SET @userName = vUserName;
|
||||
SET @userSignature = util.hmacSha2(256, CONCAT_WS('/', vUserId, vUserName), vKey);
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,15 @@
|
|||
DROP PROCEDURE IF EXISTS account.myUser_logout;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `account`.`myUser_logout`()
|
||||
BEGIN
|
||||
/**
|
||||
* Logouts the user.
|
||||
*/
|
||||
SET @userId = NULL;
|
||||
SET @userName = NULL;
|
||||
SET @userSignature = NULL;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON PROCEDURE account.myUser_logout TO account@localhost;
|
|
@ -0,0 +1,52 @@
|
|||
DROP FUNCTION IF EXISTS account.passwordGenerate;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`passwordGenerate`() RETURNS text CHARSET utf8
|
||||
BEGIN
|
||||
/**
|
||||
* Generates a random password that meets the minimum requirements.
|
||||
*
|
||||
* @return Generated password
|
||||
*/
|
||||
DECLARE vMinLength TINYINT;
|
||||
DECLARE vMinAlpha TINYINT;
|
||||
DECLARE vMinUpper TINYINT;
|
||||
DECLARE vMinDigits TINYINT;
|
||||
DECLARE vMinPunct TINYINT;
|
||||
DECLARE vAlpha TINYINT DEFAULT 0;
|
||||
DECLARE vUpper TINYINT DEFAULT 0;
|
||||
DECLARE vDigits TINYINT DEFAULT 0;
|
||||
DECLARE vPunct TINYINT DEFAULT 0;
|
||||
DECLARE vRandIndex INT;
|
||||
DECLARE vPwd TEXT DEFAULT '';
|
||||
|
||||
DECLARE vAlphaChars TEXT DEFAULT 'abcdefghijklmnopqrstuvwxyz';
|
||||
DECLARE vUpperChars TEXT DEFAULT 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
DECLARE vDigitChars TEXT DEFAULT '1234567890';
|
||||
DECLARE vPunctChars TEXT DEFAULT '!$%&()=.';
|
||||
|
||||
SELECT length, nAlpha, nUpper, nDigits, nPunct
|
||||
INTO vMinLength, vMinAlpha, vMinUpper, vMinDigits, vMinPunct FROM userPassword;
|
||||
|
||||
WHILE LENGTH(vPwd) < vMinLength OR vAlpha < vMinAlpha
|
||||
OR vUpper < vMinUpper OR vDigits < vMinDigits OR vPunct < vMinPunct DO
|
||||
SET vRandIndex = FLOOR((RAND() * 4) + 1);
|
||||
|
||||
CASE
|
||||
WHEN vRandIndex = 1 THEN
|
||||
SET vPwd = CONCAT(vPwd, SUBSTRING(vAlphaChars, FLOOR((RAND() * 26) + 1), 1));
|
||||
SET vAlpha = vAlpha + 1;
|
||||
WHEN vRandIndex = 2 THEN
|
||||
SET vPwd = CONCAT(vPwd, SUBSTRING(vUpperChars, FLOOR((RAND() * 26) + 1), 1));
|
||||
SET vUpper = vUpper + 1;
|
||||
WHEN vRandIndex = 3 THEN
|
||||
SET vPwd = CONCAT(vPwd, SUBSTRING(vDigitChars, FLOOR((RAND() * 10) + 1), 1));
|
||||
SET vDigits = vDigits + 1;
|
||||
WHEN vRandIndex = 4 THEN
|
||||
SET vPwd = CONCAT(vPwd, SUBSTRING(vPunctChars, FLOOR((RAND() * LENGTH(vPunctChars)) + 1), 1));
|
||||
SET vPunct = vPunct + 1;
|
||||
END CASE;
|
||||
END WHILE;
|
||||
RETURN vPwd;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,18 @@
|
|||
DROP PROCEDURE IF EXISTS account.role_checkName;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE PROCEDURE account.role_checkName(vRoleName VARCHAR(255))
|
||||
BEGIN
|
||||
/**
|
||||
* Checks that role name meets the necessary syntax requirements, otherwise it
|
||||
* throws an exception.
|
||||
* Role name must be written in camelCase.
|
||||
*
|
||||
* @param vRoleName The role name
|
||||
*/
|
||||
IF BINARY vRoleName NOT REGEXP '^[a-z][a-zA-Z]+$' THEN
|
||||
SIGNAL SQLSTATE '45000'
|
||||
SET MESSAGE_TEXT = 'Role name must be written in camelCase';
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,66 @@
|
|||
DROP PROCEDURE IF EXISTS account.role_getDescendents;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `account`.`role_getDescendents`(vSelf INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Gets the identifiers of all the subroles implemented by a role (Including
|
||||
* itself).
|
||||
*
|
||||
* @param vSelf The role identifier
|
||||
* @table tmp.role Subroles implemented by the role
|
||||
*/
|
||||
DECLARE vIsRoot BOOL;
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS
|
||||
tmp.role, parents, childs;
|
||||
|
||||
CREATE TEMPORARY TABLE tmp.role
|
||||
(UNIQUE (id))
|
||||
ENGINE = MEMORY
|
||||
SELECT vSelf AS id;
|
||||
|
||||
CREATE TEMPORARY TABLE parents
|
||||
ENGINE = MEMORY
|
||||
SELECT vSelf AS id;
|
||||
|
||||
CREATE TEMPORARY TABLE childs
|
||||
LIKE parents;
|
||||
|
||||
REPEAT
|
||||
DELETE FROM childs;
|
||||
INSERT INTO childs
|
||||
SELECT DISTINCT r.inheritsFrom id
|
||||
FROM parents p
|
||||
JOIN roleInherit r ON r.role = p.id
|
||||
LEFT JOIN tmp.role t ON t.id = r.inheritsFrom
|
||||
WHERE t.id IS NULL;
|
||||
|
||||
DELETE FROM parents;
|
||||
INSERT INTO parents
|
||||
SELECT * FROM childs;
|
||||
|
||||
INSERT INTO tmp.role
|
||||
SELECT * FROM childs;
|
||||
|
||||
UNTIL ROW_COUNT() <= 0
|
||||
END REPEAT;
|
||||
|
||||
-- If it is root all the roles are added
|
||||
|
||||
SELECT COUNT(*) > 0 INTO vIsRoot
|
||||
FROM tmp.role t
|
||||
JOIN role r ON r.id = t.id
|
||||
WHERE r.`name` = 'root';
|
||||
|
||||
IF vIsRoot THEN
|
||||
INSERT IGNORE INTO tmp.role (id)
|
||||
SELECT id FROM role;
|
||||
END IF;
|
||||
|
||||
-- Cleaning
|
||||
|
||||
DROP TEMPORARY TABLE
|
||||
parents, childs;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,53 @@
|
|||
DROP PROCEDURE IF EXISTS account.role_sync;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `account`.`role_sync`()
|
||||
BEGIN
|
||||
/**
|
||||
* Synchronize the @roleRole table with the current role hierarchy. This
|
||||
* procedure must be called every time the @roleInherit table is modified so
|
||||
* that the changes made on it are effective.
|
||||
*/
|
||||
DECLARE vRoleId INT;
|
||||
DECLARE vDone BOOL;
|
||||
|
||||
DECLARE cur CURSOR FOR
|
||||
SELECT id FROM role;
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tRoleRole;
|
||||
CREATE TEMPORARY TABLE tRoleRole
|
||||
ENGINE = MEMORY
|
||||
SELECT * FROM roleRole LIMIT 0;
|
||||
|
||||
OPEN cur;
|
||||
|
||||
l: LOOP
|
||||
SET vDone = FALSE;
|
||||
FETCH cur INTO vRoleId;
|
||||
|
||||
IF vDone THEN
|
||||
LEAVE l;
|
||||
END IF;
|
||||
|
||||
CALL role_getDescendents(vRoleId);
|
||||
|
||||
INSERT INTO tRoleRole (role, inheritsFrom)
|
||||
SELECT vRoleId, id FROM tmp.role;
|
||||
|
||||
DROP TEMPORARY TABLE tmp.role;
|
||||
END LOOP;
|
||||
|
||||
CLOSE cur;
|
||||
|
||||
START TRANSACTION;
|
||||
DELETE FROM roleRole;
|
||||
INSERT INTO roleRole SELECT * FROM tRoleRole;
|
||||
COMMIT;
|
||||
|
||||
DROP TEMPORARY TABLE tRoleRole;
|
||||
|
||||
CALL role_syncPrivileges;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,494 @@
|
|||
DROP PROCEDURE IF EXISTS account.role_syncPrivileges;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `account`.`role_syncPrivileges`()
|
||||
BEGIN
|
||||
/**
|
||||
* Synchronizes permissions of MySQL role users based on role hierarchy.
|
||||
* The computed role users of permission mix will be named according to
|
||||
* pattern z-[role_name].
|
||||
*
|
||||
* If any@localhost user exists, it will be taken as a template for basic
|
||||
* attributes.
|
||||
*
|
||||
* Warning! This procedure should only be called when MySQL privileges
|
||||
* are modified. If role hierarchy is modified, you must call the role_sync()
|
||||
* procedure wich calls this internally.
|
||||
*/
|
||||
DECLARE vIsMysql BOOL DEFAULT VERSION() NOT LIKE '%MariaDB%';
|
||||
DECLARE vVersion INT DEFAULT SUBSTRING_INDEX(VERSION(), '.', 1);
|
||||
DECLARE vTplUser VARCHAR(255) DEFAULT 'any';
|
||||
DECLARE vTplHost VARCHAR(255) DEFAULT '%';
|
||||
DECLARE vRoleHost VARCHAR(255) DEFAULT 'localhost';
|
||||
DECLARE vAllHost VARCHAR(255) DEFAULT '%';
|
||||
DECLARE vPrefix VARCHAR(2) DEFAULT 'z-';
|
||||
DECLARE vPrefixedLike VARCHAR(255);
|
||||
DECLARE vPassword VARCHAR(255) DEFAULT '';
|
||||
|
||||
-- Deletes computed role users
|
||||
|
||||
SET vPrefixedLike = CONCAT(vPrefix, '%');
|
||||
|
||||
DELETE FROM mysql.user
|
||||
WHERE `User` LIKE vPrefixedLike;
|
||||
|
||||
DELETE FROM mysql.db
|
||||
WHERE `User` LIKE vPrefixedLike;
|
||||
|
||||
DELETE FROM mysql.tables_priv
|
||||
WHERE `User` LIKE vPrefixedLike;
|
||||
|
||||
DELETE FROM mysql.columns_priv
|
||||
WHERE `User` LIKE vPrefixedLike;
|
||||
|
||||
DELETE FROM mysql.procs_priv
|
||||
WHERE `User` LIKE vPrefixedLike;
|
||||
|
||||
DELETE FROM mysql.proxies_priv
|
||||
WHERE `Proxied_user` LIKE vPrefixedLike;
|
||||
|
||||
-- Temporary tables
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tRole;
|
||||
CREATE TEMPORARY TABLE tRole
|
||||
(INDEX (id))
|
||||
ENGINE = MEMORY
|
||||
SELECT
|
||||
id,
|
||||
`name` role,
|
||||
CONCAT(vPrefix, `name`) prefixedRole
|
||||
FROM role
|
||||
WHERE hasLogin;
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tRoleInherit;
|
||||
CREATE TEMPORARY TABLE tRoleInherit
|
||||
(INDEX (inheritsFrom))
|
||||
ENGINE = MEMORY
|
||||
SELECT
|
||||
r.prefixedRole,
|
||||
ri.`name` inheritsFrom
|
||||
FROM tRole r
|
||||
JOIN roleRole rr ON rr.role = r.id
|
||||
JOIN role ri ON ri.id = rr.inheritsFrom;
|
||||
|
||||
-- Recreate role users
|
||||
|
||||
IF vIsMysql THEN
|
||||
DROP TEMPORARY TABLE IF EXISTS tUser;
|
||||
CREATE TEMPORARY TABLE tUser
|
||||
SELECT
|
||||
r.prefixedRole `User`,
|
||||
vTplHost `Host`,
|
||||
IFNULL(t.`authentication_string`,
|
||||
'') `authentication_string`,
|
||||
IFNULL(t.`plugin`,
|
||||
'mysql_native_password') `plugin`,
|
||||
IFNULL(IF('' != u.`ssl_type`,
|
||||
u.`ssl_type`, t.`ssl_type`),
|
||||
'') `ssl_type`,
|
||||
IFNULL(IF('' != u.`ssl_cipher`,
|
||||
u.`ssl_cipher`, t.`ssl_cipher`),
|
||||
'') `ssl_cipher`,
|
||||
IFNULL(IF('' != u.`x509_issuer`,
|
||||
u.`x509_issuer`, t.`x509_issuer`),
|
||||
'') `x509_issuer`,
|
||||
IFNULL(IF('' != u.`x509_subject`,
|
||||
u.`x509_subject`, t.`x509_subject`),
|
||||
'') `x509_subject`,
|
||||
IFNULL(IF(0 != u.`max_questions`,
|
||||
u.`max_questions`, t.`max_questions`),
|
||||
0) `max_questions`,
|
||||
IFNULL(IF(0 != u.`max_updates`,
|
||||
u.`max_updates`, t.`max_updates`),
|
||||
0) `max_updates`,
|
||||
IFNULL(IF(0 != u.`max_connections`,
|
||||
u.`max_connections`, t.`max_connections`),
|
||||
0) `max_connections`,
|
||||
IFNULL(IF(0 != u.`max_user_connections`,
|
||||
u.`max_user_connections`, t.`max_user_connections`),
|
||||
0) `max_user_connections`
|
||||
FROM tRole r
|
||||
LEFT JOIN mysql.user t
|
||||
ON t.`User` = vTplUser
|
||||
AND t.`Host` = vRoleHost
|
||||
LEFT JOIN mysql.user u
|
||||
ON u.`User` = r.role
|
||||
AND u.`Host` = vRoleHost;
|
||||
|
||||
IF vVersion <= 5 THEN
|
||||
SELECT `Password` INTO vPassword
|
||||
FROM mysql.user
|
||||
WHERE `User` = vTplUser
|
||||
AND `Host` = vRoleHost;
|
||||
|
||||
INSERT INTO mysql.user (
|
||||
`User`,
|
||||
`Host`,
|
||||
`Password`,
|
||||
`authentication_string`,
|
||||
`plugin`,
|
||||
`ssl_type`,
|
||||
`ssl_cipher`,
|
||||
`x509_issuer`,
|
||||
`x509_subject`,
|
||||
`max_questions`,
|
||||
`max_updates`,
|
||||
`max_connections`,
|
||||
`max_user_connections`
|
||||
)
|
||||
SELECT
|
||||
`User`,
|
||||
`Host`,
|
||||
vPassword,
|
||||
`authentication_string`,
|
||||
`plugin`,
|
||||
`ssl_type`,
|
||||
`ssl_cipher`,
|
||||
`x509_issuer`,
|
||||
`x509_subject`,
|
||||
`max_questions`,
|
||||
`max_updates`,
|
||||
`max_connections`,
|
||||
`max_user_connections`
|
||||
FROM tUser;
|
||||
ELSE
|
||||
INSERT INTO mysql.user (
|
||||
`User`,
|
||||
`Host`,
|
||||
`authentication_string`,
|
||||
`plugin`,
|
||||
`ssl_type`,
|
||||
`ssl_cipher`,
|
||||
`x509_issuer`,
|
||||
`x509_subject`,
|
||||
`max_questions`,
|
||||
`max_updates`,
|
||||
`max_connections`,
|
||||
`max_user_connections`
|
||||
)
|
||||
SELECT
|
||||
`User`,
|
||||
`Host`,
|
||||
`authentication_string`,
|
||||
`plugin`,
|
||||
`ssl_type`,
|
||||
`ssl_cipher`,
|
||||
`x509_issuer`,
|
||||
`x509_subject`,
|
||||
`max_questions`,
|
||||
`max_updates`,
|
||||
`max_connections`,
|
||||
`max_user_connections`
|
||||
FROM tUser;
|
||||
END IF;
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tUser;
|
||||
ELSE
|
||||
INSERT INTO mysql.global_priv (
|
||||
`User`,
|
||||
`Host`,
|
||||
`Priv`
|
||||
)
|
||||
SELECT
|
||||
r.prefixedRole,
|
||||
vTplHost,
|
||||
JSON_MERGE_PATCH(
|
||||
IFNULL(t.`Priv`, '{}'),
|
||||
IFNULL(u.`Priv`, '{}')
|
||||
)
|
||||
FROM tRole r
|
||||
LEFT JOIN mysql.global_priv t
|
||||
ON t.`User` = vTplUser
|
||||
AND t.`Host` = vRoleHost
|
||||
LEFT JOIN mysql.global_priv u
|
||||
ON u.`User` = r.role
|
||||
AND u.`Host` = vRoleHost;
|
||||
END IF;
|
||||
|
||||
INSERT INTO mysql.proxies_priv (
|
||||
`User`,
|
||||
`Host`,
|
||||
`Proxied_user`,
|
||||
`Proxied_host`,
|
||||
`Grantor`
|
||||
)
|
||||
SELECT
|
||||
'',
|
||||
vAllHost,
|
||||
prefixedRole,
|
||||
vTplHost,
|
||||
CONCAT(prefixedRole, '@', vTplHost)
|
||||
FROM tRole;
|
||||
|
||||
-- Copies global privileges
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tUserPriv;
|
||||
|
||||
IF vIsMysql THEN
|
||||
CREATE TEMPORARY TABLE tUserPriv
|
||||
(INDEX (prefixedRole))
|
||||
ENGINE = MEMORY
|
||||
SELECT
|
||||
r.prefixedRole,
|
||||
MAX(u.`Select_priv`) `Select_priv`,
|
||||
MAX(u.`Insert_priv`) `Insert_priv`,
|
||||
MAX(u.`Update_priv`) `Update_priv`,
|
||||
MAX(u.`Delete_priv`) `Delete_priv`,
|
||||
MAX(u.`Create_priv`) `Create_priv`,
|
||||
MAX(u.`Drop_priv`) `Drop_priv`,
|
||||
MAX(u.`Reload_priv`) `Reload_priv`,
|
||||
MAX(u.`Shutdown_priv`) `Shutdown_priv`,
|
||||
MAX(u.`Process_priv`) `Process_priv`,
|
||||
MAX(u.`File_priv`) `File_priv`,
|
||||
MAX(u.`Grant_priv`) `Grant_priv`,
|
||||
MAX(u.`References_priv`) `References_priv`,
|
||||
MAX(u.`Index_priv`) `Index_priv`,
|
||||
MAX(u.`Alter_priv`) `Alter_priv`,
|
||||
MAX(u.`Show_db_priv`) `Show_db_priv`,
|
||||
MAX(u.`Super_priv`) `Super_priv`,
|
||||
MAX(u.`Create_tmp_table_priv`) `Create_tmp_table_priv`,
|
||||
MAX(u.`Lock_tables_priv`) `Lock_tables_priv`,
|
||||
MAX(u.`Execute_priv`) `Execute_priv`,
|
||||
MAX(u.`Repl_slave_priv`) `Repl_slave_priv`,
|
||||
MAX(u.`Repl_client_priv`) `Repl_client_priv`,
|
||||
MAX(u.`Create_view_priv`) `Create_view_priv`,
|
||||
MAX(u.`Show_view_priv`) `Show_view_priv`,
|
||||
MAX(u.`Create_routine_priv`) `Create_routine_priv`,
|
||||
MAX(u.`Alter_routine_priv`) `Alter_routine_priv`,
|
||||
MAX(u.`Create_user_priv`) `Create_user_priv`,
|
||||
MAX(u.`Event_priv`) `Event_priv`,
|
||||
MAX(u.`Trigger_priv`) `Trigger_priv`,
|
||||
MAX(u.`Create_tablespace_priv`) `Create_tablespace_priv`
|
||||
FROM tRoleInherit r
|
||||
JOIN mysql.user u
|
||||
ON u.`User` = r.inheritsFrom
|
||||
AND u.`Host`= vRoleHost
|
||||
GROUP BY r.prefixedRole;
|
||||
|
||||
UPDATE mysql.user u
|
||||
JOIN tUserPriv t
|
||||
ON u.`User` = t.prefixedRole
|
||||
AND u.`Host` = vTplHost
|
||||
SET
|
||||
u.`Select_priv`
|
||||
= t.`Select_priv`,
|
||||
u.`Insert_priv`
|
||||
= t.`Insert_priv`,
|
||||
u.`Update_priv`
|
||||
= t.`Update_priv`,
|
||||
u.`Delete_priv`
|
||||
= t.`Delete_priv`,
|
||||
u.`Create_priv`
|
||||
= t.`Create_priv`,
|
||||
u.`Drop_priv`
|
||||
= t.`Drop_priv`,
|
||||
u.`Reload_priv`
|
||||
= t.`Reload_priv`,
|
||||
u.`Shutdown_priv`
|
||||
= t.`Shutdown_priv`,
|
||||
u.`Process_priv`
|
||||
= t.`Process_priv`,
|
||||
u.`File_priv`
|
||||
= t.`File_priv`,
|
||||
u.`Grant_priv`
|
||||
= t.`Grant_priv`,
|
||||
u.`References_priv`
|
||||
= t.`References_priv`,
|
||||
u.`Index_priv`
|
||||
= t.`Index_priv`,
|
||||
u.`Alter_priv`
|
||||
= t.`Alter_priv`,
|
||||
u.`Show_db_priv`
|
||||
= t.`Show_db_priv`,
|
||||
u.`Super_priv`
|
||||
= t.`Super_priv`,
|
||||
u.`Create_tmp_table_priv`
|
||||
= t.`Create_tmp_table_priv`,
|
||||
u.`Lock_tables_priv`
|
||||
= t.`Lock_tables_priv`,
|
||||
u.`Execute_priv`
|
||||
= t.`Execute_priv`,
|
||||
u.`Repl_slave_priv`
|
||||
= t.`Repl_slave_priv`,
|
||||
u.`Repl_client_priv`
|
||||
= t.`Repl_client_priv`,
|
||||
u.`Create_view_priv`
|
||||
= t.`Create_view_priv`,
|
||||
u.`Show_view_priv`
|
||||
= t.`Show_view_priv`,
|
||||
u.`Create_routine_priv`
|
||||
= t.`Create_routine_priv`,
|
||||
u.`Alter_routine_priv`
|
||||
= t.`Alter_routine_priv`,
|
||||
u.`Create_user_priv`
|
||||
= t.`Create_user_priv`,
|
||||
u.`Event_priv`
|
||||
= t.`Event_priv`,
|
||||
u.`Trigger_priv`
|
||||
= t.`Trigger_priv`,
|
||||
u.`Create_tablespace_priv`
|
||||
= t.`Create_tablespace_priv`;
|
||||
ELSE
|
||||
CREATE TEMPORARY TABLE tUserPriv
|
||||
(INDEX (prefixedRole))
|
||||
SELECT
|
||||
r.prefixedRole,
|
||||
BIT_OR(JSON_VALUE(p.`Priv`, '$.access')) access
|
||||
FROM tRoleInherit r
|
||||
JOIN mysql.global_priv p
|
||||
ON p.`User` = r.inheritsFrom
|
||||
AND p.`Host`= vRoleHost
|
||||
GROUP BY r.prefixedRole;
|
||||
|
||||
UPDATE mysql.global_priv p
|
||||
JOIN tUserPriv t
|
||||
ON p.`User` = t.prefixedRole
|
||||
AND p.`Host` = vTplHost
|
||||
SET
|
||||
p.`Priv` = JSON_SET(p.`Priv`, '$.access', t.access);
|
||||
END IF;
|
||||
|
||||
DROP TEMPORARY TABLE tUserPriv;
|
||||
|
||||
-- Copy schema level privileges
|
||||
|
||||
INSERT INTO mysql.db (
|
||||
`User`,
|
||||
`Host`,
|
||||
`Db`,
|
||||
`Select_priv`,
|
||||
`Insert_priv`,
|
||||
`Update_priv`,
|
||||
`Delete_priv`,
|
||||
`Create_priv`,
|
||||
`Drop_priv`,
|
||||
`Grant_priv`,
|
||||
`References_priv`,
|
||||
`Index_priv`,
|
||||
`Alter_priv`,
|
||||
`Create_tmp_table_priv`,
|
||||
`Lock_tables_priv`,
|
||||
`Create_view_priv`,
|
||||
`Show_view_priv`,
|
||||
`Create_routine_priv`,
|
||||
`Alter_routine_priv`,
|
||||
`Execute_priv`,
|
||||
`Event_priv`,
|
||||
`Trigger_priv`
|
||||
)
|
||||
SELECT
|
||||
r.prefixedRole,
|
||||
vTplHost,
|
||||
t.`Db`,
|
||||
MAX(t.`Select_priv`),
|
||||
MAX(t.`Insert_priv`),
|
||||
MAX(t.`Update_priv`),
|
||||
MAX(t.`Delete_priv`),
|
||||
MAX(t.`Create_priv`),
|
||||
MAX(t.`Drop_priv`),
|
||||
MAX(t.`Grant_priv`),
|
||||
MAX(t.`References_priv`),
|
||||
MAX(t.`Index_priv`),
|
||||
MAX(t.`Alter_priv`),
|
||||
MAX(t.`Create_tmp_table_priv`),
|
||||
MAX(t.`Lock_tables_priv`),
|
||||
MAX(t.`Create_view_priv`),
|
||||
MAX(t.`Show_view_priv`),
|
||||
MAX(t.`Create_routine_priv`),
|
||||
MAX(t.`Alter_routine_priv`),
|
||||
MAX(t.`Execute_priv`),
|
||||
MAX(t.`Event_priv`),
|
||||
MAX(t.`Trigger_priv`)
|
||||
FROM tRoleInherit r
|
||||
JOIN mysql.db t
|
||||
ON t.`User` = r.inheritsFrom
|
||||
AND t.`Host`= vRoleHost
|
||||
GROUP BY r.prefixedRole, t.`Db`;
|
||||
|
||||
-- Copy table level privileges
|
||||
|
||||
INSERT INTO mysql.tables_priv (
|
||||
`User`,
|
||||
`Host`,
|
||||
`Db`,
|
||||
`Table_name`,
|
||||
`Grantor`,
|
||||
`Timestamp`,
|
||||
`Table_priv`,
|
||||
`Column_priv`
|
||||
)
|
||||
SELECT
|
||||
r.prefixedRole,
|
||||
vTplHost,
|
||||
t.`Db`,
|
||||
t.`Table_name`,
|
||||
t.`Grantor`,
|
||||
MAX(t.`Timestamp`),
|
||||
IFNULL(GROUP_CONCAT(NULLIF(t.`Table_priv`, '')), ''),
|
||||
IFNULL(GROUP_CONCAT(NULLIF(t.`Column_priv`, '')), '')
|
||||
FROM tRoleInherit r
|
||||
JOIN mysql.tables_priv t
|
||||
ON t.`User` = r.inheritsFrom
|
||||
AND t.`Host`= vRoleHost
|
||||
GROUP BY r.prefixedRole, t.`Db`, t.`Table_name`;
|
||||
|
||||
-- Copy column level privileges
|
||||
|
||||
INSERT INTO mysql.columns_priv (
|
||||
`User`,
|
||||
`Host`,
|
||||
`Db`,
|
||||
`Table_name`,
|
||||
`Column_name`,
|
||||
`Timestamp`,
|
||||
`Column_priv`
|
||||
)
|
||||
SELECT
|
||||
r.prefixedRole,
|
||||
vTplHost,
|
||||
t.`Db`,
|
||||
t.`Table_name`,
|
||||
t.`Column_name`,
|
||||
MAX(t.`Timestamp`),
|
||||
IFNULL(GROUP_CONCAT(NULLIF(t.`Column_priv`, '')), '')
|
||||
FROM tRoleInherit r
|
||||
JOIN mysql.columns_priv t
|
||||
ON t.`User` = r.inheritsFrom
|
||||
AND t.`Host`= vRoleHost
|
||||
GROUP BY r.prefixedRole, t.`Db`, t.`Table_name`, t.`Column_name`;
|
||||
|
||||
-- Copy routine privileges
|
||||
|
||||
INSERT IGNORE INTO mysql.procs_priv (
|
||||
`User`,
|
||||
`Host`,
|
||||
`Db`,
|
||||
`Routine_name`,
|
||||
`Routine_type`,
|
||||
`Grantor`,
|
||||
`Timestamp`,
|
||||
`Proc_priv`
|
||||
)
|
||||
SELECT
|
||||
r.prefixedRole,
|
||||
vTplHost,
|
||||
t.`Db`,
|
||||
t.`Routine_name`,
|
||||
t.`Routine_type`,
|
||||
t.`Grantor`,
|
||||
t.`Timestamp`,
|
||||
t.`Proc_priv`
|
||||
FROM tRoleInherit r
|
||||
JOIN mysql.procs_priv t
|
||||
ON t.`User` = r.inheritsFrom
|
||||
AND t.`Host`= vRoleHost;
|
||||
|
||||
-- Free memory
|
||||
|
||||
DROP TEMPORARY TABLE
|
||||
tRole,
|
||||
tRoleInherit;
|
||||
|
||||
FLUSH PRIVILEGES;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,15 @@
|
|||
DROP FUNCTION IF EXISTS account.userGetId;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`userGetId`() RETURNS int(11)
|
||||
READS SQL DATA
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
/**
|
||||
* @deprecated Use myUser_getId()
|
||||
*/
|
||||
RETURN myUser_getId();
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION account.userGetId TO guest@localhost;
|
|
@ -0,0 +1,11 @@
|
|||
DROP FUNCTION IF EXISTS account.userGetMysqlRole;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`userGetMysqlRole`(vUserName VARCHAR(255)) RETURNS varchar(255) CHARSET utf8
|
||||
BEGIN
|
||||
/**
|
||||
* @deprecated Use user_getMysqlRole()
|
||||
*/
|
||||
RETURN user_getMysqlRole();
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,15 @@
|
|||
DROP FUNCTION IF EXISTS account.userGetName;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`userGetName`() RETURNS varchar(30) CHARSET utf8
|
||||
NO SQL
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
/**
|
||||
* @deprecated Use myUser_getName()
|
||||
*/
|
||||
RETURN myUser_getName();
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION account.userGetName TO guest@localhost;
|
|
@ -0,0 +1,11 @@
|
|||
DROP FUNCTION IF EXISTS account.userGetNameFromId;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`userGetNameFromId`(vSelf INT) RETURNS varchar(30) CHARSET utf8
|
||||
BEGIN
|
||||
/**
|
||||
* @deprecated Use user_getNameFromId();
|
||||
*/
|
||||
RETURN user_getNameFromId(vSelf);
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,12 @@
|
|||
DROP FUNCTION IF EXISTS account.userHasRole;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`userHasRole`(vUserName VARCHAR(255), vRoleName VARCHAR(255)) RETURNS tinyint(1)
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
/**
|
||||
* @deprecated Use user_hasRole()
|
||||
*/
|
||||
RETURN user_hasRole(vUserName, vRoleName);
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,12 @@
|
|||
DROP FUNCTION IF EXISTS account.userHasRoleId;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`userHasRoleId`(vUser VARCHAR(255), vRoleId INT) RETURNS tinyint(1)
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
/**
|
||||
* @deprecated Use user_hasRoleId()
|
||||
*/
|
||||
RETURN user_hasRoleId(vUser, vRoleId);
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,14 @@
|
|||
DROP PROCEDURE IF EXISTS account.userLogin;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `account`.`userLogin`(vUserName VARCHAR(255), vPassword VARCHAR(255))
|
||||
READS SQL DATA
|
||||
BEGIN
|
||||
/**
|
||||
* @deprecated Use myUser_login()
|
||||
*/
|
||||
CALL myUser_login(vUserName, vPassword);
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON PROCEDURE account.userLogin TO guest@localhost;
|
|
@ -0,0 +1,14 @@
|
|||
DROP PROCEDURE IF EXISTS account.userLoginWithKey;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `account`.`userLoginWithKey`(vUserName VARCHAR(255), vKey VARCHAR(255))
|
||||
READS SQL DATA
|
||||
BEGIN
|
||||
/**
|
||||
* @deprecated Use myUser_loginWithKey()
|
||||
*/
|
||||
CALL myUser_loginWithKey(vUserName, vKey);
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON PROCEDURE account.userLoginWithKey TO guest@localhost;
|
|
@ -0,0 +1,12 @@
|
|||
DROP PROCEDURE IF EXISTS account.userLoginWithName;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `account`.`userLoginWithName`(vUserName VARCHAR(255))
|
||||
READS SQL DATA
|
||||
BEGIN
|
||||
/**
|
||||
* @deprecated Use myUser_loginWithName()
|
||||
*/
|
||||
CALL myUser_loginWithName(vUserName);
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,14 @@
|
|||
DROP PROCEDURE IF EXISTS account.myUserLogout;
|
||||
|
||||
DELIMITER $$
|
||||
$$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `account`.`myUserLogout`()
|
||||
BEGIN
|
||||
/**
|
||||
* @deprecated Use myUser_Logout()
|
||||
*/
|
||||
CALL myUser_logout;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
GRANT EXECUTE ON PROCEDURE account.myUserLogout TO account@localhost;
|
|
@ -0,0 +1,16 @@
|
|||
DROP PROCEDURE IF EXISTS account.userSetPassword;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `account`.`userSetPassword`(vUserName VARCHAR(255), vPassword VARCHAR(255))
|
||||
BEGIN
|
||||
/**
|
||||
* @deprecated Use user_setPassword()
|
||||
*/
|
||||
DECLARE vUserId INT;
|
||||
|
||||
SELECT id INTO vUserId
|
||||
FROM user WHERE `name` = vUserName;
|
||||
|
||||
CALL user_setPassword(vUserId, vPassword);
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,27 @@
|
|||
DROP PROCEDURE IF EXISTS account.user_changePassword;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE account.user_changePassword(vSelf INT, vOldPassword VARCHAR(255), vPassword VARCHAR(255))
|
||||
BEGIN
|
||||
/**
|
||||
* Changes the user password.
|
||||
*
|
||||
* @param vSelf The user id
|
||||
* @param vOldPassword The current password
|
||||
* @param vPassword The new password
|
||||
*/
|
||||
DECLARE vPasswordOk BOOL;
|
||||
DECLARE vUserName VARCHAR(255);
|
||||
|
||||
SELECT `password` = MD5(vOldPassword), `name`
|
||||
INTO vPasswordOk, vUserName
|
||||
FROM user WHERE id = vSelf;
|
||||
|
||||
IF NOT vPasswordOk THEN
|
||||
SIGNAL SQLSTATE '45000'
|
||||
SET MESSAGE_TEXT = 'Invalid password';
|
||||
END IF;
|
||||
|
||||
CALL user_setPassword(vSelf, vPassword);
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,17 @@
|
|||
DROP PROCEDURE IF EXISTS account.user_checkName;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `account`.`user_checkName`(vUserName VARCHAR(255))
|
||||
BEGIN
|
||||
/**
|
||||
* Checks that username meets the necessary syntax requirements, otherwise it
|
||||
* throws an exception.
|
||||
* The user name must only contain lowercase letters or, starting with second
|
||||
* character, numbers or underscores.
|
||||
*/
|
||||
IF vUserName NOT REGEXP '^[a-z0-9_-]*$' THEN
|
||||
SIGNAL SQLSTATE '45000'
|
||||
SET MESSAGE_TEXT = 'INVALID_USER_NAME';
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,22 @@
|
|||
DROP FUNCTION IF EXISTS account.user_getMysqlRole;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`user_getMysqlRole`(vUserName VARCHAR(255)) RETURNS varchar(255) CHARSET utf8
|
||||
BEGIN
|
||||
/**
|
||||
* From a username, it returns the associated MySQL wich should be used when
|
||||
* using external authentication systems.
|
||||
*
|
||||
* @param vUserName The user name
|
||||
* @return The associated MySQL role
|
||||
*/
|
||||
DECLARE vRole VARCHAR(255);
|
||||
|
||||
SELECT CONCAT(IF(r.hasLogin, 'z-', ''), r.name) INTO vRole
|
||||
FROM role r
|
||||
JOIN user u ON u.role = r.id
|
||||
WHERE u.name = vUserName;
|
||||
|
||||
RETURN vRole;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,20 @@
|
|||
DROP FUNCTION IF EXISTS account.user_getNameFromId;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`user_getNameFromId`(vSelf INT) RETURNS varchar(30) CHARSET utf8
|
||||
BEGIN
|
||||
/**
|
||||
* Gets user name from it's id.
|
||||
*
|
||||
* @param vSelf The user id
|
||||
* @return The user name
|
||||
*/
|
||||
DECLARE vName VARCHAR(30);
|
||||
|
||||
SELECT `name` INTO vName
|
||||
FROM user
|
||||
WHERE id = vId;
|
||||
|
||||
RETURN vSelf;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,25 @@
|
|||
DROP FUNCTION IF EXISTS account.user_hasRole;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`user_hasRole`(vUserName VARCHAR(255), vRoleName VARCHAR(255)) RETURNS tinyint(1)
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
/**
|
||||
* Checks if user has/inherits a role.
|
||||
*
|
||||
* @param vUserName The user name
|
||||
* @param vRoleName Role to check
|
||||
* @return %TRUE if it has role, %FALSE otherwise
|
||||
*/
|
||||
DECLARE vHasRole BOOL DEFAULT FALSE;
|
||||
|
||||
SELECT COUNT(*) > 0 INTO vHasRole
|
||||
FROM user u
|
||||
JOIN roleRole rr ON rr.role = u.role
|
||||
JOIN role r ON r.id = rr.inheritsFrom
|
||||
WHERE u.`name` = vUserName
|
||||
AND r.`name` = vRoleName COLLATE 'utf8_unicode_ci';
|
||||
|
||||
RETURN vHasRole;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,25 @@
|
|||
DROP FUNCTION IF EXISTS account.user_hasRoleId;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` FUNCTION `account`.`user_hasRoleId`(vUser VARCHAR(255), vRoleId INT) RETURNS tinyint(1)
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
/**
|
||||
* Checks if user has/inherits a role.
|
||||
*
|
||||
* @param vUserName The user name
|
||||
* @param vRoleId Role id to check
|
||||
* @return %TRUE if it has role, %FALSE otherwise
|
||||
*/
|
||||
DECLARE vHasRole BOOL DEFAULT FALSE;
|
||||
|
||||
SELECT COUNT(*) > 0 INTO vHasRole
|
||||
FROM user u
|
||||
JOIN roleRole rr ON rr.role = u.role
|
||||
JOIN role r ON r.id = rr.inheritsFrom
|
||||
WHERE u.`name` = vUser
|
||||
AND r.id = vRoleId;
|
||||
|
||||
RETURN vHasRole;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,21 @@
|
|||
DROP PROCEDURE IF EXISTS account.user_setPassword;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE account.user_setPassword(vSelf INT, vPassword VARCHAR(255))
|
||||
BEGIN
|
||||
/**
|
||||
* Change the password of the passed as a parameter. Only administrators should
|
||||
* have execute privileges on the procedure since it does not request the user's
|
||||
* current password.
|
||||
*
|
||||
* @param vSelf The user id
|
||||
* @param vPassword New password
|
||||
*/
|
||||
CALL user_checkPassword(vPassword);
|
||||
|
||||
UPDATE user SET
|
||||
`password` = MD5(vPassword),
|
||||
`recoverPass` = FALSE
|
||||
WHERE id = vSelf;
|
||||
END$$
|
||||
DELIMITER ;
|
File diff suppressed because one or more lines are too long
|
@ -12,10 +12,6 @@ INSERT INTO `vn`.`ticketConfig` (`id`, `scopeDays`)
|
|||
VALUES
|
||||
('1', '6');
|
||||
|
||||
INSERT INTO `account`.`mailConfig` (`id`, `domain`)
|
||||
VALUES
|
||||
('1', 'verdnatura.es');
|
||||
|
||||
INSERT INTO `vn`.`bionicConfig` (`generalInflationCoeficient`, `minimumDensityVolumetricWeight`, `verdnaturaVolumeBox`, `itemCarryBox`)
|
||||
VALUES
|
||||
(1.30, 167.00, 138000, 71);
|
||||
|
@ -33,12 +29,16 @@ INSERT INTO `vn`.`packagingConfig`(`upperGap`)
|
|||
('10');
|
||||
|
||||
UPDATE `account`.`role` SET id = 100 WHERE id = 0;
|
||||
CALL `account`.`role_sync`;
|
||||
|
||||
INSERT INTO `account`.`user`(`id`,`name`, `nickname`, `password`,`role`,`active`,`email`, `lang`)
|
||||
SELECT id, name, CONCAT(name, 'Nick'),MD5('nightmare'), id, 1, CONCAT(name, '@mydomain.com'), 'en'
|
||||
FROM `account`.`role` WHERE id <> 20
|
||||
ORDER BY id;
|
||||
|
||||
INSERT INTO `account`.`account`(`id`)
|
||||
SELECT id FROM `account`.`user`;
|
||||
|
||||
INSERT INTO `vn`.`worker`(`id`,`code`, `firstName`, `lastName`, `userFk`, `bossFk`)
|
||||
SELECT id,UPPER(LPAD(role, 3, '0')), name, name, id, 9
|
||||
FROM `vn`.`user`;
|
||||
|
@ -68,6 +68,24 @@ INSERT INTO `account`.`user`(`id`,`name`,`nickname`, `password`,`role`,`active`,
|
|||
(111, 'Missing', 'Missing', 'ac754a330530832ba1bf7687f577da91', 2, 0, NULL, 'en'),
|
||||
(112, 'Trash', 'Trash', 'ac754a330530832ba1bf7687f577da91', 2, 0, NULL, 'en');
|
||||
|
||||
INSERT INTO `account`.`mailAlias`(`id`, `alias`, `description`, `isPublic`)
|
||||
VALUES
|
||||
(1, 'general', 'General mailing list', FALSE),
|
||||
(2, 'it' , 'IT department' , TRUE),
|
||||
(3, 'sales' , 'Sales department' , TRUE);
|
||||
|
||||
INSERT INTO `account`.`mailAliasAccount`(`mailAlias`, `account`)
|
||||
VALUES
|
||||
(1, 1),
|
||||
(1, 18),
|
||||
(3, 18),
|
||||
(1, 9),
|
||||
(2, 9);
|
||||
|
||||
INSERT INTO `account`.`mailForward`(`account`, `forwardTo`)
|
||||
VALUES
|
||||
(1, 'employee@domain.local');
|
||||
|
||||
INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossFk`, `phone`)
|
||||
VALUES
|
||||
(106, 'LGN', 'David Charles', 'Haller', 106, 19, 432978106),
|
||||
|
@ -88,6 +106,15 @@ INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`,
|
|||
(19,'Francia', 1, 'FR', 1, 27),
|
||||
(30,'Canarias', 1, 'IC', 1, 24);
|
||||
|
||||
INSERT INTO `hedera`.`language` (`code`, `name`, `orgName`, `isActive`)
|
||||
VALUES
|
||||
('ca', 'Català' , 'Catalan' , TRUE),
|
||||
('en', 'English' , 'English' , TRUE),
|
||||
('es', 'Español' , 'Spanish' , TRUE),
|
||||
('fr', 'Français' , 'French' , TRUE),
|
||||
('mn', 'Португалий', 'Mongolian' , TRUE),
|
||||
('pt', 'Português' , 'Portuguese', TRUE);
|
||||
|
||||
INSERT INTO `vn`.`warehouseAlias`(`id`, `name`)
|
||||
VALUES
|
||||
(1, 'Main Warehouse'),
|
||||
|
@ -237,6 +264,7 @@ INSERT INTO `vn`.`contactChannel`(`id`, `name`)
|
|||
(3, 'Daily Bugle'),
|
||||
(4, 'GCN Channel'),
|
||||
(5, 'The Newspaper');
|
||||
|
||||
INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city`,`postcode`,`phone`,`mobile`,`fax`,`isRelevant`,`email`,`iban`,`dueDay`,`accountingAccount`,`isEqualizated`,`provinceFk`,`hasToInvoice`,`credit`,`countryFk`,`isActive`,`gestdocFk`,`quality`,`payMethodFk`,`created`,`isToBeMailed`,`contactChannelFk`,`hasSepaVnl`,`hasCoreVnl`,`hasCoreVnh`,`riskCalculated`,`clientTypeFk`,`mailAddress`,`cplusTerIdNifFk`,`hasToInvoiceByAddress`,`isTaxDataChecked`,`isFreezed`,`creditInsurance`,`isCreatedAsServed`,`hasInvoiceSimplified`,`salesPersonFk`,`isVies`,`eypbc`)
|
||||
VALUES
|
||||
(101, 'Bruce Wayne', '84612325V', 'Batman', 'Alfred', '1007 Mountain Drive, Gotham', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceWayne@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1),
|
||||
|
@ -455,8 +483,6 @@ INSERT INTO `vn`.`expence`(`id`, `taxTypeFk`, `name`, `isWithheld`)
|
|||
(6210000567, 0, 'Alquiler VNH', 0),
|
||||
(7001000000, 1, 'Mercaderia', 0);
|
||||
|
||||
|
||||
|
||||
INSERT INTO `vn`.`invoiceOutExpence`(`id`, `invoiceOutFk`, `amount`, `expenceFk`, `created`)
|
||||
VALUES
|
||||
(1, 1, 813.06, 2000000000, CURDATE()),
|
||||
|
@ -540,32 +566,32 @@ INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agen
|
|||
(6, NULL, 57, CURDATE(), 5, 7, 'sixth route', 1.7, 60, CURDATE(), CURDATE(), 3),
|
||||
(7, NULL, 57, CURDATE(), 6, 8, 'seventh route', 0, 70, CURDATE(), CURDATE(), 5);
|
||||
|
||||
INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`, `isDeleted`, `zoneFk`, `created`)
|
||||
INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`, `isDeleted`, `zoneFk`, `zonePrice`, `zoneBonus`, `created`)
|
||||
VALUES
|
||||
(1 , 3, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Bat cave', 121, 'T1111111', 0, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
|
||||
(2 , 1, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T1111111', 0, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
|
||||
(3 , 1, 7, 1, 6, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -2 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T2222222', 0, 3, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)),
|
||||
(4 , 3, 2, 1, 2, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -3 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T3333333', 0, 9, DATE_ADD(CURDATE(), INTERVAL -3 MONTH)),
|
||||
(5 , 3, 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -4 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T4444444', 0, 10, DATE_ADD(CURDATE(), INTERVAL -4 MONTH)),
|
||||
(6 , 1, 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Mountain Drive Gotham', 1, 'A1111111', 0, 10, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
|
||||
(7 , NULL, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'Mountain Drive Gotham', 1, NULL, 0, 3, CURDATE()),
|
||||
(8 , NULL, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'Bat cave', 121, NULL, 0, 3, CURDATE()),
|
||||
(9 , NULL, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 104, 'Stark tower', 124, NULL, 0, 3, CURDATE()),
|
||||
(10, 1, 1, 5, 1, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'Ingram Street', 2, NULL, 0, 1, CURDATE()),
|
||||
(11, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'NY roofs', 122, NULL, 0, 3, CURDATE()),
|
||||
(12, 1, 1, 1, 1, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, 1, CURDATE()),
|
||||
(13, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, 3, CURDATE()),
|
||||
(14, 1, 2, 1, NULL, CURDATE(), CURDATE(), 104, 'Malibu Point', 4, NULL, 0, 9, CURDATE()),
|
||||
(15, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 105, 'An incredibly long alias for testing purposes', 125, NULL, 0, 3, CURDATE()),
|
||||
(16, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()),
|
||||
(17, 1, 7, 2, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()),
|
||||
(18, 1, 4, 4, 4, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 108, 'Cerebro', 128, NULL, 0, 12, CURDATE()),
|
||||
(19, 1, 5, 5, NULL, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 1, 13, CURDATE()),
|
||||
(20, 1, 5, 5, 3, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
|
||||
(21, NULL, 5, 5, 5, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Holland', 102, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
|
||||
(22, NULL, 5, 5, 5, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Japan', 103, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
|
||||
(23, NULL, 8, 1, 7, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'address 21', 121, NULL, 0, 5, CURDATE()),
|
||||
(24 ,NULL, 8, 1, 7, CURDATE(), CURDATE(), 101, 'Bruce Wayne', 1, NULL, 0, 5, CURDATE());
|
||||
(1 , 3, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Bat cave', 121, 'T1111111', 0, 1, 5, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
|
||||
(2 , 1, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T1111111', 0, 1, 5, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
|
||||
(3 , 1, 7, 1, 6, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -2 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T2222222', 0, 3, 5, 1, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)),
|
||||
(4 , 3, 2, 1, 2, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -3 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T3333333', 0, 9, 5, 1, DATE_ADD(CURDATE(), INTERVAL -3 MONTH)),
|
||||
(5 , 3, 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -4 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T4444444', 0, 10, 5, 1, DATE_ADD(CURDATE(), INTERVAL -4 MONTH)),
|
||||
(6 , 1, 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Mountain Drive Gotham', 1, 'A1111111', 0, 10, 5, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
|
||||
(7 , NULL, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'Mountain Drive Gotham', 1, NULL, 0, 3, 5, 1, CURDATE()),
|
||||
(8 , NULL, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'Bat cave', 121, NULL, 0, 3, 5, 1, CURDATE()),
|
||||
(9 , NULL, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 104, 'Stark tower', 124, NULL, 0, 3, 5, 1, CURDATE()),
|
||||
(10, 1, 1, 5, 1, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'Ingram Street', 2, NULL, 0, 1, 5, 1, CURDATE()),
|
||||
(11, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'NY roofs', 122, NULL, 0, 3, 5, 1, CURDATE()),
|
||||
(12, 1, 1, 1, 1, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, 1, 5, 1, CURDATE()),
|
||||
(13, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, 3, 5, 1, CURDATE()),
|
||||
(14, 1, 2, 1, NULL, CURDATE(), CURDATE(), 104, 'Malibu Point', 4, NULL, 0, 9, 5, 1, CURDATE()),
|
||||
(15, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 105, 'An incredibly long alias for testing purposes', 125, NULL, 0, 3, 5, 1, CURDATE()),
|
||||
(16, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, 5, 1, CURDATE()),
|
||||
(17, 1, 7, 2, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, 5, 1, CURDATE()),
|
||||
(18, 1, 4, 4, 4, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 108, 'Cerebro', 128, NULL, 0, 12, 5, 1, CURDATE()),
|
||||
(19, 1, 5, 5, NULL, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 1, NULL, 5, 1, CURDATE()),
|
||||
(20, 1, 5, 5, 3, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 0, 13, 5, 1, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
|
||||
(21, NULL, 5, 5, 5, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Holland', 102, NULL, 0, 13, 5, 1, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
|
||||
(22, NULL, 5, 5, 5, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Japan', 103, NULL, 0, 13, 5, 1, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
|
||||
(23, NULL, 8, 1, 7, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'address 21', 121, NULL, 0, 5, 5, 1, CURDATE()),
|
||||
(24 ,NULL, 8, 1, 7, CURDATE(), CURDATE(), 101, 'Bruce Wayne', 1, NULL, 0, 5, 5, 1, CURDATE());
|
||||
|
||||
INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`)
|
||||
VALUES
|
||||
|
@ -584,7 +610,6 @@ INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `des
|
|||
-- FIX for state hours on local, inter_afterInsert
|
||||
UPDATE vncontrol.inter SET odbc_date = DATE_ADD(CURDATE(), INTERVAL -10 SECOND);
|
||||
|
||||
|
||||
INSERT INTO `vn`.`ticketTracking`(`ticketFk`, `stateFk`, `workerFk`, `created`)
|
||||
VALUES
|
||||
(1, 16, 5 , DATE_ADD(NOW(), INTERVAL -1 MONTH)),
|
||||
|
@ -688,11 +713,13 @@ INSERT INTO `vn`.`itemType`(`id`, `code`, `name`, `categoryFk`, `life`,`workerFk
|
|||
(5, 'CON', 'Container', 3, NULL, 35, 1),
|
||||
(6, 'ALS', 'Alstroemeria', 1, 31, 35, 0);
|
||||
|
||||
INSERT INTO `vn`.`ink`(`id`, `name`, `picture`, `showOrder`)
|
||||
INSERT INTO `vn`.`ink`(`id`, `name`, `picture`, `showOrder`, `hex`)
|
||||
VALUES
|
||||
('YEL', 'Yellow', 1, 1),
|
||||
('BLU', 'Blue', 1, 2),
|
||||
('RED', 'Red', 1, 3);
|
||||
('YEL', 'Yellow', 1, 1, 'F4D03F'),
|
||||
('BLU', 'Blue', 1, 2, '5DADE2'),
|
||||
('RED', 'Red', 1, 3, 'EC7063'),
|
||||
('SLV', 'Silver', 1, 4, 'CACFD2'),
|
||||
('BRW', 'Brown', 1, 5, 'DC7633');
|
||||
|
||||
INSERT INTO `vn`.`origin`(`id`,`code`, `name`)
|
||||
VALUES
|
||||
|
@ -735,20 +762,20 @@ INSERT INTO `vn`.`intrastat`(`id`, `description`, `taxClassFk`, `taxCodeFk`)
|
|||
|
||||
INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `isOnOffer`, `expenceFk`, `isBargain`, `comment`, `relevancy`, `image`, `taxClassFk`, `subName`, `minPrice`)
|
||||
VALUES
|
||||
(1, 2, 70, 'AMA', 1, 1, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 67, 1, NULL, 0),
|
||||
(2, 2, 70, 'AZL', 1, 2, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 66, 1, NULL, 0),
|
||||
(3, 1, 60, 'AMR', 1, 3, NULL, 1, 05080000, 0, 4751000000, 0, NULL, 0, 65, 1, NULL, 0),
|
||||
(4, 1, 60, 'AMR', 1, 1, 'Increases block', 1, 05080000, 1, 4751000000, 0, NULL, 0, 69, 2, NULL, 0),
|
||||
(5, 3, 30, 'GRE', 1, 2, NULL, 2, 06021010, 1, 4751000000, 0, NULL, 0, 74, 2, NULL, 0),
|
||||
(6, 5, 30, 'GRE', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 62, 2, NULL, 0),
|
||||
(7, 5, 90, 'AZL', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 64, 2, NULL, 0),
|
||||
(8, 2, 70, 'AMA', 1, 1, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 75, 1, NULL, 0),
|
||||
(9, 2, 70, 'AZL', 1, 2, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 76, 1, NULL, 0),
|
||||
(10, 1, 60, 'AMR', 1, 3, NULL, 1, 05080000, 0, 4751000000, 0, NULL, 0, 77, 1, NULL, 0),
|
||||
(11, 1, 60, 'AMR', 1, 1, NULL, 1, 05080000, 1, 4751000000, 0, NULL, 0, 78, 2, NULL, 0),
|
||||
(12, 3, 30, 'GRE', 1, 2, NULL, 2, 06021010, 1, 4751000000, 0, NULL, 0, 82, 2, NULL, 0),
|
||||
(13, 5, 30, 'GRE', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 83, 2, NULL, 0),
|
||||
(14, 5, 90, 'AZL', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 84, 2, NULL, 0),
|
||||
(1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 67, 1, NULL, 0),
|
||||
(2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 66, 1, NULL, 0),
|
||||
(3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 0, 4751000000, 0, NULL, 0, 65, 1, NULL, 0),
|
||||
(4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 1, 4751000000, 0, NULL, 0, 69, 2, NULL, 0),
|
||||
(5, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 1, 4751000000, 0, NULL, 0, 74, 2, NULL, 0),
|
||||
(6, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 62, 2, NULL, 0),
|
||||
(7, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 64, 2, NULL, 0),
|
||||
(8, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 75, 1, NULL, 0),
|
||||
(9, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 76, 1, NULL, 0),
|
||||
(10, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 0, 4751000000, 0, NULL, 0, 77, 1, NULL, 0),
|
||||
(11, 1, 60, 'YEL', 1, 1, NULL, 1, 05080000, 1, 4751000000, 0, NULL, 0, 78, 2, NULL, 0),
|
||||
(12, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 1, 4751000000, 0, NULL, 0, 82, 2, NULL, 0),
|
||||
(13, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 83, 2, NULL, 0),
|
||||
(14, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 84, 2, NULL, 0),
|
||||
(15, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, NULL, 0),
|
||||
(16, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, NULL, 0),
|
||||
(71, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 1, 4751000000, 0, NULL, 0, 88, 2, NULL, 0);
|
||||
|
@ -766,25 +793,9 @@ INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `isBox`, `create
|
|||
(9, 3, 6, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 1, 1, 18),
|
||||
(10, 7, 7, 71, CURDATE(), 1, 1, 1, 18);
|
||||
|
||||
INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `isOnOffer`, `expenceFk`, `isBargain`, `comment`, `relevancy`, `image`, `taxClassFk`, `subName`)
|
||||
INSERT INTO `vn`.`expeditionBoxVol`(`boxFk`, `m3`, `ratio`)
|
||||
VALUES
|
||||
(1, 2, 70, 'AMA', 1, 1, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 67, 1, NULL),
|
||||
(2, 2, 70, 'AZL', 1, 2, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 66, 1, NULL),
|
||||
(3, 1, 60, 'AMR', 1, 3, NULL, 1, 05080000, 0, 4751000000, 0, NULL, 0, 65, 1, NULL),
|
||||
(4, 1, 60, 'AMR', 1, 1, NULL, 1, 05080000, 1, 4751000000, 0, NULL, 0, 69, 2, NULL),
|
||||
(5, 3, 30, 'GRE', 1, 2, NULL, 2, 06021010, 1, 4751000000, 0, NULL, 0, 74, 2, NULL),
|
||||
(6, 5, 30, 'GRE', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 62, 2, NULL),
|
||||
(7, 5, 90, 'AZL', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 64, 2, NULL),
|
||||
(8, 2, 70, 'AMA', 1, 1, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 75, 1, NULL),
|
||||
(9, 2, 70, 'AZL', 1, 2, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 76, 1, NULL),
|
||||
(10, 1, 60, 'AMR', 1, 3, NULL, 1, 05080000, 0, 4751000000, 0, NULL, 0, 77, 1, NULL),
|
||||
(11, 1, 60, 'AMR', 1, 1, NULL, 1, 05080000, 1, 4751000000, 0, NULL, 0, 78, 2, NULL),
|
||||
(12, 3, 30, 'GRE', 1, 2, NULL, 2, 06021010, 1, 4751000000, 0, NULL, 0, 82, 2, NULL),
|
||||
(13, 5, 30, 'GRE', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 83, 2, NULL),
|
||||
(14, 5, 90, 'AZL', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 84, 2, NULL),
|
||||
(15, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, NULL),
|
||||
(16, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, NULL),
|
||||
(71, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 1, 4751000000, 0, NULL, 0, 88, 2, NULL);
|
||||
(71,0.141,1);
|
||||
|
||||
INSERT INTO `vn`.`packaging`(`id`, `volume`, `width`, `height`, `depth`, `isPackageReturnable`, `created`, `itemFk`, `price`)
|
||||
VALUES
|
||||
|
@ -797,19 +808,6 @@ INSERT INTO `vn`.`packaging`(`id`, `volume`, `width`, `height`, `depth`, `isPack
|
|||
('cc', 1640038.00, 56.00, 220.00, 128.00, 1, CURDATE(), 15, 90.00),
|
||||
('pallet 100', 2745600.00, 100.00, 220.00, 120.00, 1, CURDATE(), 16, 0.00);
|
||||
|
||||
INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `isBox`, `created`, `itemFk`, `counter`, `workerFk`, `packagingFk`)
|
||||
VALUES
|
||||
(1, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 1, 1, 1),
|
||||
(2, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 2, 1, 1),
|
||||
(3, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 2, 3, 1, 1),
|
||||
(4, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 4, 4, 1, 1),
|
||||
(5, 1, 2, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 1, 1, 1),
|
||||
(6, 7, 3, 71, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), 1, 1, 1, 1),
|
||||
(7, 2, 4, 71, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), 1, 1, 1, 1),
|
||||
(8, 3, 5, 71, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), 1, 1, 1, 1),
|
||||
(9, 3, 6, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 1, 1, 1),
|
||||
(10, 7, 7, 71, CURDATE(), 1, 1, 1, 1);
|
||||
|
||||
INSERT INTO `vn`.`ticketPackaging`(`id`, `ticketFk`, `packagingFk`, `quantity`, `created`, `pvp`)
|
||||
VALUES
|
||||
(1, 1, 2, 2, CURDATE(), NULL),
|
||||
|
@ -888,7 +886,6 @@ INSERT INTO `vn`.`saleComponent`(`saleFk`, `componentFk`, `value`)
|
|||
(8, 28, 1.25),
|
||||
(8, 29, 0.42),
|
||||
(8, 39, 0.017),
|
||||
|
||||
(9, 15, 3.0949),
|
||||
(9, 21, 0.001),
|
||||
(9, 28, 53),
|
||||
|
@ -1052,7 +1049,6 @@ INSERT INTO `vn`.`ticketCollection` (`ticketFk`, `collectionFk`, `level`)
|
|||
VALUES
|
||||
(1, 1, 1);
|
||||
|
||||
|
||||
INSERT INTO `edi`.`genus`(`genus_id`, `latin_genus_name`, `entry_date`, `expiry_date`, `change_date_time`)
|
||||
VALUES
|
||||
(1, 'Abelia' , CURDATE(), NULL, CURDATE()),
|
||||
|
@ -1087,85 +1083,85 @@ INSERT INTO `vn`.`itemTag`(`id`,`itemFk`,`tagFk`,`value`,`priority`)
|
|||
(10, 2, 27, '15cm', 3),
|
||||
(11, 2, 36, 'Stark Industries', 4),
|
||||
(12, 2, 1, 'Silver', 5),
|
||||
(13, 2, 67, 'concussion', 6),
|
||||
(14, 2, 23, '1', 7),
|
||||
(13, 2, 67, 'Concussion', 6),
|
||||
(14, 2, 23, '2', 7),
|
||||
(15, 3, 56, 'Ranged weapon', 1),
|
||||
(16, 3, 58, 'sniper rifle', 2),
|
||||
(17, 3, 4, '300mm', 3),
|
||||
(18, 3, 36, 'Stark Industries', 4),
|
||||
(19, 3, 1, 'Green', 5),
|
||||
(20, 3, 67, 'precission', 6),
|
||||
(21, 3, 23, '1', 7),
|
||||
(21, 3, 23, '3', 7),
|
||||
(22, 4, 56, 'Melee weapon', 1),
|
||||
(23, 4, 58, 'heavy shield', 2),
|
||||
(24, 4, 4, '1x0.5m', 3),
|
||||
(25, 4, 36, 'Stark Industries', 4),
|
||||
(26, 4, 1, 'Black', 5),
|
||||
(27, 4, 67, 'containtment', 6),
|
||||
(28, 4, 23, '1', 7),
|
||||
(28, 4, 23, '4', 7),
|
||||
(29, 5, 56, 'Ranged weapon', 1),
|
||||
(30, 5, 58, 'pistol', 2),
|
||||
(31, 5, 27, '9mm', 3),
|
||||
(32, 5, 36, 'Stark Industries', 4),
|
||||
(33, 5, 1, 'Silver', 5),
|
||||
(34, 5, 67, 'rapid fire', 6),
|
||||
(35, 5, 23, '1', 7),
|
||||
(35, 5, 23, '5', 7),
|
||||
(36, 6, 56, 'Container', 1),
|
||||
(37, 6, 58, 'ammo box', 2),
|
||||
(38, 6, 27, '1m', 3),
|
||||
(39, 6, 36, 'Stark Industries', 4),
|
||||
(40, 6, 1, 'Green', 5),
|
||||
(41, 6, 67, 'supply', 6),
|
||||
(42, 6, 23, '1', 7),
|
||||
(42, 6, 23, '6', 7),
|
||||
(43, 7, 56, 'Container', 1),
|
||||
(44, 7, 58, 'medical box', 2),
|
||||
(45, 7, 27, '1m', 3),
|
||||
(46, 7, 36, 'Stark Industries', 4),
|
||||
(47, 7, 1, 'White', 5),
|
||||
(48, 7, 67, 'supply', 6),
|
||||
(49, 7, 23, '1', 7),
|
||||
(49, 7, 23, '7', 7),
|
||||
(50, 8, 56, 'Ranged Reinforced weapon', 1),
|
||||
(51, 8, 58, '+1 longbow', 2),
|
||||
(52, 8, 27, '2m', 3),
|
||||
(53, 8, 36, 'Stark Industries', 4),
|
||||
(54, 8, 1, 'Brown', 5),
|
||||
(55, 8, 67, 'precission', 6),
|
||||
(56, 8, 23, '1', 7),
|
||||
(56, 8, 23, '8', 7),
|
||||
(57, 9, 56, 'Melee Reinforced weapon', 1),
|
||||
(58, 9, 58, 'combat fist', 2),
|
||||
(59, 9, 27, '15cm', 3),
|
||||
(60, 9, 36, 'Stark Industries', 4),
|
||||
(61, 9, 1, 'Silver', 5),
|
||||
(62, 9, 67, 'concussion', 6),
|
||||
(63, 9, 23, '1', 7),
|
||||
(62, 9, 67, 'Concussion', 6),
|
||||
(63, 9, 23, '9', 7),
|
||||
(64, 10, 56, 'Ranged Reinforced weapon', 1),
|
||||
(65, 10, 58, 'sniper rifle', 2),
|
||||
(66, 10, 4, '300mm', 3),
|
||||
(67, 10, 36, 'Stark Industries', 4),
|
||||
(68, 10, 1, 'Green', 5),
|
||||
(69, 10, 67, 'precission', 6),
|
||||
(70, 10, 23, '1', 7),
|
||||
(70, 10, 23, '10', 7),
|
||||
(71, 11, 56, 'Melee Reinforced weapon', 1),
|
||||
(72, 11, 58, 'heavy shield', 2),
|
||||
(73, 11, 4, '1x0.5m', 3),
|
||||
(74, 11, 36, 'Stark Industries', 4),
|
||||
(75, 11, 1, 'Black', 5),
|
||||
(76, 11, 67, 'containtment', 6),
|
||||
(77, 11, 23, '1', 7),
|
||||
(77, 11, 23, '11', 7),
|
||||
(78, 12, 56, 'Ranged Reinforced weapon', 1),
|
||||
(79, 12, 58, 'pistol', 2),
|
||||
(80, 12, 27, '9mm', 3),
|
||||
(81, 12, 36, 'Stark Industries', 4),
|
||||
(82, 12, 1, 'Silver', 5),
|
||||
(83, 12, 67, 'rapid fire', 6),
|
||||
(84, 12, 23, '1', 7),
|
||||
(84, 12, 23, '12', 7),
|
||||
(85, 13, 56, 'Chest', 1),
|
||||
(86, 13, 58, 'ammo box', 2),
|
||||
(87, 13, 27, '1m', 3),
|
||||
(88, 13, 36, 'Stark Industries', 4),
|
||||
(89, 13, 1, 'Green', 5),
|
||||
(90, 13, 67, 'supply', 6),
|
||||
(91, 13, 23, '1', 7),
|
||||
(91, 13, 23, '13', 7),
|
||||
(92, 14, 56, 'Chest', 1),
|
||||
(93, 14, 58, 'medical box', 2),
|
||||
(94, 14, 27, '1m', 3),
|
||||
|
@ -1756,39 +1752,39 @@ CALL `vn`.zoneGeo_calcTree(); -- this is an auto calculate for table vn.zoneGeo,
|
|||
|
||||
INSERT INTO `vn`.`zoneIncluded` (`zoneFk`, `geoFk`, `isIncluded`)
|
||||
VALUES
|
||||
(1, 3, 0),
|
||||
(1, 4, 0),
|
||||
(1, 5, 0),
|
||||
(1, 1, 1),
|
||||
(2, 3, 0),
|
||||
(2, 4, 0),
|
||||
(2, 5, 0),
|
||||
(2, 1, 1),
|
||||
(3, 3, 0),
|
||||
(3, 4, 0),
|
||||
(3, 5, 0),
|
||||
(3, 1, 1),
|
||||
(4, 3, 0),
|
||||
(4, 4, 0),
|
||||
(4, 5, 0),
|
||||
(4, 1, 1),
|
||||
(5, 3, 1),
|
||||
(5, 4, 0),
|
||||
(5, 5, 1),
|
||||
(5, 1, 1),
|
||||
(6, 3, 1),
|
||||
(6, 4, 0),
|
||||
(6, 5, 1),
|
||||
(6, 1, 1),
|
||||
(7, 3, 0),
|
||||
(7, 4, 0),
|
||||
(7, 5, 0),
|
||||
(7, 1, 1),
|
||||
(8, 3, 0),
|
||||
(8, 4, 0),
|
||||
(8, 5, 0),
|
||||
(8, 1, 1),
|
||||
(10, 10, 1);
|
||||
(1, 3, 0),
|
||||
(1, 4, 0),
|
||||
(1, 5, 0),
|
||||
(1, 1, 1),
|
||||
(2, 3, 0),
|
||||
(2, 4, 0),
|
||||
(2, 5, 0),
|
||||
(2, 1, 1),
|
||||
(3, 3, 0),
|
||||
(3, 4, 0),
|
||||
(3, 5, 0),
|
||||
(3, 1, 1),
|
||||
(4, 3, 0),
|
||||
(4, 4, 0),
|
||||
(4, 5, 0),
|
||||
(4, 1, 1),
|
||||
(5, 3, 1),
|
||||
(5, 4, 0),
|
||||
(5, 5, 1),
|
||||
(5, 1, 1),
|
||||
(6, 3, 1),
|
||||
(6, 4, 0),
|
||||
(6, 5, 1),
|
||||
(6, 1, 1),
|
||||
(7, 3, 0),
|
||||
(7, 4, 0),
|
||||
(7, 5, 0),
|
||||
(7, 1, 1),
|
||||
(8, 3, 0),
|
||||
(8, 4, 0),
|
||||
(8, 5, 0),
|
||||
(8, 1, 1),
|
||||
(10, 10, 1);
|
||||
|
||||
INSERT INTO `vn`.`zoneEvent`(`zoneFk`, `type`, `dated`)
|
||||
VALUES
|
||||
|
@ -2012,26 +2008,26 @@ INSERT INTO `vn`.`workerTimeControl`(`userFk`, `timed`, `manual`, `direction`)
|
|||
|
||||
INSERT INTO `vn`.`dmsType`(`id`, `name`, `path`, `readRoleFk`, `writeRoleFk`, `code`)
|
||||
VALUES
|
||||
(1, 'Facturas Recibidas', 'recibidas', NULL, NULL, 'invoiceIn'),
|
||||
(2, 'Doc oficial', 'oficial', NULL, NULL, 'officialDoc'),
|
||||
(3, 'Laboral', 'laboral', 37, 37, 'hhrrData'),
|
||||
(4, 'Albaranes recibidos', 'entradas', NULL, NULL, 'deliveryNote'),
|
||||
(5, 'Otros', 'otros', 1, 1, 'miscellaneous'),
|
||||
(6, 'Pruebas', 'pruebas', NULL, NULL, 'tests'),
|
||||
(7, 'IAE Clientes', 'IAE_Clientes', 1, 1, 'economicActivitiesTax'),
|
||||
(8, 'Fiscal', 'fiscal', NULL, NULL, 'fiscal'),
|
||||
(9, 'Vehiculos', 'vehiculos', NULL, NULL, 'vehicles'),
|
||||
(10, 'Plantillas', 'plantillas', NULL, NULL, 'templates'),
|
||||
(11, 'Contratos', 'contratos', NULL, NULL, 'contracts'),
|
||||
(12, 'ley de pagos', 'ley pagos', 1, 1, 'paymentsLaw'),
|
||||
(13, 'Basura', 'basura', 1, 1, 'trash'),
|
||||
(14, 'Ticket', 'tickets', 1, 1, 'ticket'),
|
||||
(15, 'Presupuestos', 'Presupuestos', NULL, NULL, 'budgets'),
|
||||
(16, 'Logistica', 'logistica', NULL, NULL, 'logistics'),
|
||||
(17, 'cmr', 'cmr', NULL, NULL, 'cmr'),
|
||||
(18, 'dua', 'dua', NULL, NULL, 'dua'),
|
||||
(19, 'inmovilizado', 'inmovilizado', NULL, NULL, 'fixedAssets'),
|
||||
(20, 'Reclamación', 'reclamacion', 1, 1, 'claim');
|
||||
(1, 'Facturas Recibidas', 'recibidas', NULL, NULL, 'invoiceIn'),
|
||||
(2, 'Doc oficial', 'oficial', NULL, NULL, 'officialDoc'),
|
||||
(3, 'Laboral', 'laboral', 37, 37, 'hhrrData'),
|
||||
(4, 'Albaranes recibidos', 'entradas', NULL, NULL, 'deliveryNote'),
|
||||
(5, 'Otros', 'otros', 1, 1, 'miscellaneous'),
|
||||
(6, 'Pruebas', 'pruebas', NULL, NULL, 'tests'),
|
||||
(7, 'IAE Clientes', 'IAE_Clientes', 1, 1, 'economicActivitiesTax'),
|
||||
(8, 'Fiscal', 'fiscal', NULL, NULL, 'fiscal'),
|
||||
(9, 'Vehiculos', 'vehiculos', NULL, NULL, 'vehicles'),
|
||||
(10, 'Plantillas', 'plantillas', NULL, NULL, 'templates'),
|
||||
(11, 'Contratos', 'contratos', NULL, NULL, 'contracts'),
|
||||
(12, 'ley de pagos', 'ley pagos', 1, 1, 'paymentsLaw'),
|
||||
(13, 'Basura', 'basura', 1, 1, 'trash'),
|
||||
(14, 'Ticket', 'tickets', 1, 1, 'ticket'),
|
||||
(15, 'Presupuestos', 'Presupuestos', NULL, NULL, 'budgets'),
|
||||
(16, 'Logistica', 'logistica', NULL, NULL, 'logistics'),
|
||||
(17, 'cmr', 'cmr', NULL, NULL, 'cmr'),
|
||||
(18, 'dua', 'dua', NULL, NULL, 'dua'),
|
||||
(19, 'inmovilizado', 'inmovilizado', NULL, NULL, 'fixedAssets'),
|
||||
(20, 'Reclamación', 'reclamacion', 1, 1, 'claim');
|
||||
|
||||
INSERT INTO `vn`.`dms`(`id`, `dmsTypeFk`, `file`, `contentType`, `workerFk`, `warehouseFk`, `companyFk`, `hardCopyNumber`, `hasFile`, `reference`, `description`, `created`)
|
||||
VALUES
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -22,6 +22,9 @@ TABLES=(
|
|||
role
|
||||
roleInherit
|
||||
roleRole
|
||||
userPassword
|
||||
accountConfig
|
||||
mailConfig
|
||||
)
|
||||
dump_tables ${TABLES[@]}
|
||||
|
||||
|
|
|
@ -275,7 +275,8 @@ export default {
|
|||
name: 'vn-item-basic-data vn-textfield[ng-model="$ctrl.item.name"]',
|
||||
relevancy: 'vn-item-basic-data vn-input-number[ng-model="$ctrl.item.relevancy"]',
|
||||
origin: 'vn-autocomplete[ng-model="$ctrl.item.originFk"]',
|
||||
expense: 'vn-autocomplete[ng-model="$ctrl.item.expenseFk"]',
|
||||
compression: 'vn-item-basic-data vn-input-number[ng-model="$ctrl.item.compression"]',
|
||||
isFragile: 'vn-check[ng-model="$ctrl.item.isFragile"]',
|
||||
longName: 'vn-textfield[ng-model="$ctrl.item.longName"]',
|
||||
isActiveCheckbox: 'vn-check[label="Active"]',
|
||||
priceInKgCheckbox: 'vn-check[label="Price in kg"]',
|
||||
|
@ -521,11 +522,11 @@ export default {
|
|||
zone: 'vn-autocomplete[ng-model="$ctrl.zoneId"]',
|
||||
nextStepButton: 'vn-step-control .buttons > section:last-child vn-button',
|
||||
finalizeButton: 'vn-step-control .buttons > section:last-child button[type=submit]',
|
||||
stepTwoTotalPriceDif: 'vn-ticket-basic-data-step-two vn-tfoot > vn-tr > :nth-child(6)',
|
||||
stepTwoTotalPriceDif: 'vn-ticket-basic-data-step-two > vn-side-menu div:nth-child(4)',
|
||||
chargesReason: 'vn-ticket-basic-data-step-two div:nth-child(3) > vn-radio',
|
||||
},
|
||||
ticketComponents: {
|
||||
base: 'vn-ticket-components [name="base-sum"]'
|
||||
base: 'vn-ticket-components > vn-side-menu div:nth-child(1) > div:nth-child(2)'
|
||||
},
|
||||
ticketRequests: {
|
||||
addRequestButton: 'vn-ticket-request-index > a > vn-float-button > button',
|
||||
|
@ -666,15 +667,21 @@ export default {
|
|||
},
|
||||
orderCatalog: {
|
||||
plantRealmButton: 'vn-order-catalog > vn-side-menu vn-icon[icon="icon-plant"]',
|
||||
type: 'vn-autocomplete[data="$ctrl.itemTypes"]',
|
||||
type: 'vn-order-catalog vn-autocomplete[data="$ctrl.itemTypes"]',
|
||||
itemId: 'vn-order-catalog > vn-side-menu vn-textfield[vn-id="itemId"]',
|
||||
itemTagValue: 'vn-order-catalog > vn-side-menu vn-datalist[vn-id="search"]',
|
||||
openTagSearch: 'vn-order-catalog > vn-side-menu > div > vn-vertical > vn-datalist[vn-id="search"] .append i',
|
||||
itemTagValue: 'vn-order-catalog vn-textfield[vn-id="search"]',
|
||||
openTagSearch: 'vn-order-catalog vn-vertical:nth-child(4) append > vn-icon > i',
|
||||
tag: 'vn-order-catalog-search-panel vn-autocomplete[ng-model="filter.tagFk"]',
|
||||
tagValue: 'vn-order-catalog-search-panel vn-textfield[ng-model="filter.value"]',
|
||||
firstTagAutocomplete: 'vn-order-catalog-search-panel vn-horizontal:nth-child(2) vn-autocomplete[ng-model="tagValue.value"]',
|
||||
secondTagAutocomplete: 'vn-order-catalog-search-panel vn-horizontal:nth-child(3) vn-autocomplete[ng-model="tagValue.value"]',
|
||||
firstTagValue: 'vn-order-catalog-search-panel vn-horizontal:nth-child(2) vn-textfield[ng-model="tagValue.value"]',
|
||||
secondTagValue: 'vn-order-catalog-search-panel vn-horizontal:nth-child(3) vn-textfield[ng-model="tagValue.value"]',
|
||||
addTagButton: 'vn-order-catalog-search-panel vn-icon-button[icon="add_circle"]',
|
||||
searchTagButton: 'vn-order-catalog-search-panel button[type=submit]',
|
||||
thirdFilterRemoveButton: 'vn-order-catalog > vn-side-menu .chips > vn-chip:nth-child(3) vn-icon[icon=cancel]',
|
||||
fourthFilterRemoveButton: 'vn-order-catalog > vn-side-menu .chips > vn-chip:nth-child(4) vn-icon[icon=cancel]',
|
||||
fifthFilterRemoveButton: 'vn-order-catalog > vn-side-menu .chips > vn-chip:nth-child(5) vn-icon[icon=cancel]',
|
||||
sixthFilterRemoveButton: 'vn-order-catalog > vn-side-menu .chips > vn-chip:nth-child(6) vn-icon[icon=cancel]',
|
||||
},
|
||||
orderBasicData: {
|
||||
client: 'vn-autocomplete[label="Client"]',
|
||||
|
@ -896,6 +903,21 @@ export default {
|
|||
confirmed: 'vn-entry-summary vn-check[label="Confirmed"]',
|
||||
anyBuyLine: 'vn-entry-summary tr.dark-row'
|
||||
},
|
||||
entryBasicData: {
|
||||
reference: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.ref"]',
|
||||
notes: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.notes"]',
|
||||
observations: 'vn-entry-basic-data vn-textarea[ng-model="$ctrl.entry.observation"]',
|
||||
supplier: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.supplierFk"]',
|
||||
currency: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.currencyFk"]',
|
||||
commission: 'vn-entry-basic-data vn-input-number[ng-model="$ctrl.entry.commission"]',
|
||||
company: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.companyFk"]',
|
||||
ordered: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isOrdered"]',
|
||||
confirmed: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isConfirmed"]',
|
||||
inventory: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isInventory"]',
|
||||
raid: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isRaid"]',
|
||||
booked: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isBooked"]',
|
||||
save: 'vn-entry-basic-data button[type=submit]',
|
||||
},
|
||||
entryDescriptor: {
|
||||
agency: 'vn-entry-descriptor div.body vn-label-value:nth-child(1) span',
|
||||
travelsQuicklink: 'vn-entry-descriptor vn-quick-link[icon="local_airport"] > a',
|
||||
|
|
|
@ -45,6 +45,7 @@ describe('Client balance path', () => {
|
|||
});
|
||||
|
||||
it('should create a new payment that clears the debt', async() => {
|
||||
await page.closePopup();
|
||||
await page.waitToClick(selectors.clientBalance.newPaymentButton);
|
||||
await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Pay on receipt');
|
||||
await page.waitToClick(selectors.clientBalance.saveButton);
|
||||
|
|
|
@ -28,11 +28,13 @@ describe('Item Edit basic data path', () => {
|
|||
await page.clearInput(selectors.itemBasicData.relevancy);
|
||||
await page.write(selectors.itemBasicData.relevancy, '1');
|
||||
await page.autocompleteSearch(selectors.itemBasicData.origin, 'Spain');
|
||||
await page.autocompleteSearch(selectors.itemBasicData.expense, 'Alquiler VNH');
|
||||
await page.clearInput(selectors.itemBasicData.compression);
|
||||
await page.write(selectors.itemBasicData.compression, '2');
|
||||
await page.clearInput(selectors.itemBasicData.longName);
|
||||
await page.write(selectors.itemBasicData.longName, 'RS Rose of Purity');
|
||||
await page.waitToClick(selectors.itemBasicData.isActiveCheckbox);
|
||||
await page.waitToClick(selectors.itemBasicData.priceInKgCheckbox);
|
||||
await page.waitToClick(selectors.itemBasicData.isFragile);
|
||||
await page.waitToClick(selectors.itemBasicData.submitBasicDataButton);
|
||||
const message = await page.waitForSnackbar();
|
||||
|
||||
|
@ -93,11 +95,11 @@ describe('Item Edit basic data path', () => {
|
|||
expect(result).toEqual('Spain');
|
||||
});
|
||||
|
||||
it(`should confirm the item expence was edited`, async() => {
|
||||
it(`should confirm the item compression was edited`, async() => {
|
||||
const result = await page
|
||||
.waitToGetProperty(selectors.itemBasicData.expense, 'value');
|
||||
.waitToGetProperty(selectors.itemBasicData.compression, 'value');
|
||||
|
||||
expect(result).toEqual('Alquiler VNH');
|
||||
expect(result).toEqual('2');
|
||||
});
|
||||
|
||||
it(`should confirm the item long name was edited`, async() => {
|
||||
|
@ -107,6 +109,13 @@ describe('Item Edit basic data path', () => {
|
|||
expect(result).toEqual('RS Rose of Purity');
|
||||
});
|
||||
|
||||
it('should confirm isFragile checkbox is unchecked', async() => {
|
||||
const result = await page
|
||||
.checkboxState(selectors.itemBasicData.isFragile);
|
||||
|
||||
expect(result).toBe('checked');
|
||||
});
|
||||
|
||||
it('should confirm isActive checkbox is unchecked', async() => {
|
||||
const result = await page
|
||||
.checkboxState(selectors.itemBasicData.isActiveCheckbox);
|
||||
|
|
|
@ -24,7 +24,6 @@ describe('Ticket List components path', () => {
|
|||
await page.waitPropertyLength(selectors.ticketComponents.base, 'innerText', minLength);
|
||||
const base = await page.waitToGetProperty(selectors.ticketComponents.base, 'innerText');
|
||||
|
||||
|
||||
expect(base).toContain('Base');
|
||||
expect(base.length).toBeGreaterThan(minLength);
|
||||
});
|
||||
|
|
|
@ -37,31 +37,50 @@ describe('Order catalog', () => {
|
|||
expect(result).toEqual(4);
|
||||
});
|
||||
|
||||
it('should search for the item tag value +1 and find two results', async() => {
|
||||
await page.write(selectors.orderCatalog.itemTagValue, '+1');
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitForNumberOfElements('section.product', 2);
|
||||
const result = await page.countElement('section.product');
|
||||
|
||||
expect(result).toEqual(2);
|
||||
it('should perfom an "OR" search for the item tag colors silver and brown', async() => {
|
||||
await page.waitToClick(selectors.orderCatalog.openTagSearch);
|
||||
await page.autocompleteSearch(selectors.orderCatalog.tag, 'Color');
|
||||
await page.autocompleteSearch(selectors.orderCatalog.firstTagAutocomplete, 'silver');
|
||||
await page.waitToClick(selectors.orderCatalog.addTagButton);
|
||||
await page.autocompleteSearch(selectors.orderCatalog.secondTagAutocomplete, 'brown');
|
||||
await page.waitToClick(selectors.orderCatalog.searchTagButton);
|
||||
await page.waitForNumberOfElements('section.product', 4);
|
||||
});
|
||||
|
||||
it('should search for the item tag categoria +1 and find two results', async() => {
|
||||
it('should perfom an "OR" search for the item tag tallos 2 and 9', async() => {
|
||||
await page.waitToClick(selectors.orderCatalog.openTagSearch);
|
||||
await page.autocompleteSearch(selectors.orderCatalog.tag, 'categoria');
|
||||
await page.write(selectors.orderCatalog.tagValue, '+1');
|
||||
await page.autocompleteSearch(selectors.orderCatalog.tag, 'Tallos');
|
||||
await page.write(selectors.orderCatalog.firstTagValue, '2');
|
||||
await page.waitToClick(selectors.orderCatalog.addTagButton);
|
||||
await page.write(selectors.orderCatalog.secondTagValue, '9');
|
||||
await page.waitToClick(selectors.orderCatalog.searchTagButton);
|
||||
await page.waitForNumberOfElements('section.product', 2);
|
||||
});
|
||||
|
||||
it('should perform a general search for category', async() => {
|
||||
await page.write(selectors.orderCatalog.itemTagValue, 'concussion');
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitForNumberOfElements('section.product', 2);
|
||||
});
|
||||
|
||||
it('should perfom an "AND" search for the item tag tallos 2', async() => {
|
||||
await page.waitToClick(selectors.orderCatalog.openTagSearch);
|
||||
await page.autocompleteSearch(selectors.orderCatalog.tag, 'Tallos');
|
||||
await page.write(selectors.orderCatalog.firstTagValue, '2');
|
||||
await page.waitToClick(selectors.orderCatalog.searchTagButton);
|
||||
await page.waitForNumberOfElements('section.product', 1);
|
||||
const result = await page.countElement('section.product');
|
||||
|
||||
expect(result).toEqual(1);
|
||||
});
|
||||
|
||||
it('should remove the tag filters and have 4 results', async() => {
|
||||
await page.waitForContentLoaded();
|
||||
await page.waitToClick(selectors.orderCatalog.sixthFilterRemoveButton);
|
||||
await page.waitForContentLoaded();
|
||||
await page.waitToClick(selectors.orderCatalog.fifthFilterRemoveButton);
|
||||
await page.waitForContentLoaded();
|
||||
await page.waitToClick(selectors.orderCatalog.fourthFilterRemoveButton);
|
||||
await page.waitForContentLoaded();
|
||||
await page.waitToClick(selectors.orderCatalog.thirdFilterRemoveButton);
|
||||
|
||||
await page.waitForNumberOfElements('.product', 4);
|
||||
const result = await page.countElement('section.product');
|
||||
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
import selectors from '../../helpers/selectors.js';
|
||||
import getBrowser from '../../helpers/puppeteer';
|
||||
|
||||
describe('Entry basic data path', () => {
|
||||
let browser;
|
||||
let page;
|
||||
|
||||
beforeAll(async() => {
|
||||
browser = await getBrowser();
|
||||
page = browser.page;
|
||||
await page.loginAndModule('buyer', 'entry');
|
||||
await page.accessToSearchResult('2');
|
||||
await page.accessToSection('entry.card.basicData');
|
||||
});
|
||||
|
||||
afterAll(async() => {
|
||||
await browser.close();
|
||||
});
|
||||
|
||||
it('should edit the basic data', async() => {
|
||||
await page.write(selectors.entryBasicData.reference, 'new movement 8');
|
||||
await page.write(selectors.entryBasicData.notes, 'new notes');
|
||||
await page.write(selectors.entryBasicData.observations, ' edited');
|
||||
await page.autocompleteSearch(selectors.entryBasicData.supplier, 'Plants nick');
|
||||
await page.autocompleteSearch(selectors.entryBasicData.currency, 'eur');
|
||||
await page.clearInput(selectors.entryBasicData.commission);
|
||||
await page.write(selectors.entryBasicData.commission, '100');
|
||||
await page.autocompleteSearch(selectors.entryBasicData.company, 'CCs');
|
||||
await page.waitToClick(selectors.entryBasicData.ordered);
|
||||
await page.waitToClick(selectors.entryBasicData.confirmed);
|
||||
await page.waitToClick(selectors.entryBasicData.inventory);
|
||||
await page.waitToClick(selectors.entryBasicData.raid);
|
||||
await page.waitToClick(selectors.entryBasicData.booked);
|
||||
await page.waitToClick(selectors.entryBasicData.save);
|
||||
|
||||
const message = await page.waitForSnackbar();
|
||||
|
||||
expect(message.text).toBe('Data saved!');
|
||||
});
|
||||
|
||||
it('should confirm the reference was edited', async() => {
|
||||
await page.reloadSection('entry.card.basicData');
|
||||
const result = await page.waitToGetProperty(selectors.entryBasicData.reference, 'value');
|
||||
|
||||
expect(result).toEqual('new movement 8');
|
||||
});
|
||||
|
||||
it('should confirm the note was edited', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.entryBasicData.notes, 'value');
|
||||
|
||||
expect(result).toEqual('new notes');
|
||||
});
|
||||
|
||||
it('should confirm the observation was edited', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.entryBasicData.observations, 'value');
|
||||
|
||||
expect(result).toEqual('observation two edited');
|
||||
});
|
||||
|
||||
it('should confirm the supplier was edited', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.entryBasicData.supplier, 'value');
|
||||
|
||||
expect(result).toEqual('1 - Plants nick');
|
||||
});
|
||||
|
||||
it('should confirm the currency was edited', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.entryBasicData.currency, 'value');
|
||||
|
||||
expect(result).toEqual('EUR');
|
||||
});
|
||||
|
||||
it('should confirm the commission was edited', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.entryBasicData.commission, 'value');
|
||||
|
||||
expect(result).toEqual('100');
|
||||
});
|
||||
|
||||
it('should confirm the company was edited', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.entryBasicData.company, 'value');
|
||||
|
||||
expect(result).toEqual('CCs');
|
||||
});
|
||||
|
||||
it('should confirm ordered was edited', async() => {
|
||||
const result = await page.checkboxState(selectors.entryBasicData.ordered);
|
||||
|
||||
expect(result).toBe('checked');
|
||||
});
|
||||
|
||||
it('should confirm confirmed was edited', async() => {
|
||||
const result = await page.checkboxState(selectors.entryBasicData.confirmed);
|
||||
|
||||
expect(result).toBe('checked');
|
||||
});
|
||||
|
||||
it('should confirm inventory was edited', async() => {
|
||||
const result = await page.checkboxState(selectors.entryBasicData.inventory);
|
||||
|
||||
expect(result).toBe('checked');
|
||||
});
|
||||
|
||||
it('should confirm raid was edited', async() => {
|
||||
const result = await page.checkboxState(selectors.entryBasicData.raid);
|
||||
|
||||
expect(result).toBe('checked');
|
||||
});
|
||||
|
||||
it('should confirm booked was edited', async() => {
|
||||
const result = await page.checkboxState(selectors.entryBasicData.booked);
|
||||
|
||||
expect(result).toBe('checked');
|
||||
});
|
||||
});
|
|
@ -134,7 +134,7 @@ export default class CrudModel extends ModelProxy {
|
|||
*/
|
||||
save() {
|
||||
if (!this.isChanged)
|
||||
return null;
|
||||
return this.$q.resolve();
|
||||
|
||||
let deletes = [];
|
||||
let updates = [];
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<div ng-if="$ctrl.isReady">
|
||||
<div ng-transclude></div>
|
||||
<vn-pagination
|
||||
ng-if="$ctrl.model"
|
||||
model="$ctrl.model"
|
||||
class="vn-pt-md">
|
||||
</vn-pagination>
|
||||
|
|
|
@ -32,7 +32,6 @@ vn-list,
|
|||
|
||||
vn-item,
|
||||
.vn-item {
|
||||
@extend %clickable;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: inherit;
|
||||
|
@ -85,4 +84,6 @@ vn-item,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
a.vn-item {
|
||||
@extend %clickable;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import ngModule from '../../module';
|
||||
import Popover from '../popover';
|
||||
import './style.scss';
|
||||
|
||||
export default class Menu extends Popover {
|
||||
show(parent) {
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
@import "./effects";
|
||||
|
||||
.vn-menu {
|
||||
vn-item, .vn-item {
|
||||
@extend %clickable;
|
||||
}
|
||||
}
|
|
@ -107,15 +107,16 @@ export default class ModelProxy extends DataModel {
|
|||
* Removes a row from the model and emits the 'rowRemove' event.
|
||||
*
|
||||
* @param {Number} index The row index
|
||||
* @return {Promise} The save request promise
|
||||
*/
|
||||
remove(index) {
|
||||
let [item] = this.data.splice(index, 1);
|
||||
let [row] = this.data.splice(index, 1);
|
||||
|
||||
let proxiedIndex = this.proxiedData.indexOf(item);
|
||||
let proxiedIndex = this.proxiedData.indexOf(row);
|
||||
this.proxiedData.splice(proxiedIndex, 1);
|
||||
|
||||
if (!item.$isNew)
|
||||
this.removed.push(item);
|
||||
if (!row.$isNew)
|
||||
this.removed.push(row);
|
||||
|
||||
this.isChanged = true;
|
||||
if (!this.data.length)
|
||||
|
@ -125,7 +126,19 @@ export default class ModelProxy extends DataModel {
|
|||
this.emit('dataUpdate');
|
||||
|
||||
if (this.autoSave)
|
||||
this.save();
|
||||
return this.save();
|
||||
else
|
||||
return this.$q.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a row from the model and emits the 'rowRemove' event.
|
||||
*
|
||||
* @param {Object} row The row object
|
||||
* @return {Promise} The save request promise
|
||||
*/
|
||||
removeRow(row) {
|
||||
return this.remove(this.data.indexOf(row));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
@import "variables";
|
||||
|
||||
.vn-radio {
|
||||
|
||||
& > .btn {
|
||||
border-radius: 50%;
|
||||
|
||||
|
@ -25,4 +26,8 @@
|
|||
&.disabled.checked > .btn > .mark {
|
||||
background-color: $color-font-secondary;
|
||||
}
|
||||
> div {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Search by: Search by {{module | translate}}
|
||||
Search for: Search {{module}}
|
|
@ -1 +1 @@
|
|||
Search by: Buscar por {{module | translate}}
|
||||
Search for: Buscar {{module}}
|
|
@ -16,6 +16,7 @@ import './style.scss';
|
|||
* @property {Function} onSearch Function to call when search is submited
|
||||
* @property {CrudModel} model The model used for searching
|
||||
* @property {Function} exprBuilder If defined, is used to build each non-null param expresion
|
||||
* @property {String} baseState The base state for searchs
|
||||
*/
|
||||
export default class Searchbar extends Component {
|
||||
constructor($element, $) {
|
||||
|
@ -23,6 +24,8 @@ export default class Searchbar extends Component {
|
|||
this.searchState = '.';
|
||||
this.placeholder = 'Search';
|
||||
this.autoState = true;
|
||||
this.separateIndex = true;
|
||||
this.entityState = 'card.summary';
|
||||
|
||||
this.deregisterCallback = this.$transitions.onSuccess(
|
||||
{}, transition => this.onStateChange(transition));
|
||||
|
@ -33,11 +36,13 @@ export default class Searchbar extends Component {
|
|||
if (!this.baseState) {
|
||||
let stateParts = this.$state.current.name.split('.');
|
||||
this.baseState = stateParts[0];
|
||||
}
|
||||
this.searchState = `${this.baseState}.index`;
|
||||
} else
|
||||
this.searchState = this.baseState;
|
||||
|
||||
this.searchState = `${this.baseState}.index`;
|
||||
this.placeholder = this.$t('Search by', {
|
||||
module: this.baseState
|
||||
let description = this.$state.get(this.baseState).description;
|
||||
this.placeholder = this.$t('Search for', {
|
||||
module: this.$t(description).toLowerCase()
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -222,7 +227,7 @@ export default class Searchbar extends Component {
|
|||
subState += '.index';
|
||||
break;
|
||||
default:
|
||||
subState = 'card.summary';
|
||||
subState = this.entityState;
|
||||
}
|
||||
|
||||
if (this.stateParams)
|
||||
|
@ -292,8 +297,10 @@ ngModule.vnComponent('vnSearchbar', {
|
|||
panel: '@',
|
||||
info: '@?',
|
||||
onSearch: '&?',
|
||||
baseState: '@?',
|
||||
autoState: '<?',
|
||||
baseState: '@?',
|
||||
entityState: '@?',
|
||||
separateIndex: '<?',
|
||||
stateParams: '&?',
|
||||
model: '<?',
|
||||
exprBuilder: '&?',
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
<div class="focus-mark"></div>
|
||||
<div class="mark"></div>
|
||||
</div>
|
||||
<span translate>
|
||||
<div translate>
|
||||
{{::$ctrl.label}}
|
||||
</span>
|
||||
</div>
|
|
@ -1,5 +1,6 @@
|
|||
import ngModule from '../../module';
|
||||
import Component from '../../lib/component';
|
||||
import {kebabToCamel} from '../../lib/string';
|
||||
import './style.scss';
|
||||
|
||||
let positions = ['left', 'right', 'up', 'down'];
|
||||
|
@ -206,8 +207,8 @@ ngModule.vnComponent('vnTooltip', {
|
|||
}
|
||||
});
|
||||
|
||||
directive.$inject = ['$document', '$compile', '$templateRequest'];
|
||||
export function directive($document, $compile, $templateRequest) {
|
||||
directive.$inject = ['$document', '$compile'];
|
||||
export function directive($document, $compile) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function($scope, $element, $attrs) {
|
||||
|
|
|
@ -1,70 +1,220 @@
|
|||
import ngModule from '../../module';
|
||||
import Component from '../../lib/component';
|
||||
import getModifiedData from '../../lib/modified';
|
||||
import copyObject from '../../lib/copy';
|
||||
import isEqual from '../../lib/equals';
|
||||
import isFullEmpty from '../../lib/full-empty';
|
||||
import UserError from '../../lib/user-error';
|
||||
import {mergeFilters} from 'vn-loopback/util/filter';
|
||||
|
||||
/**
|
||||
* Component that checks for changes on a specific model property and
|
||||
* asks the user to save or discard it when the state changes.
|
||||
* Also it can save the data to the server when the @url and @idField
|
||||
* properties are provided.
|
||||
* Component that checks for changes on a specific model property and asks the
|
||||
* user to save or discard it when the state changes.
|
||||
* Also it can save the data to the server when the @url and @idField properties
|
||||
* are provided.
|
||||
*
|
||||
* @property {String} idField The id field name, 'id' if not specified
|
||||
* @property {*} idValue The id field value
|
||||
* @property {Boolean} isNew Whether is a new instance
|
||||
* @property {Boolean} insertMode Whether to enable insert mode
|
||||
* @property {String} url The base HTTP request path
|
||||
* @property {Boolean} get Whether to fetch initial data
|
||||
*/
|
||||
export default class Watcher extends Component {
|
||||
constructor($element, $, $state, $stateParams, $transitions, $http, vnApp, $translate, $attrs, $q) {
|
||||
super($element);
|
||||
Object.assign(this, {
|
||||
$,
|
||||
$state,
|
||||
$stateParams,
|
||||
$http,
|
||||
_: $translate,
|
||||
$attrs,
|
||||
vnApp,
|
||||
$q
|
||||
});
|
||||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.idField = 'id';
|
||||
this.get = true;
|
||||
this.insertMode = false;
|
||||
this.state = null;
|
||||
this.deregisterCallback = $transitions.onStart({},
|
||||
this.deregisterCallback = this.$transitions.onStart({},
|
||||
transition => this.callback(transition));
|
||||
this.updateOriginalData();
|
||||
this.snapshot();
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
if (this.get && this.url)
|
||||
this.fetchData();
|
||||
else if (this.get && !this.url)
|
||||
throw new Error('URL parameter ommitted');
|
||||
}
|
||||
let fetch = !this.insertMode
|
||||
&& this.get
|
||||
&& this.url
|
||||
&& this.idValue;
|
||||
|
||||
$onChanges() {
|
||||
if (this.data)
|
||||
this.updateOriginalData();
|
||||
if (fetch)
|
||||
this.fetch();
|
||||
else {
|
||||
this.isNew = !!this.insertMode;
|
||||
this.snapshot();
|
||||
}
|
||||
}
|
||||
|
||||
$onDestroy() {
|
||||
this.deregisterCallback();
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {Booelan} The computed instance HTTP path
|
||||
*/
|
||||
get instanceUrl() {
|
||||
return `${this.url}/${this.idValue}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {Object} The instance data
|
||||
*/
|
||||
get data() {
|
||||
return this._data;
|
||||
}
|
||||
|
||||
set data(value) {
|
||||
this._data = value;
|
||||
this.isNew = !!this.insertMode;
|
||||
this.snapshot();
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {Booelan} Whether it's popullated with data
|
||||
*/
|
||||
get hasData() {
|
||||
return !!this.data;
|
||||
}
|
||||
|
||||
set hasData(value) {
|
||||
if (value)
|
||||
this.fill();
|
||||
else
|
||||
this.delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {Booelan} Whether instance data have been modified
|
||||
*/
|
||||
get dirty() {
|
||||
return this.form && this.form.$dirty || this.dataChanged();
|
||||
}
|
||||
|
||||
dataChanged() {
|
||||
let data = this.copyInNewObject(this.data);
|
||||
return !isEqual(data, this.orgData);
|
||||
fetch() {
|
||||
let filter = mergeFilters({
|
||||
fields: this.fields,
|
||||
where: this.where,
|
||||
include: this.include
|
||||
}, this.filter);
|
||||
|
||||
let params = filter ? {filter} : null;
|
||||
|
||||
return this.$http.get(this.instanceUrl, params)
|
||||
.then(json => {
|
||||
this.overwrite(json.data);
|
||||
this.isNew = false;
|
||||
this.snapshot();
|
||||
})
|
||||
.catch(err => {
|
||||
if (!(err.name == 'HttpError' && err.status == 404))
|
||||
throw err;
|
||||
|
||||
if (this.autoFill) {
|
||||
this.insert();
|
||||
this.snapshot();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fetchData() {
|
||||
let id = this.data[this.idField];
|
||||
return this.$http.get(`${this.url}/${id}`).then(
|
||||
json => {
|
||||
this.data = copyObject(json.data);
|
||||
this.updateOriginalData();
|
||||
}
|
||||
);
|
||||
insert(data) {
|
||||
this.assign({[this.idField]: this.idValue}, data);
|
||||
this.isNew = true;
|
||||
this.deleted = null;
|
||||
}
|
||||
|
||||
delete() {
|
||||
if (!this.hasData) return;
|
||||
this.deleted = this.makeSnapshot();
|
||||
this.clear();
|
||||
this.isNew = false;
|
||||
}
|
||||
|
||||
recover() {
|
||||
if (!this.deleted) return;
|
||||
this.restoreSnapshot(this.deleted);
|
||||
}
|
||||
|
||||
fill() {
|
||||
if (this.hasData)
|
||||
return;
|
||||
|
||||
if (this.deleted)
|
||||
this.recover();
|
||||
else if (this.original && this.original.data)
|
||||
this.reset();
|
||||
else
|
||||
this.insert();
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.restoreSnapshot(this.original);
|
||||
this.setPristine();
|
||||
}
|
||||
|
||||
snapshot() {
|
||||
const snapshot = this.makeSnapshot();
|
||||
|
||||
if (snapshot.data) {
|
||||
const idValue = snapshot.data[this.idField];
|
||||
if (idValue) this.idValue = idValue;
|
||||
}
|
||||
|
||||
this.original = snapshot;
|
||||
this.orgData = snapshot.data;
|
||||
this.deleted = null;
|
||||
this.setPristine();
|
||||
}
|
||||
|
||||
makeSnapshot() {
|
||||
return {
|
||||
data: this.copyData(),
|
||||
isNew: this.isNew,
|
||||
ref: this.data
|
||||
};
|
||||
}
|
||||
|
||||
restoreSnapshot(snapshot) {
|
||||
if (!snapshot) return;
|
||||
this._data = snapshot.ref;
|
||||
this.overwrite(snapshot.data);
|
||||
this.isNew = snapshot.isNew;
|
||||
this.deleted = null;
|
||||
}
|
||||
|
||||
writeData(res) {
|
||||
if (this.hasData)
|
||||
this.assign(res.data);
|
||||
this.isNew = false;
|
||||
this.snapshot();
|
||||
return res;
|
||||
}
|
||||
|
||||
clear() {
|
||||
this._data = null;
|
||||
}
|
||||
|
||||
overwrite(data) {
|
||||
if (data) {
|
||||
if (!this.data) this._data = {};
|
||||
overwrite(this.data, data);
|
||||
} else
|
||||
this._data = null;
|
||||
}
|
||||
|
||||
assign(...args) {
|
||||
this._data = Object.assign(this.data || {}, ...args);
|
||||
}
|
||||
|
||||
copyData() {
|
||||
return copyObject(this.data);
|
||||
}
|
||||
|
||||
refresh() {
|
||||
return this.fetch();
|
||||
}
|
||||
|
||||
dataChanged() {
|
||||
return !isEqual(this.orgData, this.copyData());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,9 +250,10 @@ export default class Watcher extends Component {
|
|||
*/
|
||||
submit() {
|
||||
try {
|
||||
if (this.requestMethod() !== 'post')
|
||||
if (this.isNew)
|
||||
this.isInvalid();
|
||||
else
|
||||
this.check();
|
||||
else this.isInvalid();
|
||||
} catch (err) {
|
||||
return this.$q.reject(err);
|
||||
}
|
||||
|
@ -122,65 +273,42 @@ export default class Watcher extends Component {
|
|||
if (this.form)
|
||||
this.form.$setSubmitted();
|
||||
|
||||
const isPost = (this.requestMethod() === 'post');
|
||||
if (!this.dataChanged() && !isPost) {
|
||||
this.updateOriginalData();
|
||||
if (!this.dataChanged() && !this.isNew) {
|
||||
this.snapshot();
|
||||
return this.$q.resolve();
|
||||
}
|
||||
|
||||
let changedData = isPost
|
||||
let changedData = this.isNew
|
||||
? this.data
|
||||
: getModifiedData(this.data, this.orgData);
|
||||
|
||||
let id = this.idField ? this.orgData[this.idField] : null;
|
||||
|
||||
// If watcher is associated to mgCrud
|
||||
|
||||
if (this.save && this.save.accept) {
|
||||
if (id)
|
||||
changedData[this.idField] = id;
|
||||
|
||||
this.save.model = changedData;
|
||||
return this.$q((resolve, reject) => {
|
||||
this.save.accept().then(
|
||||
json => this.writeData({data: json}, resolve),
|
||||
reject
|
||||
);
|
||||
});
|
||||
return this.save.accept()
|
||||
.then(json => this.writeData({data: json}));
|
||||
}
|
||||
|
||||
// When mgCrud is not used
|
||||
|
||||
if (id) {
|
||||
return this.$q((resolve, reject) => {
|
||||
this.$http.patch(`${this.url}/${id}`, changedData).then(
|
||||
json => this.writeData(json, resolve),
|
||||
reject
|
||||
);
|
||||
});
|
||||
}
|
||||
let req;
|
||||
|
||||
return this.$q((resolve, reject) => {
|
||||
this.$http.post(this.url, changedData).then(
|
||||
json => this.writeData(json, resolve),
|
||||
reject
|
||||
);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* return the request method.
|
||||
*/
|
||||
if (this.deleted)
|
||||
req = this.$http.delete(this.instanceUrl);
|
||||
else if (this.isNew)
|
||||
req = this.$http.post(this.url, changedData);
|
||||
else
|
||||
req = this.$http.patch(this.instanceUrl, changedData);
|
||||
|
||||
requestMethod() {
|
||||
return this.$attrs.save && this.$attrs.save.toLowerCase();
|
||||
return req.then(res => this.writeData(res));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if data is ready to send.
|
||||
*/
|
||||
check() {
|
||||
if (this.form && this.form.$invalid)
|
||||
throw new UserError('Some fields are invalid');
|
||||
this.isInvalid();
|
||||
if (!this.dirty)
|
||||
throw new UserError('No changes to save');
|
||||
}
|
||||
|
@ -220,62 +348,82 @@ export default class Watcher extends Component {
|
|||
|
||||
onConfirmResponse(response) {
|
||||
if (response === 'accept') {
|
||||
if (this.data)
|
||||
Object.assign(this.data, this.orgData);
|
||||
this.reset();
|
||||
this.$state.go(this.state);
|
||||
} else
|
||||
this.state = null;
|
||||
}
|
||||
|
||||
writeData(json, resolve) {
|
||||
Object.assign(this.data, json.data);
|
||||
this.updateOriginalData();
|
||||
resolve(json);
|
||||
}
|
||||
|
||||
updateOriginalData() {
|
||||
this.orgData = this.copyInNewObject(this.data);
|
||||
this.setPristine();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use reset()
|
||||
*/
|
||||
loadOriginalData() {
|
||||
const orgData = JSON.parse(JSON.stringify(this.orgData));
|
||||
this.data = Object.assign(this.data, orgData);
|
||||
this.setPristine();
|
||||
this.reset();
|
||||
}
|
||||
|
||||
copyInNewObject(data) {
|
||||
let newCopy = {};
|
||||
if (data && typeof data === 'object') {
|
||||
Object.keys(data).forEach(
|
||||
key => {
|
||||
let value = data[key];
|
||||
if (value instanceof Date)
|
||||
newCopy[key] = new Date(value.getTime());
|
||||
else if (!isFullEmpty(value)) {
|
||||
if (typeof value === 'object')
|
||||
newCopy[key] = this.copyInNewObject(value);
|
||||
else
|
||||
newCopy[key] = value;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return newCopy;
|
||||
/**
|
||||
* @deprecated Use snapshot()
|
||||
*/
|
||||
updateOriginalData() {
|
||||
this.snapshot();
|
||||
}
|
||||
}
|
||||
Watcher.$inject = ['$element', '$scope', '$state', '$stateParams', '$transitions', '$http', 'vnApp', '$translate', '$attrs', '$q'];
|
||||
Watcher.$inject = ['$element', '$scope'];
|
||||
|
||||
function copyObject(data) {
|
||||
let newCopy;
|
||||
|
||||
if (data && typeof data === 'object') {
|
||||
newCopy = {};
|
||||
Object.keys(data).forEach(
|
||||
key => {
|
||||
let value = data[key];
|
||||
if (value instanceof Date)
|
||||
newCopy[key] = new Date(value.getTime());
|
||||
else if (!isFullEmpty(value)) {
|
||||
if (typeof value === 'object')
|
||||
newCopy[key] = copyObject(value);
|
||||
else
|
||||
newCopy[key] = value;
|
||||
}
|
||||
}
|
||||
);
|
||||
} else
|
||||
newCopy = data;
|
||||
|
||||
return newCopy;
|
||||
}
|
||||
|
||||
function clearObject(obj) {
|
||||
if (!obj) return;
|
||||
for (let key in obj) {
|
||||
if (obj.hasOwnProperty(key))
|
||||
delete obj[key];
|
||||
}
|
||||
}
|
||||
|
||||
function overwrite(obj, data) {
|
||||
if (!obj) return;
|
||||
clearObject(obj);
|
||||
Object.assign(obj, data);
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnWatcher', {
|
||||
template: require('./watcher.html'),
|
||||
bindings: {
|
||||
url: '@?',
|
||||
idField: '@?',
|
||||
data: '<',
|
||||
idValue: '<?',
|
||||
data: '=',
|
||||
form: '<',
|
||||
save: '<',
|
||||
get: '<?'
|
||||
save: '<?',
|
||||
get: '<?',
|
||||
insertMode: '<?',
|
||||
autoFill: '<?',
|
||||
filter: '<?',
|
||||
fields: '<?',
|
||||
where: '<?',
|
||||
include: '<?'
|
||||
},
|
||||
controller: Watcher
|
||||
});
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import './watcher.js';
|
||||
import getModifiedData from '../../lib/modified';
|
||||
|
||||
describe('Component vnWatcher', () => {
|
||||
let $scope;
|
||||
|
@ -9,10 +8,16 @@ describe('Component vnWatcher', () => {
|
|||
let controller;
|
||||
let $attrs;
|
||||
let $q;
|
||||
let data;
|
||||
|
||||
beforeEach(ngModule('vnCore'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _$state_, _$q_) => {
|
||||
data = {
|
||||
id: 1,
|
||||
foo: 'bar'
|
||||
};
|
||||
|
||||
$scope = $rootScope.$new();
|
||||
$element = angular.element('<div></div>');
|
||||
$state = _$state_;
|
||||
|
@ -25,38 +30,49 @@ describe('Component vnWatcher', () => {
|
|||
}));
|
||||
|
||||
describe('$onInit()', () => {
|
||||
it('should call fetchData() if controllers get and url properties are defined', () => {
|
||||
controller.get = () => {};
|
||||
controller.url = 'test.com';
|
||||
jest.spyOn(controller, 'fetchData').mockReturnThis();
|
||||
it('should set data empty by default', () => {
|
||||
controller.$onInit();
|
||||
|
||||
expect(controller.fetchData).toHaveBeenCalledWith();
|
||||
expect(controller.data).toBeUndefined();
|
||||
});
|
||||
|
||||
it(`should throw an error if $onInit is called without url defined`, () => {
|
||||
controller.get = () => {};
|
||||
it('should set new data when insert mode is enabled', () => {
|
||||
controller.insertMode = true;
|
||||
controller.data = data;
|
||||
|
||||
expect(function() {
|
||||
controller.$onInit();
|
||||
}).toThrowError(/parameter/);
|
||||
controller.$onInit();
|
||||
|
||||
expect(controller.orgData).toEqual(data);
|
||||
expect(controller.orgData).toEqual(data);
|
||||
expect(controller.isNew).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should call backend and fetch data if url and idValue properties are defined', () => {
|
||||
controller.url = 'Foos';
|
||||
controller.idValue = 1;
|
||||
|
||||
$httpBackend.expectGET('Foos/1').respond(data);
|
||||
controller.$onInit();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.orgData).toEqual(data);
|
||||
expect(controller.orgData).toEqual(data);
|
||||
expect(controller.orgData).not.toBe(controller.data);
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchData()', () => {
|
||||
it(`should perform a query then store the received data into controller.data and call updateOriginalData()`, () => {
|
||||
jest.spyOn(controller, 'updateOriginalData');
|
||||
let json = {data: 'some data'};
|
||||
controller.data = [1];
|
||||
controller.idField = 0;
|
||||
controller.url = 'test.com';
|
||||
$httpBackend.whenGET('test.com/1').respond(json);
|
||||
$httpBackend.expectGET('test.com/1');
|
||||
controller.fetchData();
|
||||
describe('fetch()', () => {
|
||||
it(`should perform a query then store the received data into data property and make an snapshot into orgData`, () => {
|
||||
controller.url = 'Bars';
|
||||
controller.idValue = 1;
|
||||
|
||||
$httpBackend.expectGET('Bars/1').respond(data);
|
||||
controller.$onInit();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.data).toEqual({data: 'some data'});
|
||||
expect(controller.updateOriginalData).toHaveBeenCalledWith();
|
||||
expect(controller.orgData).toEqual(data);
|
||||
expect(controller.orgData).toEqual(data);
|
||||
expect(controller.orgData).not.toBe(controller.data);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -95,14 +111,6 @@ describe('Component vnWatcher', () => {
|
|||
controller.check();
|
||||
}).toThrowError();
|
||||
});
|
||||
|
||||
it(`should throw error if controller.dirty is true`, () => {
|
||||
controller.form = {$invalid: true};
|
||||
|
||||
expect(function() {
|
||||
controller.check();
|
||||
}).toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('realSubmit()', () => {
|
||||
|
@ -130,59 +138,60 @@ describe('Component vnWatcher', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('when id is defined', () => {
|
||||
it(`should perform a query then call controller.writeData()`, done => {
|
||||
controller.dataChanged = () => {
|
||||
return true;
|
||||
};
|
||||
controller.data = {id: 2};
|
||||
controller.orgData = {id: 1};
|
||||
let changedData = getModifiedData(controller.data, controller.orgData);
|
||||
controller.idField = 'id';
|
||||
controller.url = 'test.com';
|
||||
let json = {data: 'some data'};
|
||||
jest.spyOn(controller, 'writeData');
|
||||
$httpBackend.whenPATCH(`${controller.url}/1`, changedData).respond(json);
|
||||
$httpBackend.expectPATCH(`${controller.url}/1`);
|
||||
controller.realSubmit()
|
||||
.then(() => {
|
||||
expect(controller.writeData).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Function));
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
describe('should perform a PATCH query and save the data', () => {
|
||||
it(`should perform a query then call controller.writeData()`, () => {
|
||||
controller.url = 'Foos';
|
||||
controller.data = data;
|
||||
|
||||
const changedData = {baz: 'value'};
|
||||
Object.assign(controller.data, changedData);
|
||||
|
||||
$httpBackend.expectPATCH('Foos/1', changedData).respond({newProp: 'some'});
|
||||
controller.realSubmit();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.data).toEqual(Object.assign({}, data, changedData));
|
||||
});
|
||||
});
|
||||
|
||||
it(`should perform a POST query then call controller.writeData()`, done => {
|
||||
controller.dataChanged = () => {
|
||||
return true;
|
||||
};
|
||||
controller.data = {id: 2};
|
||||
controller.orgData = {id: 1};
|
||||
controller.url = 'test.com';
|
||||
let json = {data: 'some data'};
|
||||
jest.spyOn(controller, 'writeData');
|
||||
$httpBackend.whenPOST(`${controller.url}`, controller.data).respond(json);
|
||||
$httpBackend.expectPOST(`${controller.url}`, controller.data);
|
||||
controller.realSubmit()
|
||||
.then(() => {
|
||||
expect(controller.writeData).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Function));
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
it(`should perform a POST query and save the data`, () => {
|
||||
controller.insertMode = true;
|
||||
controller.url = 'Foos';
|
||||
controller.data = data;
|
||||
|
||||
const changedData = {baz: 'value'};
|
||||
Object.assign(controller.data, changedData);
|
||||
|
||||
$httpBackend.expectPOST('Foos', controller.data).respond({newProp: 'some'});
|
||||
controller.realSubmit();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.data).toEqual(Object.assign({}, data, changedData));
|
||||
});
|
||||
|
||||
describe('should perform a DELETE query and save empty data', () => {
|
||||
it(`should perform a query then call controller.writeData()`, () => {
|
||||
controller.url = 'Foos';
|
||||
controller.data = data;
|
||||
controller.delete();
|
||||
|
||||
$httpBackend.expectDELETE('Foos/1').respond();
|
||||
controller.realSubmit();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.data).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('writeData()', () => {
|
||||
it(`should call Object.asssign() function over controllers.data with json.data, then call updateOriginalData function and finally call resolve() function`, () => {
|
||||
jest.spyOn(controller, 'updateOriginalData');
|
||||
controller.data = {};
|
||||
let json = {data: 'some data'};
|
||||
let resolve = jasmine.createSpy('resolve');
|
||||
controller.writeData(json, resolve);
|
||||
it(`should save data into orgData`, () => {
|
||||
controller.data = data;
|
||||
Object.assign(controller.data, {baz: 'value'});
|
||||
|
||||
expect(controller.updateOriginalData).toHaveBeenCalledWith();
|
||||
expect(resolve).toHaveBeenCalledWith(json);
|
||||
controller.writeData({});
|
||||
|
||||
expect(controller.data).toEqual(controller.orgData);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -224,37 +233,38 @@ describe('Component vnWatcher', () => {
|
|||
|
||||
describe(`onConfirmResponse()`, () => {
|
||||
describe(`when response is accept`, () => {
|
||||
it(`should call Object.assing on controlle.data with controller.orgData then call go() on state`, () => {
|
||||
let response = 'accept';
|
||||
controller.data = {};
|
||||
controller.orgData = {name: 'Batman'};
|
||||
it(`should reset data them go to state`, () => {
|
||||
let data = {key: 'value'};
|
||||
controller.data = data;
|
||||
data.foo = 'bar';
|
||||
controller.$state = {go: jasmine.createSpy('go')};
|
||||
controller.state = 'Batman';
|
||||
controller.onConfirmResponse(response);
|
||||
controller.state = 'foo.bar';
|
||||
controller.onConfirmResponse('accept');
|
||||
|
||||
expect(controller.data).toEqual(controller.orgData);
|
||||
expect(controller.data).toEqual({key: 'value'});
|
||||
expect(controller.$state.go).toHaveBeenCalledWith(controller.state);
|
||||
});
|
||||
});
|
||||
|
||||
describe(`when response is not accept`, () => {
|
||||
it(`should set controller.state to null`, () => {
|
||||
let response = 'anything but accept';
|
||||
controller.state = 'Batman';
|
||||
controller.onConfirmResponse(response);
|
||||
controller.onConfirmResponse('cancel');
|
||||
|
||||
expect(controller.state).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe(`loadOriginalData()`, () => {
|
||||
it(`should iterate over the current data object, delete all properties then assign the ones from original data`, () => {
|
||||
controller.data = {name: 'Bruce'};
|
||||
controller.orgData = {name: 'Batman'};
|
||||
controller.loadOriginalData();
|
||||
describe(`reset()`, () => {
|
||||
it(`should reset data as it was before changing it`, () => {
|
||||
let data = {key: 'value'};
|
||||
|
||||
expect(controller.data).toEqual(controller.orgData);
|
||||
controller.data = data;
|
||||
data.foo = 'bar';
|
||||
controller.reset();
|
||||
|
||||
expect(data).toEqual({key: 'value'});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -65,7 +65,7 @@ export function directive($translate, $window) {
|
|||
};
|
||||
|
||||
if (form)
|
||||
$scope.$watch(form.$submitted, refreshError);
|
||||
$scope.$watch(() => form.$submitted, refreshError);
|
||||
}
|
||||
}
|
||||
ngModule.directive('rule', directive);
|
||||
|
|
|
@ -25,4 +25,10 @@
|
|||
%active {
|
||||
background-color: $color-active;
|
||||
color: $color-active-font;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: $color-active;
|
||||
color: $color-active-font;
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -18,5 +18,6 @@ export default function moduleImport(moduleName) {
|
|||
case 'invoiceOut' : return import('invoiceOut/front');
|
||||
case 'route' : return import('route/front');
|
||||
case 'entry' : return import('entry/front');
|
||||
case 'account' : return import('account/front');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
<div class="header">
|
||||
<a
|
||||
translate-attr="{title: 'Go to module index'}"
|
||||
ui-sref="{{::$ctrl.module}}.index"
|
||||
ui-sref="{{::$ctrl.indexState}}"
|
||||
name="goToModuleIndex">
|
||||
<vn-icon icon="{{$ctrl.moduleMap[$ctrl.module].icon}}"></vn-icon>
|
||||
</a>
|
||||
<a
|
||||
translate-attr="{title: 'Preview'}"
|
||||
ui-sref="{{::$ctrl.module}}.card.summary({id: $ctrl.descriptor.id})">
|
||||
ui-sref="{{::$ctrl.summaryState}}({id: $ctrl.descriptor.id})">
|
||||
<vn-icon icon="desktop_windows"></vn-icon>
|
||||
</a>
|
||||
<vn-icon-button
|
||||
|
|
|
@ -15,6 +15,8 @@ export default class Descriptor extends Component {
|
|||
}
|
||||
|
||||
$postLink() {
|
||||
super.$postLink();
|
||||
|
||||
const content = this.element.querySelector('vn-descriptor-content');
|
||||
if (!content) throw new Error('Directive vnDescriptorContent not found');
|
||||
|
||||
|
@ -104,6 +106,14 @@ export class DescriptorContent {
|
|||
this.$transclude = $transclude;
|
||||
this.moduleMap = vnModules.getMap();
|
||||
}
|
||||
|
||||
get summaryState() {
|
||||
return `${this.baseState || this.module}.card.summary`;
|
||||
}
|
||||
|
||||
get indexState() {
|
||||
return this.baseState || `${this.module}.index`;
|
||||
}
|
||||
}
|
||||
DescriptorContent.$inject = ['$transclude', 'vnModules'];
|
||||
|
||||
|
@ -112,6 +122,7 @@ ngModule.vnComponent('vnDescriptorContent', {
|
|||
controller: DescriptorContent,
|
||||
bindings: {
|
||||
module: '@',
|
||||
baseState: '@?',
|
||||
description: '<',
|
||||
descriptor: '<?'
|
||||
},
|
||||
|
|
|
@ -15,7 +15,7 @@ export class Layout extends Component {
|
|||
getUserData() {
|
||||
this.$http.get('Accounts/getCurrentUserData').then(json => {
|
||||
this.$.$root.user = json.data;
|
||||
window.localStorage.currentUserWorkerId = json.data.workerId;
|
||||
window.localStorage.currentUserWorkerId = json.data.id;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<ul class="vn-list" ng-if="::$ctrl.items.length > 0">
|
||||
<li ng-repeat="item in ::$ctrl.items" name="{{::item.description}}">
|
||||
<a ng-if="!item.external"
|
||||
<a ng-if="::!item.external"
|
||||
ui-sref="{{::item.state}}"
|
||||
class="vn-item"
|
||||
ng-class="{active: item.active && !item.childs, expanded: item.active}"
|
||||
|
@ -15,7 +15,7 @@
|
|||
<vn-icon icon="keyboard_arrow_down" ng-if="::item.childs.length > 0"></vn-icon>
|
||||
</vn-item-section>
|
||||
</a>
|
||||
<a ng-if="item.external"
|
||||
<a ng-if="::item.external"
|
||||
href="{{::item.url}}"
|
||||
class="vn-item">
|
||||
<vn-item-section avatar>
|
||||
|
|
|
@ -32,73 +32,86 @@ export default class LeftMenu {
|
|||
let moduleIndex = this.$state.current.data.moduleIndex;
|
||||
let moduleFile = window.routes[moduleIndex] || [];
|
||||
let menu = moduleFile.menus && moduleFile.menus[this.source] || [];
|
||||
let items = [];
|
||||
|
||||
let addItem = (items, item) => {
|
||||
let state = states[item.state];
|
||||
if (state) {
|
||||
state = state.self;
|
||||
let acl = state.data.acl;
|
||||
let cloneItems = (items, parent) => {
|
||||
let myItems = [];
|
||||
|
||||
if (acl && !this.aclService.hasAny(acl))
|
||||
return;
|
||||
} else if (!item.external) {
|
||||
console.warn('wrong left-menu definition');
|
||||
return;
|
||||
for (let item of items) {
|
||||
let state = states[item.state];
|
||||
if (state) {
|
||||
state = state.self;
|
||||
let acl = state.data.acl;
|
||||
|
||||
if (acl && !this.aclService.hasAny(acl))
|
||||
continue;
|
||||
}
|
||||
|
||||
let myItem = {
|
||||
icon: item.icon,
|
||||
description: item.description || state.description,
|
||||
state: item.state,
|
||||
external: item.external,
|
||||
url: item.url,
|
||||
parent
|
||||
};
|
||||
|
||||
if (item.childs) {
|
||||
let myChilds = cloneItems(item.childs, myItem);
|
||||
|
||||
if (myChilds.length > 0) {
|
||||
myItem.childs = myChilds;
|
||||
myItems.push(myItem);
|
||||
}
|
||||
} else
|
||||
myItems.push(myItem);
|
||||
}
|
||||
|
||||
items.push({
|
||||
icon: item.icon,
|
||||
description: item.description || state.description,
|
||||
state: item.state,
|
||||
external: item.external,
|
||||
url: item.url
|
||||
});
|
||||
return myItems;
|
||||
};
|
||||
|
||||
for (let item of menu) {
|
||||
if (item.state || item.external)
|
||||
addItem(items, item);
|
||||
else {
|
||||
let childs = [];
|
||||
|
||||
for (let child of item.childs)
|
||||
addItem(childs, child);
|
||||
|
||||
if (childs.length > 0) {
|
||||
items.push({
|
||||
icon: item.icon,
|
||||
description: item.description,
|
||||
childs: childs
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
return cloneItems(menu);
|
||||
}
|
||||
|
||||
activateItem() {
|
||||
let myState = this.$state.current.name
|
||||
.split('.')
|
||||
.slice(0, this._depth)
|
||||
.join('.');
|
||||
let re = new RegExp(`^${myState}(\\..*)?$`);
|
||||
if (!this.items) return;
|
||||
let currentState = this.$state.current.name;
|
||||
let maxSpecificity = 0;
|
||||
let selectedItem;
|
||||
|
||||
if (this.items) {
|
||||
// Check items matching current path
|
||||
for (let item of this.items) {
|
||||
item.active = re.test(item.state);
|
||||
function isParentState(state, currentState) {
|
||||
if (!state) return 0;
|
||||
let match = state.match(/^(.*)\.index$/);
|
||||
if (match) state = match[1];
|
||||
|
||||
if (item.childs) {
|
||||
for (let child of item.childs) {
|
||||
child.active = re.test(child.state);
|
||||
if (child.active)
|
||||
item.active = child.active;
|
||||
}
|
||||
let isParent =
|
||||
currentState.startsWith(`${state}.`) ||
|
||||
currentState === state;
|
||||
|
||||
return isParent
|
||||
? (state.match(/\./g) || []).length + 1
|
||||
: 0;
|
||||
}
|
||||
|
||||
function selectItem(items) {
|
||||
if (!items) return;
|
||||
for (let item of items) {
|
||||
item.active = false;
|
||||
let specificity = isParentState(item.state, currentState);
|
||||
if (specificity > maxSpecificity) {
|
||||
selectedItem = item;
|
||||
maxSpecificity = specificity;
|
||||
}
|
||||
selectItem(item.childs);
|
||||
}
|
||||
}
|
||||
|
||||
// Check items matching current path
|
||||
selectItem(this.items);
|
||||
|
||||
while (selectedItem) {
|
||||
selectedItem.active = true;
|
||||
selectedItem = selectedItem.parent;
|
||||
}
|
||||
}
|
||||
|
||||
setActive(item) {
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
</vn-icon-button>
|
||||
</div>
|
||||
<a
|
||||
ui-sref="worker.card.summary({id: $root.user.workerId})"
|
||||
ui-sref="worker.card.summary({id: $root.user.id})"
|
||||
class="vn-button colored"
|
||||
translate>
|
||||
My account
|
||||
|
|
|
@ -44,6 +44,7 @@ Routes: Rutas
|
|||
Locator: Localizador
|
||||
Invoices out: Facturas emitidas
|
||||
Entries: Entradas
|
||||
Users: Usuarios
|
||||
|
||||
# Common
|
||||
|
||||
|
|
|
@ -134,5 +134,14 @@
|
|||
"This ticket is deleted": "Este ticket está eliminado",
|
||||
"A travel with this data already exists": "Ya existe un travel con estos datos",
|
||||
"This thermograph id already exists": "La id del termógrafo ya existe",
|
||||
"Choose a date range or days forward": "Selecciona un rango de fechas o días en adelante"
|
||||
"Choose a date range or days forward": "Selecciona un rango de fechas o días en adelante",
|
||||
"ORDER_ALREADY_CONFIRMED": "ORDER_ALREADY_CONFIRMED",
|
||||
"Invalid password": "Invalid password",
|
||||
"Password does not meet requirements": "Password does not meet requirements",
|
||||
"Role already assigned": "Role already assigned",
|
||||
"Invalid role name": "Invalid role name",
|
||||
"Role name must be written in camelCase": "Role name must be written in camelCase",
|
||||
"can't be set": "can't be set",
|
||||
"Email already exists": "Email already exists",
|
||||
"User already exists": "User already exists"
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
const ldap = require('../../util/ldapjs-extra');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('sync', {
|
||||
description: 'Synchronizes the user with the other user databases',
|
||||
http: {
|
||||
path: `/sync`,
|
||||
verb: 'PATCH'
|
||||
}
|
||||
});
|
||||
|
||||
Self.sync = async function() {
|
||||
let $ = Self.app.models;
|
||||
|
||||
let ldapConfig = await $.LdapConfig.findOne({
|
||||
fields: ['host', 'rdn', 'password', 'groupDn']
|
||||
});
|
||||
let accountConfig = await $.AccountConfig.findOne({
|
||||
fields: ['idBase']
|
||||
});
|
||||
|
||||
if (!ldapConfig) return;
|
||||
|
||||
// Connect
|
||||
|
||||
let client = ldap.createClient({
|
||||
url: `ldap://${ldapConfig.host}:389`
|
||||
});
|
||||
|
||||
let ldapPassword = Buffer
|
||||
.from(ldapConfig.password, 'base64')
|
||||
.toString('ascii');
|
||||
await client.bind(ldapConfig.rdn, ldapPassword);
|
||||
|
||||
let err;
|
||||
try {
|
||||
// Delete roles
|
||||
|
||||
let opts = {
|
||||
scope: 'sub',
|
||||
attributes: ['dn'],
|
||||
filter: 'objectClass=posixGroup'
|
||||
};
|
||||
res = await client.search(ldapConfig.groupDn, opts);
|
||||
|
||||
let reqs = [];
|
||||
await new Promise((resolve, reject) => {
|
||||
res.on('error', err => {
|
||||
if (err.name === 'NoSuchObjectError')
|
||||
err = new Error(`Object '${ldapConfig.groupDn}' does not exist`);
|
||||
reject(err);
|
||||
});
|
||||
res.on('searchEntry', e => {
|
||||
reqs.push(client.del(e.object.dn));
|
||||
});
|
||||
res.on('end', resolve);
|
||||
});
|
||||
await Promise.all(reqs);
|
||||
|
||||
// Recreate roles
|
||||
|
||||
let roles = await $.Role.find({
|
||||
fields: ['id', 'name']
|
||||
});
|
||||
let accounts = await $.UserAccount.find({
|
||||
fields: ['id'],
|
||||
include: {
|
||||
relation: 'user',
|
||||
scope: {
|
||||
fields: ['name'],
|
||||
include: {
|
||||
relation: 'roles',
|
||||
scope: {
|
||||
fields: ['inheritsFrom']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let map = new Map();
|
||||
for (let account of accounts) {
|
||||
let user = account.user();
|
||||
for (let inherit of user.roles()) {
|
||||
let roleId = inherit.inheritsFrom;
|
||||
if (!map.has(roleId)) map.set(roleId, []);
|
||||
map.get(roleId).push(user.name);
|
||||
}
|
||||
}
|
||||
|
||||
reqs = [];
|
||||
for (let role of roles) {
|
||||
let newEntry = {
|
||||
objectClass: ['top', 'posixGroup'],
|
||||
cn: role.name,
|
||||
gidNumber: accountConfig.idBase + role.id
|
||||
};
|
||||
|
||||
let memberUid = map.get(role.id);
|
||||
if (memberUid) newEntry.memberUid = memberUid;
|
||||
|
||||
let dn = `cn=${role.name},${ldapConfig.groupDn}`;
|
||||
reqs.push(client.add(dn, newEntry));
|
||||
}
|
||||
await Promise.all(reqs);
|
||||
} catch (e) {
|
||||
err = e;
|
||||
}
|
||||
|
||||
// FIXME: Cannot disconnect, hangs on undind() call
|
||||
// await client.unbind();
|
||||
if (err) throw err;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('syncById', {
|
||||
description: 'Synchronizes the user with the other user databases',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
description: 'The user id',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'password',
|
||||
type: 'string',
|
||||
description: 'The password'
|
||||
}
|
||||
],
|
||||
http: {
|
||||
path: `/:id/syncById`,
|
||||
verb: 'PATCH'
|
||||
}
|
||||
});
|
||||
|
||||
Self.syncById = async function(id, password) {
|
||||
let user = await Self.app.models.Account.findById(id, {fields: ['name']});
|
||||
await Self.sync(user.name, password);
|
||||
};
|
||||
};
|
|
@ -0,0 +1,267 @@
|
|||
const ldap = require('../../util/ldapjs-extra');
|
||||
const nthash = require('smbhash').nthash;
|
||||
const ssh = require('node-ssh');
|
||||
const crypto = require('crypto');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('sync', {
|
||||
description: 'Synchronizes the user with the other user databases',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'userName',
|
||||
type: 'string',
|
||||
description: 'The user name',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'password',
|
||||
type: 'string',
|
||||
description: 'The password'
|
||||
}
|
||||
],
|
||||
http: {
|
||||
path: `/sync`,
|
||||
verb: 'PATCH'
|
||||
}
|
||||
});
|
||||
|
||||
Self.sync = async function(userName, password) {
|
||||
let $ = Self.app.models;
|
||||
|
||||
let user = await $.Account.findOne({
|
||||
fields: ['id'],
|
||||
where: {name: userName}
|
||||
});
|
||||
let isSync = !await $.UserSync.exists(userName);
|
||||
|
||||
if (user && isSync) return;
|
||||
|
||||
let accountConfig;
|
||||
let mailConfig;
|
||||
let extraParams;
|
||||
let hasAccount = false;
|
||||
|
||||
if (user) {
|
||||
accountConfig = await $.AccountConfig.findOne({
|
||||
fields: ['homedir', 'shell', 'idBase']
|
||||
});
|
||||
mailConfig = await $.MailConfig.findOne({
|
||||
fields: ['domain']
|
||||
});
|
||||
|
||||
user = await $.Account.findById(user.id, {
|
||||
fields: [
|
||||
'id',
|
||||
'nickname',
|
||||
'email',
|
||||
'lang',
|
||||
'roleFk',
|
||||
'sync',
|
||||
'active',
|
||||
'created',
|
||||
'updated'
|
||||
],
|
||||
where: {name: userName},
|
||||
include: {
|
||||
relation: 'roles',
|
||||
scope: {
|
||||
include: {
|
||||
relation: 'inherits',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
extraParams = {
|
||||
corporateMail: `${userName}@${mailConfig.domain}`,
|
||||
uidNumber: accountConfig.idBase + user.id
|
||||
};
|
||||
|
||||
hasAccount = user.active
|
||||
&& await $.UserAccount.exists(user.id);
|
||||
}
|
||||
|
||||
if (user) {
|
||||
let bcryptPassword = $.User.hashPassword(password);
|
||||
|
||||
await $.Account.upsertWithWhere({id: user.id},
|
||||
{bcryptPassword}
|
||||
);
|
||||
await $.user.upsert({
|
||||
id: user.id,
|
||||
username: userName,
|
||||
password: bcryptPassword,
|
||||
email: user.email,
|
||||
created: user.created,
|
||||
updated: user.updated
|
||||
});
|
||||
}
|
||||
|
||||
// SIP
|
||||
|
||||
if (hasAccount) {
|
||||
await Self.rawSql('CALL pbx.sip_setPassword(?, ?)',
|
||||
[user.id, password]
|
||||
);
|
||||
}
|
||||
|
||||
// LDAP
|
||||
|
||||
let ldapConfig = await $.LdapConfig.findOne({
|
||||
fields: ['host', 'rdn', 'password', 'baseDn', 'groupDn']
|
||||
});
|
||||
|
||||
if (ldapConfig) {
|
||||
let ldapClient = ldap.createClient({
|
||||
url: `ldap://${ldapConfig.host}:389`
|
||||
});
|
||||
|
||||
let ldapPassword = Buffer
|
||||
.from(ldapConfig.password, 'base64')
|
||||
.toString('ascii');
|
||||
await ldapClient.bind(ldapConfig.rdn, ldapPassword);
|
||||
|
||||
let err;
|
||||
try {
|
||||
// Deletes user
|
||||
|
||||
try {
|
||||
let dn = `uid=${userName},${ldapConfig.baseDn}`;
|
||||
await ldapClient.del(dn);
|
||||
} catch (e) {
|
||||
if (e.name !== 'NoSuchObjectError') throw e;
|
||||
}
|
||||
|
||||
// Removes user from groups
|
||||
|
||||
let opts = {
|
||||
scope: 'sub',
|
||||
attributes: ['dn'],
|
||||
filter: `&(memberUid=${userName})(objectClass=posixGroup)`
|
||||
};
|
||||
res = await ldapClient.search(ldapConfig.groupDn, opts);
|
||||
|
||||
let oldGroups = [];
|
||||
await new Promise((resolve, reject) => {
|
||||
res.on('error', reject);
|
||||
res.on('searchEntry', e => oldGroups.push(e.object));
|
||||
res.on('end', resolve);
|
||||
});
|
||||
|
||||
let reqs = [];
|
||||
for (oldGroup of oldGroups) {
|
||||
let change = new ldap.Change({
|
||||
operation: 'delete',
|
||||
modification: {memberUid: userName}
|
||||
});
|
||||
reqs.push(ldapClient.modify(oldGroup.dn, change));
|
||||
}
|
||||
await Promise.all(reqs);
|
||||
|
||||
if (hasAccount) {
|
||||
// Recreates user
|
||||
|
||||
let nameArgs = user.nickname.split(' ');
|
||||
let sshaPassword = crypto
|
||||
.createHash('sha1')
|
||||
.update(password)
|
||||
.digest('base64');
|
||||
|
||||
let dn = `uid=${userName},${ldapConfig.baseDn}`;
|
||||
let newEntry = {
|
||||
uid: userName,
|
||||
objectClass: [
|
||||
'inetOrgPerson',
|
||||
'posixAccount',
|
||||
'sambaSamAccount'
|
||||
],
|
||||
cn: user.nickname || userName,
|
||||
displayName: user.nickname,
|
||||
givenName: nameArgs[0],
|
||||
sn: nameArgs[1] || 'Empty',
|
||||
mail: extraParams.corporateMail,
|
||||
userPassword: `{SSHA}${sshaPassword}`,
|
||||
preferredLanguage: user.lang,
|
||||
homeDirectory: `${accountConfig.homedir}/${userName}`,
|
||||
loginShell: accountConfig.shell,
|
||||
uidNumber: extraParams.uidNumber,
|
||||
gidNumber: accountConfig.idBase + user.roleFk,
|
||||
sambaSID: '-',
|
||||
sambaNTPassword: nthash(password)
|
||||
};
|
||||
await ldapClient.add(dn, newEntry);
|
||||
|
||||
// Adds user to groups
|
||||
|
||||
let reqs = [];
|
||||
for (let role of user.roles()) {
|
||||
let change = new ldap.Change({
|
||||
operation: 'add',
|
||||
modification: {memberUid: userName}
|
||||
});
|
||||
let roleName = role.inherits().name;
|
||||
let dn = `cn=${roleName},${ldapConfig.groupDn}`;
|
||||
reqs.push(ldapClient.modify(dn, change));
|
||||
}
|
||||
await Promise.all(reqs);
|
||||
}
|
||||
} catch (e) {
|
||||
err = e;
|
||||
}
|
||||
|
||||
// FIXME: Cannot disconnect, hangs on undind() call
|
||||
// await ldapClient.unbind();
|
||||
if (err) throw err;
|
||||
}
|
||||
|
||||
// Samba
|
||||
|
||||
let sambaConfig = await $.SambaConfig.findOne({
|
||||
fields: ['host', 'sshUser', 'sshPass']
|
||||
});
|
||||
|
||||
if (sambaConfig) {
|
||||
let sshPassword = Buffer
|
||||
.from(sambaConfig.sshPass, 'base64')
|
||||
.toString('ascii');
|
||||
|
||||
let sshClient = new ssh.NodeSSH();
|
||||
await sshClient.connect({
|
||||
host: sambaConfig.host,
|
||||
username: sambaConfig.sshUser,
|
||||
password: sshPassword
|
||||
});
|
||||
|
||||
let commands;
|
||||
|
||||
if (hasAccount) {
|
||||
commands = [
|
||||
`samba-tool user create "${userName}" `
|
||||
+ `--uid-number=${extraParams.uidNumber} `
|
||||
+ `--mail-address="${extraParams.corporateMail}" `
|
||||
+ `--random-password`,
|
||||
`samba-tool user setexpiry "${userName}" `
|
||||
+ `--noexpiry`,
|
||||
`samba-tool user setpassword "${userName}" `
|
||||
+ `--newpassword="${password}"`,
|
||||
`mkhomedir_helper "${userName}" 0027`
|
||||
];
|
||||
} else {
|
||||
commands = [
|
||||
`samba-tool user delete "${userName}"`
|
||||
];
|
||||
}
|
||||
|
||||
for (let command of commands)
|
||||
await sshClient.execCommand(command);
|
||||
|
||||
await sshClient.dispose();
|
||||
}
|
||||
|
||||
// Mark as synchronized
|
||||
|
||||
await $.UserSync.destroyById(userName);
|
||||
};
|
||||
};
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"AccountConfig": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"LdapConfig": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"MailAlias": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"MailAliasAccount": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"MailConfig": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"MailForward": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"RoleInherit": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"RoleRole": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"SambaConfig": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"UserAccount": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"UserPassword": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"UserSync": {
|
||||
"dataSource": "vn"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"name": "AccountConfig",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "account.accountConfig"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"id": true
|
||||
},
|
||||
"homedir": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"shell": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"idBase": {
|
||||
"type": "number",
|
||||
"required": true
|
||||
},
|
||||
"min": {
|
||||
"type": "number",
|
||||
"required": true
|
||||
},
|
||||
"max": {
|
||||
"type": "number",
|
||||
"required": true
|
||||
},
|
||||
"warn": {
|
||||
"type": "number",
|
||||
"required": true
|
||||
},
|
||||
"inact": {
|
||||
"type": "number",
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"name": "LdapConfig",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "account.ldapConfig"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"id": true
|
||||
},
|
||||
"host": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"rdn": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"baseDn": {
|
||||
"type": "string"
|
||||
},
|
||||
"filter": {
|
||||
"type": "string"
|
||||
},
|
||||
"groupDn": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"name": "MailAliasAccount",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "account.mailAliasAccount"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"id": true
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
"alias": {
|
||||
"type": "belongsTo",
|
||||
"model": "MailAlias",
|
||||
"foreignKey": "mailAlias"
|
||||
},
|
||||
"user": {
|
||||
"type": "belongsTo",
|
||||
"model": "Account",
|
||||
"foreignKey": "account"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"name": "MailAlias",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "account.mailAlias"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"id": true
|
||||
},
|
||||
"alias": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"isPublic": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
"accounts": {
|
||||
"type": "hasMany",
|
||||
"model": "MailAliasAccount",
|
||||
"foreignKey": "mailAlias",
|
||||
"property": "id"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "MailConfig",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "account.mailConfig"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"id": true
|
||||
},
|
||||
"domain": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"name": "MailForward",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "account.mailForward"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"account": {
|
||||
"id": true
|
||||
},
|
||||
"forwardTo": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
"user": {
|
||||
"type": "belongsTo",
|
||||
"model": "Account",
|
||||
"foreignKey": "account"
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue