const models = require('vn-loopback/server/server').models; module.exports = Self => { Object.assign(Self, { linkers: [], addLinker(linker) { this.linkers.push(linker); }, async initEngine() { const accountConfig = await Self.findOne({ fields: ['homedir', 'shell', 'idBase'] }); 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() { const engine = await Self.initEngine(); let usersToSync = new Set(); for (const linker of engine.linkers) await linker.getUsers(usersToSync); 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 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 Self.deinitEngine(engine); await Self.syncRoles(); }, async syncUserBase(engine, userName, password, syncGroups) { if (!userName) return; userName = userName.toLowerCase(); // Skip conflicting users if (['administrator', 'root'].indexOf(userName) >= 0) return; const user = await models.VnUser.findOne({ where: {name: userName}, fields: [ 'id', 'nickname', 'email', 'lang', 'roleFk', 'sync', 'active', 'created', 'password', 'updated' ], include: [ { relation: 'roles', scope: { include: { relation: 'inherits', scope: { fields: ['name'] } } } }, { relation: 'role', fields: ['name'] } ] }); const info = { user, hasAccount: false }; if (user) { const exists = await models.Account.exists(user.id); const {accountConfig} = engine; Object.assign(info, { hasAccount: user.active && exists, corporateMail: `${userName}@${accountConfig.domain}`, uidNumber: accountConfig.idBase + user.id }); } const errs = []; for (const linker of engine.linkers) { try { await linker.syncUser(userName, info, password); if (syncGroups) await linker.syncUserGroups(userName, info); } catch (err) { errs.push(err); } } if (errs.length) throw errs[0]; }, async syncRoles() { const engine = await Self.initEngine(); try { await Self.rawSql(`CALL account.role_sync`); for (const linker of engine.linkers) await linker.syncRoles(); } finally { await Self.deinitEngine(engine); } } }); };