diff --git a/modules/account/back/methods/account-synchronizer/test.js b/modules/account/back/methods/account-linker/test.js similarity index 59% rename from modules/account/back/methods/account-synchronizer/test.js rename to modules/account/back/methods/account-linker/test.js index a77940168..990af2df8 100644 --- a/modules/account/back/methods/account-synchronizer/test.js +++ b/modules/account/back/methods/account-linker/test.js @@ -1,3 +1,4 @@ +const NotFoundError = require('vn-loopback/util/not-found-error'); module.exports = Self => { Self.remoteMethod('test', { @@ -9,7 +10,8 @@ module.exports = Self => { }); Self.test = async function() { - let connector = await Self.getSynchronizer(); + const connector = await Self.getLinker(); + if (!connector) throw new NotFoundError('Linker not configured'); await connector.test(); }; }; diff --git a/modules/account/back/mixins/account-synchronizer.js b/modules/account/back/mixins/account-linker.js similarity index 85% rename from modules/account/back/mixins/account-synchronizer.js rename to modules/account/back/mixins/account-linker.js index 8ba8bfe9d..c882d0893 100644 --- a/modules/account/back/mixins/account-synchronizer.js +++ b/modules/account/back/mixins/account-linker.js @@ -3,14 +3,14 @@ const app = require('vn-loopback/server/server'); const UserError = require('vn-loopback/util/user-error'); module.exports = function(Self, options) { - require('../methods/account-synchronizer/test')(Self); + require('../methods/account-linker/test')(Self); Self.once('attached', function() { - app.models.AccountConfig.addSynchronizer(Self); + app.models.AccountConfig.addLinker(Self); }); /** - * Mixin for user synchronizers. + * Mixin for account linkers. * * @property {Array} $ * @property {Object} accountConfig @@ -18,12 +18,12 @@ module.exports = function(Self, options) { */ let Mixin = { /** - * Initalizes the synchronizer. + * Initalizes the linker. */ async init() {}, /** - * Deinitalizes the synchronizer. + * Deinitalizes the linker. */ async deinit() {}, @@ -57,7 +57,7 @@ module.exports = function(Self, options) { async syncRoles() {}, /** - * Tests synchronizer configuration. + * Tests linker configuration. */ async test() { try { diff --git a/modules/account/back/models/account-config.js b/modules/account/back/models/account-config.js index 0db699b99..2cc6b240d 100644 --- a/modules/account/back/models/account-config.js +++ b/modules/account/back/models/account-config.js @@ -3,94 +3,85 @@ const models = require('vn-loopback/server/server').models; module.exports = Self => { Object.assign(Self, { - synchronizers: [], + linkers: [], - addSynchronizer(synchronizer) { - this.synchronizers.push(synchronizer); + addLinker(linker) { + this.linkers.push(linker); }, - async getInstance() { - let instance = await Self.findOne({ + async initEngine() { + const accountConfig = await Self.findOne({ fields: ['homedir', 'shell', 'idBase'] }); - await instance.synchronizerInit(); - return instance; + const mailConfig = await models.MailConfig.findOne({ + fields: ['domain'] + }); + + const linkers = []; + + for (const Linker of Self.linkers) { + const linker = await Linker.getLinker(); + if (!linker) continue; + Object.assign(linker, {accountConfig}); + await linker.init(); + linkers.push(linker); + } + + Object.assign(accountConfig, { + linkers, + domain: mailConfig.domain + }); + + return { + accountConfig, + linkers + }; + }, + + async deinitEngine(engine) { + for (const linker of engine.linkers) + await linker.deinit(); + }, + + async syncUser(userName, password) { + const engine = await Self.initEngine(); + try { + await Self.syncUserBase(engine, userName, password, true); + } finally { + await Self.deinitEngine(engine); + } }, async syncUsers() { - let instance = await Self.getInstance(); + const engine = await Self.initEngine(); + + let usersToSync = new Set(); + for (const linker of engine.linkers) + await linker.getUsers(usersToSync); - let usersToSync = await instance.synchronizerGetUsers(); usersToSync = Array.from(usersToSync.values()) .sort((a, b) => a.localeCompare(b)); for (let userName of usersToSync) { try { + // eslint-disable-next-line no-console console.log(`Synchronizing user '${userName}'`); - await instance.synchronizerSyncUser(userName); + + await Self.syncUserBase(engine, userName); + + // eslint-disable-next-line no-console console.log(` -> User '${userName}' sinchronized`); } catch (err) { + // eslint-disable-next-line no-console console.error(` -> User '${userName}' synchronization error:`, err.message); } } - await instance.synchronizerDeinit(); + await Self.deinitEngine(engine); await Self.syncRoles(); }, - async syncUser(userName, password) { - let instance = await Self.getInstance(); - try { - await instance.synchronizerSyncUser(userName, password, true); - } finally { - await instance.synchronizerDeinit(); - } - }, - - async syncRoles() { - let instance = await Self.getInstance(); - try { - await instance.synchronizerSyncRoles(); - } finally { - await instance.synchronizerDeinit(); - } - }, - - async getSynchronizer() { - return await Self.findOne(); - } - }); - - Object.assign(Self.prototype, { - async synchronizerInit() { - let mailConfig = await models.MailConfig.findOne({ - fields: ['domain'] - }); - - let synchronizers = []; - - for (let Synchronizer of Self.synchronizers) { - let synchronizer = await Synchronizer.getSynchronizer(); - if (!synchronizer) continue; - Object.assign(synchronizer, { - accountConfig: this - }); - await synchronizer.init(); - synchronizers.push(synchronizer); - } - - Object.assign(this, { - synchronizers, - domain: mailConfig.domain - }); - }, - - async synchronizerDeinit() { - for (let synchronizer of this.synchronizers) - await synchronizer.deinit(); - }, - - async synchronizerSyncUser(userName, password, syncGroups) { + async syncUserBase(engine, userName, password, syncGroups) { if (!userName) return; userName = userName.toLowerCase(); @@ -98,7 +89,7 @@ module.exports = Self => { if (['administrator', 'root'].indexOf(userName) >= 0) return; - let user = await models.VnUser.findOne({ + const user = await models.VnUser.findOne({ where: {name: userName}, fields: [ 'id', @@ -130,27 +121,28 @@ module.exports = Self => { ] }); - let info = { + const info = { user, hasAccount: false }; if (user) { - let exists = await models.Account.exists(user.id); + const exists = await models.Account.exists(user.id); + const {accountConfig} = engine; Object.assign(info, { hasAccount: user.active && exists, - corporateMail: `${userName}@${this.domain}`, - uidNumber: this.idBase + user.id + corporateMail: `${userName}@${accountConfig.domain}`, + uidNumber: accountConfig.idBase + user.id }); } - let errs = []; + const errs = []; - for (let synchronizer of this.synchronizers) { + for (const linker of engine.linkers) { try { - await synchronizer.syncUser(userName, info, password); + await linker.syncUser(userName, info, password); if (syncGroups) - await synchronizer.syncUserGroups(userName, info); + await linker.syncUserGroups(userName, info); } catch (err) { errs.push(err); } @@ -159,18 +151,16 @@ module.exports = Self => { if (errs.length) throw errs[0]; }, - async synchronizerGetUsers() { - let usersToSync = new Set(); + async syncRoles() { + const engine = await Self.initEngine(); + try { + await Self.rawSql(`CALL account.role_sync`); - for (let synchronizer of this.synchronizers) - await synchronizer.getUsers(usersToSync); - - return usersToSync; - }, - - async synchronizerSyncRoles() { - for (let synchronizer of this.synchronizers) - await synchronizer.syncRoles(); + for (const linker of engine.linkers) + await linker.syncRoles(); + } finally { + await Self.deinitEngine(engine); + } } }); }; diff --git a/modules/account/back/models/ldap-config.js b/modules/account/back/models/ldap-config.js index 9dcc4136d..b557d243c 100644 --- a/modules/account/back/models/ldap-config.js +++ b/modules/account/back/models/ldap-config.js @@ -7,7 +7,7 @@ const nthash = require('smbhash').nthash; module.exports = Self => { const shouldSync = process.env.NODE_ENV !== 'test'; - Self.getSynchronizer = async function() { + Self.getLinker = async function() { return await Self.findOne({ fields: [ 'server', @@ -24,6 +24,7 @@ module.exports = Self => { this.client = ldap.createClient({ url: this.server }); + this.client.on('error', () => {}); await this.client.bind(this.rdn, this.password); }, diff --git a/modules/account/back/models/ldap-config.json b/modules/account/back/models/ldap-config.json index 2fd5aa901..d4d3a094d 100644 --- a/modules/account/back/models/ldap-config.json +++ b/modules/account/back/models/ldap-config.json @@ -7,7 +7,7 @@ } }, "mixins": { - "AccountSynchronizer": {} + "AccountLinker": {} }, "properties": { "id": { diff --git a/modules/account/back/models/role-config.js b/modules/account/back/models/role-config.js index b90ef75fb..d6c57b70b 100644 --- a/modules/account/back/models/role-config.js +++ b/modules/account/back/models/role-config.js @@ -1,6 +1,6 @@ module.exports = Self => { - Self.getSynchronizer = async function() { + Self.getLinker = async function() { let NODE_ENV = process.env.NODE_ENV; if (!NODE_ENV || NODE_ENV == 'development') return null; @@ -45,6 +45,7 @@ module.exports = Self => { } if (!isUpdatable) { + // eslint-disable-next-line no-console console.warn(`RoleConfig.syncUser(): User '${userName}' cannot be updated, not managed by me`); return; } @@ -82,6 +83,7 @@ module.exports = Self => { [mysqlUser, this.userHost]); } catch (err) { if (err.code == 'ER_REVOKE_GRANTS') + // eslint-disable-next-line no-console console.warn(`${err.code}: ${err.sqlMessage}: ${err.sql}`); else throw err; diff --git a/modules/account/back/models/role-config.json b/modules/account/back/models/role-config.json index f4138bea8..3b843eaea 100644 --- a/modules/account/back/models/role-config.json +++ b/modules/account/back/models/role-config.json @@ -7,7 +7,7 @@ } }, "mixins": { - "AccountSynchronizer": {} + "AccountLinker": {} }, "properties": { "id": { diff --git a/modules/account/back/models/role-inherit.js b/modules/account/back/models/role-inherit.js index 7d31e62b1..e994f844e 100644 --- a/modules/account/back/models/role-inherit.js +++ b/modules/account/back/models/role-inherit.js @@ -9,7 +9,7 @@ module.exports = Self => { Self.observe(hook, async() => { try { await Self.rawSql(` - CREATE EVENT account.role_sync + CREATE DEFINER = CURRENT_ROLE EVENT account.role_sync ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 5 SECOND DO CALL role_sync; `); diff --git a/modules/account/back/models/samba-config.js b/modules/account/back/models/samba-config.js index 7714fb01c..f5672ca21 100644 --- a/modules/account/back/models/samba-config.js +++ b/modules/account/back/models/samba-config.js @@ -13,7 +13,7 @@ const UserAccountControlFlags = { module.exports = Self => { const shouldSync = process.env.NODE_ENV !== 'test'; - Self.getSynchronizer = async function() { + Self.getLinker = async function() { return await Self.findOne({ fields: [ 'host', @@ -39,6 +39,7 @@ module.exports = Self => { url: `ldaps://${this.adController}:636`, tlsOptions: {rejectUnauthorized: this.verifyCert} }); + adClient.on('error', () => {}); await adClient.bind(bindDn, this.adPassword); Object.assign(this, { adClient, diff --git a/modules/account/back/models/samba-config.json b/modules/account/back/models/samba-config.json index 28cbb2689..4c9e0a794 100644 --- a/modules/account/back/models/samba-config.json +++ b/modules/account/back/models/samba-config.json @@ -7,7 +7,7 @@ } }, "mixins": { - "AccountSynchronizer": {} + "AccountLinker": {} }, "properties": { "id": { diff --git a/modules/account/back/models/sip-config.js b/modules/account/back/models/sip-config.js index 3b5cb2dbb..703783337 100644 --- a/modules/account/back/models/sip-config.js +++ b/modules/account/back/models/sip-config.js @@ -2,7 +2,7 @@ const app = require('vn-loopback/server/server'); module.exports = Self => { - Self.getSynchronizer = async function() { + Self.getLinker = async function() { return await Self.findOne({fields: ['id']}); }; diff --git a/modules/account/back/models/sip-config.json b/modules/account/back/models/sip-config.json index 6c5ba3db3..a25d09c67 100644 --- a/modules/account/back/models/sip-config.json +++ b/modules/account/back/models/sip-config.json @@ -7,7 +7,7 @@ } }, "mixins": { - "AccountSynchronizer": {} + "AccountLinker": {} }, "properties": { "id": { @@ -16,4 +16,3 @@ } } } - \ No newline at end of file diff --git a/modules/account/front/descriptor/index.html b/modules/account/front/descriptor/index.html index b0a70edd1..86e78dfce 100644 --- a/modules/account/front/descriptor/index.html +++ b/modules/account/front/descriptor/index.html @@ -68,7 +68,6 @@ Deactivate user - + Do you want to synchronize user? diff --git a/modules/worker/front/calendar/index.html b/modules/worker/front/calendar/index.html index d64c22408..1b0608633 100644 --- a/modules/worker/front/calendar/index.html +++ b/modules/worker/front/calendar/index.html @@ -70,17 +70,18 @@ fields="['started', 'ended']" ng-model="$ctrl.businessId" search-function="{businessFk: $search}" + show-field="businessFk" value-field="businessFk" order="businessFk DESC" limit="5"> - -
#{{businessFk}}
-
- {{started | date: 'dd/MM/yyyy'}} - {{ended ? (ended | date: 'dd/MM/yyyy') : 'Indef.'}} -
-
- - + +
#{{businessFk}}
+
+ {{started | date: 'dd/MM/yyyy'}} - {{ended ? (ended | date: 'dd/MM/yyyy') : 'Indef.'}} +
+
+ +
@@ -110,3 +111,4 @@ message="This item will be deleted" question="Are you sure you want to continue?"> + diff --git a/modules/worker/front/time-control/index.js b/modules/worker/front/time-control/index.js index 0a955c586..f8a94be52 100644 --- a/modules/worker/front/time-control/index.js +++ b/modules/worker/front/time-control/index.js @@ -111,10 +111,8 @@ class Controller extends Section { dayIndex.setDate(dayIndex.getDate() + 1); } - if (this.worker) { - this.fetchHours(); - this.getWeekData(); - } + this.fetchHours(); + this.getWeekData(); } set weekTotalHours(totalHours) { diff --git a/modules/zone/back/models/zone-closure.js b/modules/zone/back/models/zone-closure.js index d25d6f707..61350ef56 100644 --- a/modules/zone/back/models/zone-closure.js +++ b/modules/zone/back/models/zone-closure.js @@ -14,7 +14,7 @@ module.exports = Self => { async function doCalc(ctx) { try { await Self.rawSql(` - CREATE EVENT zoneClosure_doRecalc + CREATE DEFINER = CURRENT_ROLE EVENT zoneClosure_doRecalc ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 15 SECOND DO CALL zoneClosure_recalc; `);