From 26db22bc7ab44be1eb7c9a05492b0b7adbdd70b0 Mon Sep 17 00:00:00 2001 From: pierre-lehnen-rc <55164754+pierre-lehnen-rc@users.noreply.github.com> Date: Fri, 17 Sep 2021 14:36:57 -0300 Subject: [PATCH] [BREAK] LDAP Refactoring (#23171) --- app/2fa/client/TOTPLDAP.js | 2 +- app/api/server/index.js | 1 + app/api/server/v1/ldap.ts | 33 + app/importer-slack/server/importer.js | 3 +- .../server/classes/ImportDataConverter.ts | 210 ++++-- app/importer/server/classes/ImporterBase.js | 2 +- .../server/classes/VirtualDataConverter.ts | 149 ++++ .../definitions/IConversionCallbacks.ts | 11 + app/importer/server/index.js | 2 - app/ldap/client/index.js | 1 - app/ldap/client/loginHelper.js | 34 - app/ldap/server/index.js | 5 - app/ldap/server/ldap.js | 520 -------------- app/ldap/server/loginHandler.js | 184 ----- app/ldap/server/settings.js | 134 ---- app/ldap/server/sync.js | 629 ----------------- app/ldap/server/syncUsers.js | 31 - app/ldap/server/testConnection.js | 43 -- app/models/server/index.js | 2 + .../server/models/ImportData.ts | 6 +- app/models/server/models/Users.js | 6 - app/models/server/raw/ImportData.ts | 18 + app/models/server/raw/Users.js | 18 + app/models/server/raw/index.ts | 3 + app/settings/lib/settings.ts | 20 +- .../server/functions/settings.mocks.ts | 12 +- app/settings/server/functions/settings.ts | 85 ++- .../server/lib/getServicesStatistics.ts | 10 +- app/utils/server/lib/cron/Cronjobs.ts | 13 +- client/contexts/EditableSettingsContext.ts | 21 +- client/contexts/ModalContext.ts | 12 +- client/contexts/ServerContext/endpoints.ts | 2 + .../ServerContext/endpoints/v1/ldap.ts | 14 + client/contexts/SettingsContext.ts | 3 +- client/importPackages.ts | 1 - client/providers/EditableSettingsProvider.tsx | 129 ++-- client/startup/index.ts | 1 + client/startup/ldap.ts | 20 + client/views/account/AccountProfilePage.js | 8 +- client/views/admin/settings/GroupPage.js | 11 +- client/views/admin/settings/GroupSelector.tsx | 9 +- .../views/admin/settings/MemoizedSetting.js | 5 + client/views/admin/settings/Section.js | 13 +- client/views/admin/settings/Setting.js | 2 + .../admin/settings/groups/LDAPGroupPage.tsx | 103 +++ .../admin/settings/groups/TabbedGroupPage.tsx | 66 ++ .../IImportChannel.ts | 0 .../IImportMessage.ts | 0 .../IImportRecord.ts | 12 +- .../definitions => definition}/IImportUser.ts | 4 +- definition/IRoom.ts | 4 + definition/ISetting.ts | 3 + definition/IUser.ts | 12 + definition/ldap-escape.d.ts | 4 + definition/ldap/ILDAPCallback.ts | 12 + definition/ldap/ILDAPEntry.ts | 3 + definition/ldap/ILDAPLoginRequest.ts | 6 + definition/ldap/ILDAPLoginResult.ts | 5 + definition/ldap/ILDAPOptions.ts | 27 + definition/ldap/ILDAPUniqueIdentifierField.ts | 4 + definition/meteor-sha.d.ts | 3 + ee/app/ldap-enterprise/README.md | 22 - .../server/hooks/beforeSearchAll.js | 11 - .../server/hooks/syncExistentUser.js | 19 - ee/app/ldap-enterprise/server/index.js | 69 -- .../ldap-enterprise/server/ldapEnterprise.js | 144 ---- ee/app/ldap-enterprise/server/listener.js | 30 - ee/app/ldap-enterprise/server/settings.js | 112 --- ee/definition/ldap/ILDAPEEOptions.ts | 5 + ee/server/api/index.ts | 1 + ee/server/api/ldap.ts | 31 + ee/server/configuration/ldap.ts | 57 ++ ee/server/index.js | 3 +- ee/server/lib/ldap/Connection.ts | 65 ++ ee/server/lib/ldap/Manager.ts | 501 ++++++++++++++ ee/server/local-services/ldap/service.ts | 16 + ee/server/sdk/index.ts | 4 + ee/server/sdk/types/ILDAPEEService.ts | 3 + package-lock.json | 75 +- package.json | 4 +- packages/rocketchat-i18n/i18n/af.i18n.json | 6 - packages/rocketchat-i18n/i18n/ar.i18n.json | 6 - packages/rocketchat-i18n/i18n/az.i18n.json | 6 - packages/rocketchat-i18n/i18n/be-BY.i18n.json | 6 - packages/rocketchat-i18n/i18n/bg.i18n.json | 6 - packages/rocketchat-i18n/i18n/bs.i18n.json | 6 - packages/rocketchat-i18n/i18n/ca.i18n.json | 55 +- packages/rocketchat-i18n/i18n/cs.i18n.json | 53 +- packages/rocketchat-i18n/i18n/cy.i18n.json | 6 - packages/rocketchat-i18n/i18n/da.i18n.json | 55 +- packages/rocketchat-i18n/i18n/de-AT.i18n.json | 6 - packages/rocketchat-i18n/i18n/de-IN.i18n.json | 6 - packages/rocketchat-i18n/i18n/de.i18n.json | 55 +- packages/rocketchat-i18n/i18n/el.i18n.json | 6 - packages/rocketchat-i18n/i18n/en.i18n.json | 86 ++- packages/rocketchat-i18n/i18n/eo.i18n.json | 6 - packages/rocketchat-i18n/i18n/es.i18n.json | 55 +- packages/rocketchat-i18n/i18n/fa.i18n.json | 9 - packages/rocketchat-i18n/i18n/fi.i18n.json | 6 - packages/rocketchat-i18n/i18n/fr.i18n.json | 55 +- packages/rocketchat-i18n/i18n/he.i18n.json | 6 - packages/rocketchat-i18n/i18n/hr.i18n.json | 6 - packages/rocketchat-i18n/i18n/hu.i18n.json | 13 +- packages/rocketchat-i18n/i18n/id.i18n.json | 6 - packages/rocketchat-i18n/i18n/it.i18n.json | 6 - packages/rocketchat-i18n/i18n/ja.i18n.json | 55 +- packages/rocketchat-i18n/i18n/ka-GE.i18n.json | 55 +- packages/rocketchat-i18n/i18n/km.i18n.json | 15 - packages/rocketchat-i18n/i18n/ko.i18n.json | 55 +- packages/rocketchat-i18n/i18n/ku.i18n.json | 6 - packages/rocketchat-i18n/i18n/lo.i18n.json | 9 - packages/rocketchat-i18n/i18n/lt.i18n.json | 6 - packages/rocketchat-i18n/i18n/lv.i18n.json | 8 - packages/rocketchat-i18n/i18n/mn.i18n.json | 6 - packages/rocketchat-i18n/i18n/ms-MY.i18n.json | 6 - packages/rocketchat-i18n/i18n/nl.i18n.json | 55 +- packages/rocketchat-i18n/i18n/no.i18n.json | 11 - packages/rocketchat-i18n/i18n/pl.i18n.json | 55 +- packages/rocketchat-i18n/i18n/pt-BR.i18n.json | 54 +- packages/rocketchat-i18n/i18n/pt.i18n.json | 6 - packages/rocketchat-i18n/i18n/ro.i18n.json | 6 - packages/rocketchat-i18n/i18n/ru.i18n.json | 55 +- packages/rocketchat-i18n/i18n/sk-SK.i18n.json | 6 - packages/rocketchat-i18n/i18n/sl-SI.i18n.json | 6 - packages/rocketchat-i18n/i18n/sq.i18n.json | 6 - packages/rocketchat-i18n/i18n/sr.i18n.json | 3 - packages/rocketchat-i18n/i18n/sv.i18n.json | 6 - packages/rocketchat-i18n/i18n/ta-IN.i18n.json | 6 - packages/rocketchat-i18n/i18n/th-TH.i18n.json | 6 - packages/rocketchat-i18n/i18n/tr.i18n.json | 8 +- packages/rocketchat-i18n/i18n/ug.i18n.json | 6 - packages/rocketchat-i18n/i18n/uk.i18n.json | 26 +- packages/rocketchat-i18n/i18n/vi-VN.i18n.json | 6 - packages/rocketchat-i18n/i18n/zh-HK.i18n.json | 6 - packages/rocketchat-i18n/i18n/zh-TW.i18n.json | 55 +- packages/rocketchat-i18n/i18n/zh.i18n.json | 55 +- server/configuration/ldap.ts | 46 ++ server/importPackages.js | 1 - server/lib/ldap/Connection.ts | 648 ++++++++++++++++++ server/lib/ldap/DataConverter.ts | 42 ++ server/lib/ldap/Logger.ts | 7 + server/lib/ldap/Manager.ts | 413 +++++++++++ server/lib/ldap/getLDAPConditionalSetting.ts | 8 + server/main.d.ts | 2 + server/main.js | 2 + server/sdk/index.ts | 2 + server/sdk/types/ILDAPService.ts | 6 + server/services/ldap/service.ts | 16 + server/services/startup.ts | 2 + server/settings/index.ts | 1 + server/settings/ldap.ts | 376 ++++++++++ server/startup/migrations/index.js | 1 + server/startup/migrations/v237.ts | 110 +++ 153 files changed, 3732 insertions(+), 3025 deletions(-) create mode 100644 app/api/server/v1/ldap.ts create mode 100644 app/importer/server/classes/VirtualDataConverter.ts create mode 100644 app/importer/server/definitions/IConversionCallbacks.ts delete mode 100644 app/ldap/client/index.js delete mode 100644 app/ldap/client/loginHelper.js delete mode 100644 app/ldap/server/index.js delete mode 100644 app/ldap/server/ldap.js delete mode 100644 app/ldap/server/loginHandler.js delete mode 100644 app/ldap/server/settings.js delete mode 100644 app/ldap/server/sync.js delete mode 100644 app/ldap/server/syncUsers.js delete mode 100644 app/ldap/server/testConnection.js rename app/{importer => models}/server/models/ImportData.ts (88%) create mode 100644 app/models/server/raw/ImportData.ts create mode 100644 client/contexts/ServerContext/endpoints/v1/ldap.ts create mode 100644 client/startup/ldap.ts create mode 100644 client/views/admin/settings/groups/LDAPGroupPage.tsx create mode 100644 client/views/admin/settings/groups/TabbedGroupPage.tsx rename {app/importer/server/definitions => definition}/IImportChannel.ts (100%) rename {app/importer/server/definitions => definition}/IImportMessage.ts (100%) rename {app/importer/server/definitions => definition}/IImportRecord.ts (70%) rename {app/importer/server/definitions => definition}/IImportUser.ts (80%) create mode 100644 definition/ldap-escape.d.ts create mode 100644 definition/ldap/ILDAPCallback.ts create mode 100644 definition/ldap/ILDAPEntry.ts create mode 100644 definition/ldap/ILDAPLoginRequest.ts create mode 100644 definition/ldap/ILDAPLoginResult.ts create mode 100644 definition/ldap/ILDAPOptions.ts create mode 100644 definition/ldap/ILDAPUniqueIdentifierField.ts create mode 100644 definition/meteor-sha.d.ts delete mode 100644 ee/app/ldap-enterprise/README.md delete mode 100644 ee/app/ldap-enterprise/server/hooks/beforeSearchAll.js delete mode 100644 ee/app/ldap-enterprise/server/hooks/syncExistentUser.js delete mode 100644 ee/app/ldap-enterprise/server/index.js delete mode 100644 ee/app/ldap-enterprise/server/ldapEnterprise.js delete mode 100644 ee/app/ldap-enterprise/server/listener.js delete mode 100644 ee/app/ldap-enterprise/server/settings.js create mode 100644 ee/definition/ldap/ILDAPEEOptions.ts create mode 100644 ee/server/api/ldap.ts create mode 100644 ee/server/configuration/ldap.ts create mode 100644 ee/server/lib/ldap/Connection.ts create mode 100644 ee/server/lib/ldap/Manager.ts create mode 100644 ee/server/local-services/ldap/service.ts create mode 100644 ee/server/sdk/index.ts create mode 100644 ee/server/sdk/types/ILDAPEEService.ts create mode 100644 server/configuration/ldap.ts create mode 100644 server/lib/ldap/Connection.ts create mode 100644 server/lib/ldap/DataConverter.ts create mode 100644 server/lib/ldap/Logger.ts create mode 100644 server/lib/ldap/Manager.ts create mode 100644 server/lib/ldap/getLDAPConditionalSetting.ts create mode 100644 server/sdk/types/ILDAPService.ts create mode 100644 server/services/ldap/service.ts create mode 100644 server/settings/index.ts create mode 100644 server/settings/ldap.ts create mode 100644 server/startup/migrations/v237.ts diff --git a/app/2fa/client/TOTPLDAP.js b/app/2fa/client/TOTPLDAP.js index 0d74719f7cf8..1983584b1e52 100644 --- a/app/2fa/client/TOTPLDAP.js +++ b/app/2fa/client/TOTPLDAP.js @@ -2,7 +2,7 @@ import { Meteor } from 'meteor/meteor'; import { Accounts } from 'meteor/accounts-base'; import { Utils2fa } from './lib/2fa'; -import '../../ldap/client/loginHelper'; +import '../../../client/startup/ldap'; Meteor.loginWithLDAPAndTOTP = function(...args) { // Pull username and password diff --git a/app/api/server/index.js b/app/api/server/index.js index b5a5c0d6f1dc..3c4be4dfaf66 100644 --- a/app/api/server/index.js +++ b/app/api/server/index.js @@ -23,6 +23,7 @@ import './v1/im'; import './v1/integrations'; import './v1/invites'; import './v1/import'; +import './v1/ldap'; import './v1/misc'; import './v1/permissions'; import './v1/push'; diff --git a/app/api/server/v1/ldap.ts b/app/api/server/v1/ldap.ts new file mode 100644 index 000000000000..c8cc10701e4d --- /dev/null +++ b/app/api/server/v1/ldap.ts @@ -0,0 +1,33 @@ +import { hasRole } from '../../../authorization/server'; +import { settings } from '../../../settings/server'; +import { API } from '../api'; +import { SystemLogger } from '../../../../server/lib/logger/system'; +import { LDAP } from '../../../../server/sdk'; + + +API.v1.addRoute('ldap.testConnection', { authRequired: true }, { + post() { + if (!this.userId) { + throw new Error('error-invalid-user'); + } + + if (!hasRole(this.userId, 'admin')) { + throw new Error('error-not-authorized'); + } + + if (settings.get('LDAP_Enable') !== true) { + throw new Error('LDAP_disabled'); + } + + try { + Promise.await(LDAP.testConnection()); + } catch (error) { + SystemLogger.error(error); + throw new Error('Connection_failed'); + } + + return API.v1.success({ + message: 'Connection_success', + }); + }, +}); diff --git a/app/importer-slack/server/importer.js b/app/importer-slack/server/importer.js index c913c77cbb1d..8c490192ac5d 100644 --- a/app/importer-slack/server/importer.js +++ b/app/importer-slack/server/importer.js @@ -3,10 +3,9 @@ import _ from 'underscore'; import { Base, ProgressStep, - ImportData, ImporterWebsocket, } from '../../importer/server'; -import { Messages } from '../../models'; +import { Messages, ImportData } from '../../models/server'; import { settings } from '../../settings/server'; import { MentionsParser } from '../../mentions/lib/MentionsParser'; import { getUserAvatarURL } from '../../utils/lib/getUserAvatarURL'; diff --git a/app/importer/server/classes/ImportDataConverter.ts b/app/importer/server/classes/ImportDataConverter.ts index 3729c2f62ab6..c1adb2323cc6 100644 --- a/app/importer/server/classes/ImportDataConverter.ts +++ b/app/importer/server/classes/ImportDataConverter.ts @@ -2,18 +2,17 @@ import { Meteor } from 'meteor/meteor'; import { Accounts } from 'meteor/accounts-base'; import _ from 'underscore'; -import { ImportData } from '../models/ImportData'; -import { IImportUser } from '../definitions/IImportUser'; -import { IImportMessage, IImportMessageReaction } from '../definitions/IImportMessage'; -import { IImportChannel } from '../definitions/IImportChannel'; -import { IImportUserRecord, IImportChannelRecord, IImportMessageRecord } from '../definitions/IImportRecord'; -import { Users, Rooms, Subscriptions } from '../../../models/server'; +import { ImportData as ImportDataRaw } from '../../../models/server/raw'; +import { IImportUser } from '../../../../definition/IImportUser'; +import { IImportMessage, IImportMessageReaction } from '../../../../definition/IImportMessage'; +import { IImportChannel } from '../../../../definition/IImportChannel'; +import { IConversionCallbacks } from '../definitions/IConversionCallbacks'; +import { IImportUserRecord, IImportChannelRecord, IImportMessageRecord } from '../../../../definition/IImportRecord'; +import { Users, Rooms, Subscriptions, ImportData } from '../../../models/server'; import { generateUsernameSuggestion, insertMessage } from '../../../lib/server'; import { setUserActiveStatus } from '../../../lib/server/functions/setUserActiveStatus'; import { IUser } from '../../../../definition/IUser'; - -// @ts-ignore //@ToDo: Add the Logger class definitions. -type FakeLogger = Logger; +import type { Logger } from '../../../../server/lib/logger/Logger'; type IRoom = Record; type IMessage = Record; @@ -38,14 +37,9 @@ type IMessageReaction = { type IMessageReactions = Record; -interface IConversionCallbacks { - beforeImportFn?: { - (data: IImportUser | IImportChannel | IImportMessage, type: string): boolean; - }; - afterImportFn?: { - (data: IImportUser | IImportChannel | IImportMessage, type: string): void; - }; -} +export type IConverterOptions = { + flagEmailsAsVerified?: boolean; +}; const guessNameFromUsername = (username: string): string => username @@ -64,16 +58,25 @@ export class ImportDataConverter { private _roomNameCache: Map; - private _logger: FakeLogger; + private _logger: Logger; + + private _options: IConverterOptions; + + public get options(): IConverterOptions { + return this._options; + } - constructor() { + constructor(options?: IConverterOptions) { + this._options = options || { + flagEmailsAsVerified: false, + }; this._userCache = new Map(); this._userDisplayNameCache = new Map(); this._roomCache = new Map(); this._roomNameCache = new Map(); } - setLogger(logger: FakeLogger): void { + setLogger(logger: Logger): void { this._logger = logger; } @@ -113,7 +116,7 @@ export class ImportDataConverter { this.addUserToCache(userData.importIds[0], userData._id, userData.username); } - addObject(type: string, data: Record, options: Record = {}): void { + protected addObject(type: string, data: Record, options: Record = {}): void { ImportData.model.rawCollection().insert({ data, dataType: type, @@ -135,17 +138,7 @@ export class ImportDataConverter { }); } - updateUserId(_id: string, userData: IImportUser): void { - const updateData: Record = { - $set: { - statusText: userData.statusText || undefined, - roles: userData.roles || ['user'], - type: userData.type || 'user', - bio: userData.bio || undefined, - name: userData.name || undefined, - }, - }; - + addUserImportId(updateData: Record, userData: IImportUser): void { if (userData.importIds?.length) { updateData.$addToSet = { importIds: { @@ -153,7 +146,79 @@ export class ImportDataConverter { }, }; } + } + + addUserServices(updateData: Record, userData: IImportUser): void { + if (!userData.services) { + return; + } + + for (const serviceKey in userData.services) { + if (!userData.services[serviceKey]) { + continue; + } + + const service = userData.services[serviceKey]; + + for (const key in service) { + if (!service[key]) { + continue; + } + + updateData.$set[`services.${ serviceKey }.${ key }`] = service[key]; + } + } + } + + flagEmailsAsVerified(updateData: Record, userData: IImportUser): void { + if (!this.options.flagEmailsAsVerified || !userData.emails.length) { + return; + } + + updateData.$set['emails.$[].verified'] = true; + } + + addCustomFields(updateData: Record, userData: IImportUser): void { + if (!userData.customFields) { + return; + } + + const subset = (source: Record, currentPath: string): void => { + for (const key in source) { + if (!source.hasOwnProperty(key)) { + continue; + } + + const keyPath = `${ currentPath }.${ key }`; + if (typeof source[key] === 'object' && !Array.isArray(source[key])) { + subset(source[key], keyPath); + continue; + } + updateData.$set[keyPath] = source[key]; + } + }; + + subset(userData.customFields, 'customFields'); + } + + updateUserId(_id: string, userData: IImportUser): void { + // #ToDo: #TODO: Move this to the model class + const updateData: Record = { + $set: { + roles: userData.roles || ['user'], + type: userData.type || 'user', + ...userData.statusText && { statusText: userData.statusText }, + ...userData.bio && { bio: userData.bio }, + ...userData.name && { name: userData.name }, + ...userData.services?.ldap && { ldap: true }, + }, + }; + + this.addCustomFields(updateData, userData); + this.addUserServices(updateData, userData); + this.addUserImportId(updateData, userData); + this.flagEmailsAsVerified(updateData, userData); Users.update({ _id }, updateData); } @@ -220,9 +285,28 @@ export class ImportDataConverter { return user; } - convertUsers({ beforeImportFn, afterImportFn }: IConversionCallbacks = {}): void { - const users = ImportData.find({ dataType: 'user' }); - users.forEach(({ data, _id }: IImportUserRecord) => { + protected async getUsersToImport(): Promise> { + return ImportDataRaw.getAllUsers().toArray(); + } + + findExistingUser(data: IImportUser): IUser | undefined { + if (data.emails.length) { + const emailUser = Users.findOneByEmailAddress(data.emails[0], {}); + + if (emailUser) { + return emailUser; + } + } + + // If we couldn't find one by their email address, try to find an existing user by their username + if (data.username) { + return Users.findOneByUsernameIgnoringCase(data.username, {}); + } + } + + public convertUsers({ beforeImportFn, afterImportFn }: IConversionCallbacks = {}): void { + const users = Promise.await(this.getUsersToImport()); + users.forEach(({ data, _id }) => { try { if (beforeImportFn && !beforeImportFn(data, 'user')) { this.skipRecord(_id); @@ -236,23 +320,16 @@ export class ImportDataConverter { throw new Error('importer-user-missing-email-and-username'); } - let existingUser; - if (data.emails.length) { - existingUser = Users.findOneByEmailAddress(data.emails[0], {}); - } - - if (data.username) { - // If we couldn't find one by their email address, try to find an existing user by their username - if (!existingUser) { - existingUser = Users.findOneByUsernameIgnoringCase(data.username, {}); - } - } else { + let existingUser = this.findExistingUser(data); + if (!data.username) { data.username = generateUsernameSuggestion({ name: data.name, emails: data.emails, }); } + const isNewUser = !existingUser; + if (existingUser) { this.updateUser(existingUser, data); } else { @@ -266,28 +343,21 @@ export class ImportDataConverter { // Deleted users are 'inactive' users in Rocket.Chat if (data.deleted && existingUser?.active) { setUserActiveStatus(data._id, false, true); + } else if (data.deleted === false && existingUser?.active === false) { + setUserActiveStatus(data._id, true); } if (afterImportFn) { - afterImportFn(data, 'user'); + afterImportFn(data, 'user', isNewUser); } } catch (e) { + this._logger.error(e); this.saveError(_id, e); } }); } - saveNewId(importId: string, newId: string): void { - ImportData.update({ - _id: importId, - }, { - $set: { - id: newId, - }, - }); - } - - saveError(importId: string, error: Error): void { + protected saveError(importId: string, error: Error): void { this._logger.error(error); ImportData.update({ _id: importId, @@ -301,7 +371,7 @@ export class ImportDataConverter { }); } - skipRecord(_id: string): void { + protected skipRecord(_id: string): void { ImportData.update({ _id, }, { @@ -424,9 +494,13 @@ export class ImportDataConverter { return result; } + protected async getMessagesToImport(): Promise> { + return ImportDataRaw.getAllMessages().toArray(); + } + convertMessages({ beforeImportFn, afterImportFn }: IConversionCallbacks = {}): void { const rids: Array = []; - const messages = ImportData.find({ dataType: 'message' }); + const messages = Promise.await(this.getMessagesToImport()); messages.forEach(({ data: m, _id }: IImportMessageRecord) => { try { if (beforeImportFn && !beforeImportFn(m, 'message')) { @@ -498,7 +572,7 @@ export class ImportDataConverter { } if (afterImportFn) { - afterImportFn(m, 'message'); + afterImportFn(m, 'message', true); } } catch (e) { this.saveError(_id, e); @@ -528,7 +602,7 @@ export class ImportDataConverter { this.updateRoomId(room._id, roomData); } - findDMForImportedUsers(...users: Array): IImportChannel | undefined { + public findDMForImportedUsers(...users: Array): IImportChannel | undefined { const record = ImportData.findDMForImportedUsers(...users); if (record) { return record.data; @@ -709,7 +783,7 @@ export class ImportDataConverter { roomData._id = roomInfo.rid; }); } catch (e) { - this._logger.warn(roomData.name, members); + this._logger.warn({ msg: 'Failed to create new room', name: roomData.name, members }); this._logger.error(e); throw e; } @@ -768,8 +842,12 @@ export class ImportDataConverter { return Rooms.findOneByNonValidatedName(data.name, {}); } + protected async getChannelsToImport(): Promise> { + return ImportDataRaw.getAllChannels().toArray(); + } + convertChannels(startedByUserId: string, { beforeImportFn, afterImportFn }: IConversionCallbacks = {}): void { - const channels = ImportData.find({ dataType: 'channel' }); + const channels = Promise.await(this.getChannelsToImport()); channels.forEach(({ data: c, _id }: IImportChannelRecord) => { try { if (beforeImportFn && !beforeImportFn(c, 'channel')) { @@ -801,7 +879,7 @@ export class ImportDataConverter { } if (afterImportFn) { - afterImportFn(c, 'channel'); + afterImportFn(c, 'channel', !existingRoom); } } catch (e) { this.saveError(_id, e); @@ -824,7 +902,7 @@ export class ImportDataConverter { }); } - clearImportData(): void { + public clearImportData(): void { // Using raw collection since its faster Promise.await(ImportData.model.rawCollection().remove({})); } diff --git a/app/importer/server/classes/ImporterBase.js b/app/importer/server/classes/ImporterBase.js index 75120f6965b9..29767fdafead 100644 --- a/app/importer/server/classes/ImporterBase.js +++ b/app/importer/server/classes/ImporterBase.js @@ -14,7 +14,7 @@ import { RawImports } from '../models/RawImports'; import { Settings, Imports } from '../../../models'; import { Logger } from '../../../logger'; import { ImportDataConverter } from './ImportDataConverter'; -import { ImportData } from '../models/ImportData'; +import { ImportData } from '../../../models/server'; import { t } from '../../../utils/server'; import { Selection, diff --git a/app/importer/server/classes/VirtualDataConverter.ts b/app/importer/server/classes/VirtualDataConverter.ts new file mode 100644 index 000000000000..5baf334e394b --- /dev/null +++ b/app/importer/server/classes/VirtualDataConverter.ts @@ -0,0 +1,149 @@ +import { Random } from 'meteor/random'; + +import type { IImportUserRecord, IImportChannelRecord, IImportMessageRecord, IImportRecord, IImportRecordType, IImportData } from '../../../../definition/IImportRecord'; +import { IImportChannel } from '../../../../definition/IImportChannel'; +import { ImportDataConverter } from './ImportDataConverter'; +import type { IConverterOptions } from './ImportDataConverter'; + +export class VirtualDataConverter extends ImportDataConverter { + protected _userRecords: Array; + + protected _channelRecords: Array; + + protected _messageRecords: Array; + + protected useVirtual: boolean; + + constructor(virtual = true, options?: IConverterOptions) { + super(options); + + this.useVirtual = virtual; + if (virtual) { + this.clearVirtualData(); + } + } + + public clearImportData(): void { + if (!this.useVirtual) { + return super.clearImportData(); + } + + this.clearVirtualData(); + } + + public clearSuccessfullyImportedData(): void { + if (!this.useVirtual) { + return super.clearSuccessfullyImportedData(); + } + + this.clearVirtualData(); + } + + public findDMForImportedUsers(...users: Array): IImportChannel | undefined { + if (!this.useVirtual) { + return super.findDMForImportedUsers(...users); + } + + // The original method is only used by the hipchat importer so we probably don't need to implement this on the virtual converter. + return undefined; + } + + protected addObject(type: IImportRecordType, data: IImportData, options: Record = {}): void { + if (!this.useVirtual) { + return super.addObject(type, data, options); + } + + const list = this.getObjectList(type); + + list.push({ + _id: Random.id(), + data, + dataType: type, + ...options, + }); + } + + protected async getUsersToImport(): Promise> { + if (!this.useVirtual) { + return super.getUsersToImport(); + } + + return this._userRecords; + } + + protected saveError(importId: string, error: Error): void { + if (!this.useVirtual) { + return super.saveError(importId, error); + } + + const record = this.getVirtualRecordById(importId); + + if (!record) { + return; + } + + if (!record.errors) { + record.errors = []; + } + + record.errors.push({ + message: error.message, + stack: error.stack, + }); + } + + protected skipRecord(_id: string): void { + if (!this.useVirtual) { + return super.skipRecord(_id); + } + + const record = this.getVirtualRecordById(_id); + + if (record) { + record.skipped = true; + } + } + + protected async getMessagesToImport(): Promise { + if (!this.useVirtual) { + return super.getMessagesToImport(); + } + + return this._messageRecords; + } + + protected async getChannelsToImport(): Promise { + if (!this.useVirtual) { + return super.getChannelsToImport(); + } + + return this._channelRecords; + } + + private clearVirtualData(): void { + this._userRecords = []; + this._channelRecords = []; + this._messageRecords = []; + } + + private getObjectList(type: IImportRecordType): Array { + switch (type) { + case 'user': + return this._userRecords; + case 'channel': + return this._channelRecords; + case 'message': + return this._messageRecords; + } + } + + private getVirtualRecordById(id: string): IImportRecord | undefined { + for (const store of [this._userRecords, this._channelRecords, this._messageRecords]) { + for (const record of store) { + if (record._id === id) { + return record; + } + } + } + } +} diff --git a/app/importer/server/definitions/IConversionCallbacks.ts b/app/importer/server/definitions/IConversionCallbacks.ts new file mode 100644 index 000000000000..80df62fc6f9e --- /dev/null +++ b/app/importer/server/definitions/IConversionCallbacks.ts @@ -0,0 +1,11 @@ +import { IImportUser } from '../../../../definition/IImportUser'; +import { IImportMessage } from '../../../../definition/IImportMessage'; +import { IImportChannel } from '../../../../definition/IImportChannel'; + +export type ImporterBeforeImportCallback = {(data: IImportUser | IImportChannel | IImportMessage, type: string): boolean} +export type ImporterAfterImportCallback = {(data: IImportUser | IImportChannel | IImportMessage, type: string, isNewRecord: boolean): void}; + +export interface IConversionCallbacks { + beforeImportFn?: ImporterBeforeImportCallback; + afterImportFn?: ImporterAfterImportCallback; +} diff --git a/app/importer/server/index.js b/app/importer/server/index.js index dd9e89ba0209..0fed91e5b660 100644 --- a/app/importer/server/index.js +++ b/app/importer/server/index.js @@ -2,7 +2,6 @@ import { Base } from './classes/ImporterBase'; import { ImporterWebsocket } from './classes/ImporterWebsocket'; import { Progress } from './classes/ImporterProgress'; import { RawImports } from './models/RawImports'; -import { ImportData } from './models/ImportData'; import { Selection } from './classes/ImporterSelection'; import { SelectionChannel } from './classes/ImporterSelectionChannel'; import { SelectionUser } from './classes/ImporterSelectionUser'; @@ -26,7 +25,6 @@ export { Progress, ProgressStep, RawImports, - ImportData, Selection, SelectionChannel, SelectionUser, diff --git a/app/ldap/client/index.js b/app/ldap/client/index.js deleted file mode 100644 index fecf898e1ae4..000000000000 --- a/app/ldap/client/index.js +++ /dev/null @@ -1 +0,0 @@ -import './loginHelper'; diff --git a/app/ldap/client/loginHelper.js b/app/ldap/client/loginHelper.js deleted file mode 100644 index b2d6cf5d71ff..000000000000 --- a/app/ldap/client/loginHelper.js +++ /dev/null @@ -1,34 +0,0 @@ -// Pass in username, password as normal -// customLdapOptions should be passed in if you want to override LDAP_DEFAULTS -// on any particular call (if you have multiple ldap servers you'd like to connect to) -// You'll likely want to set the dn value here {dn: "..."} -import { Meteor } from 'meteor/meteor'; -import { Accounts } from 'meteor/accounts-base'; - -Meteor.loginWithLDAP = function(...args) { - // Pull username and password - const username = args.shift(); - const password = args.shift(); - - // Check if last argument is a function - // if it is, pop it off and set callback to it - const callback = typeof args[args.length - 1] === 'function' ? args.pop() : null; - - // if args still holds options item, grab it - const customLdapOptions = args.length > 0 ? args.shift() : {}; - - // Set up loginRequest object - const loginRequest = { - ldap: true, - username, - ldapPass: password, - ldapOptions: customLdapOptions, - }; - - Accounts.callLoginMethod({ - // Call login method with ldap = true - // This will hook into our login handler for ldap - methodArguments: [loginRequest], - userCallback: callback, - }); -}; diff --git a/app/ldap/server/index.js b/app/ldap/server/index.js deleted file mode 100644 index acdd21c00c48..000000000000 --- a/app/ldap/server/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import './loginHandler'; -import './settings'; -import './testConnection'; -import './syncUsers'; -import './sync'; diff --git a/app/ldap/server/ldap.js b/app/ldap/server/ldap.js deleted file mode 100644 index a3bae173b835..000000000000 --- a/app/ldap/server/ldap.js +++ /dev/null @@ -1,520 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import ldapjs from 'ldapjs'; -import Bunyan from 'bunyan'; - -import { callbacks } from '../../callbacks/server'; -import { settings } from '../../settings'; -import { Logger } from '../../logger'; - -const logger = new Logger('LDAP'); - -export const connLogger = logger.section('Connection'); -export const bindLogger = logger.section('Bind'); -export const searchLogger = logger.section('Search'); -export const authLogger = logger.section('Auth'); - -export default class LDAP { - constructor() { - this.ldapjs = ldapjs; - - this.connected = false; - - this.options = { - host: settings.get('LDAP_Host'), - port: settings.get('LDAP_Port'), - Reconnect: settings.get('LDAP_Reconnect'), - Internal_Log_Level: settings.get('LDAP_Internal_Log_Level'), - timeout: settings.get('LDAP_Timeout'), - connect_timeout: settings.get('LDAP_Connect_Timeout'), - idle_timeout: settings.get('LDAP_Idle_Timeout'), - encryption: settings.get('LDAP_Encryption'), - ca_cert: settings.get('LDAP_CA_Cert'), - reject_unauthorized: settings.get('LDAP_Reject_Unauthorized') || false, - Authentication: settings.get('LDAP_Authentication'), - Authentication_UserDN: settings.get('LDAP_Authentication_UserDN'), - Authentication_Password: settings.get('LDAP_Authentication_Password'), - BaseDN: settings.get('LDAP_BaseDN'), - User_Search_Filter: settings.get('LDAP_User_Search_Filter'), - User_Search_Scope: settings.get('LDAP_User_Search_Scope'), - User_Search_Field: settings.get('LDAP_User_Search_Field'), - Search_Page_Size: settings.get('LDAP_Search_Page_Size'), - Search_Size_Limit: settings.get('LDAP_Search_Size_Limit'), - group_filter_enabled: settings.get('LDAP_Group_Filter_Enable'), - group_filter_object_class: settings.get('LDAP_Group_Filter_ObjectClass'), - group_filter_group_id_attribute: settings.get('LDAP_Group_Filter_Group_Id_Attribute'), - group_filter_group_member_attribute: settings.get('LDAP_Group_Filter_Group_Member_Attribute'), - group_filter_group_member_format: settings.get('LDAP_Group_Filter_Group_Member_Format'), - group_filter_group_name: settings.get('LDAP_Group_Filter_Group_Name'), - find_user_after_login: settings.get('LDAP_Find_User_After_Login'), - }; - } - - connectSync(...args) { - if (!this._connectSync) { - this._connectSync = Meteor.wrapAsync(this.connectAsync, this); - } - return this._connectSync(...args); - } - - searchAllSync(...args) { - if (!this._searchAllSync) { - this._searchAllSync = Meteor.wrapAsync(this.searchAllAsync, this); - } - return this._searchAllSync(...args); - } - - connectAsync(callback) { - connLogger.info('Init setup'); - - let replied = false; - - const connectionOptions = { - url: `${ this.options.host }:${ this.options.port }`, - timeout: this.options.timeout, - connectTimeout: this.options.connect_timeout, - idleTimeout: this.options.idle_timeout, - reconnect: this.options.Reconnect, - }; - - if (this.options.Internal_Log_Level !== 'disabled') { - connectionOptions.log = new Bunyan({ - name: 'ldapjs', - component: 'client', - stream: process.stderr, - level: this.options.Internal_Log_Level, - }); - } - - const tlsOptions = { - rejectUnauthorized: this.options.reject_unauthorized, - }; - - if (this.options.ca_cert && this.options.ca_cert !== '') { - // Split CA cert into array of strings - const chainLines = settings.get('LDAP_CA_Cert').split('\n'); - let cert = []; - const ca = []; - chainLines.forEach((line) => { - cert.push(line); - if (line.match(/-END CERTIFICATE-/)) { - ca.push(cert.join('\n')); - cert = []; - } - }); - tlsOptions.ca = ca; - } - - if (this.options.encryption === 'ssl') { - connectionOptions.url = `ldaps://${ connectionOptions.url }`; - connectionOptions.tlsOptions = tlsOptions; - } else { - connectionOptions.url = `ldap://${ connectionOptions.url }`; - } - - connLogger.info({ msg: 'Connecting', url: connectionOptions.url }); - connLogger.debug({ msg: 'connectionOptions', connectionOptions }); - - this.client = ldapjs.createClient(connectionOptions); - - this.bindSync = Meteor.wrapAsync(this.client.bind, this.client); - - this.client.on('error', (error) => { - connLogger.error({ msg: 'connection', err: error }); - if (replied === false) { - replied = true; - callback(error, null); - } - }); - - this.client.on('idle', () => { - searchLogger.info('Idle'); - this.disconnect(); - }); - - this.client.on('close', () => { - searchLogger.info('Closed'); - }); - - if (this.options.encryption === 'tls') { - // Set host parameter for tls.connect which is used by ldapjs starttls. This shouldn't be needed in newer nodejs versions (e.g v5.6.0). - // https://github.com/RocketChat/Rocket.Chat/issues/2035 - // https://github.com/mcavage/node-ldapjs/issues/349 - tlsOptions.host = this.options.host; - - connLogger.info('Starting TLS'); - connLogger.debug({ tlsOptions }); - - this.client.starttls(tlsOptions, null, (error, response) => { - if (error) { - connLogger.error({ msg: 'TLS connection', err: error }); - if (replied === false) { - replied = true; - callback(error, null); - } - return; - } - - connLogger.info('TLS connected'); - this.connected = true; - if (replied === false) { - replied = true; - callback(null, response); - } - }); - } else { - this.client.on('connect', (response) => { - connLogger.info('LDAP connected'); - this.connected = true; - if (replied === false) { - replied = true; - callback(null, response); - } - }); - } - - setTimeout(() => { - if (replied === false) { - connLogger.error({ msg: 'connection time out', connectTimeout: connectionOptions.connectTimeout }); - replied = true; - callback(new Error('Timeout')); - } - }, connectionOptions.connectTimeout); - } - - getUserFilter(username) { - const filter = []; - - if (this.options.User_Search_Filter !== '') { - if (this.options.User_Search_Filter[0] === '(') { - filter.push(`${ this.options.User_Search_Filter }`); - } else { - filter.push(`(${ this.options.User_Search_Filter })`); - } - } - - const usernameFilter = this.options.User_Search_Field.split(',').map((item) => `(${ item }=${ username })`); - - if (usernameFilter.length === 0) { - logger.error('LDAP_LDAP_User_Search_Field not defined'); - } else if (usernameFilter.length === 1) { - filter.push(`${ usernameFilter[0] }`); - } else { - filter.push(`(|${ usernameFilter.join('') })`); - } - - return `(&${ filter.join('') })`; - } - - bindIfNecessary() { - if (this.domainBinded === true) { - return; - } - - if (this.options.Authentication !== true) { - return; - } - - bindLogger.info({ msg: 'Binding UserDN', userDN: this.options.Authentication_UserDN }); - this.bindSync(this.options.Authentication_UserDN, this.options.Authentication_Password); - this.domainBinded = true; - } - - searchUsersSync(username, page) { - this.bindIfNecessary(); - - const searchOptions = { - filter: this.getUserFilter(username), - scope: this.options.User_Search_Scope || 'sub', - sizeLimit: this.options.Search_Size_Limit, - }; - - if (this.options.Search_Page_Size > 0) { - searchOptions.paged = { - pageSize: this.options.Search_Page_Size, - pagePause: !!page, - }; - } - - searchLogger.info({ msg: 'Searching user', username }); - searchLogger.debug({ searchOptions, BaseDN: this.options.BaseDN }); - - if (page) { - return this.searchAllPaged(this.options.BaseDN, searchOptions, page); - } - - return this.searchAllSync(this.options.BaseDN, searchOptions); - } - - getUserByIdSync(id, attribute) { - this.bindIfNecessary(); - - const Unique_Identifier_Field = settings.get('LDAP_Unique_Identifier_Field').split(','); - - let filter; - - if (attribute) { - filter = new this.ldapjs.filters.EqualityFilter({ - attribute, - value: Buffer.from(id, 'hex'), - }); - } else { - const filters = []; - Unique_Identifier_Field.forEach((item) => { - filters.push(new this.ldapjs.filters.EqualityFilter({ - attribute: item, - value: Buffer.from(id, 'hex'), - })); - }); - - filter = new this.ldapjs.filters.OrFilter({ filters }); - } - - const searchOptions = { - filter, - scope: 'sub', - attributes: ['*', '+'], - }; - - searchLogger.info({ msg: 'Searching by id', id }); - searchLogger.debug({ msg: 'search filter', filter: searchOptions.filter, BaseDN: this.options.BaseDN }); - - const result = this.searchAllSync(this.options.BaseDN, searchOptions); - - if (!Array.isArray(result) || result.length === 0) { - return; - } - - if (result.length > 1) { - searchLogger.error(`Search by id ${ id } returned ${ result.length } records`); - } - - return result[0]; - } - - getUserByUsernameSync(username) { - this.bindIfNecessary(); - - const searchOptions = { - filter: this.getUserFilter(username), - scope: this.options.User_Search_Scope || 'sub', - }; - - searchLogger.info({ msg: 'Searching user', username }); - searchLogger.debug({ searchOptions, BaseDN: this.options.BaseDN }); - - const result = this.searchAllSync(this.options.BaseDN, searchOptions); - - if (!Array.isArray(result) || result.length === 0) { - return; - } - - if (result.length > 1) { - searchLogger.error(`Search by username ${ username } returned ${ result.length } records`); - } - - return result[0]; - } - - isUserInGroup(username, userdn) { - if (!this.options.group_filter_enabled) { - return true; - } - - const filter = ['(&']; - - if (this.options.group_filter_object_class !== '') { - filter.push(`(objectclass=${ this.options.group_filter_object_class })`); - } - - if (this.options.group_filter_group_member_attribute !== '') { - filter.push(`(${ this.options.group_filter_group_member_attribute }=${ this.options.group_filter_group_member_format })`); - } - - if (this.options.group_filter_group_id_attribute !== '') { - filter.push(`(${ this.options.group_filter_group_id_attribute }=${ this.options.group_filter_group_name })`); - } - filter.push(')'); - - const searchOptions = { - filter: filter.join('').replace(/#{username}/g, username).replace(/#{userdn}/g, userdn), - scope: 'sub', - }; - - searchLogger.debug({ msg: 'Group filter LDAP:', filter: searchOptions.filter }); - - const result = this.searchAllSync(this.options.BaseDN, searchOptions); - - if (!Array.isArray(result) || result.length === 0) { - return false; - } - return true; - } - - extractLdapEntryData(entry) { - const values = { - _raw: entry.raw, - }; - - Object.keys(values._raw).forEach((key) => { - const value = values._raw[key]; - - if (!['thumbnailPhoto', 'jpegPhoto'].includes(key)) { - if (value instanceof Buffer) { - values[key] = value.toString(); - } else { - values[key] = value; - } - } - - if (key === 'ou' && Array.isArray(value)) { - value.forEach((item, index) => { - if (item instanceof Buffer) { - value[index] = item.toString(); - } - }); - } - }); - - return values; - } - - searchAllPaged(BaseDN, options, page) { - this.bindIfNecessary(); - - ({ BaseDN, options } = callbacks.run('ldap.beforeSearchAll', { BaseDN, options })); - - const processPage = ({ entries, title, end, next }) => { - searchLogger.info(title); - // Force LDAP idle to wait the record processing - this.client._updateIdle(true); - page(null, entries, { end, - next: () => { - // Reset idle timer - this.client._updateIdle(); - next && next(); - } }); - }; - - this.client.search(BaseDN, options, (error, res) => { - if (error) { - searchLogger.error(error); - page(error); - return; - } - - res.on('error', (error) => { - searchLogger.error(error); - page(error); - }); - - let entries = []; - - const internalPageSize = options.paged && options.paged.pageSize > 0 ? options.paged.pageSize * 2 : 500; - - res.on('searchEntry', (entry) => { - entries.push(this.extractLdapEntryData(entry)); - - if (entries.length >= internalPageSize) { - processPage({ - entries, - title: 'Internal Page', - end: false, - }); - entries = []; - } - }); - - res.on('page', (result, next) => { - if (!next) { - this.client._updateIdle(true); - processPage({ - entries, - title: 'Final Page', - end: true, - }); - entries = []; - } else if (entries.length) { - processPage({ - entries, - title: 'Page', - end: false, - next, - }); - entries = []; - } - }); - - res.on('end', () => { - if (entries.length) { - processPage({ - entries, - title: 'Final Page', - end: true, - }); - entries = []; - } - }); - }); - } - - searchAllAsync(BaseDN, options, callback) { - this.bindIfNecessary(); - - ({ BaseDN, options } = callbacks.run('ldap.beforeSearchAll', { BaseDN, options })); - - this.client.search(BaseDN, options, (error, res) => { - if (error) { - searchLogger.error(error); - callback(error); - return; - } - - res.on('error', (error) => { - searchLogger.error(error); - callback(error); - }); - - const entries = []; - - res.on('searchEntry', (entry) => { - entries.push(this.extractLdapEntryData(entry)); - }); - - res.on('end', () => { - searchLogger.info(`Search result count ${ entries.length }`); - callback(null, entries); - }); - }); - } - - authSync(dn, password) { - authLogger.info({ msg: 'Authenticating', dn }); - - try { - this.bindSync(dn, password); - if (this.options.find_user_after_login) { - const searchOptions = { - scope: this.options.User_Search_Scope || 'sub', - }; - const result = this.searchAllSync(dn, searchOptions); - if (result.length === 0) { - authLogger.info({ msg: 'Bind successful but user was not found via search', dn, searchOptions }); - return false; - } - } - authLogger.info({ msg: 'Authenticated', dn }); - return true; - } catch (error) { - authLogger.info({ msg: 'Not authenticated', dn }); - authLogger.debug(error); - return false; - } - } - - disconnect() { - this.connected = false; - this.domainBinded = false; - connLogger.info('Disconecting'); - this.client.unbind(); - } -} diff --git a/app/ldap/server/loginHandler.js b/app/ldap/server/loginHandler.js deleted file mode 100644 index 4f271b49ee6c..000000000000 --- a/app/ldap/server/loginHandler.js +++ /dev/null @@ -1,184 +0,0 @@ -import { SHA256 } from 'meteor/sha'; -import { Meteor } from 'meteor/meteor'; -import { Accounts } from 'meteor/accounts-base'; -import ldapEscape from 'ldap-escape'; - -import { slug, getLdapUsername, getLdapUserUniqueID, syncUserData, addLdapUser } from './sync'; -import LDAP from './ldap'; -import { settings } from '../../settings'; -import { callbacks } from '../../callbacks'; -import { Logger } from '../../logger'; - - -const logger = new Logger('LDAPHandler'); - -function fallbackDefaultAccountSystem(bind, username, password) { - if (typeof username === 'string') { - if (username.indexOf('@') === -1) { - username = { username }; - } else { - username = { email: username }; - } - } - - logger.info('Fallback to default account system', username); - - const loginRequest = { - user: username, - password: { - digest: SHA256(password), - algorithm: 'sha-256', - }, - }; - - return Accounts._runLoginHandlers(bind, loginRequest); -} - -Accounts.registerLoginHandler('ldap', function(loginRequest) { - if (!loginRequest.ldap || !loginRequest.ldapOptions) { - return undefined; - } - - logger.info('Init LDAP login', loginRequest.username); - - if (settings.get('LDAP_Enable') !== true) { - return fallbackDefaultAccountSystem(this, loginRequest.username, loginRequest.ldapPass); - } - - const self = this; - const ldap = new LDAP(); - let ldapUser; - - const escapedUsername = ldapEscape.filter`${ loginRequest.username }`; - - try { - ldap.connectSync(); - const users = ldap.searchUsersSync(escapedUsername); - - if (users.length !== 1) { - logger.info('Search returned', users.length, 'record(s) for', escapedUsername); - throw new Error('User not Found'); - } - - if (ldap.authSync(users[0].dn, loginRequest.ldapPass) === true) { - if (ldap.isUserInGroup(escapedUsername, users[0].dn)) { - ldapUser = users[0]; - } else { - throw new Error('User not in a valid group'); - } - } else { - logger.info('Wrong password for', escapedUsername); - } - } catch (error) { - logger.error(error); - } - - if (ldapUser === undefined) { - return fallbackDefaultAccountSystem(self, loginRequest.username, loginRequest.ldapPass); - } - - // Look to see if user already exists - let userQuery; - - const Unique_Identifier_Field = getLdapUserUniqueID(ldapUser); - let user; - - if (Unique_Identifier_Field) { - userQuery = { - 'services.ldap.id': Unique_Identifier_Field.value, - }; - - logger.info('Querying user'); - logger.debug('userQuery', userQuery); - - user = Meteor.users.findOne(userQuery); - } - - let username; - - if (settings.get('LDAP_Username_Field') !== '') { - username = slug(getLdapUsername(ldapUser)); - } else { - username = slug(loginRequest.username); - } - - if (!user) { - userQuery = { - username, - }; - - logger.debug('userQuery', userQuery); - - user = Meteor.users.findOne(userQuery); - } - - // Login user if they exist - if (user) { - if (user.ldap !== true && settings.get('LDAP_Merge_Existing_Users') !== true) { - logger.info('User exists without "ldap: true"'); - throw new Meteor.Error('LDAP-login-error', `LDAP Authentication succeeded, but there's already an existing user with provided username [${ username }] in Mongo.`); - } - - logger.info('Logging user'); - - syncUserData(user, ldapUser, ldap); - - if (settings.get('LDAP_Login_Fallback') === true && typeof loginRequest.ldapPass === 'string' && loginRequest.ldapPass.trim() !== '') { - Accounts.setPassword(user._id, loginRequest.ldapPass, { logout: false }); - } - logger.info('running afterLDAPLogin'); - callbacks.run('afterLDAPLogin', { user, ldapUser, ldap }); - return { - userId: user._id, - }; - } - - logger.info('User does not exist, creating', username); - - if (settings.get('LDAP_Username_Field') === '') { - username = undefined; - } - - if (settings.get('LDAP_Login_Fallback') !== true) { - loginRequest.ldapPass = undefined; - } - - // Create new user - const result = addLdapUser(ldapUser, username, loginRequest.ldapPass, ldap); - - if (result instanceof Error) { - throw result; - } - callbacks.run('afterLDAPLogin', { user: result, ldapUser, ldap }); - - return result; -}); - -let LDAP_Enable; -settings.get('LDAP_Enable', (key, value) => { - if (LDAP_Enable === value) { - return; - } - LDAP_Enable = value; - - if (!value) { - return callbacks.remove('beforeValidateLogin', 'validateLdapLoginFallback'); - } - - callbacks.add('beforeValidateLogin', (login) => { - if (!login.allowed) { - return login; - } - - // The fallback setting should only block password logins, so users that have other login services can continue using them - if (login.type !== 'password') { - return login; - } - - if (login.user.services && login.user.services.ldap && login.user.services.ldap.id) { - login.allowed = !!settings.get('LDAP_Login_Fallback'); - } - - return login; - }, callbacks.priority.MEDIUM, 'validateLdapLoginFallback'); -}); diff --git a/app/ldap/server/settings.js b/app/ldap/server/settings.js deleted file mode 100644 index 10e8d90bfe34..000000000000 --- a/app/ldap/server/settings.js +++ /dev/null @@ -1,134 +0,0 @@ -import { settings } from '../../settings'; - -settings.addGroup('LDAP', function() { - const enableQuery = { _id: 'LDAP_Enable', value: true }; - const enableAuthentication = [ - enableQuery, - { _id: 'LDAP_Authentication', value: true }, - ]; - const enableTLSQuery = [ - enableQuery, - { _id: 'LDAP_Encryption', value: { $in: ['tls', 'ssl'] } }, - ]; - const syncDataQuery = [ - enableQuery, - { _id: 'LDAP_Sync_User_Data', value: true }, - ]; - const syncGroupsQuery = [ - enableQuery, - { _id: 'LDAP_Sync_User_Data_Groups', value: true }, - ]; - const syncGroupsChannelsQuery = [ - enableQuery, - { _id: 'LDAP_Sync_User_Data_Groups', value: true }, - { _id: 'LDAP_Sync_User_Data_Groups_AutoChannels', value: true }, - ]; - const groupFilterQuery = [ - enableQuery, - { _id: 'LDAP_Group_Filter_Enable', value: true }, - ]; - const backgroundSyncQuery = [ - enableQuery, - { _id: 'LDAP_Background_Sync', value: true }, - ]; - - this.add('LDAP_Enable', false, { type: 'boolean', public: true }); - this.add('LDAP_Login_Fallback', false, { type: 'boolean', enableQuery: null }); - this.add('LDAP_Find_User_After_Login', true, { type: 'boolean', enableQuery }); - this.add('LDAP_Host', '', { type: 'string', enableQuery }); - this.add('LDAP_Port', '389', { type: 'int', enableQuery }); - this.add('LDAP_Reconnect', false, { type: 'boolean', enableQuery }); - this.add('LDAP_Encryption', 'plain', { type: 'select', values: [{ key: 'plain', i18nLabel: 'No_Encryption' }, { key: 'tls', i18nLabel: 'StartTLS' }, { key: 'ssl', i18nLabel: 'SSL/LDAPS' }], enableQuery }); - this.add('LDAP_CA_Cert', '', { type: 'string', multiline: true, enableQuery: enableTLSQuery, secret: true }); - this.add('LDAP_Reject_Unauthorized', true, { type: 'boolean', enableQuery: enableTLSQuery }); - this.add('LDAP_BaseDN', '', { type: 'string', enableQuery }); - this.add('LDAP_Internal_Log_Level', 'disabled', { - type: 'select', - values: [ - { key: 'disabled', i18nLabel: 'Disabled' }, - { key: 'error', i18nLabel: 'Error' }, - { key: 'warn', i18nLabel: 'Warn' }, - { key: 'info', i18nLabel: 'Info' }, - { key: 'debug', i18nLabel: 'Debug' }, - { key: 'trace', i18nLabel: 'Trace' }, - ], - enableQuery, - }); - this.add('LDAP_Test_Connection', 'ldap_test_connection', { type: 'action', actionText: 'Test_Connection' }); - - this.section('Authentication', function() { - this.add('LDAP_Authentication', false, { type: 'boolean', enableQuery }); - this.add('LDAP_Authentication_UserDN', '', { type: 'string', enableQuery: enableAuthentication, secret: true }); - this.add('LDAP_Authentication_Password', '', { type: 'password', enableQuery: enableAuthentication, secret: true }); - }); - - this.section('Timeouts', function() { - this.add('LDAP_Timeout', 60000, { type: 'int', enableQuery }); - this.add('LDAP_Connect_Timeout', 1000, { type: 'int', enableQuery }); - this.add('LDAP_Idle_Timeout', 1000, { type: 'int', enableQuery }); - }); - - this.section('User Search', function() { - this.add('LDAP_User_Search_Filter', '(objectclass=*)', { type: 'string', enableQuery }); - this.add('LDAP_User_Search_Scope', 'sub', { type: 'string', enableQuery }); - this.add('LDAP_User_Search_Field', 'sAMAccountName', { type: 'string', enableQuery }); - this.add('LDAP_Search_Page_Size', 250, { type: 'int', enableQuery }); - this.add('LDAP_Search_Size_Limit', 1000, { type: 'int', enableQuery }); - }); - - this.section('User Search (Group Validation)', function() { - this.add('LDAP_Group_Filter_Enable', false, { type: 'boolean', enableQuery }); - this.add('LDAP_Group_Filter_ObjectClass', 'groupOfUniqueNames', { type: 'string', enableQuery: groupFilterQuery }); - this.add('LDAP_Group_Filter_Group_Id_Attribute', 'cn', { type: 'string', enableQuery: groupFilterQuery }); - this.add('LDAP_Group_Filter_Group_Member_Attribute', 'uniqueMember', { type: 'string', enableQuery: groupFilterQuery }); - this.add('LDAP_Group_Filter_Group_Member_Format', 'uniqueMember', { type: 'string', enableQuery: groupFilterQuery }); - this.add('LDAP_Group_Filter_Group_Name', 'ROCKET_CHAT', { type: 'string', enableQuery: groupFilterQuery }); - }); - - this.section('Sync / Import', function() { - this.add('LDAP_Username_Field', 'sAMAccountName', { - type: 'string', - enableQuery, - // public so that it's visible to AccountProfilePage: - public: true, - }); - this.add('LDAP_Unique_Identifier_Field', 'objectGUID,ibm-entryUUID,GUID,dominoUNID,nsuniqueId,uidNumber', { type: 'string', enableQuery }); - this.add('LDAP_Default_Domain', '', { type: 'string', enableQuery }); - this.add('LDAP_Merge_Existing_Users', false, { type: 'boolean', enableQuery }); - - this.add('LDAP_Sync_User_Data', false, { type: 'boolean', enableQuery }); - this.add('LDAP_Sync_User_Data_FieldMap', '{"cn":"name", "mail":"email"}', { type: 'string', enableQuery: syncDataQuery }); - - this.add('LDAP_Sync_User_Data_Groups', false, { type: 'boolean', enableQuery }); - this.add('LDAP_Sync_User_Data_Groups_AutoRemove', false, { type: 'boolean', enableQuery: syncGroupsQuery }); - this.add('LDAP_Sync_User_Data_Groups_Filter', '(&(cn=#{groupName})(memberUid=#{username}))', { type: 'string', enableQuery: syncGroupsQuery }); - this.add('LDAP_Sync_User_Data_Groups_BaseDN', '', { type: 'string', enableQuery: syncGroupsQuery }); - this.add('LDAP_Sync_User_Data_GroupsMap', '{\n\t"rocket-admin": "admin",\n\t"tech-support": "support"\n}', { - type: 'code', - multiline: true, - public: false, - code: 'application/json', - enableQuery: syncGroupsQuery, - }); - this.add('LDAP_Sync_User_Data_Groups_AutoChannels', false, { type: 'boolean', enableQuery: syncGroupsQuery }); - this.add('LDAP_Sync_User_Data_Groups_AutoChannels_Admin', 'rocket.cat', { type: 'string', enableQuery: syncGroupsChannelsQuery }); - this.add('LDAP_Sync_User_Data_Groups_AutoChannelsMap', '{\n\t"employee": "general",\n\t"techsupport": [\n\t\t"helpdesk",\n\t\t"support"\n\t]\n}', { - type: 'code', - multiline: true, - public: false, - code: 'application/json', - enableQuery: syncGroupsChannelsQuery, - }); - this.add('LDAP_Sync_User_Data_Groups_Enforce_AutoChannels', false, { type: 'boolean', enableQuery: syncGroupsChannelsQuery }); - - this.add('LDAP_Sync_User_Avatar', true, { type: 'boolean', enableQuery }); - this.add('LDAP_Avatar_Field', '', { type: 'string', enableQuery }); - - this.add('LDAP_Background_Sync', false, { type: 'boolean', enableQuery }); - this.add('LDAP_Background_Sync_Interval', 'Every 24 hours', { type: 'string', enableQuery: backgroundSyncQuery }); - this.add('LDAP_Background_Sync_Import_New_Users', true, { type: 'boolean', enableQuery: backgroundSyncQuery }); - this.add('LDAP_Background_Sync_Keep_Existant_Users_Updated', true, { type: 'boolean', enableQuery: backgroundSyncQuery }); - - this.add('LDAP_Sync_Now', 'ldap_sync_now', { type: 'action', actionText: 'Execute_Synchronization_Now' }); - }); -}); diff --git a/app/ldap/server/sync.js b/app/ldap/server/sync.js deleted file mode 100644 index 23cbe47c8304..000000000000 --- a/app/ldap/server/sync.js +++ /dev/null @@ -1,629 +0,0 @@ -import limax from 'limax'; -import { Meteor } from 'meteor/meteor'; -import { Accounts } from 'meteor/accounts-base'; -import { SyncedCron } from 'meteor/littledata:synced-cron'; -import _ from 'underscore'; - -import LDAP from './ldap'; -import { callbacks } from '../../callbacks/server'; -import { RocketChatFile } from '../../file'; -import { settings } from '../../settings'; -import { Users, Roles, Rooms, Subscriptions } from '../../models'; -import { Logger } from '../../logger'; -import { _setRealName } from '../../lib'; -import { templateVarHandler } from '../../utils'; -import { FileUpload } from '../../file-upload'; -import { addUserToRoom, removeUserFromRoom, createRoom, saveUserIdentity } from '../../lib/server/functions'; -import { api } from '../../../server/sdk/api'; - -export const logger = new Logger('LDAPSync'); - -export function isUserInLDAPGroup(ldap, ldapUser, user, ldapGroup) { - const syncUserRolesFilter = settings.get('LDAP_Sync_User_Data_Groups_Filter').trim(); - const syncUserRolesBaseDN = settings.get('LDAP_Sync_User_Data_Groups_BaseDN').trim(); - - if (!syncUserRolesFilter || !syncUserRolesBaseDN) { - logger.error('Please setup LDAP Group Filter and LDAP Group BaseDN in LDAP Settings.'); - return false; - } - const searchOptions = { - filter: syncUserRolesFilter.replace(/#{username}/g, user.username).replace(/#{groupName}/g, ldapGroup).replace(/#{userdn}/g, ldapUser.dn), - scope: 'sub', - }; - - const result = ldap.searchAllSync(syncUserRolesBaseDN, searchOptions); - if (!Array.isArray(result) || result.length === 0) { - logger.debug(`${ user.username } is not in ${ ldapGroup } group!!!`); - } else { - logger.debug(`${ user.username } is in ${ ldapGroup } group.`); - return true; - } - - return false; -} - -export function slug(text) { - if (settings.get('UTF8_Names_Slugify') !== true) { - return text; - } - text = limax(text, { replacement: '.' }); - return text.replace(/[^0-9a-z-_.]/g, ''); -} - - -export function getPropertyValue(obj, key) { - try { - return _.reduce(key.split('.'), (acc, el) => acc[el], obj); - } catch (err) { - return undefined; - } -} - - -export function getLdapUsername(ldapUser) { - const usernameField = settings.get('LDAP_Username_Field'); - - if (usernameField.indexOf('#{') > -1) { - return usernameField.replace(/#{(.+?)}/g, function(match, field) { - return ldapUser[field]; - }); - } - - return ldapUser[usernameField]; -} - - -export function getLdapUserUniqueID(ldapUser) { - let Unique_Identifier_Field = settings.get('LDAP_Unique_Identifier_Field'); - - if (Unique_Identifier_Field !== '') { - Unique_Identifier_Field = Unique_Identifier_Field.replace(/\s/g, '').split(','); - } else { - Unique_Identifier_Field = []; - } - - let User_Search_Field = settings.get('LDAP_User_Search_Field'); - - if (User_Search_Field !== '') { - User_Search_Field = User_Search_Field.replace(/\s/g, '').split(','); - } else { - User_Search_Field = []; - } - - Unique_Identifier_Field = Unique_Identifier_Field.concat(User_Search_Field); - - if (Unique_Identifier_Field.length > 0) { - Unique_Identifier_Field = Unique_Identifier_Field.find((field) => !_.isEmpty(ldapUser._raw[field])); - if (Unique_Identifier_Field) { - Unique_Identifier_Field = { - attribute: Unique_Identifier_Field, - value: ldapUser._raw[Unique_Identifier_Field].toString('hex'), - }; - } - return Unique_Identifier_Field; - } -} - -export function getDataToSyncUserData(ldapUser, user) { - const syncUserData = settings.get('LDAP_Sync_User_Data'); - const syncUserDataFieldMap = settings.get('LDAP_Sync_User_Data_FieldMap').trim(); - - const userData = {}; - - if (syncUserData && syncUserDataFieldMap) { - const whitelistedUserFields = ['email', 'name', 'customFields']; - const fieldMap = JSON.parse(syncUserDataFieldMap); - const emailList = []; - _.map(fieldMap, function(userField, ldapField) { - switch (userField) { - case 'email': - if (!ldapUser.hasOwnProperty(ldapField)) { - logger.debug(`user does not have attribute: ${ ldapField }`); - return; - } - - const verified = settings.get('Accounts_Verify_Email_For_External_Accounts'); - - if (_.isObject(ldapUser[ldapField])) { - _.map(ldapUser[ldapField], function(item) { - emailList.push({ address: item, verified }); - }); - } else { - emailList.push({ address: ldapUser[ldapField], verified }); - } - break; - - default: - const [outerKey, innerKeys] = userField.split(/\.(.+)/); - - if (!_.find(whitelistedUserFields, (el) => el === outerKey)) { - logger.debug(`user attribute not whitelisted: ${ userField }`); - return; - } - - if (outerKey === 'customFields') { - let customFieldsMeta; - - try { - customFieldsMeta = JSON.parse(settings.get('Accounts_CustomFields')); - } catch (e) { - logger.debug('Invalid JSON for Custom Fields'); - return; - } - - if (!getPropertyValue(customFieldsMeta, innerKeys)) { - logger.debug(`user attribute does not exist: ${ userField }`); - return; - } - } - - const tmpUserField = getPropertyValue(user, userField); - const tmpLdapField = templateVarHandler(ldapField, ldapUser); - - if (tmpLdapField && tmpUserField !== tmpLdapField) { - // creates the object structure instead of just assigning 'tmpLdapField' to - // 'userData[userField]' in order to avoid the "cannot use the part (...) - // to traverse the element" (MongoDB) error that can happen. Do not handle - // arrays. - // TODO: Find a better solution. - const dKeys = userField.split('.'); - const lastKey = _.last(dKeys); - _.reduce(dKeys, (obj, currKey) => { - if (currKey === lastKey) { - obj[currKey] = tmpLdapField; - } else { - obj[currKey] = obj[currKey] || {}; - } - return obj[currKey]; - }, userData); - logger.debug(`user.${ userField } changed to: ${ tmpLdapField }`); - } - } - }); - - if (emailList.length > 0) { - if (JSON.stringify(user.emails) !== JSON.stringify(emailList)) { - userData.emails = emailList; - } - } - } - - const uniqueId = getLdapUserUniqueID(ldapUser); - - if (uniqueId && (!user.services || !user.services.ldap || user.services.ldap.id !== uniqueId.value || user.services.ldap.idAttribute !== uniqueId.attribute)) { - userData['services.ldap.id'] = uniqueId.value; - userData['services.ldap.idAttribute'] = uniqueId.attribute; - } - - if (user.ldap !== true) { - userData.ldap = true; - } - - if (_.size(userData)) { - return userData; - } -} -export function mapLdapGroupsToUserRoles(ldap, ldapUser, user) { - const syncUserRoles = settings.get('LDAP_Sync_User_Data_Groups'); - const syncUserRolesAutoRemove = settings.get('LDAP_Sync_User_Data_Groups_AutoRemove'); - const syncUserRolesFieldMap = settings.get('LDAP_Sync_User_Data_GroupsMap').trim(); - - if (!syncUserRoles || !syncUserRolesFieldMap) { - logger.debug('not syncing user roles'); - return []; - } - - const roles = Roles.find({}, { - fields: { - _updatedAt: 0, - }, - }).fetch(); - - if (!roles) { - return []; - } - - let fieldMap; - - try { - fieldMap = JSON.parse(syncUserRolesFieldMap); - } catch (err) { - logger.error(`Unexpected error : ${ err.message }`); - return []; - } - if (!fieldMap) { - return []; - } - - const userRoles = []; - - for (const ldapField in fieldMap) { - if (!fieldMap.hasOwnProperty(ldapField)) { - continue; - } - - const userField = fieldMap[ldapField]; - - const [roleName] = userField.split(/\.(.+)/); - if (!_.find(roles, (el) => el._id === roleName)) { - logger.debug(`User Role doesn't exist: ${ roleName }`); - continue; - } - - logger.debug(`User role exists for mapping ${ ldapField } -> ${ roleName }`); - - if (isUserInLDAPGroup(ldap, ldapUser, user, ldapField)) { - userRoles.push(roleName); - continue; - } - - if (!syncUserRolesAutoRemove) { - continue; - } - - const del = Roles.removeUserRoles(user._id, roleName); - if (settings.get('UI_DisplayRoles') && del) { - api.broadcast('user.roleUpdate', { - type: 'removed', - _id: roleName, - u: { - _id: user._id, - username: user.username, - }, - }); - } - } - - return userRoles; -} -export function createRoomForSync(channel) { - logger.info(`Channel '${ channel }' doesn't exist, creating it.`); - - const room = createRoom('c', channel, settings.get('LDAP_Sync_User_Data_Groups_AutoChannels_Admin'), [], false, { customFields: { ldap: true } }); - if (!room || !room.rid) { - logger.error(`Unable to auto-create channel '${ channel }' during ldap sync.`); - return; - } - room._id = room.rid; - return room; -} - -export function mapLDAPGroupsToChannels(ldap, ldapUser, user) { - const syncUserRoles = settings.get('LDAP_Sync_User_Data_Groups'); - const syncUserRolesAutoChannels = settings.get('LDAP_Sync_User_Data_Groups_AutoChannels'); - const syncUserRolesEnforceAutoChannels = settings.get('LDAP_Sync_User_Data_Groups_Enforce_AutoChannels'); - const syncUserRolesChannelFieldMap = settings.get('LDAP_Sync_User_Data_Groups_AutoChannelsMap').trim(); - - const userChannels = []; - if (!syncUserRoles || !syncUserRolesAutoChannels || !syncUserRolesChannelFieldMap) { - logger.debug('not syncing groups to channels'); - return []; - } - - let fieldMap; - try { - fieldMap = JSON.parse(syncUserRolesChannelFieldMap); - } catch (err) { - logger.error(`Unexpected error : ${ err.message }`); - return []; - } - - if (!fieldMap) { - return []; - } - - _.map(fieldMap, function(channels, ldapField) { - if (!Array.isArray(channels)) { - channels = [channels]; - } - - for (const channel of channels) { - let room = Rooms.findOneByNonValidatedName(channel); - - if (!room) { - room = createRoomForSync(channel); - } - if (isUserInLDAPGroup(ldap, ldapUser, user, ldapField)) { - if (room.teamMain) { - logger.error(`Can't add user to channel ${ channel } because it is a team.`); - } else { - userChannels.push(room._id); - } - } else if (syncUserRolesEnforceAutoChannels && !room.teamMain) { - const subscription = Subscriptions.findOneByRoomIdAndUserId(room._id, user._id); - if (subscription) { - removeUserFromRoom(room._id, user); - } - } - } - }); - - return userChannels; -} - -function syncUserAvatar(user, ldapUser) { - if (!user?._id || settings.get('LDAP_Sync_User_Avatar') !== true) { - return; - } - - const avatarField = (settings.get('LDAP_Avatar_Field') || 'thumbnailPhoto').trim(); - const avatar = ldapUser._raw[avatarField] || ldapUser._raw.thumbnailPhoto || ldapUser._raw.jpegPhoto; - if (!avatar) { - return; - } - - logger.info('Syncing user avatar'); - - Meteor.defer(() => { - const rs = RocketChatFile.bufferToStream(avatar); - const fileStore = FileUpload.getStore('Avatars'); - fileStore.deleteByName(user.username); - - const file = { - userId: user._id, - type: 'image/jpeg', - size: avatar.length, - }; - - Meteor.runAsUser(user._id, () => { - fileStore.insert(file, rs, (err, result) => { - Meteor.setTimeout(function() { - Users.setAvatarData(user._id, 'ldap', result.etag); - api.broadcast('user.avatarUpdate', { username: user.username, avatarETag: result.etag }); - }, 500); - }); - }); - }); -} - -export function syncUserData(user, ldapUser, ldap) { - logger.info('Syncing user data'); - logger.debug('user', { email: user.email, _id: user._id }); - logger.debug('ldapUser', ldapUser.object); - - const userData = getDataToSyncUserData(ldapUser, user); - - // Returns a list of Rocket.Chat Groups a user should belong - // to if their LDAP group matches the LDAP_Sync_User_Data_GroupsMap - const userRoles = mapLdapGroupsToUserRoles(ldap, ldapUser, user); - - // Returns a list of Rocket.Chat Channels a user should belong - // to if their LDAP group matches the LDAP_Sync_User_Data_Groups_AutoChannelsMap - const userChannels = mapLDAPGroupsToChannels(ldap, ldapUser, user); - - if (user && user._id && userData) { - logger.debug({ msg: 'setting', userData }); - if (userData.name) { - _setRealName(user._id, userData.name); - delete userData.name; - } - userData.customFields = { - ...user.customFields, ...userData.customFields, - }; - Meteor.users.update(user._id, { $set: userData }); - user = Meteor.users.findOne({ _id: user._id }); - } - - if (settings.get('LDAP_Username_Field') !== '') { - const username = slug(getLdapUsername(ldapUser)); - if (user && user._id && username !== user.username) { - logger.info('Syncing user username', user.username, '->', username); - saveUserIdentity({ _id: user._id, username }); - } - } - - if (settings.get('LDAP_Sync_User_Data_Groups') === true) { - for (const roleName of userRoles) { - const add = Roles.addUserRoles(user._id, roleName); - if (settings.get('UI_DisplayRoles') && add) { - api.broadcast('user.roleUpdate', { - type: 'added', - _id: roleName, - u: { - _id: user._id, - username: user.username, - }, - }); - } - logger.info('Synced user group', roleName, 'from LDAP for', user.username); - } - } - - if (settings.get('LDAP_Sync_User_Data_Groups_AutoChannels') === true) { - for (const userChannel of userChannels) { - addUserToRoom(userChannel, user); - logger.info('Synced user channel', userChannel, 'from LDAP for', user.username); - } - } - - syncUserAvatar(user, ldapUser); -} - -export function addLdapUser(ldapUser, username, password, ldap) { - const uniqueId = getLdapUserUniqueID(ldapUser); - - const userObject = {}; - - if (username) { - userObject.username = username; - } - - const userData = getDataToSyncUserData(ldapUser, {}); - - if (userData && userData.emails && userData.emails[0] && userData.emails[0].address) { - if (Array.isArray(userData.emails[0].address)) { - userObject.email = userData.emails[0].address[0]; - } else { - userObject.email = userData.emails[0].address; - } - } else if (ldapUser.mail && ldapUser.mail.indexOf('@') > -1) { - userObject.email = ldapUser.mail; - } else if (settings.get('LDAP_Default_Domain') !== '') { - userObject.email = `${ username || uniqueId.value }@${ settings.get('LDAP_Default_Domain') }`; - } else { - const error = new Meteor.Error('LDAP-login-error', 'LDAP Authentication succeeded, there is no email to create an account. Have you tried setting your Default Domain in LDAP Settings?'); - logger.error(error); - throw error; - } - - logger.debug('New user data', userObject); - - if (password) { - userObject.password = password; - } - - try { - userObject._id = Accounts.createUser(userObject); - } catch (error) { - logger.error('Error creating user', error); - return error; - } - - syncUserData(userObject, ldapUser, ldap); - - return { - userId: userObject._id, - }; -} - -export function importNewUsers(ldap) { - if (settings.get('LDAP_Enable') !== true) { - logger.error('Can\'t run LDAP Import, LDAP is disabled'); - return; - } - - if (!ldap) { - ldap = new LDAP(); - } - - if (!ldap.connected) { - ldap.connectSync(); - } - - let count = 0; - ldap.searchUsersSync('*', Meteor.bindEnvironment((error, ldapUsers, { next, end } = {}) => { - if (error) { - throw error; - } - - ldapUsers.forEach((ldapUser) => { - count++; - - const uniqueId = getLdapUserUniqueID(ldapUser); - // Look to see if user already exists - const userQuery = { - 'services.ldap.id': uniqueId.value, - }; - - logger.debug('userQuery', userQuery); - - let username; - if (settings.get('LDAP_Username_Field') !== '') { - username = slug(getLdapUsername(ldapUser)); - } - - // Add user if it was not added before - let user = Meteor.users.findOne(userQuery); - - if (!user && username && settings.get('LDAP_Merge_Existing_Users') === true) { - const userQuery = { - username, - }; - - logger.debug('userQuery merge', userQuery); - - user = Meteor.users.findOne(userQuery); - if (user) { - syncUserData(user, ldapUser, ldap); - } - } - - if (!user) { - addLdapUser(ldapUser, username, undefined, ldap); - } - - if (count % 100 === 0) { - logger.info('Import running. Users imported until now:', count); - } - }); - - if (end) { - logger.info('Import finished. Users imported:', count); - } - - next(count); - })); -} - -export function sync() { - if (settings.get('LDAP_Enable') !== true) { - return; - } - - const ldap = new LDAP(); - - try { - ldap.connectSync(); - - let users; - if (settings.get('LDAP_Background_Sync_Keep_Existant_Users_Updated') === true) { - users = Users.findLDAPUsers(); - } - - if (settings.get('LDAP_Background_Sync_Import_New_Users') === true) { - importNewUsers(ldap); - } - - if (settings.get('LDAP_Background_Sync_Keep_Existant_Users_Updated') === true) { - users.forEach(function(user) { - let ldapUser; - - if (user.services && user.services.ldap && user.services.ldap.id) { - ldapUser = ldap.getUserByIdSync(user.services.ldap.id, user.services.ldap.idAttribute); - } else { - ldapUser = ldap.getUserByUsernameSync(user.username); - } - - if (ldapUser) { - syncUserData(user, ldapUser, ldap); - } - - callbacks.run('ldap.afterSyncExistentUser', { ldapUser, user }); - }); - } - } catch (error) { - logger.error(error); - return error; - } - return true; -} - -const jobName = 'LDAP_Sync'; - -const addCronJob = _.debounce(Meteor.bindEnvironment(function addCronJobDebounced() { - if (settings.get('LDAP_Background_Sync') !== true) { - logger.info('Disabling LDAP Background Sync'); - if (SyncedCron.nextScheduledAtDate(jobName)) { - SyncedCron.remove(jobName); - } - return; - } - - if (settings.get('LDAP_Background_Sync_Interval')) { - logger.info('Enabling LDAP Background Sync'); - SyncedCron.add({ - name: jobName, - schedule: (parser) => parser.text(settings.get('LDAP_Background_Sync_Interval')), - job() { - sync(); - }, - }); - } -}), 500); - -Meteor.startup(() => { - Meteor.defer(() => { - settings.get('LDAP_Background_Sync', addCronJob); - settings.get('LDAP_Background_Sync_Interval', addCronJob); - }); -}); diff --git a/app/ldap/server/syncUsers.js b/app/ldap/server/syncUsers.js deleted file mode 100644 index 312d4dbe96d2..000000000000 --- a/app/ldap/server/syncUsers.js +++ /dev/null @@ -1,31 +0,0 @@ -import { Meteor } from 'meteor/meteor'; - -import { sync } from './sync'; -import { hasRole } from '../../authorization'; -import { settings } from '../../settings'; - -Meteor.methods({ - ldap_sync_now() { - const user = Meteor.user(); - if (!user) { - throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'ldap_sync_users' }); - } - - if (!hasRole(user._id, 'admin')) { - throw new Meteor.Error('error-not-authorized', 'Not authorized', { method: 'ldap_sync_users' }); - } - - if (settings.get('LDAP_Enable') !== true) { - throw new Meteor.Error('LDAP_disabled'); - } - - Meteor.defer(() => { - sync(); - }); - - return { - message: 'Sync_in_progress', - params: [], - }; - }, -}); diff --git a/app/ldap/server/testConnection.js b/app/ldap/server/testConnection.js deleted file mode 100644 index 98be62dcb991..000000000000 --- a/app/ldap/server/testConnection.js +++ /dev/null @@ -1,43 +0,0 @@ -import { Meteor } from 'meteor/meteor'; - -import LDAP from './ldap'; -import { hasRole } from '../../authorization/server'; -import { settings } from '../../settings/server'; -import { SystemLogger } from '../../../server/lib/logger/system'; - -Meteor.methods({ - ldap_test_connection() { - const user = Meteor.user(); - if (!user) { - throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'ldap_test_connection' }); - } - - if (!hasRole(user._id, 'admin')) { - throw new Meteor.Error('error-not-authorized', 'Not authorized', { method: 'ldap_test_connection' }); - } - - if (settings.get('LDAP_Enable') !== true) { - throw new Meteor.Error('LDAP_disabled'); - } - - let ldap; - try { - ldap = new LDAP(); - ldap.connectSync(); - } catch (error) { - SystemLogger.error(error); - throw new Meteor.Error(error.message); - } - - try { - ldap.bindIfNecessary(); - } catch (error) { - throw new Meteor.Error(error.name || error.message); - } - - return { - message: 'Connection_success', - params: [], - }; - }, -}); diff --git a/app/models/server/index.js b/app/models/server/index.js index efcd3790302f..8c9094d654ef 100644 --- a/app/models/server/index.js +++ b/app/models/server/index.js @@ -40,6 +40,7 @@ import LivechatExternalMessage from './models/LivechatExternalMessages'; import OmnichannelQueue from './models/OmnichannelQueue'; import Analytics from './models/Analytics'; import EmailInbox from './models/EmailInbox'; +import ImportData from './models/ImportData'; export { AppsLogsModel } from './models/apps-logs-model'; export { AppsPersistenceModel } from './models/apps-persistence-model'; @@ -92,4 +93,5 @@ export { Analytics, OmnichannelQueue, EmailInbox, + ImportData, }; diff --git a/app/importer/server/models/ImportData.ts b/app/models/server/models/ImportData.ts similarity index 88% rename from app/importer/server/models/ImportData.ts rename to app/models/server/models/ImportData.ts index a6afb291e19c..785086d7ba70 100644 --- a/app/importer/server/models/ImportData.ts +++ b/app/models/server/models/ImportData.ts @@ -1,5 +1,5 @@ -import { Base } from '../../../models/server'; -import { IImportUserRecord, IImportChannelRecord } from '../definitions/IImportRecord'; +import { Base } from './_Base'; +import { IImportUserRecord, IImportChannelRecord } from '../../../../definition/IImportRecord'; class ImportDataModel extends Base { constructor() { @@ -85,4 +85,4 @@ class ImportDataModel extends Base { } } -export const ImportData = new ImportDataModel(); +export default new ImportDataModel(); diff --git a/app/models/server/models/Users.js b/app/models/server/models/Users.js index c760c4d7172a..149978b18a6b 100644 --- a/app/models/server/models/Users.js +++ b/app/models/server/models/Users.js @@ -875,12 +875,6 @@ export class Users extends Base { return this.find(query, options); } - findLDAPUsers(options) { - const query = { ldap: true }; - - return this.find(query, options); - } - findCrowdUsers(options) { const query = { crowd: true }; diff --git a/app/models/server/raw/ImportData.ts b/app/models/server/raw/ImportData.ts new file mode 100644 index 000000000000..175e64380f56 --- /dev/null +++ b/app/models/server/raw/ImportData.ts @@ -0,0 +1,18 @@ +import { Cursor } from 'mongodb'; + +import { BaseRaw } from './BaseRaw'; +import { IImportRecord, IImportUserRecord, IImportMessageRecord, IImportChannelRecord } from '../../../../definition/IImportRecord'; + +export class ImportDataRaw extends BaseRaw { + getAllUsers(): Cursor { + return this.find({ dataType: 'user' }) as Cursor; + } + + getAllMessages(): Cursor { + return this.find({ dataType: 'message' }) as Cursor; + } + + getAllChannels(): Cursor { + return this.find({ dataType: 'channel' }) as Cursor; + } +} diff --git a/app/models/server/raw/Users.js b/app/models/server/raw/Users.js index 89b491ab2f9e..b89de6b05371 100644 --- a/app/models/server/raw/Users.js +++ b/app/models/server/raw/Users.js @@ -138,6 +138,24 @@ export class UsersRaw extends BaseRaw { return this.findOne(query, options); } + async findOneByLDAPId(id, attribute = undefined) { + const query = { + 'services.ldap.id': id, + }; + + if (attribute) { + query['services.ldap.idAttribute'] = attribute; + } + + return this.findOne(query); + } + + async findLDAPUsers(options) { + const query = { ldap: true }; + + return this.find(query, options); + } + isUserInRole(userId, roleName) { const query = { _id: userId, diff --git a/app/models/server/raw/index.ts b/app/models/server/raw/index.ts index 87ecbad097d1..605218c636be 100644 --- a/app/models/server/raw/index.ts +++ b/app/models/server/raw/index.ts @@ -69,6 +69,8 @@ import EmailMessageHistoryModel from '../models/EmailMessageHistory'; import { EmailMessageHistoryRaw } from './EmailMessageHistory'; import { api } from '../../../../server/sdk/api'; import { initWatchers } from '../../../../server/modules/watchers/watchers.module'; +import ImportDataModel from '../models/ImportData'; +import { ImportDataRaw } from './ImportData'; const trashCollection = trash.rawCollection(); @@ -106,6 +108,7 @@ export const Sessions = new SessionsRaw(SessionsModel.model.rawCollection(), tra export const OmnichannelQueue = new OmnichannelQueueRaw(OmnichannelQueueModel.model.rawCollection(), trashCollection); export const EmailInbox = new EmailInboxRaw(EmailInboxModel.model.rawCollection(), trashCollection); export const EmailMessageHistory = new EmailMessageHistoryRaw(EmailMessageHistoryModel.model.rawCollection(), trashCollection); +export const ImportData = new ImportDataRaw(ImportDataModel.model.rawCollection(), trashCollection); const map = { [Messages.col.collectionName]: MessagesModel, diff --git a/app/settings/lib/settings.ts b/app/settings/lib/settings.ts index 588250fb16a6..109ed5fbb651 100644 --- a/app/settings/lib/settings.ts +++ b/app/settings/lib/settings.ts @@ -3,7 +3,7 @@ import _ from 'underscore'; import { SettingValue } from '../../../definition/ISetting'; -export type SettingComposedValue = {key: string; value: SettingValue}; +export type SettingComposedValue = {key: string; value: T}; export type SettingCallback = (key: string, value: SettingValue, initialLoad?: boolean) => void; interface ISettingRegexCallbacks { @@ -17,11 +17,15 @@ export class SettingsBase { private regexCallbacks = new Map(); // private ts = new Date() - public get(_id: RegExp, callback?: SettingCallback): SettingComposedValue[]; + public get(_id: RegExp, callback: SettingCallback): void; - public get(_id: string, callback?: SettingCallback): SettingValue | void; + public get(_id: string, callback: SettingCallback): void; - public get(_id: string | RegExp, callback?: SettingCallback): SettingValue | SettingComposedValue[] | void { + public get(_id: RegExp): SettingComposedValue[]; + + public get(_id: string): T | undefined; + + public get(_id: string | RegExp, callback?: SettingCallback): T | undefined | SettingComposedValue[] | void { if (callback != null) { this.onload(_id, callback); if (!Meteor.settings) { @@ -44,7 +48,11 @@ export class SettingsBase { } if (typeof _id === 'string') { - return Meteor.settings[_id] != null && callback(_id, Meteor.settings[_id]); + const value = Meteor.settings[_id]; + if (value != null) { + callback(_id, Meteor.settings[_id]); + } + return; } } @@ -53,7 +61,7 @@ export class SettingsBase { } if (_.isRegExp(_id)) { - return Object.keys(Meteor.settings).reduce((items: SettingComposedValue[], key) => { + return Object.keys(Meteor.settings).reduce((items: SettingComposedValue[], key) => { const value = Meteor.settings[key]; if (_id.test(key)) { items.push({ diff --git a/app/settings/server/functions/settings.mocks.ts b/app/settings/server/functions/settings.mocks.ts index d28383b14252..8db74e3285d1 100644 --- a/app/settings/server/functions/settings.mocks.ts +++ b/app/settings/server/functions/settings.mocks.ts @@ -10,8 +10,18 @@ class SettingsClass { public upsertCalls = 0; + private checkQueryMatch(key: string, data: Dictionary, queryValue: any): boolean { + if (typeof queryValue === 'object') { + if (queryValue.$exists !== undefined) { + return (data.hasOwnProperty(key) && data[key] !== undefined) === queryValue.$exists; + } + } + + return queryValue === data[key]; + } + findOne(query: Dictionary): any { - return [...this.data.values()].find((data) => Object.entries(query).every(([key, value]) => data[key] === value)); + return [...this.data.values()].find((data) => Object.entries(query).every(([key, value]) => this.checkQueryMatch(key, data, value))); } upsert(query: any, update: any): void { diff --git a/app/settings/server/functions/settings.ts b/app/settings/server/functions/settings.ts index 7341393bc60a..70e5146b7bbd 100644 --- a/app/settings/server/functions/settings.ts +++ b/app/settings/server/functions/settings.ts @@ -68,6 +68,8 @@ const overrideSetting = (_id: string, value: SettingValue, options: ISettingAddO export interface ISettingAddOptions extends Partial { force?: boolean; + actionText?: string; + code?: 'application/json'; } export interface ISettingAddGroupOptions { @@ -86,6 +88,7 @@ interface IUpdateOperator { }; $unset?: { section?: 1; + tab?: 1; }; } @@ -99,11 +102,13 @@ type Query = { type addSectionCallback = (this: { add(id: string, value: SettingValue, options: ISettingAddOptions): void; + set(options: ISettingAddOptions, cb: addSectionCallback): void; }) => void; type addGroupCallback = (this: { add(id: string, value: SettingValue, options: ISettingAddOptions): void; section(section: string, cb: addSectionCallback): void; + set(options: ISettingAddOptions, cb: addGroupCallback): void; }) => void; class Settings extends SettingsBase { @@ -113,20 +118,13 @@ class Settings extends SettingsBase { private initialLoad = false; - /* - * Add a setting - */ - add(_id: string, value: SettingValue, { editor, ...options }: ISettingAddOptions = {}): boolean { - if (!_id || value == null) { - return false; - } + private validateOptions(_id: string, value: SettingValue, options: ISettingAddOptions): void { if (options.group && this._sorter[options.group] == null) { this._sorter[options.group] = 0; } options.packageValue = value; options.valueSource = 'packageValue'; options.hidden = options.hidden || false; - options.blocked = options.blocked || false; options.requiredOnWizard = options.requiredOnWizard || false; options.secret = options.secret || false; options.enterprise = options.enterprise || false; @@ -142,8 +140,8 @@ class Settings extends SettingsBase { if (options.enableQuery != null) { options.enableQuery = JSON.stringify(options.enableQuery); } - if (options.i18nLabel == null) { - options.i18nLabel = _id; + if (options.displayQuery != null) { + options.displayQuery = JSON.stringify(options.displayQuery); } if (options.i18nDescription == null) { options.i18nDescription = `${ _id }_Description`; @@ -160,6 +158,21 @@ class Settings extends SettingsBase { if (options.autocomplete == null) { options.autocomplete = true; } + } + + /* + * Add a setting + */ + add(_id: string, value: SettingValue, { editor, ...options }: ISettingAddOptions = {}): boolean { + if (!_id || value == null) { + return false; + } + + this.validateOptions(_id, value, options); + options.blocked = options.blocked || false; + if (options.i18nLabel == null) { + options.i18nLabel = _id; + } value = overrideSetting(_id, value, options); @@ -196,6 +209,15 @@ class Settings extends SettingsBase { }; } + if (!options.tab) { + updateOperations.$unset = { + tab: 1, + }; + query.tab = { + $exists: false, + }; + } + const existentSetting = SettingsModel.findOne(query); if (existentSetting) { if (existentSetting.editor || !updateOperations.$setOnInsert.editor) { @@ -279,19 +301,36 @@ class Settings extends SettingsBase { } if (cb != null) { - cb.call({ - add: (id: string, value: SettingValue, options: ISettingAddOptions = {}) => { - options.group = _id; - return this.add(id, value, options); - }, - section: (section: string, cb: addSectionCallback) => cb.call({ - add: (id: string, value: SettingValue, options: ISettingAddOptions = {}) => { - options.group = _id; - options.section = section; - return this.add(id, value, options); - }, - }), - }); + const addWith = (preset: ISettingAddOptions) => (id: string, value: SettingValue, options: ISettingAddOptions = {}): void => { + const mergedOptions = Object.assign({}, preset, options); + this.add(id, value, mergedOptions); + }; + const sectionSetWith = (preset: ISettingAddOptions) => (options: ISettingAddOptions, cb: addSectionCallback): void => { + const mergedOptions = Object.assign({}, preset, options); + cb.call({ + add: addWith(mergedOptions), + set: sectionSetWith(mergedOptions), + }); + }; + const sectionWith = (preset: ISettingAddOptions) => (section: string, cb: addSectionCallback): void => { + const mergedOptions = Object.assign({}, preset, { section }); + cb.call({ + add: addWith(mergedOptions), + set: sectionSetWith(mergedOptions), + }); + }; + + const groupSetWith = (preset: ISettingAddOptions) => (options: ISettingAddOptions, cb: addGroupCallback): void => { + const mergedOptions = Object.assign({}, preset, options); + + cb.call({ + add: addWith(mergedOptions), + section: sectionWith(mergedOptions), + set: groupSetWith(mergedOptions), + }); + }; + + groupSetWith({ group: _id })({}, cb); } return true; } diff --git a/app/statistics/server/lib/getServicesStatistics.ts b/app/statistics/server/lib/getServicesStatistics.ts index 75bc6ca3dc2c..2bdb07b698f0 100644 --- a/app/statistics/server/lib/getServicesStatistics.ts +++ b/app/statistics/server/lib/getServicesStatistics.ts @@ -25,10 +25,10 @@ export function getServicesStatistics(): Record { loginFallback: settings.get('LDAP_Login_Fallback'), encryption: settings.get('LDAP_Encryption'), mergeUsers: settings.get('LDAP_Merge_Existing_Users'), - syncRoles: settings.get('LDAP_Sync_User_Data_Groups'), - syncRolesAutoRemove: settings.get('LDAP_Sync_User_Data_Groups_AutoRemove'), - syncData: settings.get('LDAP_Sync_User_Data'), - syncChannels: settings.get('LDAP_Sync_User_Data_Groups_AutoChannels'), + syncRoles: settings.get('LDAP_Sync_User_Data_Roles'), + syncRolesAutoRemove: settings.get('LDAP_Sync_User_Data_Roles_AutoRemove'), + syncData: settings.get('LDAP_Sync_Custom_Fields'), + syncChannels: settings.get('LDAP_Sync_User_Data_Channels'), syncAvatar: settings.get('LDAP_Sync_User_Avatar'), groupFilter: settings.get('LDAP_Group_Filter_Enable'), backgroundSync: { @@ -40,7 +40,7 @@ export function getServicesStatistics(): Record { ee: { syncActiveState: settings.get('LDAP_Sync_User_Active_State'), syncTeams: settings.get('LDAP_Enable_LDAP_Groups_To_RC_Teams'), - syncRoles: settings.get('LDAP_Enable_LDAP_Roles_To_RC_Roles'), + syncRoles: settings.get('LDAP_Sync_User_Data_Roles'), }, }, saml: { diff --git a/app/utils/server/lib/cron/Cronjobs.ts b/app/utils/server/lib/cron/Cronjobs.ts index c9cabed5a861..8ab96121e54f 100644 --- a/app/utils/server/lib/cron/Cronjobs.ts +++ b/app/utils/server/lib/cron/Cronjobs.ts @@ -1,15 +1,18 @@ import { SyncedCron } from 'meteor/littledata:synced-cron'; +type ScheduleType = 'cron' | 'text'; + export interface ICronJobs { - add(name: string, schedule: string, callback: Function): void; + add(name: string, schedule: string, callback: Function, scheduleType?: ScheduleType): void; remove(name: string): void; + nextScheduledAtDate(name: string): Date | number | undefined; } class SyncedCronJobs implements ICronJobs { - add(name: string, schedule: string, callback: Function): void { + add(name: string, schedule: string, callback: Function, scheduleType: ScheduleType = 'cron'): void { SyncedCron.add({ name, - schedule: (parser: any) => parser.cron(schedule), + schedule: (parser: any) => parser[scheduleType](schedule), job() { const [day, hour] = this.name.split('/'); callback(day, hour); @@ -20,6 +23,10 @@ class SyncedCronJobs implements ICronJobs { remove(name: string): void { SyncedCron.remove(name); } + + nextScheduledAtDate(name: string): Date | number | undefined { + return SyncedCron.nextScheduledAtDate(name); + } } export const cronJobs: ICronJobs = new SyncedCronJobs(); diff --git a/client/contexts/EditableSettingsContext.ts b/client/contexts/EditableSettingsContext.ts index 100c641c86de..dc1d5bcc3771 100644 --- a/client/contexts/EditableSettingsContext.ts +++ b/client/contexts/EditableSettingsContext.ts @@ -1,12 +1,13 @@ import { createContext, useContext, useMemo } from 'react'; import { useSubscription, Subscription, Unsubscribe } from 'use-subscription'; -import { ISetting, SectionName, SettingId, GroupId } from '../../definition/ISetting'; +import { ISetting, SectionName, SettingId, GroupId, TabId } from '../../definition/ISetting'; import { SettingsContextQuery } from './SettingsContext'; export interface IEditableSetting extends ISetting { disabled: boolean; changed: boolean; + invisible: boolean; } export type EditableSettingsContextQuery = SettingsContextQuery & { @@ -18,7 +19,8 @@ export type EditableSettingsContextValue = { readonly queryEditableSettings: ( query: EditableSettingsContextQuery, ) => Subscription; - readonly queryGroupSections: (_id: GroupId) => Subscription; + readonly queryGroupSections: (_id: GroupId, tab?: TabId) => Subscription; + readonly queryGroupTabs: (_id: GroupId) => Subscription; readonly dispatch: (changes: Partial[]) => void; }; @@ -35,6 +37,10 @@ export const EditableSettingsContext = createContext [], subscribe: (): Unsubscribe => (): void => undefined, }), + queryGroupTabs: () => ({ + getCurrentValue: (): TabId[] => [], + subscribe: (): Unsubscribe => (): void => undefined, + }), dispatch: () => undefined, }); @@ -54,10 +60,17 @@ export const useEditableSettings = (query?: EditableSettingsContextQuery): IEdit return useSubscription(subscription); }; -export const useEditableSettingsGroupSections = (_id: SettingId): SectionName[] => { +export const useEditableSettingsGroupSections = (_id: SettingId, tab?: TabId): SectionName[] => { const { queryGroupSections } = useContext(EditableSettingsContext); - const subscription = useMemo(() => queryGroupSections(_id), [queryGroupSections, _id]); + const subscription = useMemo(() => queryGroupSections(_id, tab), [queryGroupSections, _id, tab]); + return useSubscription(subscription); +}; + +export const useEditableSettingsGroupTabs = (_id: SettingId): TabId[] => { + const { queryGroupTabs } = useContext(EditableSettingsContext); + + const subscription = useMemo(() => queryGroupTabs(_id), [queryGroupTabs, _id]); return useSubscription(subscription); }; diff --git a/client/contexts/ModalContext.ts b/client/contexts/ModalContext.ts index 5cbd9deaccf2..0f36c6ece8ae 100644 --- a/client/contexts/ModalContext.ts +++ b/client/contexts/ModalContext.ts @@ -1,12 +1,16 @@ import { createContext, useContext, ReactNode } from 'react'; -type ModalContextValue = unknown & { +import { modal } from '../../app/ui-utils/client'; + +type ModalContextValue = typeof modal & { setModal: (modal: ReactNode) => void; }; -export const ModalContext = createContext({ - setModal: () => undefined, -}); +export const ModalContext = createContext( + Object.assign(modal, { + setModal: () => undefined, + }), +); export const useModal = (): ModalContextValue => useContext(ModalContext); diff --git a/client/contexts/ServerContext/endpoints.ts b/client/contexts/ServerContext/endpoints.ts index c69e2741abcf..96d5cc12ce97 100644 --- a/client/contexts/ServerContext/endpoints.ts +++ b/client/contexts/ServerContext/endpoints.ts @@ -10,6 +10,7 @@ import type { DnsEndpoints } from './endpoints/v1/dns'; import type { EmojiCustomEndpoints } from './endpoints/v1/emojiCustom'; import type { GroupsEndpoints } from './endpoints/v1/groups'; import type { ImEndpoints } from './endpoints/v1/im'; +import type { LDAPEndpoints } from './endpoints/v1/ldap'; import type { MiscEndpoints } from './endpoints/v1/misc'; import type { OmnichannelEndpoints } from './endpoints/v1/omnichannel'; import type { RoomsEndpoints } from './endpoints/v1/rooms'; @@ -25,6 +26,7 @@ type Endpoints = ChatEndpoints & EmojiCustomEndpoints & GroupsEndpoints & ImEndpoints & + LDAPEndpoints & RoomsEndpoints & TeamsEndpoints & UsersEndpoints & diff --git a/client/contexts/ServerContext/endpoints/v1/ldap.ts b/client/contexts/ServerContext/endpoints/v1/ldap.ts new file mode 100644 index 000000000000..068b797107e4 --- /dev/null +++ b/client/contexts/ServerContext/endpoints/v1/ldap.ts @@ -0,0 +1,14 @@ +import type { TranslationKey } from '../../../TranslationContext'; + +export type LDAPEndpoints = { + 'ldap.testConnection': { + POST: () => { + message: TranslationKey; + }; + }; + 'ldap.syncNow': { + POST: () => { + message: TranslationKey; + }; + }; +}; diff --git a/client/contexts/SettingsContext.ts b/client/contexts/SettingsContext.ts index e2d11f0382b2..acce6af51fd0 100644 --- a/client/contexts/SettingsContext.ts +++ b/client/contexts/SettingsContext.ts @@ -1,12 +1,13 @@ import { createContext, useCallback, useContext, useMemo } from 'react'; import { useSubscription, Subscription, Unsubscribe } from 'use-subscription'; -import { SettingId, ISetting, GroupId, SectionName } from '../../definition/ISetting'; +import { SettingId, ISetting, GroupId, SectionName, TabId } from '../../definition/ISetting'; export type SettingsContextQuery = { readonly _id?: SettingId[]; readonly group?: GroupId; readonly section?: SectionName; + readonly tab?: TabId; }; export type SettingsContextValue = { diff --git a/client/importPackages.ts b/client/importPackages.ts index 6d7330c66d65..15b23214b371 100644 --- a/client/importPackages.ts +++ b/client/importPackages.ts @@ -24,7 +24,6 @@ import '../app/importer-hipchat-enterprise/client'; import '../app/importer-slack/client'; import '../app/importer-slack-users/client'; import '../app/integrations/client/startup'; -import '../app/ldap/client'; import '../app/lib/client'; import '../app/livestream/client'; import '../app/logger/client'; diff --git a/client/providers/EditableSettingsProvider.tsx b/client/providers/EditableSettingsProvider.tsx index d8516e4937d9..489d0d8915dc 100644 --- a/client/providers/EditableSettingsProvider.tsx +++ b/client/providers/EditableSettingsProvider.tsx @@ -1,9 +1,10 @@ import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { Mongo } from 'meteor/mongo'; import { Tracker } from 'meteor/tracker'; +import { FilterQuery } from 'mongodb'; import React, { useEffect, useMemo, FunctionComponent, useRef, MutableRefObject } from 'react'; -import { SettingId, GroupId } from '../../definition/ISetting'; +import { SettingId, GroupId, ISetting, TabId } from '../../definition/ISetting'; import { EditableSettingsContext, IEditableSetting, @@ -44,37 +45,36 @@ const EditableSettingsProvider: FunctionComponent } }, [getSettingsCollection, persistedSettings]); - const queryEditableSetting = useMemo( - () => - createReactiveSubscriptionFactory((_id: SettingId): IEditableSetting | undefined => { - const settingsCollection = getSettingsCollection(); - - const editableSetting = settingsCollection.findOne(_id); - - if (!editableSetting) { - return undefined; - } - - if (editableSetting.blocked) { - return { ...editableSetting, disabled: true }; - } - - if (!editableSetting.enableQuery) { - return { ...editableSetting, disabled: false }; - } - - const queries = [].concat( - typeof editableSetting.enableQuery === 'string' - ? JSON.parse(editableSetting.enableQuery) - : editableSetting.enableQuery, - ); - return { - ...editableSetting, - disabled: !queries.every((query) => settingsCollection.find(query).count() > 0), - }; - }), - [getSettingsCollection], - ); + const queryEditableSetting = useMemo(() => { + const validateSettingQueries = ( + query: undefined | string | FilterQuery | FilterQuery[], + settingsCollection: Mongo.Collection, + ): boolean => { + if (!query) { + return true; + } + + const queries = [].concat(typeof query === 'string' ? JSON.parse(query) : query); + return queries.every((query) => settingsCollection.find(query).count() > 0); + }; + + return createReactiveSubscriptionFactory((_id: SettingId): IEditableSetting | undefined => { + const settingsCollection = getSettingsCollection(); + const editableSetting = settingsCollection.findOne(_id); + + if (!editableSetting) { + return undefined; + } + + return { + ...editableSetting, + disabled: + editableSetting.blocked || + !validateSettingQueries(editableSetting.enableQuery, settingsCollection), + invisible: !validateSettingQueries(editableSetting.displayQuery, settingsCollection), + }; + }); + }, [getSettingsCollection]); const queryEditableSettings = useMemo( () => @@ -84,13 +84,25 @@ const EditableSettingsProvider: FunctionComponent { ...('_id' in query && { _id: { $in: query._id } }), ...('group' in query && { group: query.group }), - ...('section' in query && - (query.section - ? { section: query.section } - : { - $or: [{ section: { $exists: false } }, { section: '' }], - })), ...('changed' in query && { changed: query.changed }), + $and: [ + { + ...('section' in query && + (query.section + ? { section: query.section } + : { + $or: [{ section: { $exists: false } }, { section: '' }], + })), + }, + { + ...('tab' in query && + (query.tab + ? { tab: query.tab } + : { + $or: [{ tab: { $exists: false } }, { tab: '' }], + })), + }, + ], }, { sort: { @@ -107,21 +119,26 @@ const EditableSettingsProvider: FunctionComponent const queryGroupSections = useMemo( () => - createReactiveSubscriptionFactory((_id: GroupId) => + createReactiveSubscriptionFactory((_id: GroupId, tab?: TabId) => Array.from( new Set( getSettingsCollection() .find( { group: _id, + ...(tab !== undefined + ? { tab } + : { + $or: [{ tab: { $exists: false } }, { tab: '' }], + }), }, { fields: { section: 1, }, sort: { - section: 1, sorter: 1, + section: 1, i18nLabel: 1, }, }, @@ -134,6 +151,35 @@ const EditableSettingsProvider: FunctionComponent [getSettingsCollection], ); + const queryGroupTabs = useMemo( + () => + createReactiveSubscriptionFactory((_id: GroupId) => + Array.from( + new Set( + getSettingsCollection() + .find( + { + group: _id, + }, + { + fields: { + tab: 1, + }, + sort: { + sorter: 1, + tab: 1, + i18nLabel: 1, + }, + }, + ) + .fetch() + .map(({ tab }) => tab || ''), + ), + ), + ), + [getSettingsCollection], + ); + const dispatch = useMutableCallback((changes: Partial[]): void => { for (const { _id, ...data } of changes) { if (!_id) { @@ -150,9 +196,10 @@ const EditableSettingsProvider: FunctionComponent queryEditableSetting, queryEditableSettings, queryGroupSections, + queryGroupTabs, dispatch, }), - [queryEditableSetting, queryEditableSettings, queryGroupSections, dispatch], + [queryEditableSetting, queryEditableSettings, queryGroupSections, queryGroupTabs, dispatch], ); return ; diff --git a/client/startup/index.ts b/client/startup/index.ts index 45b84b684b97..09f4a62d0c44 100644 --- a/client/startup/index.ts +++ b/client/startup/index.ts @@ -7,6 +7,7 @@ import './e2e'; import './emailVerification'; import './i18n'; import './listenActiveUsers'; +import './ldap'; import './loginViaQuery'; import './messageTypes'; import './notifications'; diff --git a/client/startup/ldap.ts b/client/startup/ldap.ts new file mode 100644 index 000000000000..03fbec1470bd --- /dev/null +++ b/client/startup/ldap.ts @@ -0,0 +1,20 @@ +import { Accounts } from 'meteor/accounts-base'; +import { Meteor } from 'meteor/meteor'; + +(Meteor as any).loginWithLDAP = function ( + username: string, + password: string, + callback?: (err?: any) => void, +): void { + Accounts.callLoginMethod({ + methodArguments: [ + { + ldap: true, + username, + ldapPass: password, + ldapOptions: {}, + }, + ], + userCallback: callback, + }); +}; diff --git a/client/views/account/AccountProfilePage.js b/client/views/account/AccountProfilePage.js index 9f0755c59215..243beac6c36d 100644 --- a/client/views/account/AccountProfilePage.js +++ b/client/views/account/AccountProfilePage.js @@ -54,16 +54,12 @@ const AccountProfilePage = () => { const erasureType = useSetting('Message_ErasureType'); const allowRealNameChange = useSetting('Accounts_AllowRealNameChange'); const allowUserStatusMessageChange = useSetting('Accounts_AllowUserStatusMessageChange'); - const allowUsernameChange = useSetting('Accounts_AllowUsernameChange'); + const canChangeUsername = useSetting('Accounts_AllowUsernameChange'); const allowEmailChange = useSetting('Accounts_AllowEmailChange'); let allowPasswordChange = useSetting('Accounts_AllowPasswordChange'); const allowOAuthPasswordChange = useSetting('Accounts_AllowPasswordChangeForOAuthUsers'); const allowUserAvatarChange = useSetting('Accounts_AllowUserAvatarChange'); const allowDeleteOwnAccount = useSetting('Accounts_AllowDeleteOwnAccount'); - const ldapEnabled = useSetting('LDAP_Enable'); - const ldapUsernameField = useSetting('LDAP_Username_Field'); - // whether the username is forced to match LDAP: - const ldapUsernameLinked = ldapEnabled && ldapUsernameField; const requireName = useSetting('Accounts_RequireNameForSignUp'); const namesRegexSetting = useSetting('UTF8_User_Names_Validation'); @@ -73,8 +69,6 @@ const AccountProfilePage = () => { const namesRegex = useMemo(() => new RegExp(`^${namesRegexSetting}$`), [namesRegexSetting]); - const canChangeUsername = allowUsernameChange && !ldapUsernameLinked; - const settings = useMemo( () => ({ allowRealNameChange, diff --git a/client/views/admin/settings/GroupPage.js b/client/views/admin/settings/GroupPage.js index 7bf46054d2cf..27605f2bc794 100644 --- a/client/views/admin/settings/GroupPage.js +++ b/client/views/admin/settings/GroupPage.js @@ -13,7 +13,14 @@ import { useTranslation, useLoadLanguage } from '../../../contexts/TranslationCo import { useUser } from '../../../contexts/UserContext'; import GroupPageSkeleton from './GroupPageSkeleton'; -function GroupPage({ children, headerButtons, _id, i18nLabel, i18nDescription }) { +function GroupPage({ + children = undefined, + headerButtons = undefined, + _id, + i18nLabel, + i18nDescription = undefined, + tabs = undefined, +}) { const changedEditableSettings = useEditableSettings( useMemo( () => ({ @@ -136,6 +143,8 @@ function GroupPage({ children, headerButtons, _id, i18nLabel, i18nDescription }) + {tabs} + {t.has(i18nDescription) && ( diff --git a/client/views/admin/settings/GroupSelector.tsx b/client/views/admin/settings/GroupSelector.tsx index 4656339ffaea..75bf54626fcf 100644 --- a/client/views/admin/settings/GroupSelector.tsx +++ b/client/views/admin/settings/GroupSelector.tsx @@ -4,8 +4,9 @@ import { GroupId } from '../../../../definition/ISetting'; import { useSettingStructure } from '../../../contexts/SettingsContext'; import GroupPage from './GroupPage'; import AssetsGroupPage from './groups/AssetsGroupPage'; -import GenericGroupPage from './groups/GenericGroupPage'; +import LDAPGroupPage from './groups/LDAPGroupPage'; import OAuthGroupPage from './groups/OAuthGroupPage'; +import TabbedGroupPage from './groups/TabbedGroupPage'; type GroupSelectorProps = { groupId: GroupId; @@ -26,7 +27,11 @@ const GroupSelector: FunctionComponent = ({ groupId }) => { return ; } - return ; + if (groupId === 'LDAP') { + return ; + } + + return ; }; export default GroupSelector; diff --git a/client/views/admin/settings/MemoizedSetting.js b/client/views/admin/settings/MemoizedSetting.js index 3454bba36e62..4aa7e73402a1 100644 --- a/client/views/admin/settings/MemoizedSetting.js +++ b/client/views/admin/settings/MemoizedSetting.js @@ -27,8 +27,13 @@ const MemoizedSetting = ({ onChangeValue = () => {}, onChangeEditor = () => {}, className, + invisible, ...inputProps }) => { + if (invisible) { + return null; + } + const InputComponent = { boolean: BooleanSettingInput, diff --git a/client/views/admin/settings/Section.js b/client/views/admin/settings/Section.js index e6f1065f8c98..fbc60b2f95ad 100644 --- a/client/views/admin/settings/Section.js +++ b/client/views/admin/settings/Section.js @@ -10,14 +10,23 @@ import { useTranslation } from '../../../contexts/TranslationContext'; import SectionSkeleton from './SectionSkeleton'; import Setting from './Setting'; -function Section({ children, groupId, hasReset = true, help, sectionName, solo }) { +function Section({ + children = undefined, + groupId, + hasReset = true, + help = undefined, + sectionName, + tabName, + solo, +}) { const editableSettings = useEditableSettings( useMemo( () => ({ group: groupId, section: sectionName, + tab: tabName, }), - [groupId, sectionName], + [groupId, sectionName, tabName], ), ); diff --git a/client/views/admin/settings/Setting.js b/client/views/admin/settings/Setting.js index ff7f724c72ba..15342fac5046 100644 --- a/client/views/admin/settings/Setting.js +++ b/client/views/admin/settings/Setting.js @@ -87,6 +87,7 @@ function Setting({ className, settingId, sectionChanged }) { i18nLabel, i18nDescription, alert, + invisible, } = setting; const label = (i18nLabel && t(i18nLabel)) || _id || t(_id); @@ -122,6 +123,7 @@ function Setting({ className, settingId, sectionChanged }) { onChangeValue={onChangeValue} onChangeEditor={onChangeEditor} onResetButtonClick={onResetButtonClick} + invisible={invisible} /> ); } diff --git a/client/views/admin/settings/groups/LDAPGroupPage.tsx b/client/views/admin/settings/groups/LDAPGroupPage.tsx new file mode 100644 index 000000000000..c32d42e8b111 --- /dev/null +++ b/client/views/admin/settings/groups/LDAPGroupPage.tsx @@ -0,0 +1,103 @@ +import { Button } from '@rocket.chat/fuselage'; +import React, { memo, useMemo } from 'react'; + +import type { ISetting } from '../../../../../definition/ISetting'; +import { useEditableSettings } from '../../../../contexts/EditableSettingsContext'; +import { useModal } from '../../../../contexts/ModalContext'; +import { useEndpoint } from '../../../../contexts/ServerContext'; +import { useSetting } from '../../../../contexts/SettingsContext'; +import { useToastMessageDispatch } from '../../../../contexts/ToastMessagesContext'; +import { useTranslation } from '../../../../contexts/TranslationContext'; +import TabbedGroupPage from './TabbedGroupPage'; + +function LDAPGroupPage({ _id, ...group }: ISetting): JSX.Element { + const t = useTranslation(); + const dispatchToastMessage = useToastMessageDispatch(); + const testConnection = useEndpoint('POST', 'ldap.testConnection'); + const syncNow = useEndpoint('POST', 'ldap.syncNow'); + const ldapEnabled = useSetting('LDAP_Enable'); + const ldapSyncEnabled = useSetting('LDAP_Background_Sync') && ldapEnabled; + const modal = useModal(); + + const editableSettings = useEditableSettings( + useMemo( + () => ({ + group: _id, + }), + [_id], + ), + ); + + const changed = useMemo( + () => editableSettings.some(({ changed }) => changed), + [editableSettings], + ); + + const handleTestConnectionButtonClick = async (): Promise => { + try { + const { message } = await testConnection(undefined); + dispatchToastMessage({ type: 'success', message: t(message) }); + } catch (error) { + dispatchToastMessage({ type: 'error', message: error }); + } + }; + + const handleSyncNowButtonClick = async (): Promise => { + try { + await testConnection(undefined); + // #ToDo: Switch to modal.setModal + modal.open( + { + title: t('Execute_Synchronization_Now'), + text: t('LDAP_Sync_Now_Description'), + confirmButtonText: t('Sync'), + showCancelButton: true, + closeOnConfirm: true, + closeOnCancel: true, + }, + async (isConfirm: boolean): Promise => { + if (!isConfirm) { + return; + } + + try { + const { message } = await syncNow(undefined); + dispatchToastMessage({ type: 'success', message: t(message) }); + } catch (error) { + dispatchToastMessage({ type: 'error', message: error }); + } + }, + ); + } catch (error) { + dispatchToastMessage({ type: 'error', message: error }); + } + }; + + return ( + + + + } + /> + ); +} + +export default memo(LDAPGroupPage); diff --git a/client/views/admin/settings/groups/TabbedGroupPage.tsx b/client/views/admin/settings/groups/TabbedGroupPage.tsx new file mode 100644 index 000000000000..53a109feb31e --- /dev/null +++ b/client/views/admin/settings/groups/TabbedGroupPage.tsx @@ -0,0 +1,66 @@ +import { Tabs } from '@rocket.chat/fuselage'; +import React, { ReactNode, memo, useState, useMemo } from 'react'; + +import { + useEditableSettingsGroupSections, + useEditableSettingsGroupTabs, +} from '../../../../contexts/EditableSettingsContext'; +import { useTranslation, TranslationKey } from '../../../../contexts/TranslationContext'; +import GroupPage from '../GroupPage'; +import Section from '../Section'; +import GenericGroupPage from './GenericGroupPage'; + +function TabbedGroupPage({ + _id, + ...group +}: { + children?: ReactNode; + headerButtons?: ReactNode; + _id: string; + i18nLabel: string; + i18nDescription?: string; + tabs?: ReactNode; +}): JSX.Element { + const t = useTranslation(); + const tabs = useEditableSettingsGroupTabs(_id); + + const [tab, setTab] = useState(tabs[0]); + const handleTabClick = useMemo(() => (tab: string) => (): void => setTab(tab), [setTab]); + const sections = useEditableSettingsGroupSections(_id, tab); + + const solo = sections.length === 1; + + if (!tabs.length || (tabs.length === 1 && !tabs[0])) { + return ; + } + + if (!tab && tabs[0]) { + setTab(tabs[0]); + } + + const tabsComponent = ( + + {tabs.map((tabName) => ( + + {tabName ? t(tabName as TranslationKey) : t(_id as TranslationKey)} + + ))} + + ); + + return ( + + {sections.map((sectionName) => ( +
+ ))} + + ); +} + +export default memo(TabbedGroupPage); diff --git a/app/importer/server/definitions/IImportChannel.ts b/definition/IImportChannel.ts similarity index 100% rename from app/importer/server/definitions/IImportChannel.ts rename to definition/IImportChannel.ts diff --git a/app/importer/server/definitions/IImportMessage.ts b/definition/IImportMessage.ts similarity index 100% rename from app/importer/server/definitions/IImportMessage.ts rename to definition/IImportMessage.ts diff --git a/app/importer/server/definitions/IImportRecord.ts b/definition/IImportRecord.ts similarity index 70% rename from app/importer/server/definitions/IImportRecord.ts rename to definition/IImportRecord.ts index 09d3a9418ef4..e95c6e5cd4dd 100644 --- a/app/importer/server/definitions/IImportRecord.ts +++ b/definition/IImportRecord.ts @@ -2,11 +2,19 @@ import { IImportUser } from './IImportUser'; import { IImportChannel } from './IImportChannel'; import { IImportMessage } from './IImportMessage'; +export type IImportRecordType = 'user' | 'channel' | 'message'; +export type IImportData = IImportUser | IImportChannel | IImportMessage; + export interface IImportRecord { - data: IImportUser | IImportChannel | IImportMessage; - dataType: 'user' | 'channel' | 'message'; + data: IImportData; + dataType: IImportRecordType; _id: string; options?: {}; + errors?: Array<{ + message: string; + stack?: string; + }>; + skipped?: boolean; } export interface IImportUserRecord extends IImportRecord { diff --git a/app/importer/server/definitions/IImportUser.ts b/definition/IImportUser.ts similarity index 80% rename from app/importer/server/definitions/IImportUser.ts rename to definition/IImportUser.ts index 6462cb054a9e..e1f8543805c6 100644 --- a/app/importer/server/definitions/IImportUser.ts +++ b/definition/IImportUser.ts @@ -7,11 +7,13 @@ export interface IImportUser { importIds: Array; name?: string; utcOffset?: number; - active?: boolean; avatarUrl?: string; deleted?: boolean; statusText?: string; roles?: Array; type: 'user' | 'bot'; bio?: string; + + services?: Record>; + customFields?: Record; } diff --git a/definition/IRoom.ts b/definition/IRoom.ts index 047fbfa198fd..307badc75255 100644 --- a/definition/IRoom.ts +++ b/definition/IRoom.ts @@ -63,6 +63,10 @@ export interface IRoom extends IRocketChatRecord { muted?: string[]; } +export interface ICreatedRoom extends IRoom { + rid: string; +} + export interface IDirectMessageRoom extends Omit { t: 'd'; uids: Array; diff --git a/definition/ISetting.ts b/definition/ISetting.ts index 8ee649a459ef..257c86f74421 100644 --- a/definition/ISetting.ts +++ b/definition/ISetting.ts @@ -2,6 +2,7 @@ import { FilterQuery } from 'mongodb'; export type SettingId = string; export type GroupId = SettingId; +export type TabId = SettingId; export type SectionName = string; export enum SettingEditor { @@ -25,6 +26,7 @@ export interface ISetting { env: boolean; group?: GroupId; section?: SectionName; + tab?: TabId; i18nLabel: string; value: SettingValue; packageValue: SettingValue; @@ -32,6 +34,7 @@ export interface ISetting { packageEditor?: SettingEditor; blocked: boolean; enableQuery?: string | FilterQuery | FilterQuery[]; + displayQuery?: string | FilterQuery | FilterQuery[]; sorter?: number; properties?: unknown; enterprise?: boolean; diff --git a/definition/IUser.ts b/definition/IUser.ts index 872c1f8dd89e..732c684961ba 100644 --- a/definition/IUser.ts +++ b/definition/IUser.ts @@ -33,6 +33,13 @@ export interface IUserEmailCode { type LoginToken = IMeteorLoginToken & IPersonalAccessToken; export type Username = string; +export type ILoginUsername = { + username: string; +} | { + email: string; +} +export type LoginUsername = string | ILoginUsername; + export interface IUserServices { password?: { bcrypt: string; @@ -64,6 +71,10 @@ export interface IUserServices { idpSession?: string; nameID?: string; }; + ldap?: { + id: string; + idAttribute?: string; + }; } export interface IUserEmail { @@ -129,6 +140,7 @@ export interface IUser extends IRocketChatRecord { }; settings?: IUserSettings; defaultRoom?: string; + ldap?: boolean; } export type IUserDataEvent = { diff --git a/definition/ldap-escape.d.ts b/definition/ldap-escape.d.ts new file mode 100644 index 000000000000..68ef34116548 --- /dev/null +++ b/definition/ldap-escape.d.ts @@ -0,0 +1,4 @@ +declare module 'ldap-escape' { + export function filter(strings: TemplateStringsArray, ...values: string[]): string; + export function dn(strings: TemplateStringsArray, ...values: string[]): string; +} diff --git a/definition/ldap/ILDAPCallback.ts b/definition/ldap/ILDAPCallback.ts new file mode 100644 index 000000000000..1b4a87b45e4c --- /dev/null +++ b/definition/ldap/ILDAPCallback.ts @@ -0,0 +1,12 @@ +export interface ILDAPCallback { + (error?: Error | null, result?: any): void; +} + +export interface ILDAPPageData { + end: boolean; + next: Function | undefined; +} + +export interface ILDAPPageCallback { + (error?: Error | null, result?: any, page?: ILDAPPageData): void; +} diff --git a/definition/ldap/ILDAPEntry.ts b/definition/ldap/ILDAPEntry.ts new file mode 100644 index 000000000000..e14ac9d4d665 --- /dev/null +++ b/definition/ldap/ILDAPEntry.ts @@ -0,0 +1,3 @@ +export interface ILDAPEntry extends Record { + _raw: Record; +} diff --git a/definition/ldap/ILDAPLoginRequest.ts b/definition/ldap/ILDAPLoginRequest.ts new file mode 100644 index 000000000000..4cdce6b55705 --- /dev/null +++ b/definition/ldap/ILDAPLoginRequest.ts @@ -0,0 +1,6 @@ +export interface ILDAPLoginRequest { + ldap?: boolean; + ldapOptions?: Record; + username: string; + ldapPass: string; +} diff --git a/definition/ldap/ILDAPLoginResult.ts b/definition/ldap/ILDAPLoginResult.ts new file mode 100644 index 000000000000..35b7dd936d1c --- /dev/null +++ b/definition/ldap/ILDAPLoginResult.ts @@ -0,0 +1,5 @@ +export interface ILDAPLoginResult extends Record { + userId?: string; +} + +export type LDAPLoginResult = ILDAPLoginResult | undefined; diff --git a/definition/ldap/ILDAPOptions.ts b/definition/ldap/ILDAPOptions.ts new file mode 100644 index 000000000000..32a8494de1d5 --- /dev/null +++ b/definition/ldap/ILDAPOptions.ts @@ -0,0 +1,27 @@ +export type LDAPEncryptionType = 'plain' | 'tls' | 'ssl'; +export type LDAPSearchScope = 'base' | 'one' | 'sub'; + +export interface ILDAPConnectionOptions { + host?: string; + port: number; + reconnect: boolean; + timeout: number; + connectionTimeout: number; + idleTimeout: number; + encryption: LDAPEncryptionType; + caCert?: string; + rejectUnauthorized: boolean; + baseDN: string; + userSearchFilter: string; + userSearchScope: LDAPSearchScope; + userSearchField: string; + searchPageSize: number; + searchSizeLimit: number; + uniqueIdentifierField?: string; + groupFilterEnabled: boolean; + groupFilterObjectClass?: string; + groupFilterGroupIdAttribute?: string; + groupFilterGroupMemberAttribute?: string; + groupFilterGroupMemberFormat?: string; + groupFilterGroupName?: string; +} diff --git a/definition/ldap/ILDAPUniqueIdentifierField.ts b/definition/ldap/ILDAPUniqueIdentifierField.ts new file mode 100644 index 000000000000..b9225eff0f7f --- /dev/null +++ b/definition/ldap/ILDAPUniqueIdentifierField.ts @@ -0,0 +1,4 @@ +export type ILDAPUniqueIdentifierField = { + attribute: string; + value: string; +} diff --git a/definition/meteor-sha.d.ts b/definition/meteor-sha.d.ts new file mode 100644 index 000000000000..2fe3e399a1ce --- /dev/null +++ b/definition/meteor-sha.d.ts @@ -0,0 +1,3 @@ +declare module 'meteor/sha' { + function SHA256(input: string): string; +} diff --git a/ee/app/ldap-enterprise/README.md b/ee/app/ldap-enterprise/README.md deleted file mode 100644 index 24c81fd3cbcb..000000000000 --- a/ee/app/ldap-enterprise/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# LDAP-Enterprise - -This package enables the administrator option to map the roles used on your LDAP server with the Rocket.Chat server roles. -With the correspondent license for this product, a new "Roles" section will be enabled in the admin panel in the LDAP group, -where the administrator can map LDAP roles to Rocket.Chat roles`(Admin panel -> LDAP -> Roles)`, following the pattern described below: - -``` -{ - "ldapRole": "["admin", "guest"], //must be an array of valid Rocket.Chat Users Roles - "anotherLdapRole": "["anonymous"] -} - -``` -**Note:** If some mapping error occurs, be aware of the server log, that the error will be shown. -
-
-In addition to the options described above, still in the same section, there are other options such as: -* `LDAP_Enable_LDAP_Roles_To_RC_Roles`: Enable or disable this feature; -* `LDAP_Validate_Roles_For_Each_Login`: If the validation should occurs for each login (**Be careful with this setting because it will overwrite -the user roles in each login, otherwise this will be validated only at the moment of user creation**); -* `LDAP_Default_Role_To_User`: The default Rocket.Chat role to be defined, if any LDAP role that the user has, is not mapped; -* `LDAP_Query_To_Get_User_Groups`: The LDAP query to get the LDAP groups that the user is part of; diff --git a/ee/app/ldap-enterprise/server/hooks/beforeSearchAll.js b/ee/app/ldap-enterprise/server/hooks/beforeSearchAll.js deleted file mode 100644 index 3bf15d468386..000000000000 --- a/ee/app/ldap-enterprise/server/hooks/beforeSearchAll.js +++ /dev/null @@ -1,11 +0,0 @@ -export const beforeSearchAll = (searchParams) => { - const { options } = searchParams; - - if (!Array.isArray(options.attributes)) { - options.attributes = options.attributes ? [options.attributes] : ['*']; - } - - options.attributes.push('pwdAccountLockedTime'); - - return searchParams; -}; diff --git a/ee/app/ldap-enterprise/server/hooks/syncExistentUser.js b/ee/app/ldap-enterprise/server/hooks/syncExistentUser.js deleted file mode 100644 index a91b574e4a34..000000000000 --- a/ee/app/ldap-enterprise/server/hooks/syncExistentUser.js +++ /dev/null @@ -1,19 +0,0 @@ -import { logger } from '../../../../../app/ldap/server/sync'; -import { setUserActiveStatus } from '../../../../../app/lib/server/functions/setUserActiveStatus'; -import { settings } from '../../../../../app/settings'; - -export const syncExistentUser = ({ ldapUser, user }) => { - const activate = !!ldapUser && !ldapUser.pwdAccountLockedTime; - - if (activate === user.active) { - return; - } - - const syncUserState = settings.get('LDAP_Sync_User_Active_State'); - if (syncUserState === 'none' || (syncUserState === 'disable' && activate)) { - return; - } - - setUserActiveStatus(user._id, activate); - logger.info(`${ activate ? 'Activating' : 'Deactivating' } user ${ user.name } (${ user._id })`); -}; diff --git a/ee/app/ldap-enterprise/server/index.js b/ee/app/ldap-enterprise/server/index.js deleted file mode 100644 index dcea594531d2..000000000000 --- a/ee/app/ldap-enterprise/server/index.js +++ /dev/null @@ -1,69 +0,0 @@ -import { Meteor } from 'meteor/meteor'; - - -import { syncExistentUser } from './hooks/syncExistentUser'; -import { beforeSearchAll } from './hooks/beforeSearchAll'; -import { callbacks } from '../../../../app/callbacks/server'; -import { settings } from '../../../../app/settings'; -import { onLicense } from '../../license/server'; - -onLicense('ldap-enterprise', () => { - const { createSettings } = require('./settings'); - const { validateLDAPRolesMappingChanges, validateLDAPTeamsMappingChanges } = require('./ldapEnterprise'); - const { onLdapLogin } = require('./listener'); - - Meteor.startup(function() { - createSettings(); - validateLDAPRolesMappingChanges(); - validateLDAPTeamsMappingChanges(); - - let LDAP_Enable_LDAP_Roles_To_RC_Roles; - let LDAP_Enable_LDAP_Groups_To_RC_Teams; - let callbackEnabled = false; - let LDAP_Sync_User_Active_State; - - const updateCallbackState = () => { - if (callbackEnabled) { - if (!LDAP_Enable_LDAP_Roles_To_RC_Roles && !LDAP_Enable_LDAP_Groups_To_RC_Teams) { - callbacks.remove('afterLDAPLogin', 'checkRoleMapping'); - callbackEnabled = false; - } - - return; - } - - if (LDAP_Enable_LDAP_Roles_To_RC_Roles || LDAP_Enable_LDAP_Groups_To_RC_Teams) { - callbackEnabled = true; - callbacks.add('afterLDAPLogin', onLdapLogin, callbacks.priority.MEDIUM, 'checkRoleMapping'); - } - }; - - settings.get('LDAP_Enable_LDAP_Roles_To_RC_Roles', (key, value) => { - LDAP_Enable_LDAP_Roles_To_RC_Roles = value; - updateCallbackState(); - }); - - settings.get('LDAP_Enable_LDAP_Groups_To_RC_Teams', (key, value) => { - LDAP_Enable_LDAP_Groups_To_RC_Teams = value; - updateCallbackState(); - }); - - settings.get('LDAP_Sync_User_Active_State', (key, value) => { - if (LDAP_Sync_User_Active_State === value) { - return; - } - - if (value === 'none') { - // If it changed to 'none', disable - callbacks.remove('ldap.afterSyncExistentUser', 'ldap-sync-user-active-state'); - } else if (LDAP_Sync_User_Active_State === 'none' || !LDAP_Sync_User_Active_State) { - // If it changed from 'none' to something else, enable - callbacks.add('ldap.afterSyncExistentUser', syncExistentUser, callbacks.priority.MEDIUM, 'ldap-sync-user-active-state'); - } - - LDAP_Sync_User_Active_State = value; - }); - - callbacks.add('ldap.beforeSearchAll', beforeSearchAll, callbacks.priority.MEDIUM, 'ldap-return-attribute-AccountLockedTime'); - }); -}); diff --git a/ee/app/ldap-enterprise/server/ldapEnterprise.js b/ee/app/ldap-enterprise/server/ldapEnterprise.js deleted file mode 100644 index 02e9718780b6..000000000000 --- a/ee/app/ldap-enterprise/server/ldapEnterprise.js +++ /dev/null @@ -1,144 +0,0 @@ -import { Meteor } from 'meteor/meteor'; - -import { Roles } from '../../../../app/models'; -import { Logger } from '../../../../app/logger'; -import { settings } from '../../../../app/settings'; -import { Team } from '../../../../server/sdk'; - -const logger = new Logger('ldapEnterprise'); - -const mustBeAnArrayOfStrings = (array) => Array.isArray(array) && array.length && array.every((item) => typeof item === 'string'); - -const validateRoleMapping = (mappedRoles) => { - const allRocketChatUserRoles = Roles.find({ scope: 'Users' }).fetch().map((role) => role._id); - const mappedRocketChatRoles = Object.values(mappedRoles); - const validRolesMapping = mappedRocketChatRoles.every((roles) => roles.every((role) => allRocketChatUserRoles.includes(role))); - if (!validRolesMapping) { - throw new Error('Please verify your mapping for LDAP X RocketChat Roles. There is some invalid Rocket Chat Role.'); - } -}; - -const validateLDAPRolesMappingStructure = (mappedRoles) => { - const mappedRocketChatRoles = Object.values(mappedRoles); - const validStructureMapping = mappedRocketChatRoles.every(mustBeAnArrayOfStrings); - if (!validStructureMapping) { - throw new Error('Please verify your mapping for LDAP X RocketChat Roles. The structure is invalid, the structure should be an object like: {key: LdapRole, value: [An array of rocket.chat roles]}'); - } -}; - -const validateLDAPTeamsMappingStructure = (mappedTeams) => { - const mappedRocketChatTeams = Object.values(mappedTeams); - const validStructureMapping = mappedRocketChatTeams.every(mustBeAnArrayOfStrings); - if (!validStructureMapping) { - throw new Error('Please verify your mapping for LDAP X RocketChat Teams. The structure is invalid, the structure should be an object like: {key: LdapTeam, value: [An array of rocket.chat teams]}'); - } -}; - -export const getLdapRolesByUsername = (username, ldap) => { - const searchOptions = { - filter: settings.get('LDAP_Query_To_Get_User_Groups').replace(/#{username}/g, username), - scope: ldap.options.User_Search_Scope || 'sub', - sizeLimit: ldap.options.Search_Size_Limit, - }; - const getLdapRoles = (ldapUserGroups) => ldapUserGroups.filter((field) => field && field.ou).map((field) => field.ou); - const ldapUserGroups = ldap.searchAllSync(ldap.options.BaseDN, searchOptions); - return Array.isArray(ldapUserGroups) ? getLdapRoles(ldapUserGroups) : []; -}; - -export const getLdapTeamsByUsername = (username, ldap) => { - const searchOptions = { - filter: settings.get('LDAP_Query_To_Get_User_Teams').replace(/#{username}/g, username), - scope: ldap.options.User_Search_Scope || 'sub', - sizeLimit: ldap.options.Search_Size_Limit, - }; - const ldapUserGroups = ldap.searchAllSync(ldap.options.BaseDN, searchOptions); - - if (!Array.isArray(ldapUserGroups)) { - return []; - } - - return ldapUserGroups.filter((field) => field && field.ou).map((field) => field.ou).flat(); -}; - -export const getRocketChatRolesByLdapRoles = (mappedRoles, ldapUserRoles) => { - const mappedLdapRoles = Object.keys(mappedRoles); - if (!ldapUserRoles.length) { - logger.error('The LDAP user has no role, so we set the default role value'); - return [settings.get('LDAP_Default_Role_To_User')]; - } - const unmappedLdapRoles = ldapUserRoles.filter((ldapRole) => !mappedLdapRoles.includes(ldapRole)); - const getRocketChatMappedRoles = (acc, role) => acc.concat(mappedRoles[role]); - const removeRepeatedRoles = (acc, role) => (acc.includes(role) ? acc : acc.concat(role)); - if (unmappedLdapRoles.length) { - logger.error(`The following LDAP roles is/are not mapped in Rocket.Chat: "${ unmappedLdapRoles.join(', ') }". Because it, we set the default LDAP role.`); - return [settings.get('LDAP_Default_Role_To_User')]; - } - return ldapUserRoles - .reduce(getRocketChatMappedRoles, []) - .reduce(removeRepeatedRoles, []); -}; - -export const getRocketChatTeamsByLdapTeams = (mappedTeams, ldapUserTeams) => { - const mappedLdapTeams = Object.keys(mappedTeams); - const filteredTeams = ldapUserTeams.filter((ldapTeam) => mappedLdapTeams.includes(ldapTeam)); - - if (filteredTeams.length < ldapUserTeams.length) { - const unmappedLdapTeams = ldapUserTeams.filter((ldapRole) => !mappedLdapTeams.includes(ldapRole)); - logger.error(`The following LDAP teams are not mapped in Rocket.Chat: "${ unmappedLdapTeams.join(', ') }".`); - } - - if (!filteredTeams.length) { - return []; - } - - return [...new Set(filteredTeams.map((ldapTeam) => mappedTeams[ldapTeam]).flat())]; -}; - -export const updateUserUsingMappedLdapRoles = (userId, roles) => { - Meteor.users.update({ _id: userId }, { $set: { roles } }); -}; - -async function updateUserUsingMappedLdapTeamsAsync(userId, teamNames, map) { - const allTeamNames = [...new Set(Object.values(map).flat())]; - const allTeams = await Team.listByNames(allTeamNames, { projection: { _id: 1, name: 1 } }); - - const inTeamIds = allTeams.filter(({ name }) => teamNames.includes(name)).map(({ _id }) => _id); - const notInTeamIds = allTeams.filter(({ name }) => !teamNames.includes(name)).map(({ _id }) => _id); - - const currentTeams = await Team.listTeamsBySubscriberUserId(userId, { projection: { teamId: 1 } }); - const currentTeamIds = await currentTeams.map(({ teamId }) => teamId); - const teamsToRemove = currentTeamIds.filter((teamId) => notInTeamIds.includes(teamId)); - const teamsToAdd = inTeamIds.filter((teamId) => !currentTeamIds.includes(teamId)); - - await Team.insertMemberOnTeams(userId, teamsToAdd); - await Team.removeMemberFromTeams(userId, teamsToRemove); -} - -export const updateUserUsingMappedLdapTeams = (userId, teamNames, map) => Promise.await(updateUserUsingMappedLdapTeamsAsync(userId, teamNames, map)); - -export const validateLDAPRolesMappingChanges = () => { - settings.get('LDAP_Roles_To_Rocket_Chat_Roles', (key, value) => { - try { - if (value) { - const mappedRoles = JSON.parse(value); - validateLDAPRolesMappingStructure(mappedRoles); - validateRoleMapping(mappedRoles); - } - } catch (error) { - logger.error(error); - } - }); -}; - -export const validateLDAPTeamsMappingChanges = () => { - settings.get('LDAP_Groups_To_Rocket_Chat_Teams', (key, value) => { - try { - if (value) { - const mappedTeams = JSON.parse(value); - validateLDAPTeamsMappingStructure(mappedTeams); - } - } catch (error) { - logger.error(error); - } - }); -}; diff --git a/ee/app/ldap-enterprise/server/listener.js b/ee/app/ldap-enterprise/server/listener.js deleted file mode 100644 index e1ed7a0e81bf..000000000000 --- a/ee/app/ldap-enterprise/server/listener.js +++ /dev/null @@ -1,30 +0,0 @@ -import { settings } from '../../../../app/settings'; -import { - getLdapRolesByUsername, - getRocketChatRolesByLdapRoles, - updateUserUsingMappedLdapRoles, - getLdapTeamsByUsername, - getRocketChatTeamsByLdapTeams, - updateUserUsingMappedLdapTeams, -} from './ldapEnterprise'; - -export const onLdapLogin = ({ user, ldapUser, ldap }) => { - const userExists = user._id; - const userId = userExists ? user._id : user.userId; - - const mapRoles = settings.get('LDAP_Enable_LDAP_Roles_To_RC_Roles') && (!userExists || settings.get('LDAP_Validate_Roles_For_Each_Login')); - const mapTeams = settings.get('LDAP_Enable_LDAP_Groups_To_RC_Teams') && (!userExists || settings.get('LDAP_Validate_Teams_For_Each_Login')); - - if (mapRoles) { - const ldapUserRoles = getLdapRolesByUsername(ldapUser.uid, ldap); - const roles = getRocketChatRolesByLdapRoles(JSON.parse(settings.get('LDAP_Roles_To_Rocket_Chat_Roles')), ldapUserRoles); - updateUserUsingMappedLdapRoles(userId, roles); - } - - if (mapTeams) { - const ldapUserTeams = getLdapTeamsByUsername(ldapUser.uid, ldap); - const map = JSON.parse(settings.get('LDAP_Groups_To_Rocket_Chat_Teams')); - const teams = getRocketChatTeamsByLdapTeams(map, ldapUserTeams); - updateUserUsingMappedLdapTeams(userId, teams, map); - } -}; diff --git a/ee/app/ldap-enterprise/server/settings.js b/ee/app/ldap-enterprise/server/settings.js deleted file mode 100644 index 2b3142b4baca..000000000000 --- a/ee/app/ldap-enterprise/server/settings.js +++ /dev/null @@ -1,112 +0,0 @@ -import { settings } from '../../../../app/settings'; -import { Roles } from '../../../../app/models'; - -export const createSettings = () => { - settings.addGroup('LDAP', function() { - this.section('Role_Mapping', function() { - this.add('LDAP_Enable_LDAP_Roles_To_RC_Roles', false, { - type: 'boolean', - enableQuery: { _id: 'LDAP_Enable', value: true }, - enterprise: true, - invalidValue: false, - modules: [ - 'ldap-enterprise', - ], - }); - this.add('LDAP_Roles_To_Rocket_Chat_Roles', '{}', { - type: 'code', - enableQuery: { _id: 'LDAP_Enable_LDAP_Roles_To_RC_Roles', value: true }, - enterprise: true, - invalidValue: '{}', - modules: [ - 'ldap-enterprise', - ], - }); - this.add('LDAP_Validate_Roles_For_Each_Login', false, { - type: 'boolean', - enableQuery: { _id: 'LDAP_Enable_LDAP_Roles_To_RC_Roles', value: true }, - enterprise: true, - invalidValue: false, - modules: [ - 'ldap-enterprise', - ], - }); - this.add('LDAP_Default_Role_To_User', 'user', { - type: 'select', - values: Roles.find({ scope: 'Users' }).fetch().map((role) => ({ key: role._id, i18nLabel: role._id })), - enableQuery: { _id: 'LDAP_Enable_LDAP_Roles_To_RC_Roles', value: true }, - enterprise: true, - invalidValue: 'user', - modules: [ - 'ldap-enterprise', - ], - }); - this.add('LDAP_Query_To_Get_User_Groups', '(&(ou=*)(uniqueMember=uid=#{username},dc=example,dc=com))', { - type: 'string', - enableQuery: { _id: 'LDAP_Enable_LDAP_Roles_To_RC_Roles', value: true }, - enterprise: true, - invalidValue: '(&(ou=*)(uniqueMember=uid=#{username},dc=example,dc=com))', - modules: [ - 'ldap-enterprise', - ], - }); - }); - - this.section('Team_Mapping', function() { - this.add('LDAP_Enable_LDAP_Groups_To_RC_Teams', false, { - type: 'boolean', - enableQuery: { _id: 'LDAP_Enable', value: true }, - enterprise: true, - invalidValue: false, - modules: [ - 'ldap-enterprise', - ], - }); - this.add('LDAP_Groups_To_Rocket_Chat_Teams', '{}', { - type: 'code', - enableQuery: { _id: 'LDAP_Enable_LDAP_Groups_To_RC_Teams', value: true }, - enterprise: true, - invalidValue: '{}', - modules: [ - 'ldap-enterprise', - ], - }); - this.add('LDAP_Validate_Teams_For_Each_Login', false, { - type: 'boolean', - enableQuery: { _id: 'LDAP_Enable_LDAP_Groups_To_RC_Teams', value: true }, - enterprise: true, - invalidValue: false, - modules: [ - 'ldap-enterprise', - ], - }); - this.add('LDAP_Query_To_Get_User_Teams', '(&(ou=*)(uniqueMember=uid=#{username},dc=example,dc=com))', { - type: 'string', - enableQuery: { _id: 'LDAP_Enable_LDAP_Groups_To_RC_Teams', value: true }, - enterprise: true, - invalidValue: '(&(ou=*)(uniqueMember=uid=#{username},dc=example,dc=com))', - modules: [ - 'ldap-enterprise', - ], - }); - }); - - this.section('LDAP_Advanced_Sync', function() { - this.add('LDAP_Sync_User_Active_State', 'disable', { - type: 'select', - values: [ - { key: 'none', i18nLabel: 'LDAP_Sync_User_Active_State_Nothing' }, - { key: 'disable', i18nLabel: 'LDAP_Sync_User_Active_State_Disable' }, - { key: 'both', i18nLabel: 'LDAP_Sync_User_Active_State_Both' }, - ], - i18nDescription: 'LDAP_Sync_User_Active_State_Description', - enableQuery: { _id: 'LDAP_Enable', value: true }, - enterprise: true, - invalidValue: 'none', - modules: [ - 'ldap-enterprise', - ], - }); - }); - }); -}; diff --git a/ee/definition/ldap/ILDAPEEOptions.ts b/ee/definition/ldap/ILDAPEEOptions.ts new file mode 100644 index 000000000000..35d62f46fa1f --- /dev/null +++ b/ee/definition/ldap/ILDAPEEOptions.ts @@ -0,0 +1,5 @@ +export interface ILDAPEEConnectionOptions { + authentication: boolean; + authenticationUserDN: string; + authenticationPassword: string; +} diff --git a/ee/server/api/index.ts b/ee/server/api/index.ts index 10d46bbdca61..a0007bcae7c6 100644 --- a/ee/server/api/index.ts +++ b/ee/server/api/index.ts @@ -1 +1,2 @@ +import './ldap'; import './licenses'; diff --git a/ee/server/api/ldap.ts b/ee/server/api/ldap.ts new file mode 100644 index 000000000000..1c4627e585d0 --- /dev/null +++ b/ee/server/api/ldap.ts @@ -0,0 +1,31 @@ +import { hasRole } from '../../../app/authorization/server'; +import { settings } from '../../../app/settings/server'; +import { API } from '../../../app/api/server/api'; +import { LDAPEE } from '../sdk'; +import { hasLicense } from '../../app/license/server/license'; + +API.v1.addRoute('ldap.syncNow', { authRequired: true }, { + post() { + if (!this.userId) { + throw new Error('error-invalid-user'); + } + + if (!hasRole(this.userId, 'admin')) { + throw new Error('error-not-authorized'); + } + + if (!hasLicense('ldap-enterprise')) { + throw new Error('error-not-authorized'); + } + + if (settings.get('LDAP_Enable') !== true) { + throw new Error('LDAP_disabled'); + } + + LDAPEE.sync(); + + return API.v1.success({ + message: 'Sync_in_progress', + }); + }, +}); diff --git a/ee/server/configuration/ldap.ts b/ee/server/configuration/ldap.ts new file mode 100644 index 000000000000..1b89f5338e3d --- /dev/null +++ b/ee/server/configuration/ldap.ts @@ -0,0 +1,57 @@ +import { Meteor } from 'meteor/meteor'; +import { Promise } from 'meteor/promise'; +import _ from 'underscore'; + +import { LDAPEE } from '../sdk'; +import { settings } from '../../../app/settings/server'; +import { logger } from '../../../server/lib/ldap/Logger'; +import { cronJobs } from '../../../app/utils/server/lib/cron/Cronjobs'; +import { LDAPEEConnection } from '../lib/ldap/Connection'; +import { LDAPEEManager } from '../lib/ldap/Manager'; +import { callbacks } from '../../../app/callbacks/server'; +import type { LDAPConnection } from '../../../server/lib/ldap/Connection'; +import type { IImportUser } from '../../../definition/IImportUser'; +import type { ILDAPEntry } from '../../../definition/ldap/ILDAPEntry'; +import { onLicense } from '../../app/license/server'; + +onLicense('ldap-enterprise', () => { + // Configure background sync cronjob + const jobName = 'LDAP_Sync'; + const addCronJob = _.debounce(Meteor.bindEnvironment(function addCronJobDebounced() { + if (settings.get('LDAP_Background_Sync') !== true) { + logger.info('Disabling LDAP Background Sync'); + if (cronJobs.nextScheduledAtDate(jobName)) { + cronJobs.remove(jobName); + } + return; + } + + const schedule = settings.get('LDAP_Background_Sync_Interval'); + if (schedule) { + logger.info('Enabling LDAP Background Sync'); + cronJobs.add(jobName, schedule, () => Promise.await(LDAPEE.sync()), 'text'); + } + }), 500); + + Meteor.defer(() => { + settings.get('LDAP_Background_Sync', addCronJob); + settings.get('LDAP_Background_Sync_Interval', addCronJob); + + settings.get('LDAP_Groups_To_Rocket_Chat_Teams', (_key, value) => { + try { + LDAPEEManager.validateLDAPTeamsMappingChanges(value as string); + } catch (error) { + logger.error(error); + } + }); + }); + + callbacks.add('getLDAPConnectionClass', function(): typeof LDAPConnection { + return LDAPEEConnection; + }, callbacks.priority.HIGH, 'replaceLDAPConnectionClass'); + + callbacks.add('mapLDAPUserData', (userData: IImportUser, ldapUser: ILDAPEntry) => { + LDAPEEManager.copyCustomFields(ldapUser, userData); + LDAPEEManager.copyActiveState(ldapUser, userData); + }, callbacks.priority.MEDIUM, 'mapLDAPCustomFields'); +}); diff --git a/ee/server/index.js b/ee/server/index.js index ff2c9664ec67..5bdf7537ca14 100644 --- a/ee/server/index.js +++ b/ee/server/index.js @@ -7,8 +7,9 @@ import '../app/auditing/server/index'; import '../app/authorization/server/index'; import '../app/canned-responses/server/index'; import '../app/engagement-dashboard/server/index'; -import '../app/ldap-enterprise/server/index'; import '../app/livechat-enterprise/server/index'; import '../app/settings/server/index'; import '../app/teams-mention/server/index'; import './api'; +import './local-services/ldap/service'; +import './configuration/ldap'; diff --git a/ee/server/lib/ldap/Connection.ts b/ee/server/lib/ldap/Connection.ts new file mode 100644 index 000000000000..13daa8d290b4 --- /dev/null +++ b/ee/server/lib/ldap/Connection.ts @@ -0,0 +1,65 @@ +import ldapjs from 'ldapjs'; + +import { LDAPConnection } from '../../../../server/lib/ldap/Connection'; +import { logger, bindLogger } from '../../../../server/lib/ldap/Logger'; +import { settings } from '../../../../app/settings/server'; +import type { ILDAPEEConnectionOptions } from '../../../definition/ldap/ILDAPEEOptions'; + +export class LDAPEEConnection extends LDAPConnection { + public eeOptions: ILDAPEEConnectionOptions; + + private usingAuthentication: boolean; + + constructor() { + super(); + + this.eeOptions = { + authentication: settings.get('LDAP_Authentication') ?? false, + authenticationUserDN: settings.get('LDAP_Authentication_UserDN') ?? '', + authenticationPassword: settings.get('LDAP_Authentication_Password') ?? '', + }; + } + + /* + Bind UserDN and Password if specified and not yet bound + */ + public async maybeBindDN(): Promise { + if (this.usingAuthentication) { + return; + } + + if (!this.eeOptions.authentication) { + return; + } + + if (!this.eeOptions.authenticationUserDN) { + logger.error('Invalid UserDN for authentication'); + return; + } + + bindLogger.info({ msg: 'Binding UserDN', userDN: this.eeOptions.authenticationUserDN }); + await this.bindDN(this.eeOptions.authenticationUserDN, this.eeOptions.authenticationPassword); + this.usingAuthentication = true; + } + + public disconnect(): void { + this.usingAuthentication = false; + super.disconnect(); + } + + public async testConnection(): Promise { + await super.testConnection(); + + await this.maybeBindDN(); + } + + protected async runBeforeSearch(searchOptions: ldapjs.SearchOptions): Promise { + await this.maybeBindDN(); + + if (!Array.isArray(searchOptions.attributes)) { + searchOptions.attributes = searchOptions.attributes ? [searchOptions.attributes] : ['*']; + } + searchOptions.attributes.push('pwdAccountLockedTime'); + super.runBeforeSearch(searchOptions); + } +} diff --git a/ee/server/lib/ldap/Manager.ts b/ee/server/lib/ldap/Manager.ts new file mode 100644 index 000000000000..2c60f326f799 --- /dev/null +++ b/ee/server/lib/ldap/Manager.ts @@ -0,0 +1,501 @@ +import _ from 'underscore'; +import type ldapjs from 'ldapjs'; + +import { ILDAPEntry } from '../../../../definition/ldap/ILDAPEntry'; +import type { IUser } from '../../../../definition/IUser'; +import type { IRoom, ICreatedRoom } from '../../../../definition/IRoom'; +import type { IRole } from '../../../../definition/IRole'; +import { IImportUser } from '../../../../definition/IImportUser'; +import { ImporterAfterImportCallback } from '../../../../app/importer/server/definitions/IConversionCallbacks'; +import { settings } from '../../../../app/settings/server'; +import { Roles, Rooms } from '../../../../app/models/server'; +import { + Users as UsersRaw, + Roles as RolesRaw, + Subscriptions as SubscriptionsRaw, +} from '../../../../app/models/server/raw'; +import { LDAPDataConverter } from '../../../../server/lib/ldap/DataConverter'; +import type { LDAPConnection } from '../../../../server/lib/ldap/Connection'; +import { LDAPManager } from '../../../../server/lib/ldap/Manager'; +import { logger } from '../../../../server/lib/ldap/Logger'; +import { templateVarHandler } from '../../../../app/utils/lib/templateVarHandler'; +import { LDAPEEConnection } from './Connection'; +import { api } from '../../../../server/sdk/api'; +import { addUserToRoom, removeUserFromRoom, createRoom } from '../../../../app/lib/server/functions'; +import { Team } from '../../../../server/sdk'; + +export class LDAPEEManager extends LDAPManager { + public static async sync(): Promise { + if (settings.get('LDAP_Enable') !== true) { + return; + } + + const options = this.getConverterOptions(); + const ldap = new LDAPEEConnection(); + const converter = new LDAPDataConverter(true, options); + + try { + await ldap.connect(); + + try { + const createNewUsers = settings.get('LDAP_Background_Sync_Import_New_Users') ?? true; + const updateExistingUsers = settings.get('LDAP_Background_Sync_Keep_Existant_Users_Updated') ?? true; + + if (createNewUsers) { + await this.importNewUsers(ldap, converter, updateExistingUsers); + } else if (updateExistingUsers) { + await this.updateExistingUsers(ldap, converter); + } + } finally { + ldap.disconnect(); + } + + converter.convertUsers({ + afterImportFn: ((data: IImportUser, _type: string, isNewRecord: boolean): void => Promise.await(this.advancedSync(ldap, data, converter, isNewRecord))) as ImporterAfterImportCallback, + }); + } catch (error) { + logger.error(error); + } + } + + public static validateLDAPTeamsMappingChanges(json: string): void { + if (!json) { + return; + } + + const mustBeAnArrayOfStrings = (array: Array): boolean => Boolean(Array.isArray(array) && array.length && array.every((item) => typeof item === 'string')); + const mappedTeams = this.parseJson(json); + if (!mappedTeams) { + return; + } + + const mappedRocketChatTeams = Object.values(mappedTeams); + const validStructureMapping = mappedRocketChatTeams.every(mustBeAnArrayOfStrings); + if (!validStructureMapping) { + throw new Error('Please verify your mapping for LDAP X RocketChat Teams. The structure is invalid, the structure should be an object like: {key: LdapTeam, value: [An array of rocket.chat teams]}'); + } + } + + private static async advancedSync(ldap: LDAPConnection, importUser: IImportUser, converter: LDAPDataConverter, isNewRecord: boolean): Promise { + const user = converter.findExistingUser(importUser); + if (!user || user.username) { + return; + } + + const dn = importUser.importIds[0]; + await this.syncUserRoles(ldap, user, dn); + await this.syncUserChannels(ldap, user, dn); + await this.syncUserTeams(ldap, user, isNewRecord); + } + + private static async isUserInGroup(ldap: LDAPConnection, baseDN: string, filter: string, { dn, username }: { dn: string; username: string }, groupName: string): Promise { + if (!filter || !baseDN) { + logger.error('Please setup LDAP Group Filter and LDAP Group BaseDN in LDAP Settings.'); + return false; + } + const searchOptions: ldapjs.SearchOptions = { + filter: filter.replace(/#{username}/g, username).replace(/#{groupName}/g, groupName).replace(/#{userdn}/g, dn), + scope: 'sub', + }; + + const result = await ldap.searchRaw(baseDN, searchOptions); + if (!Array.isArray(result) || result.length === 0) { + logger.debug(`${ username } is not in ${ groupName } group!!!`); + } else { + logger.debug(`${ username } is in ${ groupName } group.`); + return true; + } + + return false; + } + + private static parseJson(json: string): Record | undefined { + try { + return JSON.parse(json); + } catch (err) { + logger.error(`Unexpected error : ${ err.message }`); + } + } + + private static broadcastRoleChange(type: string, _id: string, uid: string, username: string): void { + // #ToDo: would be better to broadcast this only once for all users and roles, or at least once by user. + if (!settings.get('UI_DisplayRoles')) { + return; + } + + api.broadcast('user.roleUpdate', { + type, + _id, + u: { + _id: uid, + username, + }, + }); + } + + private static async syncUserRoles(ldap: LDAPConnection, user: IUser, dn: string): Promise { + const { username } = user; + if (!username) { + logger.debug('User has no username'); + return; + } + + const syncUserRoles = settings.get('LDAP_Sync_User_Data_Roles') ?? false; + const syncUserRolesAutoRemove = settings.get('LDAP_Sync_User_Data_Roles_AutoRemove') ?? false; + const syncUserRolesFieldMap = (settings.get('LDAP_Sync_User_Data_RolesMap') ?? '').trim(); + const syncUserRolesFilter = (settings.get('LDAP_Sync_User_Data_Roles_Filter') ?? '').trim(); + const syncUserRolesBaseDN = (settings.get('LDAP_Sync_User_Data_Roles_BaseDN') ?? '').trim(); + + if (!syncUserRoles || !syncUserRolesFieldMap) { + logger.debug('not syncing user roles'); + return; + } + + const roles = await RolesRaw.find({}, { + fields: { + _updatedAt: 0, + }, + }).toArray() as Array; + + if (!roles) { + return; + } + + const fieldMap = this.parseJson(syncUserRolesFieldMap); + if (!fieldMap) { + return; + } + + Object.keys(fieldMap).forEach(async (ldapField) => { + if (!fieldMap.hasOwnProperty(ldapField)) { + return; + } + + const userField = fieldMap[ldapField]; + + const [roleName] = userField.split(/\.(.+)/); + if (!_.find(roles, (el) => el._id === roleName)) { + logger.debug(`User Role doesn't exist: ${ roleName }`); + return; + } + + logger.debug(`User role exists for mapping ${ ldapField } -> ${ roleName }`); + + if (await this.isUserInGroup(ldap, syncUserRolesBaseDN, syncUserRolesFilter, { dn, username }, ldapField)) { + if (Roles.addUserRoles(user._id, roleName)) { + this.broadcastRoleChange('added', roleName, user._id, username); + } + logger.debug(`Synced user group ${ roleName } from LDAP for ${ user.username }`); + return; + } + + if (!syncUserRolesAutoRemove) { + return; + } + + if (Roles.removeUserRoles(user._id, roleName)) { + this.broadcastRoleChange('removed', roleName, user._id, username); + } + }); + } + + private static createRoomForSync(channel: string): IRoom | undefined { + logger.debug(`Channel '${ channel }' doesn't exist, creating it.`); + + const roomOwner = settings.get('LDAP_Sync_User_Data_Channels_Admin') || ''; + // #ToDo: Remove typecastings when createRoom is converted to ts. + const room = createRoom('c', channel, roomOwner, [], false, { customFields: { ldap: true } } as any) as unknown as ICreatedRoom | undefined; + if (!room?.rid) { + logger.error(`Unable to auto-create channel '${ channel }' during ldap sync.`); + return; + } + + room._id = room.rid; + return room; + } + + private static async syncUserChannels(ldap: LDAPConnection, user: IUser, dn: string): Promise { + const syncUserChannels = settings.get('LDAP_Sync_User_Data_Channels') ?? false; + const syncUserChannelsRemove = settings.get('LDAP_Sync_User_Data_Channels_Enforce_AutoChannels') ?? false; + const syncUserChannelsFieldMap = (settings.get('LDAP_Sync_User_Data_ChannelsMap') ?? '').trim(); + const syncUserChannelsFilter = (settings.get('LDAP_Sync_User_Data_Channels_Filter') ?? '').trim(); + const syncUserChannelsBaseDN = (settings.get('LDAP_Sync_User_Data_Channels_BaseDN') ?? '').trim(); + + if (!syncUserChannels || !syncUserChannelsFieldMap) { + logger.debug('not syncing groups to channels'); + return; + } + + const fieldMap = this.parseJson(syncUserChannelsFieldMap); + if (!fieldMap) { + return; + } + + const username = user.username as string; + _.map(fieldMap, (channels, ldapField) => { + if (!Array.isArray(channels)) { + channels = [channels]; + } + + channels.forEach(async (channel: string) => { + const room: IRoom | undefined = Rooms.findOneByNonValidatedName(channel) || this.createRoomForSync(channel); + if (!room) { + return; + } + + if (await this.isUserInGroup(ldap, syncUserChannelsBaseDN, syncUserChannelsFilter, { dn, username }, ldapField)) { + if (room.teamMain) { + logger.error(`Can't add user to channel ${ channel } because it is a team.`); + } else { + addUserToRoom(room._id, user); + logger.debug(`Synced user channel ${ room._id } from LDAP for ${ username }`); + } + } else if (syncUserChannelsRemove && !room.teamMain) { + const subscription = await SubscriptionsRaw.findOneByRoomIdAndUserId(room._id, user._id); + if (subscription) { + removeUserFromRoom(room._id, user); + } + } + }); + }); + } + + private static async syncUserTeams(ldap: LDAPConnection, user: IUser, isNewRecord: boolean): Promise { + if (!user.username) { + return; + } + + const mapTeams = settings.get('LDAP_Enable_LDAP_Groups_To_RC_Teams') && (isNewRecord || settings.get('LDAP_Validate_Teams_For_Each_Login')); + if (!mapTeams) { + return; + } + + const ldapUserTeams = await this.getLdapTeamsByUsername(ldap, user.username); + const mapJson = settings.get('LDAP_Groups_To_Rocket_Chat_Teams'); + if (!mapJson) { + return; + } + const map = this.parseJson(mapJson) as Record; + if (!map) { + return; + } + + const teamNames = this.getRocketChatTeamsByLdapTeams(map, ldapUserTeams); + + const allTeamNames = [...new Set(Object.values(map).flat())]; + const allTeams = await Team.listByNames(allTeamNames, { projection: { _id: 1, name: 1 } }); + + const inTeamIds = allTeams.filter(({ name }) => teamNames.includes(name)).map(({ _id }) => _id); + const notInTeamIds = allTeams.filter(({ name }) => !teamNames.includes(name)).map(({ _id }) => _id); + + const currentTeams = await Team.listTeamsBySubscriberUserId(user._id, { projection: { teamId: 1 } }); + const currentTeamIds = currentTeams && currentTeams.map(({ teamId }) => teamId); + const teamsToRemove = currentTeamIds && currentTeamIds.filter((teamId) => notInTeamIds.includes(teamId)); + const teamsToAdd = inTeamIds.filter((teamId) => !currentTeamIds?.includes(teamId)); + + await Team.insertMemberOnTeams(user._id, teamsToAdd); + if (teamsToRemove) { + await Team.removeMemberFromTeams(user._id, teamsToRemove); + } + } + + private static getRocketChatTeamsByLdapTeams(mappedTeams: Record, ldapUserTeams: Array): Array { + const mappedLdapTeams = Object.keys(mappedTeams); + const filteredTeams = ldapUserTeams.filter((ldapTeam) => mappedLdapTeams.includes(ldapTeam)); + + if (filteredTeams.length < ldapUserTeams.length) { + const unmappedLdapTeams = ldapUserTeams.filter((ldapTeam) => !mappedLdapTeams.includes(ldapTeam)); + logger.error(`The following LDAP teams are not mapped in Rocket.Chat: "${ unmappedLdapTeams.join(', ') }".`); + } + + if (!filteredTeams.length) { + return []; + } + + return [...new Set(filteredTeams.map((ldapTeam) => mappedTeams[ldapTeam]).flat())]; + } + + private static async getLdapTeamsByUsername(ldap: LDAPConnection, username: string): Promise> { + const query = settings.get('LDAP_Query_To_Get_User_Teams'); + if (!query) { + return []; + } + + const searchOptions = { + filter: query.replace(/#{username}/g, username), + scope: ldap.options.userSearchScope || 'sub', + sizeLimit: ldap.options.searchSizeLimit, + }; + + const ldapUserGroups = await ldap.searchRaw(ldap.options.baseDN, searchOptions); + if (!Array.isArray(ldapUserGroups)) { + return []; + } + + return ldapUserGroups.filter((entry) => entry?.raw?.ou).map((entry) => (ldap.extractLdapAttribute(entry.raw.ou) as string)).flat(); + } + + public static copyActiveState(ldapUser: ILDAPEntry, userData: IImportUser): void { + if (!ldapUser) { + return; + } + + const syncUserState = settings.get('LDAP_Sync_User_Active_State'); + if (syncUserState === 'none') { + return; + } + + const deleted = Boolean(ldapUser.pwdAccountLockedTime); + if (deleted === userData.deleted || (userData.deleted === undefined && !deleted)) { + return; + } + + if (syncUserState === 'disable' && !deleted) { + return; + } + + userData.deleted = deleted; + logger.debug(`${ deleted ? 'Deactivating' : 'Activating' } user ${ userData.name } (${ userData.username })`); + } + + public static copyCustomFields(ldapUser: ILDAPEntry, userData: IImportUser): void { + if (!settings.get('LDAP_Sync_Custom_Fields')) { + return; + } + + const customFieldsSettings = settings.get('Accounts_CustomFields'); + const customFieldsMap = settings.get('LDAP_CustomFieldMap'); + + if (!customFieldsMap || !customFieldsSettings) { + if (customFieldsMap) { + logger.debug('Skipping LDAP custom fields because there are no custom fields configured.'); + } + return; + } + + let map: Record; + try { + map = JSON.parse(customFieldsMap) as Record; + } catch (error) { + logger.error('Failed to parse LDAP Custom Fields mapping'); + logger.error(error); + return; + } + + let customFields: Record; + try { + customFields = JSON.parse(customFieldsSettings) as Record; + } catch (error) { + logger.error('Failed to parse Custom Fields'); + logger.error(error); + return; + } + + _.map(map, (userField, ldapField) => { + if (!this.getCustomField(customFields, userField)) { + logger.debug(`User attribute does not exist: ${ userField }`); + return; + } + + if (!userData.customFields) { + userData.customFields = {}; + } + + const value = templateVarHandler(ldapField, ldapUser); + + if (value) { + let ref: Record = userData.customFields; + const attributeNames = userField.split('.'); + let previousKey: string | undefined; + + for (const key of attributeNames) { + if (previousKey) { + if (ref[previousKey] === undefined) { + ref[previousKey] = {}; + } else if (typeof ref[previousKey] !== 'object') { + logger.error(`Failed to assign custom field: ${ userField }`); + return; + } + + ref = ref[previousKey]; + } + + previousKey = key; + } + + if (previousKey) { + ref[previousKey] = value; + logger.debug(`user.customFields.${ userField } changed to: ${ value }`); + } + } + }); + } + + private static async importNewUsers(ldap: LDAPConnection, converter: LDAPDataConverter, updateExistingUsers: boolean): Promise { + return new Promise((resolve, reject) => { + let count = 0; + + ldap.searchAllUsers({ + entryCallback: (entry: ldapjs.SearchEntry): IImportUser | undefined => { + const data = ldap.extractLdapEntryData(entry); + count++; + + if (!updateExistingUsers) { + const existingUser = Promise.await(this.findExistingLDAPUser(data)); + if (existingUser) { + return; + } + } + + const userData = this.mapUserData(data); + converter.addUser(userData); + return userData; + }, + endCallback: (error: any): void => { + if (error) { + logger.error(error); + reject(error); + return; + } + + logger.info('LDAP finished importing. New users imported:', count); + resolve(); + }, + }); + }); + } + + private static async updateExistingUsers(ldap: LDAPConnection, converter: LDAPDataConverter): Promise { + return new Promise(async (resolve, reject) => { + try { + const users = await UsersRaw.findLDAPUsers(); + for await (const user of users) { + let ldapUser: ILDAPEntry | undefined; + + if (user.services?.ldap?.id) { + ldapUser = await ldap.findOneById(user.services.ldap.id, user.services.ldap.idAttribute); + } else if (user.username) { + ldapUser = await ldap.findOneByUsername(user.username); + } + + if (ldapUser) { + const userData = this.mapUserData(ldapUser, user.username); + converter.addUser(userData); + } + } + + resolve(); + } catch (error) { + reject(error); + } + }); + } + + private static getCustomField(customFields: Record, property: string): any { + try { + return _.reduce(property.split('.'), (acc, el) => acc[el], customFields); + } catch { + // ignore errors + } + } +} diff --git a/ee/server/local-services/ldap/service.ts b/ee/server/local-services/ldap/service.ts new file mode 100644 index 000000000000..a09b22f46fba --- /dev/null +++ b/ee/server/local-services/ldap/service.ts @@ -0,0 +1,16 @@ +import '../../broker'; + +import { api } from '../../../../server/sdk/api'; +import { LDAPEEManager } from '../../lib/ldap/Manager'; +import { ILDAPEEService } from '../../sdk/types/ILDAPEEService'; +import { ServiceClass } from '../../../../server/sdk/types/ServiceClass'; + +export class LDAPEEService extends ServiceClass implements ILDAPEEService { + protected name = 'ldap-enterprise'; + + async sync(): Promise { + return LDAPEEManager.sync(); + } +} + +api.registerService(new LDAPEEService()); diff --git a/ee/server/sdk/index.ts b/ee/server/sdk/index.ts new file mode 100644 index 000000000000..1af781c63fe6 --- /dev/null +++ b/ee/server/sdk/index.ts @@ -0,0 +1,4 @@ +import { ILDAPEEService } from './types/ILDAPEEService'; +import { proxifyWithWait } from '../../../server/sdk/lib/proxify'; + +export const LDAPEE = proxifyWithWait('ldap-enterprise'); diff --git a/ee/server/sdk/types/ILDAPEEService.ts b/ee/server/sdk/types/ILDAPEEService.ts new file mode 100644 index 000000000000..1d3d5bbd04f1 --- /dev/null +++ b/ee/server/sdk/types/ILDAPEEService.ts @@ -0,0 +1,3 @@ +export interface ILDAPEEService { + sync(): Promise; +} diff --git a/package-lock.json b/package-lock.json index c386755e87a3..82bfa996d25e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11158,6 +11158,15 @@ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" }, + "@types/ldapjs": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@types/ldapjs/-/ldapjs-2.2.1.tgz", + "integrity": "sha512-rctCsjTBpG86j352gd6BfFevpcG2Rvh2K6t3BLO3VJMe6JSGDI5rovA+8O/rxL5PbXz0UFBdDu7wv/1hA/0GjA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/less": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/less/-/less-3.0.2.tgz", @@ -12354,6 +12363,11 @@ "event-target-shim": "^5.0.0" } }, + "abstract-logging": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", + "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==" + }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", @@ -25720,42 +25734,26 @@ "integrity": "sha512-81+uVrL8X5fl17Da5lImUCCp+jkJoaDRfL2k2ECkRJ1S+H8Z+my76eq0eWA/KM5/Y4/5mdtH8evRz0AvdqPy2w==" }, "ldap-filter": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/ldap-filter/-/ldap-filter-0.2.2.tgz", - "integrity": "sha1-8rhCvguG2jNSeYUFsx68rlkNd9A=", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/ldap-filter/-/ldap-filter-0.3.3.tgz", + "integrity": "sha1-KxTGiiqdQQTb28kQocqF/Riel5c=", "requires": { - "assert-plus": "0.1.5" - }, - "dependencies": { - "assert-plus": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", - "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=" - } + "assert-plus": "^1.0.0" } }, "ldapjs": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-1.0.2.tgz", - "integrity": "sha1-VE/3Ayt7g8aPBwEyjZKXqmlDQPk=", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-2.3.1.tgz", + "integrity": "sha512-kf0tHHLrpwKaBAQOhYHXgdeh2PkFuCCxWgLb1MRn67ZQVo787D2pij3mmHVZx193GIdM8xcfi8HF6AIYYnj0fQ==", "requires": { - "asn1": "0.2.3", + "abstract-logging": "^2.0.0", + "asn1": "^0.2.4", "assert-plus": "^1.0.0", "backoff": "^2.5.0", - "bunyan": "^1.8.3", - "dashdash": "^1.14.0", - "dtrace-provider": "~0.8", - "ldap-filter": "0.2.2", + "ldap-filter": "^0.3.3", "once": "^1.4.0", - "vasync": "^1.6.4", + "vasync": "^2.2.0", "verror": "^1.8.1" - }, - "dependencies": { - "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" - } } }, "left-pad": { @@ -38479,26 +38477,11 @@ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, "vasync": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/vasync/-/vasync-1.6.4.tgz", - "integrity": "sha1-3+k2Fq0OeugBszKp2Iv8XNyOHR8=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vasync/-/vasync-2.2.0.tgz", + "integrity": "sha1-z951GGChWCLbOxMrxZsRakra8Bs=", "requires": { - "verror": "1.6.0" - }, - "dependencies": { - "extsprintf": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.2.0.tgz", - "integrity": "sha1-WtlGwi9bMrp/jNdCZxHG6KP8JSk=" - }, - "verror": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.6.0.tgz", - "integrity": "sha1-fROyex+swuLakEBetepuW90lLqU=", - "requires": { - "extsprintf": "1.2.0" - } - } + "verror": "1.10.0" } }, "verror": { diff --git a/package.json b/package.json index 5146b63a42a8..f4fd3736d4b8 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,7 @@ "@types/fibers": "^3.1.0", "@types/imap": "^0.8.35", "@types/jsdom": "^16.2.12", + "@types/ldapjs": "^2.2.1", "@types/less": "^3.0.2", "@types/lodash.get": "^4.4.6", "@types/mailparser": "^3.0.2", @@ -186,7 +187,6 @@ "blockstack": "19.3.0", "body-parser": "1.19.0", "bson": "^4.5.1", - "bunyan": "^1.8.15", "busboy": "^0.3.1", "bytebuffer": "5.0.1", "cas": "https://github.com/kcbanner/node-cas/tarball/fcd27dad333223b3b75a048bce27973fb3ca0f62", @@ -229,7 +229,7 @@ "juice": "^8.0.0", "katex": "^0.11.1", "ldap-escape": "^2.0.5", - "ldapjs": "^1.0.2", + "ldapjs": "^2.3.1", "less": "https://github.com/meteor/less.js/tarball/8130849eb3d7f0ecf0ca8d0af7c4207b0442e3f6", "less-plugin-autoprefixer": "^2.1.0", "limax": "^3.0.0", diff --git a/packages/rocketchat-i18n/i18n/af.i18n.json b/packages/rocketchat-i18n/i18n/af.i18n.json index 742a2e2144c0..984702cb8eef 100644 --- a/packages/rocketchat-i18n/i18n/af.i18n.json +++ b/packages/rocketchat-i18n/i18n/af.i18n.json @@ -1519,7 +1519,6 @@ "LDAP_Connect_Timeout": "Connection Time-out (ms)", "LDAP_Default_Domain": "Verstek Domein", "LDAP_Default_Domain_Description": "As dit voorsien word, sal die standaard domein gebruik word om 'n unieke e-pos vir gebruikers te skep waar e-pos nie vanaf LDAP ingevoer is nie. Die e-pos sal gemonteer word as `gebruikersnaam@default_domain` of `unique_id@default_domain`.
Voorbeeld: `rocket.chat`", - "LDAP_Description": "LDAP is 'n hiërargiese databasis wat baie maatskappye gebruik om 'n enkele teken aan te bied - 'n fasiliteit om een ​​wagwoord tussen verskeie webwerwe en dienste te deel. Vir gevorderde konfigurasie inligting en voorbeelde, raadpleeg asseblief ons wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "in staat te stel", "LDAP_Enable_Description": "Probeer om LDAP vir verifikasie te gebruik.", "LDAP_Encryption": "enkripsie", @@ -1561,11 +1560,6 @@ "LDAP_Sync_Now": "Agtergrondsinkronisering Nou", "LDAP_Sync_Now_Description": "Sal die ** Agtergrondsinkronisering ** nou uitvoer eerder as om die ** Sync Interval ** te wag, selfs al is ** Agtergrondsinkronisering ** vals.
Hierdie aksie is asynchroon. Sien asseblief die logs vir meer inligting oor die proses", "LDAP_Sync_User_Avatar": "Sinkroniseer gebruiker avatar", - "LDAP_Sync_User_Data": "Sinkroniseer gebruikersdata", - "LDAP_Sync_User_Data_Description": "Hou gebruikersdata in lyn met die bediener op ** aanmelding ** of op ** agtergrondsinkronisering ** (bv. Naam, e-pos).", - "LDAP_Sync_User_Data_FieldMap": "Gebruiker data veld kaart", - "LDAP_Sync_User_Data_FieldMap_Description": "Stel in hoe gebruikersrekeningvelde (soos e-pos) gevul word uit 'n rekord in LDAP (een keer gevind).
As 'n voorbeeld, sal `{\" cn \":\" naam \",\" pos \":\" e-pos \"}` 'n mens se leesbare naam uit die cn-kenmerk en hul e-pos van die posattribuut kies. Daarbenewens is dit moontlik om veranderlikes te gebruik, byvoorbeeld: `{\" # {givenName} # {sn} \":\" naam \",\" pos \":\" e-pos \"}` gebruik 'n kombinasie van die gebruiker se voornaam en van raket chat `naam` veld.
Beskikbare velde in Rocket.Chat:` name`, `email` en` customFields`.", - "LDAP_Test_Connection": "Toets verbinding", "LDAP_Timeout": "Time-out (ms)", "LDAP_Timeout_Description": "Hoeveel kilometer-sekondes wag vir 'n soekresultaat voordat 'n fout terugkom", "LDAP_Unique_Identifier_Field": "Unieke Identifiseringsveld", diff --git a/packages/rocketchat-i18n/i18n/ar.i18n.json b/packages/rocketchat-i18n/i18n/ar.i18n.json index 9651807b1eed..8aefe72dd4c3 100644 --- a/packages/rocketchat-i18n/i18n/ar.i18n.json +++ b/packages/rocketchat-i18n/i18n/ar.i18n.json @@ -1537,7 +1537,6 @@ "LDAP_Connect_Timeout": "انتهاء مدة الاتصال (بالملي ثانية)", "LDAP_Default_Domain": "المجال الافتراضي", "LDAP_Default_Domain_Description": "إذا تم توفير النطاق الافتراضي سيتم استخدامه لإنشاء بريد إلكتروني فريد للمستخدمين حيث لم يتم استيراد البريد الإلكتروني من لداب. سيتم تثبيت الرسالة الإلكترونية باسم `أوزرنام @ default_domain` أور` unique_id @ default_domain`.
مثال: `rocket.chat`", - "LDAP_Description": "LDAP هي قاعدة بيانات هرمية التي تستخدم العديد من الشركات لتقديم إشارة واحدة على - مرفق لتقاسم كلمة مرور واحدة بين المواقع وخدمات متعددة. للحصول على معلومات التكوين المتقدمة والأمثلة، يرجى الرجوع لدينا ويكي: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "تفعيل", "LDAP_Enable_Description": "محاولة استخدام LDAP للمصادقة.", "LDAP_Encryption": "التشفير", @@ -1579,11 +1578,6 @@ "LDAP_Sync_Now": "خلفية مزامنة الآن", "LDAP_Sync_Now_Description": "سيتم تنفيذ ** مزامنة الخلفية ** الآن بدلا من الانتظار ** مزامنة الفاصل الزمني ** حتى لو ** مزامنة الخلفية ** هو خطأ.
هذا الإجراء غير متزامن، يرجى الاطلاع على سجلات لمزيد من المعلومات حول معالجة", "LDAP_Sync_User_Avatar": "تزامن العضو الرمزية", - "LDAP_Sync_User_Data": "مزامنة البيانات", - "LDAP_Sync_User_Data_Description": "حافظ على بيانات المستخدم في تزامن مع الخادم على تسجيل الدخول (على سبيل المثال: الاسم، البريد الإلكتروني).", - "LDAP_Sync_User_Data_FieldMap": "العضو بيانات خريطة الميدان", - "LDAP_Sync_User_Data_FieldMap_Description": "تكوين كيف يتم ملؤها الحقول حساب المستخدم (مثل البريد الإلكتروني) من مستوى قياسي في LDAP (وجدت مرة واحدة).
وكمثال على ذلك، `{\" CN \":\" اسم \"،\" البريد الإلكتروني \":\" البريد الإلكتروني \"}` سيختار اسم الشخص البشري للقراءة من سمة CN، وبريدهم الإلكتروني من السمة البريد.
وتشمل المجالات المتاحة `name`، و` email`.", - "LDAP_Test_Connection": "اختبار الاتصال", "LDAP_Timeout": "مهلة (مللي ثانية)", "LDAP_Timeout_Description": "كم عدد الأميال التي تنتظر نتيجة بحث قبل إرجاع خطأ", "LDAP_Unique_Identifier_Field": "معرف الميدان وفريدة من نوعها", diff --git a/packages/rocketchat-i18n/i18n/az.i18n.json b/packages/rocketchat-i18n/i18n/az.i18n.json index d8cadc0c9601..695e4349cc75 100644 --- a/packages/rocketchat-i18n/i18n/az.i18n.json +++ b/packages/rocketchat-i18n/i18n/az.i18n.json @@ -1519,7 +1519,6 @@ "LDAP_Connect_Timeout": "Bağlantı Təminatı (ms)", "LDAP_Default_Domain": "Default Domain", "LDAP_Default_Domain_Description": "Varsa, Default Domain e-poçt LDAP-dan idxal olunmayan istifadəçilər üçün unikal bir e-poçt yaratmaq üçün istifadə olunacaq. E-poçt 'username @ default_domain' və ya 'unique_id @ default_domain' kimi quraşdırılacaq.
Məsələn: 'rocket.chat`", - "LDAP_Description": "LDAP, bir çox şirkət və birdən çox sayt arasında bir parol paylaşma imkanı olan bir çox şirkətin vahid işarəsi təmin etmək üçün istifadə etdiyi hiyerarşik bir verilənlər bazasıdır. Ətraflı konfiqurasiya məlumatları və nümunələr üçün, bizim wiki müraciət edin: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Enable", "LDAP_Enable_Description": "Doğrulama üçün LDAP-dan istifadə etməyə cəhd.", "LDAP_Encryption": "Şifrələmə", @@ -1561,11 +1560,6 @@ "LDAP_Sync_Now": "İndi Arxa Sinxronlaşdırın", "LDAP_Sync_Now_Description": "** Arxa Sinxronlaşdırma ** indi ** Sinxronlaşdırma Aralığını ** Arxa Sinxronlaşdırma ** səhv olsa da gözləyin.
Bu Fəaliyyət asinxron deyil, xahiş edirik, prosesi", "LDAP_Sync_User_Avatar": "İstifadəçi Avatarını sinxronlaşdırın", - "LDAP_Sync_User_Data": "İstifadəçi məlumatlarını sinxronlaşdırın", - "LDAP_Sync_User_Data_Description": "Istifadəçi məlumatlarını ** girişdə server ilə senkronize edin ** və ya ** fonda sinxronlaşdırma zamanı ** (məsələn, adı, e-poçt).", - "LDAP_Sync_User_Data_FieldMap": "İstifadəçi Məlumatın Sahəsi xəritəsi", - "LDAP_Sync_User_Data_FieldMap_Description": "LDAP-da (bir dəfə tapıldı) bir istifadəçi hesabının sahələrinin (e-poçt kimi) necə yerləşdirildiyini konfiqurasiya.
Məsələn, `{\" cn \":\" adı \",\" poçt \":\" e-poçt \"}, bir şəxsin cn xüsusiyyətindən insan oxunaqlı adını və onların e-poçtunu poçt xassəsindən seçəcək. Əlavə olaraq, dəyişənləri istifadə etmək mümkündür, məsələn: `{\" # {givenName} # {sn} \":\" adı \",\" poçt \":\" e-poçt \"}` istifadəçinin adı və soyadının birləşməsini istifadə edir roket chat` adı `sahəsində.
Rocket.Chat-də mövcud sahələr:` adı`, `email` və` customFields`.", - "LDAP_Test_Connection": "Test keçid", "LDAP_Timeout": "Timeout (ms)", "LDAP_Timeout_Description": "Bir neçə dəqiqə ara bir axtarış nəticə gözləməyincə, bir səhv qaytarır", "LDAP_Unique_Identifier_Field": "Nadir Təsdiq Alan", diff --git a/packages/rocketchat-i18n/i18n/be-BY.i18n.json b/packages/rocketchat-i18n/i18n/be-BY.i18n.json index 01decdbc3e72..22ab9d29b8fc 100644 --- a/packages/rocketchat-i18n/i18n/be-BY.i18n.json +++ b/packages/rocketchat-i18n/i18n/be-BY.i18n.json @@ -1532,7 +1532,6 @@ "LDAP_Connect_Timeout": "Час чакання злучэння (мс)", "LDAP_Default_Domain": "Дамен па змаўчанні", "LDAP_Default_Domain_Description": "Пры наяўнасці дамен па змаўчанні будзе выкарыстоўвацца для стварэння унікальнага адрасы электроннай пошты для карыстальнікаў, дзе электронная пошта не была завезена з LDAP. . Адрас электроннай пошты будзе змантаваны як `імя карыстальніка @ default_domain` или` unique_id @ default_domain`
Прыклад:` rocket.chat`", - "LDAP_Description": "LDAP ўяўляе сабой іерархічную базу дадзеных, што многія кампаніі выкарыстоўваюць для забеспячэння адзінага ўваходу - аб'ект для абмену адзін пароля паміж некалькімі сайтамі і паслугамі. Для папярэдняй інфармацыі аб канфігурацыі і прыклады, калі ласка, звярніцеся ў наш вікі: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Ўключыць", "LDAP_Enable_Description": "Спроба выкарыстоўваць LDAP для аўтэнтыфікацыі.", "LDAP_Encryption": "шыфраванне", @@ -1574,11 +1573,6 @@ "LDAP_Sync_Now": "Фонавая сінхранізацыя Цяпер", "LDAP_Sync_Now_Description": "Ці будзе выконваць ** Фонавая сінхранізацыя ** зараз, а не чакаць ** Інтэрвал сінхранізацыі з ** нават калі ** Фонавая сінхранізацыя ** з'яўляецца false.
Гэта дзеянне з'яўляецца асінхронным, калі ласка, глядзіце часопісы для атрымання дадатковых звестак аб працэс", "LDAP_Sync_User_Avatar": "Сінхранізацыя Аватар карыстальніка", - "LDAP_Sync_User_Data": "Сінхранізацыя дадзеных карыстальніка", - "LDAP_Sync_User_Data_Description": "Захоўваць дадзеныя карыстальніка ў сінхранізацыі з серверам на ** лагін ** або ** ** фон сінхранізацыі (напрыклад, імя, адрас электроннай пошты).", - "LDAP_Sync_User_Data_FieldMap": "Дадзеныя карыстальніка Карта Поле", - "LDAP_Sync_User_Data_FieldMap_Description": "Настройка як поля ўліковага запісу карыстальніка (напрыклад, электронная пошта) запаўняюцца з запісу ў LDAP (калісьці знайшло).
У якасці прыкладу, `{« сп »:« Імя »,« пошта »:« электронная пошта »}` падбярэ лёгкачытальным імя чалавека з атрыбуту сп, і іх электронную пошту ад атрыбуту пошты. Акрамя таго, можна выкарыстоўваць зменныя, напрыклад: `{« # {GivenName} # {ЗП} »:« Імя »,« пошта »:« электронная пошта »}` выкарыстоўвае камбінацыю імя карыстальніка і прозвішча для ракета чат `name` поле
Даступныя поля ў Rocket.Chat: .` name`,` `email` і customFields`.", - "LDAP_Test_Connection": "Пров.соед", "LDAP_Timeout": "Тайм-аўт (мс)", "LDAP_Timeout_Description": "Колькі mileseconds чакаць выніку пошуку, перш чым вярнуць памылку", "LDAP_Unique_Identifier_Field": "Унікальны ідэнтыфікатар поля", diff --git a/packages/rocketchat-i18n/i18n/bg.i18n.json b/packages/rocketchat-i18n/i18n/bg.i18n.json index 74a0650d3c68..e664781570a8 100644 --- a/packages/rocketchat-i18n/i18n/bg.i18n.json +++ b/packages/rocketchat-i18n/i18n/bg.i18n.json @@ -1517,7 +1517,6 @@ "LDAP_Connect_Timeout": "Времетраене на връзката (ms)", "LDAP_Default_Domain": "Начален домейн", "LDAP_Default_Domain_Description": "Ако е предвидено, Домейнът по подразбиране ще бъде използван за създаване на уникален имейл за потребителите, в които имейлът не е бил импортиран от LDAP. Имейлът ще бъде монтиран като \"username @ default_domain\" или \"unique_id @ default_domain\".
Пример: `rocket.chat`", - "LDAP_Description": "LDAP е йерархична база данни, която много компании използват за осигуряване на единичен подпис - възможност за споделяне на една парола между множество сайтове и услуги. За информация за разширената конфигурация и примери, моля, вижте нашата уики: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Активиране", "LDAP_Enable_Description": "Опит за използване на LDAP за удостоверяване.", "LDAP_Encryption": "Encryption", @@ -1559,11 +1558,6 @@ "LDAP_Sync_Now": "Синхронизиране на фона сега", "LDAP_Sync_Now_Description": "Ще изпълни ** синхронизирането на фона ** сега, вместо да чака ** интервала за синхронизиране **, дори когато ** синхронизирането на фона ** е невярно.
Това действие е асинхронно, моля вижте регистрационните файлове за повече информация за процес", "LDAP_Sync_User_Avatar": "Аватар на потребител за синхронизиране", - "LDAP_Sync_User_Data": "Синхронизиране на потребителски данни", - "LDAP_Sync_User_Data_Description": "Съхранявайте потребителските данни в синхрон със сървъра на ** вход ** или на ** синхронизиране на фона ** (напр .: име, имейл).", - "LDAP_Sync_User_Data_FieldMap": "Карта на поле на потребителски данни", - "LDAP_Sync_User_Data_FieldMap_Description": "Конфигурирайте как се попълват полетата за потребителски акаунти (като имейл) от запис в LDAP (веднъж намерен).
Като пример, \"{\" cn \":\" name \",\" mail \":\" имейл \"} ще избира човекно четливо име от атрибута cn и имейла от атрибута. Освен това е възможно да се използват променливи, например: \"{\" # {givenName} # {sn} \":\" име \",\" mail \":\" имейл \"} използва комбинация от първото и последното име на потребителя ракетен чат \"име\" поле.
Наличните полета в Rocket.Chat: \"име\", \"имейл\" и \"customFields\".", - "LDAP_Test_Connection": "Тест връзка", "LDAP_Timeout": "Timeout (ms)", "LDAP_Timeout_Description": "Колко милисекунди чакате за резултат от търсенето, преди да върнете грешка", "LDAP_Unique_Identifier_Field": "Уникално поле на идентификатора", diff --git a/packages/rocketchat-i18n/i18n/bs.i18n.json b/packages/rocketchat-i18n/i18n/bs.i18n.json index 9944ea0aab04..22e65e78dd7d 100644 --- a/packages/rocketchat-i18n/i18n/bs.i18n.json +++ b/packages/rocketchat-i18n/i18n/bs.i18n.json @@ -1516,7 +1516,6 @@ "LDAP_Connect_Timeout": "Vrijeme veze (ms)", "LDAP_Default_Domain": "Zadana domena", "LDAP_Default_Domain_Description": "Ako je predviđeno, zadana domena će se koristiti za stvaranje jedinstvene e-pošte za korisnike gdje e-pošta nije uvezena iz LDAP-a. E-adresa će biti postavljena kao \"korisničko ime @ default_domain\" ili \"unique_id @ default_domain\".
Primjer: `rocket.chat`", - "LDAP_Description": "LDAP je hijerarhijska baza podataka koja mnoge tvrtke koriste za pružanje jedinstvene prijave - usluge za dijeljenje jedne lozinke između više web-mjesta i usluga. Za napredne podatke o konfiguraciji i primjere, obratite se našem wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Omogući", "LDAP_Enable_Description": "Pokušaj koristiti LDAP za provjeru autentičnosti.", "LDAP_Encryption": "Šifriranje", @@ -1558,11 +1557,6 @@ "LDAP_Sync_Now": "Pozadinska sinkronizacija sada", "LDAP_Sync_Now_Description": "Će izvršiti ** pozadinsku sinkronizaciju ** sada, a ne čekati ** Sync Interval **, čak i ako je ** Sinkronizacija pozadine ** lažna.
Ova akcija je asinkroni, pogledajte zapisnike za više informacija o postupak", "LDAP_Sync_User_Avatar": "Sinkronizacija Korisnikovog Avatara", - "LDAP_Sync_User_Data": "Sinkronizacija podataka", - "LDAP_Sync_User_Data_Description": "Održavajte korisničke podatke sinkronizirane sa serverom pri prijavi (npr: ime i prezime, e-mail).", - "LDAP_Sync_User_Data_FieldMap": "Mapa korisničkih podataka", - "LDAP_Sync_User_Data_FieldMap_Description": "Konfigurirajte kako će korisnička polja (poput emaila) biti popunje iz zapisa na LDAPu (nakon što ih nađemo).
Na primjer, `{\"cn\":\"name\", \"mail\":\"email\"}` će odabrati čitljivo ime iz cn atributa i njihov email i mail atributa.
 Dostupna polja uključuju `name`i `email`.", - "LDAP_Test_Connection": "Testiraj vezu", "LDAP_Timeout": "Vrijeme (ms)", "LDAP_Timeout_Description": "Koliko milja čekaju rezultat pretraživanja prije nego što se vrati pogreška", "LDAP_Unique_Identifier_Field": "Jedinstveni identifikator polja", diff --git a/packages/rocketchat-i18n/i18n/ca.i18n.json b/packages/rocketchat-i18n/i18n/ca.i18n.json index 681efea44524..ea81ee641752 100644 --- a/packages/rocketchat-i18n/i18n/ca.i18n.json +++ b/packages/rocketchat-i18n/i18n/ca.i18n.json @@ -2432,12 +2432,8 @@ "LDAP_Connect_Timeout": "Temps d'espera connexió (ms)", "LDAP_Default_Domain": "Domini predeterminat", "LDAP_Default_Domain_Description": "Si es proporciona el domini per defecte s'utilitzarà per crear un correu electrònic únic per als usuaris en què el correu electrònic no s'ha importat des de LDAP. El correu electrònic es muntarà com a `nomusuari@dominiperdefecte` o `nom_usuari_unic@dominiperdefecte`.
Exemple: `rocket.chat`", - "LDAP_Default_Role_To_User": "Funció predeterminada de l'usuari", - "LDAP_Default_Role_To_User_Description": "El paper RC predeterminat que s'aplicarà a l'usuari si l'usuari té algun paper LDAP que no està assignat.", - "LDAP_Description": "LDAP és una base de dades jeràrquica que moltes empreses utilitzen per proporcionar un inici de sessió únic –una eina per tenir una sola contrasenya a múltiples llocs web i serveis. Per a exemples i informació sobre configuracions més avançades, consulteu la nostra wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Activa", "LDAP_Enable_Description": "Intentar utilitzar LDAP com a mètode d'autenticació", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "Activa el mapeig de rols de LDAP a Rocket.Chat", "LDAP_Enable_LDAP_Groups_To_RC_Teams": "Habiliteu el mapeig de l'equip de LDAP a Rocket.Chat", "LDAP_Encryption": "Xifrat", "LDAP_Encryption_Description": "Mètode de xifrat utilitzat per a la comunicació segura cap al servidor LDAP. Alguns exemples 'sense xifrat', 'SSL / LDAPS (xifrat des de l'inici), i' StartTLS '(actualitzar a comunicacions xifrades una vegada connectat).", @@ -2468,15 +2464,11 @@ "LDAP_Merge_Existing_Users_Description": "* Precaució! * A l'importar un usuari de LDAP i ja existeix un usuari amb el mateix nom d'usuari, la informació i la contrasenya d'LDAP s'establiran en l'usuari existent.", "LDAP_Port": "Port", "LDAP_Port_Description": "Port per accedir a LDAP. Ex. `389` o `636` per LDAPS", - "LDAP_Query_To_Get_User_Groups": "Consulta LDAP per obtenir grups d'usuaris", - "LDAP_Query_To_Get_User_Groups_Description": "Consulta LDAP per obtenir els grups LDAP dels quals l'usuari forma part.", "LDAP_Query_To_Get_User_Teams": "Consulta LDAP per obtenir grups d'usuaris", "LDAP_Reconnect": "Reconnecta", "LDAP_Reconnect_Description": "Proveu tornar a connectar-se automàticament quan la connexió s'interrompi per algun motiu mentre executa operacions", "LDAP_Reject_Unauthorized": "Rebutja no autoritzat", "LDAP_Reject_Unauthorized_Description": "Desactiveu aquesta opció per permetre certificats que no es poden verificar. En general, els certificats autofirmados requeriran que aquesta opció estigui desactivada per funcionar", - "LDAP_Roles_To_Rocket_Chat_Roles": "Assignació de rols de LDAP a Rocket.Chat.", - "LDAP_Roles_To_Rocket_Chat_Roles_Description": "Mapeig de rols en format d'objectes on la clau d'objecte ha de ser el rol LDAP i el valor d'objecte ha de ser una matriu de rols RC. Exemple: { 'ldapRole': ['rcRole', 'anotherRCRole'] }", "LDAP_Search_Page_Size": "Mida de la pàgina de cerca", "LDAP_Search_Page_Size_Description": "El nombre màxim d'entrades que cada pàgina de resultats tornarà a processar", "LDAP_Search_Size_Limit": "Límit de la mida de la cerca", @@ -2489,29 +2481,28 @@ "LDAP_Sync_User_Active_State_Disable": "Habilitar usuaris", "LDAP_Sync_User_Active_State_Nothing": "No fer res", "LDAP_Sync_User_Avatar": "Sincronitzar avatar de l'usuari", - "LDAP_Sync_User_Data": "Sincronitzar dades d'usuari", - "LDAP_Sync_User_Data_Description": "Mantenir les dades de l'usuari sincronitzades amb el servidor **quan s'identifiqui** o en **sincronització en background** (ex: nom, adreça de correu, etcètera).", - "LDAP_Sync_User_Data_FieldMap": "Mapatge de camps de dades d'usuari", - "LDAP_Sync_User_Data_FieldMap_Description": "Configura com els camps del compte d'usuari (com el de correu-e) s'omplen des del registre LDAP (un cop trobat).
A tall d'exemple, `{\"cn\":\"name\", \"mail\":\"email\"}` triarà el nom des de l'atribut `cn`, i l'adreça-e des de l'atribut `mail`. Addicionalment, és possible utilitzar variables, per exemple: `{ \"#{givenName} #{sn}\": \"name\", \"mail\": \"email\" }` utilitza una combinació del nom de pila i del cognom per al camp `name` de l'usuari de rocket chat.
Camps disponibles a Rocket.Chat: `name`, `email` i `customFields`.", - "LDAP_Sync_User_Data_Groups": "Sincronitza grups LDAP", - "LDAP_Sync_User_Data_Groups_AutoChannels": "Sincronització automàtica de grups LDAP a Channels", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "Channel Administrador", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin_Description": "Quan es creen canals automàticament que no existeixen durant una sincronització, aquest usuari es convertirà automàticament en l'administrador del canal.", - "LDAP_Sync_User_Data_Groups_AutoChannels_Description": "Activeu aquesta funció per afegir usuaris automàticament a un canal en funció del seu grup LDAP. Si voleu eliminar també els usuaris d'un canal, consulteu l'opció següent per eliminar usuaris automàticament.", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap": "Mapa del Channel Grup LDAP", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Default": "// Habiliteu la sincronització automàtica de grups LDAP amb els Channel anteriors", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Description": "Assigneu grups LDAP a canals Rocket.Chat.
Com a exemple, `{\"employee\":\"general\"}` afegirà qualsevol usuari del treballador del grup LDAP al canal general.", - "LDAP_Sync_User_Data_Groups_AutoRemove": "Elimina automàticament els rols d'usuari", - "LDAP_Sync_User_Data_Groups_AutoRemove_Description": "** Atenció **: si activeu això, s'eliminaran automàticament els usuaris d'una funció si no estan assignats a LDAP. Això només eliminarà automàticament els rols que es defineixen al mapa de grups de dades d'usuaris que apareix a continuació.", - "LDAP_Sync_User_Data_Groups_BaseDN": "Grup LDAP BaseDN", - "LDAP_Sync_User_Data_Groups_BaseDN_Description": "LDAP basedn utilitzat per buscar usuaris.", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels": "Elimina automàticament els usuaris de Channel s", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels_Description": "** Atenció **: Habilitar això eliminarà a qualsevol usuari en un canal que no tingui el grup LDAP corresponent! Habiliteu això només si sap el que està fent.", - "LDAP_Sync_User_Data_Groups_Filter": "Filtre de grups d'usuaris", - "LDAP_Sync_User_Data_Groups_Filter_Description": "El filtre de cerca LDAP que s'usa per verificar si un usuari està en un grup.", - "LDAP_Sync_User_Data_GroupsMap": "Mapa de grup de dades d'usuari", - "LDAP_Sync_User_Data_GroupsMap_Description": "Mapeja els grups LDAP als rols d'usuari de Rocket.Chat
Com a exemple, `{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}` mapejarà el grup LDAP de rocket- admin a el paper de \"admin\" de Rocket.", - "LDAP_Test_Connection": "Prova la connexió", + "LDAP_Sync_User_Data_Roles": "Sincronitza grups LDAP", + "LDAP_Sync_User_Data_Channels": "Sincronització automàtica de grups LDAP a Channels", + "LDAP_Sync_User_Data_Channels_Admin": "Channel Administrador", + "LDAP_Sync_User_Data_Channels_Admin_Description": "Quan es creen canals automàticament que no existeixen durant una sincronització, aquest usuari es convertirà automàticament en l'administrador del canal.", + "LDAP_Sync_User_Data_Channels_BaseDN": "Grup LDAP BaseDN", + "LDAP_Sync_User_Data_Channels_BaseDN_Description": "LDAP basedn utilitzat per buscar usuaris.", + "LDAP_Sync_User_Data_Channels_Description": "Activeu aquesta funció per afegir usuaris automàticament a un canal en funció del seu grup LDAP. Si voleu eliminar també els usuaris d'un canal, consulteu l'opció següent per eliminar usuaris automàticament.", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels": "Elimina automàticament els usuaris de Channel s", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels_Description": "** Atenció **: Habilitar això eliminarà a qualsevol usuari en un canal que no tingui el grup LDAP corresponent! Habiliteu això només si sap el que està fent.", + "LDAP_Sync_User_Data_Channels_Filter": "Filtre de grups d'usuaris", + "LDAP_Sync_User_Data_Channels_Filter_Description": "El filtre de cerca LDAP que s'usa per verificar si un usuari està en un grup.", + "LDAP_Sync_User_Data_ChannelsMap": "Mapa del Channel Grup LDAP", + "LDAP_Sync_User_Data_ChannelsMap_Default": "// Habiliteu la sincronització automàtica de grups LDAP amb els Channel anteriors", + "LDAP_Sync_User_Data_ChannelsMap_Description": "Assigneu grups LDAP a canals Rocket.Chat.
Com a exemple, `{\"employee\":\"general\"}` afegirà qualsevol usuari del treballador del grup LDAP al canal general.", + "LDAP_Sync_User_Data_Roles_AutoRemove": "Elimina automàticament els rols d'usuari", + "LDAP_Sync_User_Data_Roles_AutoRemove_Description": "** Atenció **: si activeu això, s'eliminaran automàticament els usuaris d'una funció si no estan assignats a LDAP. Això només eliminarà automàticament els rols que es defineixen al mapa de grups de dades d'usuaris que apareix a continuació.", + "LDAP_Sync_User_Data_Roles_BaseDN": "Grup LDAP BaseDN", + "LDAP_Sync_User_Data_Roles_BaseDN_Description": "LDAP basedn utilitzat per buscar usuaris.", + "LDAP_Sync_User_Data_Roles_Filter": "Filtre de grups d'usuaris", + "LDAP_Sync_User_Data_Roles_Filter_Description": "El filtre de cerca LDAP que s'usa per verificar si un usuari està en un grup.", + "LDAP_Sync_User_Data_RolesMap": "Mapa de grup de dades d'usuari", + "LDAP_Sync_User_Data_RolesMap_Description": "Mapeja els grups LDAP als rols d'usuari de Rocket.Chat
Com a exemple, `{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}` mapejarà el grup LDAP de rocket- admin a el paper de \"admin\" de Rocket.", "LDAP_Timeout": "Temps d'espera (ms)", "LDAP_Timeout_Description": "Quants mil·lisegons esperen un resultat de cerca abans de tornar un error", "LDAP_Unique_Identifier_Field": "Camp d'identificador únic", @@ -2525,8 +2516,6 @@ "LDAP_Username_Field_Description": "El camp que s'utilitzarà com a nom d'usuari (*username*) per als nous usuaris. Deixar en blanc per a utilitzar el nom d'usuari proporcionat durant l'inici de sessió.
També es poden utilitzar plantilles d'etiqueta, com `#{givenName}.#{sn}`.
El valor per defecte és `sAMAccountName`.", "LDAP_Validate_Teams_For_Each_Login": "Validar l'assignació per a cada inici de sessió", "LDAP_Validate_Teams_For_Each_Login_Description": "Determineu si els equips dels usuaris s'han d'actualitzar cada vegada que inicien sessió en Rocket.Chat. Si està desactivat, l'equip es carregarà només en el seu primer inici de sessió.", - "LDAP_Validate_Roles_For_Each_Login": "Validar l'assignació per a cada inici de sessió", - "LDAP_Validate_Roles_For_Each_Login_Description": "Si la validació ha d'ocórrer per a cada inici de sessió (vagi amb compte amb aquesta configuració perquè sobreescriurà els rols d'usuari en cada inici de sessió, en cas contrari, això es validarà només en el moment de la creació de l'usuari).", "Lead_capture_email_regex": "Regex de correu electrònic de captura de clients potencials", "Lead_capture_phone_regex": "Regex de telèfon de captura clients potencials", "Leave": "Sortir ", diff --git a/packages/rocketchat-i18n/i18n/cs.i18n.json b/packages/rocketchat-i18n/i18n/cs.i18n.json index 1d6b306d7034..c07869c6cec2 100644 --- a/packages/rocketchat-i18n/i18n/cs.i18n.json +++ b/packages/rocketchat-i18n/i18n/cs.i18n.json @@ -2149,12 +2149,8 @@ "LDAP_Connect_Timeout": "Prodleva připojení (ms)", "LDAP_Default_Domain": "Výchozí doména", "LDAP_Default_Domain_Description": "Pokud je vyplněna, Výchozí doména bude použita pro vytvoření unikátního emailu pro ty uživatele, u kterých v LDAP chybí. Bude použit formát `username@default_domain` nebo `unique_id@default_domain`.
Například `rocket.chat`", - "LDAP_Default_Role_To_User": "Výchozí role pro uživatele", - "LDAP_Default_Role_To_User_Description": "Výchozí role přidaná uživateli v případě že LDAP role není namapovaná", - "LDAP_Description": "LDAP je hierarchická databáze, kterou mnohé společnosti používají pro jednotné přihlášení - systém pro sdílení jednoho hesla mezi více webů a služeb. Pro pokročilé informace a příklady konfigurace se podívejte na naši wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/", "LDAP_Enable": "Povolit", "LDAP_Enable_Description": "Pokusit se použít LDAP pro autentizaci.", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "Povolit mapování rolí z LDAP do Rocket.Chat", "LDAP_Encryption": "Šifrování", "LDAP_Encryption_Description": "Metoda šifrování používaná k zabezpečené komunikace se serverem LDAP. Jako příklady lze uvést `plain` (bez šifrování),` SSL/LDAPS` (šifrovaný od začátku), a `StartTLS` (Šifrovaná komunikaci až po připojení).", "LDAP_Find_User_After_Login": "Najít uživatele po přihlášení", @@ -2183,15 +2179,11 @@ "LDAP_Merge_Existing_Users_Description": "*Upozornění!* Pokud importujete uživatele z LDAP a uživatel se stejným jménem již existuje, LDAP údaje a heslo budou přiřazeny tomuto uživateli", "LDAP_Port": "Port", "LDAP_Port_Description": "Port pro přístup k LDAP. např: `389` nebo `636` pro LDAPS", - "LDAP_Query_To_Get_User_Groups": "LDAP query pro získání uživatelských skupin", - "LDAP_Query_To_Get_User_Groups_Description": "LDAP query pro získání skupin do kterých patří uživatel.", "LDAP_Query_To_Get_User_Teams": "LDAP query pro získání uživatelských skupin", "LDAP_Reconnect": "Znovu připojit", "LDAP_Reconnect_Description": "Pokusit se znovu připojit automaticky pokud bylo při zpracování požadavků spojení přerušeno", "LDAP_Reject_Unauthorized": "Odmítnout neoprávněné", "LDAP_Reject_Unauthorized_Description": "Zakažte tuto volbu pro povolení neověřených certifikatů. Většinou je potřeba tuto volbu vypnout pokud se pracuje se self signed certifikáty", - "LDAP_Roles_To_Rocket_Chat_Roles": "Mapování rolí z LDAP do Rocket.Chat", - "LDAP_Roles_To_Rocket_Chat_Roles_Description": "Mapování rolí v objektovém formátu, kde klíč je LDAP role a hodnota pole Rocket.Chat rolí. Například { 'ldapRole': ['rcRole', 'anotherRCRole'] }", "LDAP_Search_Page_Size": "Počet výsledků vyhledávání na stránce", "LDAP_Search_Page_Size_Description": "Maximální počet záznamů na každé stránce výsledků pro zpracování", "LDAP_Search_Size_Limit": "Limit velikosti vyhledávání ", @@ -2204,28 +2196,27 @@ "LDAP_Sync_User_Active_State_Disable": "Zakázat uživatele", "LDAP_Sync_User_Active_State_Nothing": "Nedělat nic", "LDAP_Sync_User_Avatar": "Synchronizace uživatelských avatarů", - "LDAP_Sync_User_Data": "Synchronizace uživatelských dat", - "LDAP_Sync_User_Data_Description": "Udržujte uživatelská data synchronizovaná se serverem po přihlášení nebo při **synchronizaci na pozadí** (např: jméno, e-mail).", - "LDAP_Sync_User_Data_FieldMap": "Mapa polí uživatelských dat", - "LDAP_Sync_User_Data_FieldMap_Description": "Konfiguruje pole uživatelských dat (například e-mailu) v záznamu v LDAP.
Například `{\"cn\":\"name\", \"mail\":\"email\"}` vybere jméno osoby z atributu `cn`, a jeho e-mail z atributu `mail`. Lze používat proměnné například: `{ \"#{givenName} #{sn}\": \"name\", \"mail\": \"email\" }` použije kombinaci křestínho jména a příjmení pro pole `name` v Rocket.Chat.
Dostupná pole Rocket.Chatu jsou `name`, a `email`.", - "LDAP_Sync_User_Data_Groups": "Synchronizovat skupiny LDAP", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "Administrátor místnosti", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin_Description": "Pokud jsou automaticky vytvořeny kanály, které během synchronizace neexistují, stane se tento uživatel automaticky správcem kanálu.", - "LDAP_Sync_User_Data_Groups_AutoChannels_Description": "Povolením této funkce automaticky přidáte uživatele do kanálu na základě jejich skupiny LDAP. Pokud chcete uživatele také odebrat z kanálu, přečtěte si níže uvedenou možnost automatického odebrání uživatelů.", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap": "Mapa LDAP skupiny místností", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Default": "// Povolit automatické synchronizace skupin LDAP do výše uvedených místností", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Description": "Mapovat skupiny LDAP do kanálů Rocket.Chat.
Jako příklad, \"{\"employee\":\"general\"}\" přidá do obecného kanálu libovolného uživatele ve skupině zaměstnanců LDAP.", - "LDAP_Sync_User_Data_Groups_AutoRemove": "Automaticky odebrat uživatelské role", - "LDAP_Sync_User_Data_Groups_AutoRemove_Description": "** Pozor **: Povolení této funkce automaticky odstraní uživatele z role, pokud nejsou přiřazeni v LDAP! Tím se odstraní pouze role, které jsou nastaveny v níže uvedené mapě skupin dat uživatelů.", - "LDAP_Sync_User_Data_Groups_BaseDN": "BaseDN LDAP skupiny", - "LDAP_Sync_User_Data_Groups_BaseDN_Description": "LDAP BaseDN užívaný k vyhledávání uživatelů.", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels": "Automaticky odebírat uživatele z místností", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels_Description": "** Pozor **: Povolení této funkce se odstraní všichni uživatelé v kanálu, kteří nemají korespondující skupinu LDAP! Povolte ji, pouze pokud víte, co děláte.", - "LDAP_Sync_User_Data_Groups_Filter": "Filtr skupiny uživatelů", - "LDAP_Sync_User_Data_Groups_Filter_Description": "Vyhledávací filtr LDAP používaný ke kontrole, zda je uživatel ve skupině.", - "LDAP_Sync_User_Data_GroupsMap": "Mapa skupin uživatelských dat", - "LDAP_Sync_User_Data_GroupsMap_Description": "Mapuje skupiny LDAP na Rocket.Chat uživatelské role
Jako příklad bude \"{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}\" mapovat skupinu LDAP Rocket-admin do role „admin“ v Rocket.Chat.", - "LDAP_Test_Connection": "Test připojení", + "LDAP_Sync_User_Data_Roles": "Synchronizovat skupiny LDAP", + "LDAP_Sync_User_Data_Channels_Admin": "Administrátor místnosti", + "LDAP_Sync_User_Data_Channels_Admin_Description": "Pokud jsou automaticky vytvořeny kanály, které během synchronizace neexistují, stane se tento uživatel automaticky správcem kanálu.", + "LDAP_Sync_User_Data_Channels_BaseDN": "BaseDN LDAP skupiny", + "LDAP_Sync_User_Data_Channels_BaseDN_Description": "LDAP BaseDN užívaný k vyhledávání uživatelů.", + "LDAP_Sync_User_Data_Channels_Description": "Povolením této funkce automaticky přidáte uživatele do kanálu na základě jejich skupiny LDAP. Pokud chcete uživatele také odebrat z kanálu, přečtěte si níže uvedenou možnost automatického odebrání uživatelů.", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels": "Automaticky odebírat uživatele z místností", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels_Description": "** Pozor **: Povolení této funkce se odstraní všichni uživatelé v kanálu, kteří nemají korespondující skupinu LDAP! Povolte ji, pouze pokud víte, co děláte.", + "LDAP_Sync_User_Data_Channels_Filter": "Filtr skupiny uživatelů", + "LDAP_Sync_User_Data_Channels_Filter_Description": "Vyhledávací filtr LDAP používaný ke kontrole, zda je uživatel ve skupině.", + "LDAP_Sync_User_Data_ChannelsMap": "Mapa LDAP skupiny místností", + "LDAP_Sync_User_Data_ChannelsMap_Default": "// Povolit automatické synchronizace skupin LDAP do výše uvedených místností", + "LDAP_Sync_User_Data_ChannelsMap_Description": "Mapovat skupiny LDAP do kanálů Rocket.Chat.
Jako příklad, \"{\"employee\":\"general\"}\" přidá do obecného kanálu libovolného uživatele ve skupině zaměstnanců LDAP.", + "LDAP_Sync_User_Data_Roles_AutoRemove": "Automaticky odebrat uživatelské role", + "LDAP_Sync_User_Data_Roles_AutoRemove_Description": "** Pozor **: Povolení této funkce automaticky odstraní uživatele z role, pokud nejsou přiřazeni v LDAP! Tím se odstraní pouze role, které jsou nastaveny v níže uvedené mapě skupin dat uživatelů.", + "LDAP_Sync_User_Data_Roles_BaseDN": "BaseDN LDAP skupiny", + "LDAP_Sync_User_Data_Roles_BaseDN_Description": "LDAP BaseDN užívaný k vyhledávání uživatelů.", + "LDAP_Sync_User_Data_Roles_Filter": "Filtr skupiny uživatelů", + "LDAP_Sync_User_Data_Roles_Filter_Description": "Vyhledávací filtr LDAP používaný ke kontrole, zda je uživatel ve skupině.", + "LDAP_Sync_User_Data_RolesMap": "Mapa skupin uživatelských dat", + "LDAP_Sync_User_Data_RolesMap_Description": "Mapuje skupiny LDAP na Rocket.Chat uživatelské role
Jako příklad bude \"{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}\" mapovat skupinu LDAP Rocket-admin do role „admin“ v Rocket.Chat.", "LDAP_Timeout": "Časový limit (ms)", "LDAP_Timeout_Description": "Kolik milisekund počkat na vyhledávání než bude vrácena chyba", "LDAP_Unique_Identifier_Field": "Jedinečný identifikátor", @@ -2238,8 +2229,6 @@ "LDAP_Username_Field": "Pole Uživatelského jména", "LDAP_Username_Field_Description": "Které pole budou použity jako *Jméno* pro nové uživatele. Ponechte prázdné pro použítí jména z přihlašovací stránky.
Můžete použít šablony a tagy jako například `#{givenName}.#{sn}`.
Výchozí hodnota je `sAMAccountName`.", "LDAP_Validate_Teams_For_Each_Login": "Validovat mapování pro každé přihlášení", - "LDAP_Validate_Roles_For_Each_Login": "Validovat mapování pro každé přihlášení", - "LDAP_Validate_Roles_For_Each_Login_Description": "Zda má validace probíhat při každém přihlášení (Opatrně, taková akce přepíše uživatelské role při každém přihlášení. V opačném případě je validováno jen při vytvoření uživatele", "Lead_capture_email_regex": "Regulární výraz pro zachycení Leadu na email", "Lead_capture_phone_regex": "Regulární výraz pro zachycení Leadu na telefon", "Leave": "Opustit", diff --git a/packages/rocketchat-i18n/i18n/cy.i18n.json b/packages/rocketchat-i18n/i18n/cy.i18n.json index a14f90cc752e..540a69988cc6 100644 --- a/packages/rocketchat-i18n/i18n/cy.i18n.json +++ b/packages/rocketchat-i18n/i18n/cy.i18n.json @@ -1516,7 +1516,6 @@ "LDAP_Connect_Timeout": "Amserlen Cysylltiad (ms)", "LDAP_Default_Domain": "Maes Diofyn", "LDAP_Default_Domain_Description": "Os rhoddir y Parth Diofyn yn cael ei ddefnyddio i greu e-bost unigryw i ddefnyddwyr lle na chafodd yr e-bost ei fewnforio o LDAP. Bydd yr e-bost yn cael ei osod fel `username @ default_domain` neu` unique_id @ default_domain`.
Enghraifft: `rocket.chat`", - "LDAP_Description": "Cronfa ddata hierarchaidd yw LDAP y mae llawer o gwmnïau'n ei ddefnyddio i ddarparu arwydd sengl - cyfleuster ar gyfer rhannu un cyfrinair rhwng lluosog o safleoedd a gwasanaethau. I gael gwybodaeth ac enghreifftiau datrysiadau uwch, ewch i'n wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Galluogi", "LDAP_Enable_Description": "Ceisiwch ddefnyddio LDAP ar gyfer dilysu.", "LDAP_Encryption": "Amgryptio", @@ -1558,11 +1557,6 @@ "LDAP_Sync_Now": "Cefndir Sync Nawr", "LDAP_Sync_Now_Description": "A fydd yn gweithredu ** Cefndir Sync ** nawr yn hytrach na disgwyl ** Cyfnod Sync ** hyd yn oed os yw ** Cefndir Sync ** yn Ffug.
Mae'r Weithred hon yn asyncronous, gweler y logiau i gael rhagor o wybodaeth am y broses", "LDAP_Sync_User_Avatar": "Sync Defnyddiwr Avatar", - "LDAP_Sync_User_Data": "Sync Data Defnyddiwr", - "LDAP_Sync_User_Data_Description": "Cadwch ddata defnyddwyr mewn sync gyda gweinyddwr ** ** mewngofnodi ** neu ar ** sync cefndir ** (ee: enw, e-bost).", - "LDAP_Sync_User_Data_FieldMap": "Map Maes Data Defnyddwyr", - "LDAP_Sync_User_Data_FieldMap_Description": "Ffurfweddu sut mae meysydd cyfrif defnyddwyr (fel e-bost) wedi'u poblogi o gofnod yn LDAP (unwaith y darganfyddwyd).
Fel enghraifft, `{\" cn \":\" name \",\" mail \":\" email \"}` bydd yn dewis enw darllenadwy dynol y person o'r priodwedd cn, a'i e-bost o briodoldeb y post. Yn ogystal, mae'n bosibl defnyddio newidynnau, er enghraifft: `{\" # {givenName} # {sn} \":\" name \",\" mail \":\" email \"}` yn defnyddio cyfuniad o enw cyntaf y defnyddiwr ac enw olaf y roc sgwrsio `enw` maes.
Caeau sydd ar gael yn Rocket.Chat:` name`, `email` and` customFields`.", - "LDAP_Test_Connection": "Cysylltiad Prawf", "LDAP_Timeout": "Amserlen (ms)", "LDAP_Timeout_Description": "Faint o filltiroedd milltir sy'n aros am ganlyniad chwilio cyn dychwelyd gwall", "LDAP_Unique_Identifier_Field": "Maes Adnabod Unigryw", diff --git a/packages/rocketchat-i18n/i18n/da.i18n.json b/packages/rocketchat-i18n/i18n/da.i18n.json index 583b447629c4..2dac103209e9 100644 --- a/packages/rocketchat-i18n/i18n/da.i18n.json +++ b/packages/rocketchat-i18n/i18n/da.i18n.json @@ -2161,12 +2161,8 @@ "LDAP_Connect_Timeout": "Forbindelses-timeout (ms)", "LDAP_Default_Domain": "Standarddomæne", "LDAP_Default_Domain_Description": "Hvis det leveres, vil standarddomenet blive brugt til at oprette en unik e-mail til brugere, hvor e-mail ikke blev importeret fra LDAP. E-mailen vil blive monteret som `brugernavn @ default_domain` eller` unique_id @ default_domain`.
Eksempel: `rocket.chat`", - "LDAP_Default_Role_To_User": "Standardrolle for bruger", - "LDAP_Default_Role_To_User_Description": "Standard RC-rolle der skal tildeles en bruger, hvis brugeren har en LDAP-rolle der ikke er knyttet til noget", - "LDAP_Description": "LDAP er en hierarkisk database, som mange virksomheder bruger til at give et enkelt tegn på - en facilitet til deling af en adgangskode mellem flere websteder og tjenester. For avanceret konfigurationsinformation og eksempler, se venligst vores wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Aktivér", "LDAP_Enable_Description": "Forsøg at anvende LDAP til godkendelse.", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "Aktivér rolletilknytning fra LDAP til Rocket.Chat", "LDAP_Encryption": "Kryptering", "LDAP_Encryption_Description": "Krypteringsmetoden bruges til at sikre kommunikation til LDAP-serveren. Eksempler er `plain` (ingen kryptering),` SSL / LDAPS` (krypteret fra starten) og `StartTLS` (opgradering til krypteret kommunikation, når den er tilsluttet).", "LDAP_Find_User_After_Login": "Find brugeren efter login", @@ -2195,15 +2191,11 @@ "LDAP_Merge_Existing_Users_Description": "* Forsigtig! * Når der importeres en bruger fra LDAP, og en bruger med samme brugernavn allerede eksisterer, indstilles LDAP-info og adgangskode til den eksisterende bruger.", "LDAP_Port": "Port", "LDAP_Port_Description": "Port for at få adgang til LDAP. fx: `389` eller` 636` for LDAPS", - "LDAP_Query_To_Get_User_Groups": "LDAP-forespørgsel for at hente brugergrupper", - "LDAP_Query_To_Get_User_Groups_Description": "LDAP-forespørgsel for at hente de LDAP-grupper, som brugeren er en del af.", "LDAP_Query_To_Get_User_Teams": "LDAP-forespørgsel for at hente brugergrupper", "LDAP_Reconnect": "Tilslut", "LDAP_Reconnect_Description": "Prøv at genoprette forbindelse automatisk, når forbindelsen afbrydes af en eller anden grund under udførelsen af ​​operationer", "LDAP_Reject_Unauthorized": "Afvis uautoriseret", "LDAP_Reject_Unauthorized_Description": "Deaktiver denne mulighed for at tillade certifikater, der ikke kan verificeres. Normalt vil selvkendte certifikater kræve, at denne indstilling er deaktiveret til arbejde", - "LDAP_Roles_To_Rocket_Chat_Roles": "Rolletilknytning fra LDAP til Rocket.Chat.", - "LDAP_Roles_To_Rocket_Chat_Roles_Description": "Rolletilknytning i objektformat hvor objektnøglen skal være LDAP-rollen og objektværdien skal være en array af RC-roller. Eksempel: { 'ldapRole': ['rcRole', 'anotherRCRole'] }", "LDAP_Search_Page_Size": "Søg sidestørrelse", "LDAP_Search_Page_Size_Description": "Det maksimale antal indlæg hver resultatside vender tilbage for at blive behandlet", "LDAP_Search_Size_Limit": "Søg størrelsesbegrænsning", @@ -2216,29 +2208,28 @@ "LDAP_Sync_User_Active_State_Disable": "Deaktiver brugere", "LDAP_Sync_User_Active_State_Nothing": "Gør ikke noget", "LDAP_Sync_User_Avatar": "Synkroniser brugerens Avatar", - "LDAP_Sync_User_Data": "Synkroniser brugerdata", - "LDAP_Sync_User_Data_Description": "Hold brugerdata synkroniseret med serveren på **login** eller på **baggrunds synkronisering** (fx: navn, email).", - "LDAP_Sync_User_Data_FieldMap": "Brugerdata felt-mapping", - "LDAP_Sync_User_Data_FieldMap_Description": "Konfigurer, hvordan brugerkonto felter (som e-mail) er befolket fra en post i LDAP (en gang fundet).
Som eksempel kan '{\"cn\": \"navn\", \"mail\": \"email\"} `vælge en persons menneskelige læsbare navn fra cn-attributten og deres e-mail fra postattributtet. Derudover er det muligt at bruge variabler, for eksempel: `{\" # {givenName} # {sn} \":\" navn \",\" mail \":\" email \"}` bruger en kombination af brugerens fornavn og efternavn til rocket chat `name`-feltet.
Fås i felterne i Rocket.Chat:` name`, `email` og` customFields`.", - "LDAP_Sync_User_Data_Groups": "Synkroniser LDAP-grupper", - "LDAP_Sync_User_Data_Groups_AutoChannels": "Automatisk synkronisering af LDAP-grupper til kanaler", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "Channel Admin", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin_Description": "Når der automatisk oprettes kanaler, der ikke findes under en synkronisering, bliver denne bruger automatisk administrator for kanalen.", - "LDAP_Sync_User_Data_Groups_AutoChannels_Description": "Aktivér denne funktion for automatisk at tilføje brugere til en kanal baseret på deres LDAP-gruppe. Hvis du også gerne vil fjerne brugere fra en kanal, kan du se indstillingen nedenfor vedrørende automatisk fjernelse af brugere.", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap": "LDAP-gruppe kanaloversigt", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Default": "// Automatisk synkronisering af LDAP-grupper til kanaler ovenfor", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Description": "Kortlæg LDAP-grupper til Rocket.Chat-kanaler.
. F.eks. tilføjer '{\"employee\":\"general\"}' enhver bruger i LDAP-gruppe-medarbejderen til den generelle kanal.", - "LDAP_Sync_User_Data_Groups_AutoRemove": "Fjern automatisk brugerroller", - "LDAP_Sync_User_Data_Groups_AutoRemove_Description": "** OBS **: Aktivering af dette fjerner automatisk brugere fra en rolle, hvis de ikke er tildelt i LDAP! Dette fjerner kun roller automatisk der er indstillet under brugerdata-gruppeoversigten nedenfor.", - "LDAP_Sync_User_Data_Groups_BaseDN": "LDAP Group BaseDN", - "LDAP_Sync_User_Data_Groups_BaseDN_Description": "LDAP BaseDN til at slå brugere op med.", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels": "Fjern automatisk brugere fra kanaler", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels_Description": "** OBS **: Aktivering af dette fjerner alle brugere i en kanal, der ikke har den tilsvarende LDAP-gruppe! Aktivér kun dette hvis du ved hvad du laver.", - "LDAP_Sync_User_Data_Groups_Filter": "Brugergruppefilter", - "LDAP_Sync_User_Data_Groups_Filter_Description": "LDAP-søgefilteret der bruges til at kontrollere om en bruger er i en gruppe.", - "LDAP_Sync_User_Data_GroupsMap": "Brugerdata-gruppeoversigt", - "LDAP_Sync_User_Data_GroupsMap_Description": "Relatér LDAP-grupper til Rocket.Chat-brugerroller
F.eks. vil '{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}' relatere rocket-admin-LDAP-gruppen til Rockets \"admin\" -rolle.", - "LDAP_Test_Connection": "Testforbindelse", + "LDAP_Sync_User_Data_Roles": "Synkroniser LDAP-grupper", + "LDAP_Sync_User_Data_Channels": "Automatisk synkronisering af LDAP-grupper til kanaler", + "LDAP_Sync_User_Data_Channels_Admin": "Channel Admin", + "LDAP_Sync_User_Data_Channels_Admin_Description": "Når der automatisk oprettes kanaler, der ikke findes under en synkronisering, bliver denne bruger automatisk administrator for kanalen.", + "LDAP_Sync_User_Data_Channels_BaseDN": "LDAP Group BaseDN", + "LDAP_Sync_User_Data_Channels_BaseDN_Description": "LDAP BaseDN til at slå brugere op med.", + "LDAP_Sync_User_Data_Channels_Description": "Aktivér denne funktion for automatisk at tilføje brugere til en kanal baseret på deres LDAP-gruppe. Hvis du også gerne vil fjerne brugere fra en kanal, kan du se indstillingen nedenfor vedrørende automatisk fjernelse af brugere.", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels": "Fjern automatisk brugere fra kanaler", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels_Description": "** OBS **: Aktivering af dette fjerner alle brugere i en kanal, der ikke har den tilsvarende LDAP-gruppe! Aktivér kun dette hvis du ved hvad du laver.", + "LDAP_Sync_User_Data_Channels_Filter": "Brugergruppefilter", + "LDAP_Sync_User_Data_Channels_Filter_Description": "LDAP-søgefilteret der bruges til at kontrollere om en bruger er i en gruppe.", + "LDAP_Sync_User_Data_ChannelsMap": "LDAP-gruppe kanaloversigt", + "LDAP_Sync_User_Data_ChannelsMap_Default": "// Automatisk synkronisering af LDAP-grupper til kanaler ovenfor", + "LDAP_Sync_User_Data_ChannelsMap_Description": "Kortlæg LDAP-grupper til Rocket.Chat-kanaler.
. F.eks. tilføjer '{\"employee\":\"general\"}' enhver bruger i LDAP-gruppe-medarbejderen til den generelle kanal.", + "LDAP_Sync_User_Data_Roles_AutoRemove": "Fjern automatisk brugerroller", + "LDAP_Sync_User_Data_Roles_AutoRemove_Description": "** OBS **: Aktivering af dette fjerner automatisk brugere fra en rolle, hvis de ikke er tildelt i LDAP! Dette fjerner kun roller automatisk der er indstillet under brugerdata-gruppeoversigten nedenfor.", + "LDAP_Sync_User_Data_Roles_BaseDN": "LDAP Group BaseDN", + "LDAP_Sync_User_Data_Roles_BaseDN_Description": "LDAP BaseDN til at slå brugere op med.", + "LDAP_Sync_User_Data_Roles_Filter": "Brugergruppefilter", + "LDAP_Sync_User_Data_Roles_Filter_Description": "LDAP-søgefilteret der bruges til at kontrollere om en bruger er i en gruppe.", + "LDAP_Sync_User_Data_RolesMap": "Brugerdata-gruppeoversigt", + "LDAP_Sync_User_Data_RolesMap_Description": "Relatér LDAP-grupper til Rocket.Chat-brugerroller
F.eks. vil '{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}' relatere rocket-admin-LDAP-gruppen til Rockets \"admin\" -rolle.", "LDAP_Timeout": "Timeout (ms)", "LDAP_Timeout_Description": "Hvor mange mileseconds venter på et søgeresultat, før du returnerer en fejl", "LDAP_Unique_Identifier_Field": "Unikt identifikationsfelt", @@ -2251,8 +2242,6 @@ "LDAP_Username_Field": "Brugernavns-felt", "LDAP_Username_Field_Description": "Hvilket felt vil blive brugt som * brugernavn * til nye brugere. Lad være tom for at bruge brugernavnet informeret på login side.
Du kan også bruge skabeloner, som `# {givenName}. # {Sn}`.
Standardværdien er `sAMAccountName`.", "LDAP_Validate_Teams_For_Each_Login": "Validér tilknytning for hvert login", - "LDAP_Validate_Roles_For_Each_Login": "Validér tilknytning for hvert login", - "LDAP_Validate_Roles_For_Each_Login_Description": "Hvis validering skal ske for hvert login (Vær forsigtig med denne indstilling, fordi den vil overskrive brugerrollerne i hvert login. Ellers valideres dette kun på det tidspunkt hvor brugeren oprettes).", "Lead_capture_email_regex": "Lead capture email regex", "Lead_capture_phone_regex": "Lead capture phone regex", "Leave": "Forlad", diff --git a/packages/rocketchat-i18n/i18n/de-AT.i18n.json b/packages/rocketchat-i18n/i18n/de-AT.i18n.json index 4f769ca2cf2c..ee19054bcfb6 100644 --- a/packages/rocketchat-i18n/i18n/de-AT.i18n.json +++ b/packages/rocketchat-i18n/i18n/de-AT.i18n.json @@ -1522,7 +1522,6 @@ "LDAP_Connect_Timeout": "Verbindungstimeout (ms)", "LDAP_Default_Domain": "Standard-Domain", "LDAP_Default_Domain_Description": "Wenn die Standarddomäne bereitgestellt wird, wird eine eindeutige E-Mail für Benutzer erstellt, deren E-Mail nicht aus LDAP importiert wurde. Die E-Mail wird als `username @ default_domain` oder` unique_id @ default_domain` gemountet.
Beispiel: `rocket.chat`", - "LDAP_Description": "LDAP ist ein Frontend zu hierarchischen Datenbanken, die viele Unternehmen nutzen, um eine eine Einmalanmeldung (SSO) zu ermöglichen. Über SSO kann \"ein Benutzer nach einer einmaligen Authentifizierung an einem Arbeitsplatz auf alle Rechner und Dienste, für die er lokal berechtigt ist, am selben Arbeitsplatz zugreifen kann, ohne sich jedes Mal neu anmelden zu müssen\". Genauere Informationen zur Konfiguration von LDAP mit Konfigurationsbeispielen erhalten Sie unter folgendem Link: https://rocket.chat/docs/administrator-guides/authentication/ldap/", "LDAP_Enable": "LDAP aktivieren", "LDAP_Enable_Description": "LDAP für die Authentifizierung verwenden.", "LDAP_Encryption": "Verschlüsselung", @@ -1564,11 +1563,6 @@ "LDAP_Sync_Now": "Hintergrund-Synchronisierung jetzt", "LDAP_Sync_Now_Description": "Wird die ** Hintergrundsynchronisation ** jetzt ausführen, anstatt das ** Synchronisierungsintervall ** zu warten, selbst wenn ** Hintergrundsynchronisation ** Falsch ist.
Diese Aktion ist asynchron, bitte sehen Sie in den Protokollen nach, um weitere Informationen zu erhalten verarbeiten", "LDAP_Sync_User_Avatar": "Profilbilder synchronisieren", - "LDAP_Sync_User_Data": "Daten synchronisieren", - "LDAP_Sync_User_Data_Description": "Bei der Anmeldung die Benutzerdaten mit dem Server synchronisieren (Beispiel: Name, E-Mail).", - "LDAP_Sync_User_Data_FieldMap": "Nutzerdaten-Feldkarte", - "LDAP_Sync_User_Data_FieldMap_Description": "Konfigurieren Sie, wie Benutzer-Account-Felder (wie die E-Mail-Adresse) aus einem LDAP-Datensatz (falls gefunden) geladen werden.
Beispiel: {\"cn\":\"name\", \"mail\":\"email\"} nimmt einen von Menschen lesbaren Namen von dem cn-Attribut und die E-Mail-Adresse vom Mail-Attribut.
Verfügbare Felder beinhalten den Namen und die E-Mail-Adresse.", - "LDAP_Test_Connection": "Testverbindung", "LDAP_Timeout": "Zeitüberschreitung (ms)", "LDAP_Timeout_Description": "Wie viele Meilen warten auf ein Suchergebnis, bevor ein Fehler zurückgegeben wird", "LDAP_Unique_Identifier_Field": "Eindeutige Kennung des Felds", diff --git a/packages/rocketchat-i18n/i18n/de-IN.i18n.json b/packages/rocketchat-i18n/i18n/de-IN.i18n.json index c0bc766de28e..f3e5226920b8 100644 --- a/packages/rocketchat-i18n/i18n/de-IN.i18n.json +++ b/packages/rocketchat-i18n/i18n/de-IN.i18n.json @@ -1765,7 +1765,6 @@ "LDAP_Connect_Timeout": "Verbindungs-Timeout (ms)", "LDAP_Default_Domain": "Standard-Domain", "LDAP_Default_Domain_Description": "Wenn eine Standard-Domäne angegeben wurde, wird diese zur Erzeugung von E-Mail-Adressen verwendet, sofern keine E-Mail-Adresse aus dem LDAP importiert wurde. Die E-Mail wird konstruiert als `benutzername@standard-domäne` oder `unique_id@standard-domäne`
Beispiel: `rocket.chat`", - "LDAP_Description": "LDAP ist eine hierarchische Datenbank, die viele Unternehmen nutzen, um eine eine Einmalanmeldung (SSO) zu ermöglichen. Über SSO kann \"ein Benutzer nach einer einmaligen Authentifizierung an einem Arbeitsplatz auf alle Rechner und Dienste, für die er lokal berechtigt ist, am selben Arbeitsplatz zugreifen kann, ohne sich jedes Mal neu anmelden zu müssen\". Genauere Informationen zur Konfiguration von LDAP mit Konfigurationsbeispielen erhältst Du unter folgendem Link: https://rocket.chat/docs/administrator-guides/authentication/ldap/", "LDAP_Enable": "LDAP", "LDAP_Enable_Description": "LDAP zur Authentifizierung verwenden", "LDAP_Encryption": "Verschlüsselung", @@ -1807,11 +1806,6 @@ "LDAP_Sync_Now": "Jetzt im Hintergrund synchronisieren", "LDAP_Sync_Now_Description": "Führt jetzt eine **Synchronisierung im Hintergrund** aus, anstatt auf die nächste planmäßige Synchronisierung zu warten. Das funktioniert auch, wenn die Synchronisierung im Hintergrund deaktiviert ist.
Die Aktion läuft asynchron ab, der Fortschritt kann im Log verfolgt werden.", "LDAP_Sync_User_Avatar": "Profilbilder synchronisieren", - "LDAP_Sync_User_Data": "Benutzerdaten synchronisieren", - "LDAP_Sync_User_Data_Description": "Bei der Anmeldung die Benutzerdaten mit dem Server synchronisieren (Bspw. Name, E-Mail-Adresse).", - "LDAP_Sync_User_Data_FieldMap": "Zuordnung der Benutzer-Attribute", - "LDAP_Sync_User_Data_FieldMap_Description": "Konfiguriere, wie Benutzer-Account-Eigenschaften (wie die E-Mail-Adresse) aus einem LDAP-Datensatz (falls gefunden) geladen werden.
Beispiel: {\"cn\":\"name\", \"mail\":\"email\"} nimmt einen von Menschen lesbaren Namen aus dem cn-Attribut und die E-Mail-Adresse aus dem Mail-Attribut. Zusätzlich ist die Verwendung von Variablen möglich, wie z.B.: `{ \"#{givenName} #{sn}\": \"name\", \"mail\": \"email\" }`. Hierbei wird eine Kombination des Vor- und Nachnamens verwendet.
Verfügbare Felder in Rocket.Chat sind `name` und `email`.", - "LDAP_Test_Connection": "Verbindung prüfen", "LDAP_Timeout": "Timeout (ms)", "LDAP_Timeout_Description": "Wie lange auf ein Suchergebnis gewartet werden soll, bevor ein Fehler ausgegeben wird", "LDAP_Unique_Identifier_Field": "Feld für eindeutige Identifizierung", diff --git a/packages/rocketchat-i18n/i18n/de.i18n.json b/packages/rocketchat-i18n/i18n/de.i18n.json index 99125b939be0..ede8e5cc26cc 100644 --- a/packages/rocketchat-i18n/i18n/de.i18n.json +++ b/packages/rocketchat-i18n/i18n/de.i18n.json @@ -2295,12 +2295,8 @@ "LDAP_Connect_Timeout": "Verbindungs-Timeout (ms)", "LDAP_Default_Domain": "Standard-Domain", "LDAP_Default_Domain_Description": "Wenn eine Standard-Domäne angegeben wurde, wird diese zur Erzeugung von E-Mail-Adressen verwendet, sofern keine E-Mail-Adresse aus dem LDAP importiert wurde. Die E-Mail wird konstruiert als `benutzername@standard-domäne` oder `unique_id@standard-domäne`
Beispiel: `rocket.chat`", - "LDAP_Default_Role_To_User": "Standardrolle für Benutzer", - "LDAP_Default_Role_To_User_Description": "Die Standard-RC-Rolle, die auf den Benutzer angewendet werden soll, wenn der Benutzer eine LDAP-Rolle hat, die nicht zugeordnet ist.", - "LDAP_Description": "LDAP ist eine hierarchische Datenbank, die viele Unternehmen nutzen, um eine eine Einmalanmeldung (SSO) zu ermöglichen - eine Funktion zum Teilen eines Kennworts zwischen mehrere Standorten und Diensten. Weitere Informationen zur Konfiguration von LDAP mit Konfigurationsbeispielen erhalten Sie unter folgendem Link: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "LDAP", "LDAP_Enable_Description": "LDAP zur Authentifizierung verwenden", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "Aktivieren der Rollenzuordnung von LDAP zu Rocket.Chat", "LDAP_Enable_LDAP_Groups_To_RC_Teams": "Aktivieren der Teamzuordnung von LDAP zu Rocket.Chat", "LDAP_Encryption": "Verschlüsselung", "LDAP_Encryption_Description": "Die Verschlüsselungsmethode für sichere Kommunikation mit dem LDAP-Server. Bspw. `plain` (keine Verschlüsselung), `SSL/LDAPS` (von Anfang an verschlüsselt) und `StartTLS` (zur verschlüsselten Kommunikation wechseln, sobald verbunden wurde)", @@ -2331,15 +2327,11 @@ "LDAP_Merge_Existing_Users_Description": "*Achtung!* Wenn beim Import aus LDAP ein lokaler Benutzer mit gleichem Namen bereits existiert, wird der lokale Benutzer mit den Einstellungen aus LDAP aktualisiert.", "LDAP_Port": "LDAP-Port", "LDAP_Port_Description": "Port für den LDAP-Zugriff, bspw.Port 389 oder 636 für LDAPS", - "LDAP_Query_To_Get_User_Groups": "LDAP-Abfrage zum Abrufen von Benutzergruppen", - "LDAP_Query_To_Get_User_Groups_Description": "LDAP-Abfrage, um die LDAP-Gruppen zu erhalten, zu denen der Benutzer gehört.", "LDAP_Query_To_Get_User_Teams": "LDAP-Abfrage zum Abrufen von Benutzergruppen", "LDAP_Reconnect": "Erneut verbinden", "LDAP_Reconnect_Description": "Versuche, erneut zu verbinden, wenn die Verbindung aus unbekanntem Grund unterbrochen wurde", "LDAP_Reject_Unauthorized": "Unberechtigte ablehnen", "LDAP_Reject_Unauthorized_Description": "Deaktiviere diese Option, um nicht-verifizierte Zertifikate zu akzeptieren. Ein Deaktivieren wird üblicherweise bei der Nutzung von selbst-signierten Zertifikaten benötigt.", - "LDAP_Roles_To_Rocket_Chat_Roles": "Rollenzuordnung von LDAP zu Rocket.Chat.", - "LDAP_Roles_To_Rocket_Chat_Roles_Description": "Rollenzuordnung im Objektformat, wobei der Objektschlüssel die LDAP-Rolle sein muss und der Objektwert ein Array von RC-Rollen sein muss. Beispiel: { 'ldapRole': ['rcRole', 'anotherRCRole'] }", "LDAP_Search_Page_Size": "Seitengröße für die Suche", "LDAP_Search_Page_Size_Description": "Die maximale Anzahl von Einträgen, die auf einmal verarbeitet werden", "LDAP_Search_Size_Limit": "Maximale Treffer-Anzahl", @@ -2352,29 +2344,28 @@ "LDAP_Sync_User_Active_State_Disable": "Benutzer deaktivieren", "LDAP_Sync_User_Active_State_Nothing": "Nichts unternehmen", "LDAP_Sync_User_Avatar": "Profilbilder synchronisieren", - "LDAP_Sync_User_Data": "Benutzerdaten synchronisieren", - "LDAP_Sync_User_Data_Description": "Bei der Anmeldung die Benutzerdaten mit dem Server synchronisieren (Bspw. Name, E-Mail-Adresse).", - "LDAP_Sync_User_Data_FieldMap": "Zuordnung der Benutzer-Attribute", - "LDAP_Sync_User_Data_FieldMap_Description": "Konfigurieren Sie, wie Benutzerkontofelder (wie die E-Mail-Adresse) aus einem LDAP-Datensatz (falls gefunden) geladen werden.
Beispiel: {\"cn\":\"name\", \"mail\":\"email\"} nimmt einen von Menschen lesbaren Namen aus dem cn-Attribut und die E-Mail-Adresse aus dem Mail-Attribut. Zusätzlich ist die Verwendung von Variablen möglich, wie z.B.: `{ \"#{givenName} #{sn}\": \"name\", \"mail\": \"email\" }`. Hierbei wird eine Kombination des Vor- und Nachnamens verwendet.
Verfügbare Felder in Rocket.Chat sind `name` und `email`.", - "LDAP_Sync_User_Data_Groups": "LDAP-Gruppen synchronisieren", - "LDAP_Sync_User_Data_Groups_AutoChannels": "Automatische Synchronisierung von LDAP-Gruppen mit Channels", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "Kanal Admin", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin_Description": "Wenn während einer Synchronisierung automatisch Kanäle erstellt werden, die nicht vorhanden sind, wird dieser Benutzer automatisch zum Administrator.", - "LDAP_Sync_User_Data_Groups_AutoChannels_Description": "Aktivieren Sie diese Funktion, um Benutzer basierend auf ihrer LDAP-Gruppe automatisch zu einem Kanal hinzuzufügen. Wenn Sie auch Benutzer aus einem Kanal entfernen möchten, lesen Sie die unten stehende Option zum automatischen Entfernen von Benutzern.", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap": "LDAP-Gruppe Channel Map", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Default": "// Aktiviere die automatische Synchronisierung von LDAP-Gruppen zu Channels oben", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Description": "Ordnen Sie LDAP-Gruppen zu Rocket.Chat-Kanälen hinzu.
Als Beispiel fügt \"{\"employee\":\"general\"}\" alle Gruppenmitglieder zum allgemeinen Kanal hinzu.", - "LDAP_Sync_User_Data_Groups_AutoRemove": "Benutzerrollen automatisch entfernen", - "LDAP_Sync_User_Data_Groups_AutoRemove_Description": "**Achtung**: Wenn Sie dies aktivieren, werden Benutzer automatisch aus einer Rolle entfernt, wenn sie nicht in LDAP zugewiesen sind! Dadurch werden nur Rollen automatisch entfernt, die in der folgenden Benutzerdatengruppenzuordnung festgelegt sind.", - "LDAP_Sync_User_Data_Groups_BaseDN": "LDAP Gruppe BaseDN", - "LDAP_Sync_User_Data_Groups_BaseDN_Description": "Der LDAP BaseDN, mit dem Benutzer gesucht werden.", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels": "Benutzer automatisch aus Channels entfernen", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels_Description": "**Achtung**: Wenn Sie dies aktivieren, werden alle Benutzer in einem Kanal entfernt, die nicht über die entsprechende LDAP-Gruppe verfügen! Aktivieren Sie dies nur, wenn Sie wissen, was Sie tun.", - "LDAP_Sync_User_Data_Groups_Filter": "LDAP Benutzergruppen-Filter", - "LDAP_Sync_User_Data_Groups_Filter_Description": "Der LDAP-Suchfilter, mit dem überprüft wird, ob sich ein Benutzer in einer Gruppe befindet.", - "LDAP_Sync_User_Data_GroupsMap": "Benutzerdatengruppenzuordnung", - "LDAP_Sync_User_Data_GroupsMap_Description": "Ordnen Sie LDAP-Gruppen zu Rocket.Chat Benutzerrollen
Als Beispiel ordnet {\"rocket-admin\":\"admin\", \"tech-support\":\"support\"} die LDAP-Gruppe von rocket-admin als \"admin\" zu.", - "LDAP_Test_Connection": "Verbindung prüfen", + "LDAP_Sync_User_Data_Roles": "LDAP-Gruppen synchronisieren", + "LDAP_Sync_User_Data_Channels": "Automatische Synchronisierung von LDAP-Gruppen mit Channels", + "LDAP_Sync_User_Data_Channels_Admin": "Kanal Admin", + "LDAP_Sync_User_Data_Channels_Admin_Description": "Wenn während einer Synchronisierung automatisch Kanäle erstellt werden, die nicht vorhanden sind, wird dieser Benutzer automatisch zum Administrator.", + "LDAP_Sync_User_Data_Channels_BaseDN": "LDAP Gruppe BaseDN", + "LDAP_Sync_User_Data_Channels_BaseDN_Description": "Der LDAP BaseDN, mit dem Benutzer gesucht werden.", + "LDAP_Sync_User_Data_Channels_Description": "Aktivieren Sie diese Funktion, um Benutzer basierend auf ihrer LDAP-Gruppe automatisch zu einem Kanal hinzuzufügen. Wenn Sie auch Benutzer aus einem Kanal entfernen möchten, lesen Sie die unten stehende Option zum automatischen Entfernen von Benutzern.", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels": "Benutzer automatisch aus Channels entfernen", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels_Description": "**Achtung**: Wenn Sie dies aktivieren, werden alle Benutzer in einem Kanal entfernt, die nicht über die entsprechende LDAP-Gruppe verfügen! Aktivieren Sie dies nur, wenn Sie wissen, was Sie tun.", + "LDAP_Sync_User_Data_Channels_Filter": "LDAP Benutzergruppen-Filter", + "LDAP_Sync_User_Data_Channels_Filter_Description": "Der LDAP-Suchfilter, mit dem überprüft wird, ob sich ein Benutzer in einer Gruppe befindet.", + "LDAP_Sync_User_Data_ChannelsMap": "LDAP-Gruppe Channel Map", + "LDAP_Sync_User_Data_ChannelsMap_Default": "// Aktiviere die automatische Synchronisierung von LDAP-Gruppen zu Channels oben", + "LDAP_Sync_User_Data_ChannelsMap_Description": "Ordnen Sie LDAP-Gruppen zu Rocket.Chat-Kanälen hinzu.
Als Beispiel fügt \"{\"employee\":\"general\"}\" alle Gruppenmitglieder zum allgemeinen Kanal hinzu.", + "LDAP_Sync_User_Data_Roles_AutoRemove": "Benutzerrollen automatisch entfernen", + "LDAP_Sync_User_Data_Roles_AutoRemove_Description": "**Achtung**: Wenn Sie dies aktivieren, werden Benutzer automatisch aus einer Rolle entfernt, wenn sie nicht in LDAP zugewiesen sind! Dadurch werden nur Rollen automatisch entfernt, die in der folgenden Benutzerdatengruppenzuordnung festgelegt sind.", + "LDAP_Sync_User_Data_Roles_BaseDN": "LDAP Gruppe BaseDN", + "LDAP_Sync_User_Data_Roles_BaseDN_Description": "Der LDAP BaseDN, mit dem Benutzer gesucht werden.", + "LDAP_Sync_User_Data_Roles_Filter": "LDAP Benutzergruppen-Filter", + "LDAP_Sync_User_Data_Roles_Filter_Description": "Der LDAP-Suchfilter, mit dem überprüft wird, ob sich ein Benutzer in einer Gruppe befindet.", + "LDAP_Sync_User_Data_RolesMap": "Benutzerdatengruppenzuordnung", + "LDAP_Sync_User_Data_RolesMap_Description": "Ordnen Sie LDAP-Gruppen zu Rocket.Chat Benutzerrollen
Als Beispiel ordnet {\"rocket-admin\":\"admin\", \"tech-support\":\"support\"} die LDAP-Gruppe von rocket-admin als \"admin\" zu.", "LDAP_Timeout": "Timeout (ms)", "LDAP_Timeout_Description": "Wie lange auf ein Suchergebnis gewartet werden soll, bevor ein Fehler ausgegeben wird", "LDAP_Unique_Identifier_Field": "Feld für eindeutige Identifizierung", @@ -2388,8 +2379,6 @@ "LDAP_Username_Field_Description": "Geben Sie an, welches Feld als *Benutzername* für neue Benutzer verwendet werden soll. Lassen Sie das Feld leer, um den Nutzernamen zu verwenden, der auf der Anmeldeseite verwendet wird.
Es können auch Template-Tags wie `#{givenName}.#{sn}` verwendet werden.
Der Standardwert ist `sAMAccountName`.", "LDAP_Validate_Teams_For_Each_Login": "Validierung der Zuordnung für jede Anmeldung", "LDAP_Validate_Teams_For_Each_Login_Description": "Legen Sie fest, ob die Teams der Benutzer jedes Mal aktualisiert werden sollen, wenn sie sich bei Rocket.Chat anmelden. Wenn dies ausgeschaltet ist, wird das Team nur bei der ersten Anmeldung geladen.", - "LDAP_Validate_Roles_For_Each_Login": "Validierung der Zuordnung für jede Anmeldung", - "LDAP_Validate_Roles_For_Each_Login_Description": "Wenn die Validierung für jede Anmeldung erfolgen soll (Seien Sie vorsichtig mit dieser Einstellung, weil dadurch die Benutzerrollen bei jeder Anmeldung überschrieben werden, andernfalls wird diese nur beim Anlegen des Benutzers validiert).", "Lead_capture_email_regex": "Lead Capture E-Mail Regex", "Lead_capture_phone_regex": "Lead Capture Telefon Regex", "Leave": "Verlassen", diff --git a/packages/rocketchat-i18n/i18n/el.i18n.json b/packages/rocketchat-i18n/i18n/el.i18n.json index 9b609bb424d1..c93bc9b5efbe 100644 --- a/packages/rocketchat-i18n/i18n/el.i18n.json +++ b/packages/rocketchat-i18n/i18n/el.i18n.json @@ -1525,7 +1525,6 @@ "LDAP_Connect_Timeout": "Χρονικό όριο σύνδεσης (ms)", "LDAP_Default_Domain": "default Domain", "LDAP_Default_Domain_Description": "Εάν παρέχεται ο Προεπιλεγμένος Τομέας, θα χρησιμοποιηθεί για τη δημιουργία μιας μοναδικής διεύθυνσης ηλεκτρονικού ταχυδρομείου για χρήστες που δεν εισήχθη η διεύθυνσή τους από το LDAP. Η διεύθυνση ηλεκτρονικού ταχυδρομείου θα δημιουργηθεί ως `username@default_domain` ή `unique_id@default_domain`.
Παράδειγμα: `rocket.chat`", - "LDAP_Description": "LDAP είναι μια ιεραρχική βάση δεδομένων που πολλές εταιρείες χρησιμοποιούν για να παρέχουν Single Sign On - μια εγκατάσταση για την κοινή χρήση ενός κωδικού πρόσβασης από πολλαπλές τοποθεσίες και υπηρεσίες. Για προχωρημένους πληροφορίες διαμόρφωσης και παραδείγματα, συμβουλευτείτε wiki μας: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Καθιστώ ικανό", "LDAP_Enable_Description": "Προσπάθεια να χρησιμοποιούν το LDAP για έλεγχο ταυτότητας.", "LDAP_Encryption": "κρυπτογράφηση", @@ -1567,11 +1566,6 @@ "LDAP_Sync_Now": "Συγχρονισμός φόντου τώρα", "LDAP_Sync_Now_Description": "Θα εκτελέσει το **Συγχρονισμό Παρασκηνίου** τώρα αντί να περιμένει το **Διάστημα Συγχρονισμού** ακόμα κι αν η επιλογή **Συγχρονισμός Παρασκηνίου** είναι απενεργοποιημένη.
Αυτή η ενέργεια είναι ασύγχρονη, ανατρέξτε στα αρχεία καταγραφής για περισσότερες πληροφορίες σχετικά με την διεργασία", "LDAP_Sync_User_Avatar": "Συγχρονισμός χρήστη Avatar", - "LDAP_Sync_User_Data": "Data Sync", - "LDAP_Sync_User_Data_Description": "Κρατήστε τα δεδομένα των χρηστών σε συγχρονισμό με το διακομιστή για την είσοδο (π.χ. όνομα, διεύθυνση ηλεκτρονικού ταχυδρομείου).", - "LDAP_Sync_User_Data_FieldMap": "Πεδίου δεδομένων χρήστη Χάρτης", - "LDAP_Sync_User_Data_FieldMap_Description": "Διαμορφώστε το πώς τα πεδία λογαριασμού χρήστη (όπως το ηλεκτρονικό ταχυδρομείο) κατοικείται από τα επίπεδα ρεκόρ στα LDAP (αφού διαπίστωσε).
Ως παράδειγμα, `{\" ΣΟ \":\" όνομα \",\" mail \":\" e-mail \"}` θα επιλέξουν τα ανθρώπινα αναγνώσιμο όνομα ενός ατόμου από το χαρακτηριστικό cn, και το ηλεκτρονικό ταχυδρομείο τους από το χαρακτηριστικό αλληλογραφίας.
Διαθέσιμα πεδία περιλαμβάνουν `name`, και` email`.", - "LDAP_Test_Connection": "δοκιμή σύνδεσης", "LDAP_Timeout": "Χρονικό όριο (ms)", "LDAP_Timeout_Description": "Πόσες χιλιοστά του δευτερολέπτου περιμένουν ένα αποτέλεσμα αναζήτησης πριν επιστρέψουν κάποιο σφάλμα", "LDAP_Unique_Identifier_Field": "Μοναδικό αναγνωριστικό πεδίο", diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 8144d4c6eb27..d96ad2739938 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -954,6 +954,7 @@ "Connection_Closed": "Connection closed", "Connection_Reset": "Connection reset", "Connection_success": "LDAP Connection Successful", + "Connection_failed": "LDAP Connection Failed", "Connectivity_Services": "Connectivity Services", "Consulting": "Consulting", "Consumer_Packaged_Goods": "Consumer Packaged Goods", @@ -2413,6 +2414,30 @@ "Layout_Sidenav_Footer_description": "Footer size is 260 x 70px", "Layout_Terms_of_Service": "Terms of Service", "LDAP": "LDAP", + "LDAP_Documentation": "LDAP Documentation", + "LDAP_Connection": "Connection", + "LDAP_Connection_Authentication": "Authentication", + "LDAP_Connection_Encryption": "Encryption", + "LDAP_Connection_Timeouts": "Timeouts", + "LDAP_UserSearch": "User Search", + "LDAP_UserSearch_Filter": "Search Filter", + "LDAP_UserSearch_GroupFilter": "Group Filter", + "LDAP_DataSync": "Data Sync", + "LDAP_DataSync_DataMap": "Mapping", + "LDAP_DataSync_Avatar": "Avatar", + "LDAP_DataSync_ActiveState": "User Active State", + "LDAP_DataSync_CustomFields": "Sync Custom Fields", + "LDAP_DataSync_Roles": "Sync Roles", + "LDAP_DataSync_Channels": "Sync Channels", + "LDAP_DataSync_Teams": "Sync Teams", + "LDAP_Enterprise": "Enterprise", + "LDAP_DataSync_BackgroundSync": "Background Sync", + "LDAP_Server_Type": "Server Type", + "LDAP_Server_Type_AD": "Active Directory", + "LDAP_Server_Type_Other": "Other", + "LDAP_Name_Field": "Name Field", + "LDAP_Email_Field": "Email Field", + "LDAP_Update_Data_On_Login": "Update User Data on Login", "LDAP_Advanced_Sync": "Advanced Sync", "LDAP_Authentication": "Enable", "LDAP_Authentication_Password": "Password", @@ -2433,12 +2458,8 @@ "LDAP_Connect_Timeout": "Connection Timeout (ms)", "LDAP_Default_Domain": "Default Domain", "LDAP_Default_Domain_Description": "If provided the Default Domain will be used to create an unique email for users where email was not imported from LDAP. The email will be mounted as `username@default_domain` or `unique_id@default_domain`.
Example: `rocket.chat`", - "LDAP_Default_Role_To_User": "Default role to user", - "LDAP_Default_Role_To_User_Description": "The default RC role to be applied to user if the user has some LDAP role that is not mapped.", - "LDAP_Description": "LDAP is a hierarchical database that many companies use to provide single sign on - a facility for sharing one password between multiple sites and services. For advanced configuration information and examples, please consult our wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Enable", "LDAP_Enable_Description": "Attempt to utilize LDAP for authentication.", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "Enable role mapping from LDAP to Rocket.Chat", "LDAP_Enable_LDAP_Groups_To_RC_Teams": "Enable team mapping from LDAP to Rocket.Chat", "LDAP_Encryption": "Encryption", "LDAP_Encryption_Description": "The encryption method used to secure communications to the LDAP server. Examples include `plain` (no encryption), `SSL/LDAPS` (encrypted from the start), and `StartTLS` (upgrade to encrypted communication once connected).", @@ -2469,50 +2490,47 @@ "LDAP_Merge_Existing_Users_Description": "*Caution!* When importing a user from LDAP and an user with same username already exists the LDAP info and password will be set into the existing user.", "LDAP_Port": "Port", "LDAP_Port_Description": "Port to access LDAP. eg: `389` or `636` for LDAPS", - "LDAP_Query_To_Get_User_Groups": "LDAP query to get user groups", - "LDAP_Query_To_Get_User_Groups_Description": "LDAP query to get the LDAP groups that the user is part of.", + "LDAP_Prevent_Username_Changes": "Prevent LDAP users from changing their Rocket.Chat username", "LDAP_Query_To_Get_User_Teams": "LDAP query to get user groups", "LDAP_Reconnect": "Reconnect", "LDAP_Reconnect_Description": "Try to reconnect automatically when connection is interrupted by some reason while executing operations", "LDAP_Reject_Unauthorized": "Reject Unauthorized", "LDAP_Reject_Unauthorized_Description": "Disable this option to allow certificates that can not be verified. Usually Self Signed Certificates will require this option disabled to work", - "LDAP_Roles_To_Rocket_Chat_Roles": "Role mapping from LDAP to Rocket.Chat.", - "LDAP_Roles_To_Rocket_Chat_Roles_Description": "Role mapping in object format where the object key must be the LDAP role and the object value must be an array of RC roles. Example: { 'ldapRole': ['rcRole', 'anotherRCRole'] }", "LDAP_Search_Page_Size": "Search Page Size", "LDAP_Search_Page_Size_Description": "The maximum number of entries each result page will return to be processed", "LDAP_Search_Size_Limit": "Search Size Limit", "LDAP_Search_Size_Limit_Description": "The maximum number of entries to return.
**Attention** This number should greater than **Search Page Size**", - "LDAP_Sync_Now": "Background Sync Now", - "LDAP_Sync_Now_Description": "Will execute the **Background Sync** now rather than wait the **Sync Interval** even if **Background Sync** is False.
This Action is asynchronous, please see the logs for more information about the process", + "LDAP_Sync_Custom_Fields": "Sync Custom Fields", + "LDAP_CustomFieldMap": "Custom Fields Mapping", + "LDAP_Sync_Now": "Sync Now", + "LDAP_Sync_Now_Description": "This will start a **Background Sync** operation now, without waiting for the next scheduled Sync.\nThis action is asynchronous, please see the logs for more information.", "LDAP_Sync_User_Active_State": "Sync User Active State", "LDAP_Sync_User_Active_State_Both": "Enable and Disable Users", "LDAP_Sync_User_Active_State_Description": "Determine if users should be enabled or disabled on Rocket.Chat based on the LDAP status. The 'pwdAccountLockedTime' attribute will be used to determine if the user is disabled.", "LDAP_Sync_User_Active_State_Disable": "Disable Users", "LDAP_Sync_User_Active_State_Nothing": "Do Nothing", "LDAP_Sync_User_Avatar": "Sync User Avatar", - "LDAP_Sync_User_Data": "Sync User Data", - "LDAP_Sync_User_Data_Description": "Keep user data in sync with server on **login** or on **background sync** (eg: name, email).", - "LDAP_Sync_User_Data_FieldMap": "User Data Field Map", - "LDAP_Sync_User_Data_FieldMap_Description": "Configure how user account fields (like email) are populated from a record in LDAP (once found).
As an example, `{\"cn\":\"name\", \"mail\":\"email\"}` will choose a person's human readable name from the cn attribute, and their email from the mail attribute. Additionally it is possible to use variables, for example: `{ \"#{givenName} #{sn}\": \"name\", \"mail\": \"email\" }` uses a combination of the user's first name and last name for the rocket chat `name` field.
Available fields in Rocket.Chat: `name`, `email` and `customFields`.", - "LDAP_Sync_User_Data_Groups": "Sync LDAP Groups", - "LDAP_Sync_User_Data_Groups_AutoChannels": "Auto Sync LDAP Groups to Channels", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "Channel Admin", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin_Description": "When channels are auto-created that do not exist during a sync, this user will automatically become the admin for the channel.", - "LDAP_Sync_User_Data_Groups_AutoChannels_Description": "Enable this feature to automatically add users to a channel based on their LDAP group. If you would like to also remove users from a channel, see the option below about auto removing users.", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap": "LDAP Group Channel Map", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Default": "// Enable Auto Sync LDAP Groups to Channels above", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Description": "Map LDAP groups to Rocket.Chat channels.
As an example, `{\"employee\":\"general\"}` will add any user in the LDAP group employee, to the general channel.", - "LDAP_Sync_User_Data_Groups_AutoRemove": "Auto Remove User Roles", - "LDAP_Sync_User_Data_Groups_AutoRemove_Description": "**Attention**: Enabling this will automatically remove users from a role if they are not assigned in LDAP! This will only remove roles automatically that are set under the user data group map below.", - "LDAP_Sync_User_Data_Groups_BaseDN": "LDAP Group BaseDN", - "LDAP_Sync_User_Data_Groups_BaseDN_Description": "The LDAP BaseDN used to lookup users.", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels": "Auto Remove Users from Channels", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels_Description": "**Attention**: Enabling this will remove any users in a channel that do not have the corresponding LDAP group! Only enable this if you know what you're doing.", - "LDAP_Sync_User_Data_Groups_Filter": "User Group Filter", - "LDAP_Sync_User_Data_Groups_Filter_Description": "The LDAP search filter used to check if a user is in a group.", - "LDAP_Sync_User_Data_GroupsMap": "User Data Group Map", - "LDAP_Sync_User_Data_GroupsMap_Description": "Map LDAP groups to Rocket.Chat user roles
As an example, `{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}` will map the rocket-admin LDAP group to Rocket's \"admin\" role.", - "LDAP_Test_Connection": "Test Connection", + "LDAP_Sync_User_Data_Roles": "Sync LDAP Groups", + "LDAP_Sync_User_Data_Channels": "Auto Sync LDAP Groups to Channels", + "LDAP_Sync_User_Data_Channels_Admin": "Channel Admin", + "LDAP_Sync_User_Data_Channels_Admin_Description": "When channels are auto-created that do not exist during a sync, this user will automatically become the admin for the channel.", + "LDAP_Sync_User_Data_Channels_BaseDN": "LDAP Group BaseDN", + "LDAP_Sync_User_Data_Channels_Description": "Enable this feature to automatically add users to a channel based on their LDAP group. If you would like to also remove users from a channel, see the option below about auto removing users.", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels": "Auto Remove Users from Channels", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels_Description": "**Attention**: Enabling this will remove any users in a channel that do not have the corresponding LDAP group! Only enable this if you know what you're doing.", + "LDAP_Sync_User_Data_Channels_Filter": "User Group Filter", + "LDAP_Sync_User_Data_Channels_Filter_Description": "The LDAP search filter used to check if a user is in a group.", + "LDAP_Sync_User_Data_ChannelsMap": "LDAP Group Channel Map", + "LDAP_Sync_User_Data_ChannelsMap_Default": "// Enable Auto Sync LDAP Groups to Channels above", + "LDAP_Sync_User_Data_ChannelsMap_Description": "Map LDAP groups to Rocket.Chat channels.
As an example, `{\"employee\":\"general\"}` will add any user in the LDAP group employee, to the general channel.", + "LDAP_Sync_User_Data_Roles_AutoRemove": "Auto Remove User Roles", + "LDAP_Sync_User_Data_Roles_AutoRemove_Description": "**Attention**: Enabling this will automatically remove users from a role if they are not assigned in LDAP! This will only remove roles automatically that are set under the user data group map below.", + "LDAP_Sync_User_Data_Roles_BaseDN": "LDAP Group BaseDN", + "LDAP_Sync_User_Data_Roles_BaseDN_Description": "The LDAP BaseDN used to lookup users.", + "LDAP_Sync_User_Data_Roles_Filter": "User Group Filter", + "LDAP_Sync_User_Data_Roles_Filter_Description": "The LDAP search filter used to check if a user is in a group.", + "LDAP_Sync_User_Data_RolesMap": "User Data Group Map", + "LDAP_Sync_User_Data_RolesMap_Description": "Map LDAP groups to Rocket.Chat user roles
As an example, `{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}` will map the rocket-admin LDAP group to Rocket's \"admin\" role.", "LDAP_Timeout": "Timeout (ms)", "LDAP_Timeout_Description": "How many mileseconds wait for a search result before return an error", "LDAP_Unique_Identifier_Field": "Unique Identifier Field", @@ -2526,8 +2544,6 @@ "LDAP_Username_Field_Description": "Which field will be used as *username* for new users. Leave empty to use the username informed on login page.
You can use template tags too, like `#{givenName}.#{sn}`.
Default value is `sAMAccountName`.", "LDAP_Validate_Teams_For_Each_Login": "Validate mapping for each login", "LDAP_Validate_Teams_For_Each_Login_Description": "Determine if users' teams should be updated every time they login to Rocket.Chat. If this is turned off the team will be loaded only on their first login.", - "LDAP_Validate_Roles_For_Each_Login": "Validate mapping for each login", - "LDAP_Validate_Roles_For_Each_Login_Description": "If the validation should occurs for each login (Be careful with this setting because it will overwrite the user roles in each login, otherwise this will be validated only at the moment of user creation).", "Lead_capture_email_regex": "Lead capture email regex", "Lead_capture_phone_regex": "Lead capture phone regex", "Leave": "Leave", diff --git a/packages/rocketchat-i18n/i18n/eo.i18n.json b/packages/rocketchat-i18n/i18n/eo.i18n.json index d7d6b0b0f657..27d560473224 100644 --- a/packages/rocketchat-i18n/i18n/eo.i18n.json +++ b/packages/rocketchat-i18n/i18n/eo.i18n.json @@ -1519,7 +1519,6 @@ "LDAP_Connect_Timeout": "Konekto-Tempo (m)", "LDAP_Default_Domain": "Defaŭlta Domajno", "LDAP_Default_Domain_Description": "Se provizita la Defaŭlta Domajno estos uzata por krei solan retpoŝton por uzantoj, kie retpoŝto ne estis importita de LDAP. La retpoŝto estos muntita kiel 'uzulnomo@default_domain` aŭ' unique_id@default_domain`.
Ekzemplo: 'raketo.chat`", - "LDAP_Description": "LDAP estas hierarkia datumbazo, kiun multaj kompanioj uzas por doni unu signon al ĝi - facilecon por dividi unu pasvorton inter pluraj retejoj kaj servoj. Por altnivelaj agordoj kaj ekzemploj, bonvolu konsulti nian vikion: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Ebligu", "LDAP_Enable_Description": "Provu uzi LDAP por aŭtentikigo.", "LDAP_Encryption": "Ĉifrado", @@ -1561,11 +1560,6 @@ "LDAP_Sync_Now": "Fona Sinkro Nun", "LDAP_Sync_Now_Description": "Volas ekzekuti la **Fono-Sinkronon** nun prefere ol atendi la **Sync Interval** eĉ se **Background Sync** estas Falsa.
Ĉi tiu Ago estas asincrona, vidu la protokolojn por pli da informoj pri la procezo", "LDAP_Sync_User_Avatar": "Sinkru Uzanto-Avatar", - "LDAP_Sync_User_Data": "Sinkru Uzanto-datumoj", - "LDAP_Sync_User_Data_Description": "Konservu la datumojn de uzanto en sinkronigi kun servilo per ** ensaluto ** aŭ per ** fonklako ** (ekz: nomo, retpoŝto).", - "LDAP_Sync_User_Data_FieldMap": "Mapo de Kampoj de Uzanto Datumoj", - "LDAP_Sync_User_Data_FieldMap_Description": "Agordi kiel uzaj kontoj kampoj (kiel retpoŝto) estas popolitaj de rekordo en LDAP (iam trovita).
Ekzemple, \"{\" cn \":\" nomo \",\" poŝto \":\" retpoŝto \"}\" elektos homon legeblan nomon de homo de la atributo, kaj ilia retpoŝto de la poŝto. Aldone eblas uzi variablojn, ekzemple: '{\"# {givenName} # {sn}\": \"nomo\", \"poŝto\": \"retpoŝto\"}' uzas kombinaĵon de la unua nomo kaj familinomo de la uzanto raketo babilejo 'nomo` kampo.
Haveblaj kampoj en Rocket.Chat: `nomo`,` retpoŝto` kaj `customFields`.", - "LDAP_Test_Connection": "Testa Konekto", "LDAP_Timeout": "Tempo finiĝo (m)", "LDAP_Timeout_Description": "Kiom da jarmiloj atendas serĉan rezulton antaŭ ol redoni eraron", "LDAP_Unique_Identifier_Field": "Unika Identigilo Kampo", diff --git a/packages/rocketchat-i18n/i18n/es.i18n.json b/packages/rocketchat-i18n/i18n/es.i18n.json index 66ca0960167e..00230bebee98 100644 --- a/packages/rocketchat-i18n/i18n/es.i18n.json +++ b/packages/rocketchat-i18n/i18n/es.i18n.json @@ -2432,12 +2432,8 @@ "LDAP_Connect_Timeout": "Tiempo de espera de conexión(ms)", "LDAP_Default_Domain": "Dominio Predeterminado", "LDAP_Default_Domain_Description": "Si se proporciona, el Dominio predeterminado se usará para crear un correo electrónico exclusivo para los usuarios donde el correo electrónico no se haya importado de LDAP. El correo electrónico se montará como `username @ default_domain` o` unique_id @ default_domain`.
Ejemplo: `rocket.chat`", - "LDAP_Default_Role_To_User": "Rol de usuario por defecto", - "LDAP_Default_Role_To_User_Description": "El rol RC predeterminado que se aplicará al usuario si el usuario tiene algún rol LDAP que no está asignado.", - "LDAP_Description": "LDAP es una base de datos jerárquica que muchas empresas utilizan para proporcionar inicio de sesión único - una instalación para compartir una contraseña entre múltiples sitios y servicios. Para obtener información avanzada de configuración y ejemplos, consulte nuestra wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Habilitar", "LDAP_Enable_Description": "Intentar utilizar LDAP como método de autenticación ", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "Habilitar mapeo de roles de LDAP a Rocket.Chat", "LDAP_Enable_LDAP_Groups_To_RC_Teams": "Habilite el mapeo del equipo de LDAP a Rocket.Chat", "LDAP_Encryption": "Cifrado", "LDAP_Encryption_Description": "Metodo de cifrado usado para la comunicación segura hacia el servidor LDAP. Algunos ejemplos 'sin cifrado', 'SSL/LDAPS (cifrado desde el inicio), y 'StartTLS' ( actualizar a comunicaciónes cifradas una vez conectado).", @@ -2468,15 +2464,11 @@ "LDAP_Merge_Existing_Users_Description": "* ¡Precaución! * Al importar un usuario de LDAP y ya existe un usuario con el mismo nombre de usuario, la información y la contraseña de LDAP se establecerán en el usuario existente.", "LDAP_Port": "Puerto", "LDAP_Port_Description": "Puerto para acceder a LDAP. Por ejemplo. `389` o `636` para LDAPS", - "LDAP_Query_To_Get_User_Groups": "Consulta LDAP para obtener grupos de usuarios", - "LDAP_Query_To_Get_User_Groups_Description": "Consulta LDAP para obtener los grupos a los que pertenece el usuario.", "LDAP_Query_To_Get_User_Teams": "Consulta LDAP para obtener grupos de usuarios", "LDAP_Reconnect": "Vuelva a conectar", "LDAP_Reconnect_Description": "Intente volver a conectarse automáticamente cuando la conexión se interrumpa por algún motivo mientras ejecuta operaciones", "LDAP_Reject_Unauthorized": "Rechazar no autorizada", "LDAP_Reject_Unauthorized_Description": "Desactive esta opción para permitir certificados que no se pueden verificar. Por lo general, los certificados autofirmados requerirán que esta opción esté desactivada para funcionar", - "LDAP_Roles_To_Rocket_Chat_Roles": "Mapeo de roles de LDAP a Rocket.Chat.", - "LDAP_Roles_To_Rocket_Chat_Roles_Description": "Mapeo de rol en formato de objeto donde la clave del objeto debe ser el rol LDAP y el valor debe ser un array de roles RC. Por ejemplo: { 'ldapRole': ['rcRole', 'anotherRCRole'] }", "LDAP_Search_Page_Size": "Tamaño de página de búsqueda", "LDAP_Search_Page_Size_Description": "El número máximo de entradas que cada página de resultados volverá a procesarse", "LDAP_Search_Size_Limit": "Límite de tamaño de búsqueda", @@ -2489,29 +2481,28 @@ "LDAP_Sync_User_Active_State_Disable": "Habilitar usuarios", "LDAP_Sync_User_Active_State_Nothing": "No hacer nada", "LDAP_Sync_User_Avatar": "Sincronizar Avatar del Usuario", - "LDAP_Sync_User_Data": "Sincronizar Datos de Usuario", - "LDAP_Sync_User_Data_Description": "Mantener los datos del usuario en sincronía con el servidor al iniciar sesión (ej: nombre, correo electrónico). ", - "LDAP_Sync_User_Data_FieldMap": "Mapa de Campos de Datos de Usuario", - "LDAP_Sync_User_Data_FieldMap_Description": "Configura como los campos de usuario (como el correo electrónico) son poblados desde un registro LDAP (una vez encontrado).
Como ejemplo, `{\"cn\":\"name\", \"mail\":\"email\"}` elegirá el nombre legible por humanos de una persona del atributo cn, y su correo electrónico del atributo mail. Además es posible usar variables, por ejemplo `{ \"#{givenName} #{sn}\": \"name\", \"mail\": \"email\" }`utiliza una combinación del nombre y apellido del usuario para campo de rocket chat `name`.
Campos disponibles en Rocket.Chat:`name`, `email` y `customFields`.", - "LDAP_Sync_User_Data_Groups": "Sincronizar grupos de LDAP", - "LDAP_Sync_User_Data_Groups_AutoChannels": "Sincronizar automáticamente los grupos de LDAP a Channels", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "Channel Administrador", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin_Description": "Cuando se crean automáticamente canales que no existen durante una sincronización, este usuario se convertirá automáticamente en el administrador del canal.", - "LDAP_Sync_User_Data_Groups_AutoChannels_Description": "Habilita esta función para añadir automáticamente usuarios a un canal basado en su grupo LDAP. Si desea eliminar también los usuarios de un canal, consulte la opción que aparece a continuación sobre la eliminación automática de usuarios.", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap": "Mapa del Channel Grupo LDAP", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Default": "// Habilite la sincronización automática de grupos LDAP con los Channel anteriores", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Description": "Mapea los grupos LDAP a los canales de Rocket.Chat.
Como ejemplo, `{\"employee\":\"general\"}` agregará cualquier usuario del grupo LDAP employee, a la sala general.", - "LDAP_Sync_User_Data_Groups_AutoRemove": "Eliminar automáticamente roles de usuario", - "LDAP_Sync_User_Data_Groups_AutoRemove_Description": "**Atención*: ¡Al activar esto se eliminarán automáticamente los usuarios de un rol si no están asignados en LDAP! Esto sólo eliminará automáticamente los roles que estén establecidos en el mapa de grupo de datos de usuario de abajo.", - "LDAP_Sync_User_Data_Groups_BaseDN": "Base DN de grupos LDAP", - "LDAP_Sync_User_Data_Groups_BaseDN_Description": "LDAP BaseDN utilizado para buscar usuarios.", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels": "Eliminar automáticamente usuarios de Salas", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels_Description": "** Atención **: ¡Habilitar esto eliminará a cualquier usuario en un canal que no tenga el grupo LDAP correspondiente! Habilite esto solo si sabe lo que está haciendo.", - "LDAP_Sync_User_Data_Groups_Filter": "Filtro de grupo de usuarios", - "LDAP_Sync_User_Data_Groups_Filter_Description": "El filtro de búsqueda LDAP que se usa para verificar si un usuario está en un grupo.", - "LDAP_Sync_User_Data_GroupsMap": "Mapa de grupo de datos de usuario", - "LDAP_Sync_User_Data_GroupsMap_Description": "Mapea los grupos LDAP a los roles de usuario de Rocket.Chat
Como ejemplo, `{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}` mapeará el grupo LDAP de rocket-admin al rol de \"admin\" de Rocket.", - "LDAP_Test_Connection": "Probar Conexión ", + "LDAP_Sync_User_Data_Roles": "Sincronizar grupos de LDAP", + "LDAP_Sync_User_Data_Channels": "Sincronizar automáticamente los grupos de LDAP a Channels", + "LDAP_Sync_User_Data_Channels_Admin": "Channel Administrador", + "LDAP_Sync_User_Data_Channels_Admin_Description": "Cuando se crean automáticamente canales que no existen durante una sincronización, este usuario se convertirá automáticamente en el administrador del canal.", + "LDAP_Sync_User_Data_Channels_BaseDN": "Base DN de grupos LDAP", + "LDAP_Sync_User_Data_Channels_BaseDN_Description": "LDAP BaseDN utilizado para buscar usuarios.", + "LDAP_Sync_User_Data_Channels_Description": "Habilita esta función para añadir automáticamente usuarios a un canal basado en su grupo LDAP. Si desea eliminar también los usuarios de un canal, consulte la opción que aparece a continuación sobre la eliminación automática de usuarios.", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels": "Eliminar automáticamente usuarios de Salas", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels_Description": "** Atención **: ¡Habilitar esto eliminará a cualquier usuario en un canal que no tenga el grupo LDAP correspondiente! Habilite esto solo si sabe lo que está haciendo.", + "LDAP_Sync_User_Data_Channels_Filter": "Filtro de grupo de usuarios", + "LDAP_Sync_User_Data_Channels_Filter_Description": "El filtro de búsqueda LDAP que se usa para verificar si un usuario está en un grupo.", + "LDAP_Sync_User_Data_ChannelsMap": "Mapa del Channel Grupo LDAP", + "LDAP_Sync_User_Data_ChannelsMap_Default": "// Habilite la sincronización automática de grupos LDAP con los Channel anteriores", + "LDAP_Sync_User_Data_ChannelsMap_Description": "Mapea los grupos LDAP a los canales de Rocket.Chat.
Como ejemplo, `{\"employee\":\"general\"}` agregará cualquier usuario del grupo LDAP employee, a la sala general.", + "LDAP_Sync_User_Data_Roles_AutoRemove": "Eliminar automáticamente roles de usuario", + "LDAP_Sync_User_Data_Roles_AutoRemove_Description": "**Atención*: ¡Al activar esto se eliminarán automáticamente los usuarios de un rol si no están asignados en LDAP! Esto sólo eliminará automáticamente los roles que estén establecidos en el mapa de grupo de datos de usuario de abajo.", + "LDAP_Sync_User_Data_Roles_BaseDN": "Base DN de grupos LDAP", + "LDAP_Sync_User_Data_Roles_BaseDN_Description": "LDAP BaseDN utilizado para buscar usuarios.", + "LDAP_Sync_User_Data_Roles_Filter": "Filtro de grupo de usuarios", + "LDAP_Sync_User_Data_Roles_Filter_Description": "El filtro de búsqueda LDAP que se usa para verificar si un usuario está en un grupo.", + "LDAP_Sync_User_Data_RolesMap": "Mapa de grupo de datos de usuario", + "LDAP_Sync_User_Data_RolesMap_Description": "Mapea los grupos LDAP a los roles de usuario de Rocket.Chat
Como ejemplo, `{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}` mapeará el grupo LDAP de rocket-admin al rol de \"admin\" de Rocket.", "LDAP_Timeout": "Tiempo de espera (ms)", "LDAP_Timeout_Description": "Cuántos milisegundos esperan un resultado de búsqueda antes de devolver un error", "LDAP_Unique_Identifier_Field": "Campo Identificador Único ", @@ -2525,8 +2516,6 @@ "LDAP_Username_Field_Description": "Qué campo se utilizará como *nombre de usuario* para los nuevos usuarios. Dejar en blanco para usar el nombre de usuario informado en la página de inicio de sesión.
Puede utilizar etiquetas de plantilla también, como `#{givenName}.#{sn}`.
El valor por defecto es `sAMAccountName`.", "LDAP_Validate_Teams_For_Each_Login": "Validar la asignación para cada inicio de sesión", "LDAP_Validate_Teams_For_Each_Login_Description": "Determine si los equipos de los usuarios deben actualizarse cada vez que inician sesión en Rocket.Chat. Si está desactivado, el equipo se cargará solo en su primer inicio de sesión.", - "LDAP_Validate_Roles_For_Each_Login": "Validar la asignación para cada inicio de sesión", - "LDAP_Validate_Roles_For_Each_Login_Description": "Si la validación debe ocurrir para cada inicio de sesión (tenga cuidado con esta configuración porque sobrescribirá los roles de usuario en cada inicio de sesión, de lo contrario, esto se validará solo en el momento de la creación del usuario).", "Lead_capture_email_regex": "Regex de correo electrónico de captura de clientes potenciales", "Lead_capture_phone_regex": "Regex de teléfono de captura clientes potenciales", "Leave": "Salir", diff --git a/packages/rocketchat-i18n/i18n/fa.i18n.json b/packages/rocketchat-i18n/i18n/fa.i18n.json index 7f111fd799db..0ff28cc9efbb 100644 --- a/packages/rocketchat-i18n/i18n/fa.i18n.json +++ b/packages/rocketchat-i18n/i18n/fa.i18n.json @@ -1784,8 +1784,6 @@ "LDAP_Connect_Timeout": "زمان اتصال (ms)", "LDAP_Default_Domain": "دامنه پیشفرض", "LDAP_Default_Domain_Description": "اگر ارائه دهنده دامنه پیش فرض برای ایجاد یک ایمیل منحصر به فرد برای کاربران استفاده می شود که ایمیل از LDAP وارد نشده است. این ایمیل به عنوان `نام کاربری @ default_domain` یا` unique_id @ default_domain` قرار خواهد گرفت.
مثال: `rocket.chat`", - "LDAP_Default_Role_To_User": "نقش پیشفرض کاربر", - "LDAP_Description": "یک مرکز برای به اشتراک گذاری یک رمز عبور بین سایت و خدمات مختلف - LDAP یک پایگاه داده سلسله مراتبی است که بسیاری از شرکت ها برای ارائه یکبار ورود به سیستم است. https://rocket.chat/docs/administrator-guides/authentication/ldap/: برای کسب اطلاعات پیکربندی پیشرفته و نمونه، لطفا ویکی ما مشورت کنید.", "LDAP_Enable": "فعال کردن", "LDAP_Enable_Description": "تلاش برای استفاده از LDAP برای احراز هویت.", "LDAP_Encryption": "رمزگذاری", @@ -1816,8 +1814,6 @@ "LDAP_Merge_Existing_Users_Description": "* احتیاط! * هنگام وارد کردن کاربر از LDAP و کاربر با همان نام کاربری در حال حاضر اطلاعات LDAP و رمز عبور را به کاربر موجود تنظیم شده است.", "LDAP_Port": "درگاه", "LDAP_Port_Description": "درگاه برای دسترسی به LDAP. به عنوان مثال: `` 389` یا 636` برای LDAPS", - "LDAP_Query_To_Get_User_Groups": "کوئری LDAP برای به دست آوردن گروه های کاربر", - "LDAP_Query_To_Get_User_Groups_Description": "کوئری LDAP برای به دست آوردن گروهای LDAP که کاربر عضوی از آن است", "LDAP_Query_To_Get_User_Teams": "کوئری LDAP برای به دست آوردن گروه های کاربر", "LDAP_Reconnect": "دوباره متصل شوید", "LDAP_Reconnect_Description": "سعی کنید به صورت خودکار دوباره وصل شوید زمانی که اتصال بعضی از دلایل هنگام اجرای عملیات قطع شود", @@ -1834,11 +1830,6 @@ "LDAP_Sync_User_Active_State_Disable": "غیرفعال کردن کاربران", "LDAP_Sync_User_Active_State_Nothing": "هیچ کاری نکنید", "LDAP_Sync_User_Avatar": "همگام سازی تصویر کاربر", - "LDAP_Sync_User_Data": "همگام سازی داده ها", - "LDAP_Sync_User_Data_Description": "حفظ اطلاعات کاربران در همگام سازی با سرور در ورود (به عنوان مثال: نام، ایمیل).", - "LDAP_Sync_User_Data_FieldMap": "کاربر داده نقشه درست", - "LDAP_Sync_User_Data_FieldMap_Description": "پیکربندی زمینه حساب کاربری (مانند ایمیل) از یک رکورد در LDAP جمعیت (یک بار).
به عنوان مثال، `{\" CN \":\" نام \"،\" ایمیل \":\" ایمیل \"}` خواهد نام یک شخص قابل خواندن توسط انسان از ویژگی CN، و ایمیل خود را از ویژگی های ایمیل را انتخاب نمایید.
زمینه های موجود عبارتند از `name` و` email`.", - "LDAP_Test_Connection": "اتصال تست", "LDAP_Timeout": "زمان وقوع (ms)", "LDAP_Timeout_Description": "چند دقیقه مایل برای یک نتیجه جستجو قبل از بازگشت به یک نتیجه صبر کنید", "LDAP_Unique_Identifier_Field": "شناسه منحصر به فرد درست", diff --git a/packages/rocketchat-i18n/i18n/fi.i18n.json b/packages/rocketchat-i18n/i18n/fi.i18n.json index bc463e7df059..6a69742b2f95 100644 --- a/packages/rocketchat-i18n/i18n/fi.i18n.json +++ b/packages/rocketchat-i18n/i18n/fi.i18n.json @@ -1519,7 +1519,6 @@ "LDAP_Connect_Timeout": "Yhteys aikakatkaisu (ms)", "LDAP_Default_Domain": "Oletusdomain", "LDAP_Default_Domain_Description": "Jos olet antanut oletusalueen, luodaan yksilöllinen sähköposti käyttäjille, joissa sähköpostia ei tuotu LDAP: stä. Sähköposti asennetaan nimellä \"username@default_domain\" tai \"unique_id@default_domain\".
Esimerkki: `rocket.chat`", - "LDAP_Description": "LDAP on laajasti käytössä oleva hierarkinen tietokantapalvelu, jolla organisaatioiden palveluille mahdollistetaan kertakirjautuminen (SSO).\nMääritystiedot ja esimerkit, katso wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/", "LDAP_Enable": "Kytke LDAP päälle", "LDAP_Enable_Description": "Käytä LDAPia autentikointiin", "LDAP_Encryption": "Salaus", @@ -1561,11 +1560,6 @@ "LDAP_Sync_Now": "Taustasynkronointi nyt", "LDAP_Sync_Now_Description": "Suorittaa **Tausta Sync** nyt, eikä odota **Sync Interval** vaikka **Tausta Sync** on väärä.
Tämä toiminto on asynkroninen, katso lokit lisätietoja käsitellä asiaa", "LDAP_Sync_User_Avatar": "Synkronoi käyttäjän avatar", - "LDAP_Sync_User_Data": "Synkronoi käyttäjädata", - "LDAP_Sync_User_Data_Description": "Pidä käyttäjädata synkronoituna palvelimelta kirjautumishetkellä (esim nimi, sähköposti)", - "LDAP_Sync_User_Data_FieldMap": "Käyttäjätietojen kohdistus", - "LDAP_Sync_User_Data_FieldMap_Description": "Määrittää, miten käyttäjätietojen kentät tuodaan LDAP-palvelimelta.\nEsimerkiksi, {\"cn\":\"name\", \"mail\":\"email\"} -määritys tuo käyttäjän nimen cn-tiedosta ja sähköpostin email-tiedosta. Käytettävissä olevat kentät ovat \"name\" ja \"email\".", - "LDAP_Test_Connection": "Testaa yhteys", "LDAP_Timeout": "Aikakatkaisu (ms)", "LDAP_Timeout_Description": "Kuinka monta kilometrimäärää odottaa hakutulosta ennen virheen palauttamista", "LDAP_Unique_Identifier_Field": "Uniikin tunnisteen kenttä", diff --git a/packages/rocketchat-i18n/i18n/fr.i18n.json b/packages/rocketchat-i18n/i18n/fr.i18n.json index 421bc228a07b..2e57a13dc6d9 100644 --- a/packages/rocketchat-i18n/i18n/fr.i18n.json +++ b/packages/rocketchat-i18n/i18n/fr.i18n.json @@ -2433,12 +2433,8 @@ "LDAP_Connect_Timeout": "Délai de connexion (ms)", "LDAP_Default_Domain": "Domaine par défaut", "LDAP_Default_Domain_Description": "S'il est fourni, le domaine par défaut sera utilisé pour créer un e-mail unique pour les utilisateurs dont l'e-mail n'a pas été importé depuis LDAP. L'e-mail sera monté en tant que `username@default_domain` ou `unique_id@default_domain`.
Exemple : `rocket.chat`", - "LDAP_Default_Role_To_User": "Rôle par défaut de l'utilisateur", - "LDAP_Default_Role_To_User_Description": "Le rôle RC par défaut à appliquer à l'utilisateur, si l'utilisateur a un rôle LDAP qui n'est pas mappé.", - "LDAP_Description": "LDAP est une base de données hiérarchique que de nombreuses entreprises utilisent pour fournir une connexion unique - une fonction permettant de partager un mot de passe entre plusieurs sites et services. Pour obtenir plus d'informations et des exemples de configuration avancée, veuillez consulter notre wiki : https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Activer", "LDAP_Enable_Description": "Essayer d'utiliser LDAP pour l'authentification.", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "Activer le mappage de rôle de LDAP vers Rocket.Chat", "LDAP_Enable_LDAP_Groups_To_RC_Teams": "Activer le mappage d'équipe de LDAP vers Rocket.Chat", "LDAP_Encryption": "Chiffrement", "LDAP_Encryption_Description": "La méthode de chiffrement utilisée pour sécuriser les communications avec le serveur LDAP. Parmi les exemples on trouve `plain` (pas de chiffrement), `SSL/LDAPS` (chiffrement dès le début) et `StartTLS` (chiffrement une fois la connexion établie).", @@ -2469,15 +2465,11 @@ "LDAP_Merge_Existing_Users_Description": "*Attention !* Lors de l'importation d'un utilisateur à partir de LDAP et qu'un utilisateur avec le même nom d'utilisateur existe déjà, les informations LDAP et le mot de passe seront définis dans l'utilisateur existant.", "LDAP_Port": "Port", "LDAP_Port_Description": "Port pour accéder à LDAP. Ex. : `389` ou `636` pour LDAPS", - "LDAP_Query_To_Get_User_Groups": "Requête LDAP pour récupérer les groupes d'utilisateurs", - "LDAP_Query_To_Get_User_Groups_Description": "Requête LDAP pour obtenir les groupes LDAP dont l'utilisateur fait parti.", "LDAP_Query_To_Get_User_Teams": "Requête LDAP pour récupérer les groupes d'utilisateurs", "LDAP_Reconnect": "Reconnecter", "LDAP_Reconnect_Description": "Essayez de vous reconnecter automatiquement lorsque la connexion est interrompue pour une raison quelconque lors de l'exécution d'opérations", "LDAP_Reject_Unauthorized": "Rejeter les personnes non autorisées", "LDAP_Reject_Unauthorized_Description": "Désactivez cette option pour autoriser les certificats qui ne peuvent pas être vérifiés. Habituellement, les certificats auto-signés nécessitent que cette option soit désactivée pour fonctionner", - "LDAP_Roles_To_Rocket_Chat_Roles": "Mappage des rôles LDAP dans Rocket.Chat.", - "LDAP_Roles_To_Rocket_Chat_Roles_Description": "Mapping de rôle au format objet où la clé de l'objet doit être le rôle LDAP et la valeur d'objet doit être un tableau de rôles RC. Exemple : { 'ldapRole': ['rcRole', 'anotherRCRole'] }", "LDAP_Search_Page_Size": "Taille de la page de recherche", "LDAP_Search_Page_Size_Description": "Le nombre maximum d'entrées que chaque page de résultat retournera pour être traitée", "LDAP_Search_Size_Limit": "Limite de taille de la recherche", @@ -2490,29 +2482,28 @@ "LDAP_Sync_User_Active_State_Disable": "Désactiver les utilisateurs", "LDAP_Sync_User_Active_State_Nothing": "Ne rien faire", "LDAP_Sync_User_Avatar": "Synchronisation de l'avatar utilisateur", - "LDAP_Sync_User_Data": "Synchroniser les données utilisateur", - "LDAP_Sync_User_Data_Description": "Synchronisez les données utilisateur avec le serveur lors de la **connexion** ou de la **synchronisation en arrière-plan** (par exemple : nom, e-mail).", - "LDAP_Sync_User_Data_FieldMap": "Carte des champs de données utilisateur", - "LDAP_Sync_User_Data_FieldMap_Description": "Configurer la façon dont les champs de compte utilisateur (comme l'adresse e-mail) sont remplis à partir d'un enregistrement dans l'annuaire LDAP (une fois trouvé).
À titre d'exemple, `{\"cn\": \"name\", \"mail\": \"email\"}` choisira le nom lisible d'une personne à partir de l'attribut cn, et son adresse e-mail à partir de l'attribut mail.
Les champs disponibles dans Rocket.chat comprennent: `name`, `email` et `customFields`.", - "LDAP_Sync_User_Data_Groups": "Synchroniser les groupes LDAP", - "LDAP_Sync_User_Data_Groups_AutoChannels": "Synchronisation automatique des groupes LDAP avec les canaux", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "Administrateur du canal", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin_Description": "Lorsque des canaux sont créés automatiquement qui n'existent pas pendant une synchronisation, cet utilisateur deviendra automatiquement l'administrateur du canal.", - "LDAP_Sync_User_Data_Groups_AutoChannels_Description": "Activez cette fonction pour ajouter automatiquement des utilisateurs à un canal en fonction de leur groupe LDAP. Si vous souhaitez également supprimer des utilisateurs d'un canal, consultez l'option ci-dessous concernant la suppression automatique d'utilisateurs.", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap": "Carte des canaux du groupe LDAP", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Default": "// Activer la synchronisation automatique des groupes LDAP aux canaux ci-dessus", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Description": "Mappez les groupes LDAP aux canaux Rocket.Chat.
Par exemple, `{\"employee\":\"general\"}` ajoutera n'importe quel utilisateur du groupe LDAP employee au canal général.", - "LDAP_Sync_User_Data_Groups_AutoRemove": "Supprimer automatiquement les rôles utilisateur", - "LDAP_Sync_User_Data_Groups_AutoRemove_Description": "**Attention**: l'activation de cette option supprimera automatiquement les utilisateurs d'un rôle s'ils ne sont pas affectés dans LDAP ! Cela supprimera uniquement les rôles définis automatiquement sous la carte des groupes de données utilisateur ci-dessous.", - "LDAP_Sync_User_Data_Groups_BaseDN": "Nom de base (BaseDN) du groupe LDAP", - "LDAP_Sync_User_Data_Groups_BaseDN_Description": "Le LDAP BaseDN utilisé pour rechercher les utilisateurs.", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels": "Supprimer automatiquement les utilisateurs des canaux", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels_Description": "**Attention** : En activant cette option, vous supprimerez tous les utilisateurs d'un canal qui n'ont pas le groupe LDAP correspondant ! Activez ceci que si vous savez ce que vous faites.", - "LDAP_Sync_User_Data_Groups_Filter": "Filtre de groupe d'utilisateurs", - "LDAP_Sync_User_Data_Groups_Filter_Description": "Le filtre de recherche LDAP utilisé pour vérifier si un utilisateur fait partie d'un groupe.", - "LDAP_Sync_User_Data_GroupsMap": "Carte des groupes de données utilisateur", - "LDAP_Sync_User_Data_GroupsMap_Description": "Mappez les groupes LDAP aux rôles des utilisateurs Rocket.Chat
Par exemple, `{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}` mappera le groupe LDAP rocket-admin au rôle \"admin\" de Rocket.", - "LDAP_Test_Connection": "Tester la connexion", + "LDAP_Sync_User_Data_Roles": "Synchroniser les groupes LDAP", + "LDAP_Sync_User_Data_Channels": "Synchronisation automatique des groupes LDAP avec les canaux", + "LDAP_Sync_User_Data_Channels_Admin": "Administrateur du canal", + "LDAP_Sync_User_Data_Channels_Admin_Description": "Lorsque des canaux sont créés automatiquement qui n'existent pas pendant une synchronisation, cet utilisateur deviendra automatiquement l'administrateur du canal.", + "LDAP_Sync_User_Data_Channels_BaseDN": "Nom de base (BaseDN) du groupe LDAP", + "LDAP_Sync_User_Data_Channels_BaseDN_Description": "Le LDAP BaseDN utilisé pour rechercher les utilisateurs.", + "LDAP_Sync_User_Data_Channels_Description": "Activez cette fonction pour ajouter automatiquement des utilisateurs à un canal en fonction de leur groupe LDAP. Si vous souhaitez également supprimer des utilisateurs d'un canal, consultez l'option ci-dessous concernant la suppression automatique d'utilisateurs.", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels": "Supprimer automatiquement les utilisateurs des canaux", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels_Description": "**Attention** : En activant cette option, vous supprimerez tous les utilisateurs d'un canal qui n'ont pas le groupe LDAP correspondant ! Activez ceci que si vous savez ce que vous faites.", + "LDAP_Sync_User_Data_Channels_Filter": "Filtre de groupe d'utilisateurs", + "LDAP_Sync_User_Data_Channels_Filter_Description": "Le filtre de recherche LDAP utilisé pour vérifier si un utilisateur fait partie d'un groupe.", + "LDAP_Sync_User_Data_ChannelsMap": "Carte des canaux du groupe LDAP", + "LDAP_Sync_User_Data_ChannelsMap_Default": "// Activer la synchronisation automatique des groupes LDAP aux canaux ci-dessus", + "LDAP_Sync_User_Data_ChannelsMap_Description": "Mappez les groupes LDAP aux canaux Rocket.Chat.
Par exemple, `{\"employee\":\"general\"}` ajoutera n'importe quel utilisateur du groupe LDAP employee au canal général.", + "LDAP_Sync_User_Data_Roles_AutoRemove": "Supprimer automatiquement les rôles utilisateur", + "LDAP_Sync_User_Data_Roles_AutoRemove_Description": "**Attention**: l'activation de cette option supprimera automatiquement les utilisateurs d'un rôle s'ils ne sont pas affectés dans LDAP ! Cela supprimera uniquement les rôles définis automatiquement sous la carte des groupes de données utilisateur ci-dessous.", + "LDAP_Sync_User_Data_Roles_BaseDN": "Nom de base (BaseDN) du groupe LDAP", + "LDAP_Sync_User_Data_Roles_BaseDN_Description": "Le LDAP BaseDN utilisé pour rechercher les utilisateurs.", + "LDAP_Sync_User_Data_Roles_Filter": "Filtre de groupe d'utilisateurs", + "LDAP_Sync_User_Data_Roles_Filter_Description": "Le filtre de recherche LDAP utilisé pour vérifier si un utilisateur fait partie d'un groupe.", + "LDAP_Sync_User_Data_RolesMap": "Carte des groupes de données utilisateur", + "LDAP_Sync_User_Data_RolesMap_Description": "Mappez les groupes LDAP aux rôles des utilisateurs Rocket.Chat
Par exemple, `{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}` mappera le groupe LDAP rocket-admin au rôle \"admin\" de Rocket.", "LDAP_Timeout": "Délai d'attente (ms)", "LDAP_Timeout_Description": "Combien de millisecondens faut-il attendre pour obtenir un résultat de recherche avant de renvoyer une erreur", "LDAP_Unique_Identifier_Field": "Champ d'identifiant unique", @@ -2526,8 +2517,6 @@ "LDAP_Username_Field_Description": "Quel champ sera utilisé comme *nom d'utilisateur* pour les nouveaux utilisateurs. Laisser vide pour utiliser le nom d'utilisateur renseigné sur la page de connexion.
Vous pouvez également utiliser des balises de modèle, comme `#{givenName}.#{sn}`.
La valeur par défaut est `sAMAccountName`.", "LDAP_Validate_Teams_For_Each_Login": "Valider le mappage pour chaque connexion", "LDAP_Validate_Teams_For_Each_Login_Description": "Déterminez si les équipes des utilisateurs doivent être mises à jour à chaque fois qu'ils se connectent à Rocket.Chat. Si cette option est désactivée, l'équipe ne sera chargée qu'à sa première connexion.", - "LDAP_Validate_Roles_For_Each_Login": "Valider le mappage pour chaque connexion", - "LDAP_Validate_Roles_For_Each_Login_Description": "Si la validation doit avoir lieu pour chaque connexion (soyez prudent avec ce paramètre car il écrasera les rôles d'utilisateur à chaque connexion, sinon cela ne sera validé qu'au moment de la création de l'utilisateur).", "Lead_capture_email_regex": "Regex pour capture d'e-mail principale", "Lead_capture_phone_regex": "Regex de téléphone de capture principale", "Leave": "Quitter", diff --git a/packages/rocketchat-i18n/i18n/he.i18n.json b/packages/rocketchat-i18n/i18n/he.i18n.json index e92e72bdeb39..2e52b64f5c54 100644 --- a/packages/rocketchat-i18n/i18n/he.i18n.json +++ b/packages/rocketchat-i18n/i18n/he.i18n.json @@ -792,7 +792,6 @@ "LDAP_BaseDN_Description": "השם הייחודי מלא (DN) של עץ משנה LDAP אתה רוצה לחפש משתמשים וקבוצות. אתה יכול להוסיף כמה שאתה רוצה; עם זאת, כל קבוצה חייבת להיות מוגדרת באותו הבסיס מושלם בתור המשתמשים ששייכים אליו. אם תציין קבוצות משתמש מוגבלות, רק משתמשים השייכים לקבוצות אלו יהיו בהיקפה. אנו ממליצים לציין את הרמה העליונה של ספריית עץ LDAP שלך כבסיס התחום שלך ולהשתמש במסנן חיפוש כדי לשלוט בגישה.", "LDAP_CA_Cert": "Cert CA", "LDAP_Default_Domain": "ברירת המחדל של תחום", - "LDAP_Description": "LDAP הוא מסד נתונים היררכיים כי חברות רבות להשתמש בו כדי לספק כניסה יחידה - מתקן לשיתוף סיסמא אחת בין אתרים ושירותים רבים. לקבלת מידע תצורה מתקדמת ודוגמאות, היועץ wiki שלנו: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "אפשר", "LDAP_Enable_Description": "מנסה לאתחל LDAP עבור הזדהות.", "LDAP_Encryption": "הצף", @@ -803,11 +802,6 @@ "LDAP_Port_Description": "פורט לגישת LDAP. לדוגמה: `389` או `636` עבור LDAPS.", "LDAP_Reject_Unauthorized": "דחית מורשה", "LDAP_Sync_User_Avatar": "Sync משתמש אישי", - "LDAP_Sync_User_Data": "סנכרן מידע", - "LDAP_Sync_User_Data_Description": "דאג למידע מסונכרן על המשתמש בהתחברות לשרת (שם, אימייל).", - "LDAP_Sync_User_Data_FieldMap": "מיפוי שדה User Data", - "LDAP_Sync_User_Data_FieldMap_Description": "הגדר כיצד שדות חשבון המשתמש (כגון אימייל) ישלפו מרשומת ה-LDAP (כאשר נמצאה).
לדוגמה, `{\"cn\":\"name\", \"mail\":\"email\"}` יבחרו את השם הקריא של המשתמש מהשדה cn והאימייל שלהם מהשדה mail.
השדות האפשריים כוללים `name`, ו-`email`.", - "LDAP_Test_Connection": "בדיקת חיבור", "LDAP_Unique_Identifier_Field": "ייחודיות מזהים שדה", "LDAP_Unique_Identifier_Field_Description": "איזה שדה ישמש לקשר משתמש LDAP ומשתמש Rocket.Chat. אתה יכול להודיע ​​ערכים המופרדים באמצעות פסיק כדי לנסות להשיג את הערך מרשום LDAP.
ערך ברירת המחדל הוא `objectGUID, IBM-entryUUID, GUID, dominoUNID, nsuniqueId, uidNumber`", "LDAP_User_Search_Field_Description": "התכונה של LDAP המזהה את המשתמש LDAP שמנסה אימות. שדה זה צריך להיות `sAMAccountName` להתקנות של Active Directory ביותר, אבל זה עשוי להיות` uid` לפתרונות LDAP אחרים, כגון OpenLDAP. אתה יכול להשתמש `mail` לזהות משתמשים בדוא\"ל או כל תכונה שאתה רוצה.
תוכל להשתמש בערכים מרובים המופרדים בפסיק כדי לאפשר למשתמשים להתחבר באמצעות מזהים מרובים כמו שם משתמש או דוא\"ל.", diff --git a/packages/rocketchat-i18n/i18n/hr.i18n.json b/packages/rocketchat-i18n/i18n/hr.i18n.json index 257bdbd16c04..1b5bc8aabaa2 100644 --- a/packages/rocketchat-i18n/i18n/hr.i18n.json +++ b/packages/rocketchat-i18n/i18n/hr.i18n.json @@ -1650,7 +1650,6 @@ "LDAP_Connect_Timeout": "Vrijeme veze (ms)", "LDAP_Default_Domain": "Zadana domena", "LDAP_Default_Domain_Description": "Ako je predviđeno, zadana domena će se koristiti za stvaranje jedinstvene e-pošte za korisnike gdje e-pošta nije uvezena iz LDAP-a. E-adresa će biti postavljena kao \"korisničko ime @ default_domain\" ili \"unique_id @ default_domain\".
Primjer: `rocket.chat`", - "LDAP_Description": "LDAP je hijerarhijska baza podataka koja mnoge tvrtke koriste za pružanje jedinstvene prijave - usluge za dijeljenje jedne lozinke između više web-mjesta i usluga. Za napredne podatke o konfiguraciji i primjere, obratite se našem wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Omogući", "LDAP_Enable_Description": "Pokušaj koristiti LDAP za provjeru autentičnosti.", "LDAP_Encryption": "Šifriranje", @@ -1692,11 +1691,6 @@ "LDAP_Sync_Now": "Pozadinska sinkronizacija sada", "LDAP_Sync_Now_Description": "Će izvršiti ** pozadinsku sinkronizaciju ** sada, a ne čekati ** Sync Interval **, čak i ako je ** Sinkronizacija pozadine ** lažna.
Ova akcija je asinkroni, pogledajte zapisnike za više informacija o postupak", "LDAP_Sync_User_Avatar": "Sinkronizacija Korisnikovog Avatara", - "LDAP_Sync_User_Data": "Sinkronizacija podataka", - "LDAP_Sync_User_Data_Description": "Održavajte korisničke podatke sinkronizirane sa serverom pri prijavi (npr: ime i prezime, e-mail).", - "LDAP_Sync_User_Data_FieldMap": "Mapa korisničkih podataka", - "LDAP_Sync_User_Data_FieldMap_Description": "Konfigurirajte kako će korisnička polja (poput emaila) biti popunje iz zapisa na LDAPu (nakon što ih nađemo).
Na primjer, `{\"cn\":\"name\", \"mail\":\"email\"}` će odabrati čitljivo ime iz cn atributa i njihov email i mail atributa.
 Dostupna polja uključuju `name`i `email`.", - "LDAP_Test_Connection": "Testiraj vezu", "LDAP_Timeout": "Vrijeme (ms)", "LDAP_Timeout_Description": "Koliko milja čekaju rezultat pretraživanja prije nego što se vrati pogreška", "LDAP_Unique_Identifier_Field": "Jedinstveni identifikator polja", diff --git a/packages/rocketchat-i18n/i18n/hu.i18n.json b/packages/rocketchat-i18n/i18n/hu.i18n.json index b18866cf45d8..6cfbc365933c 100644 --- a/packages/rocketchat-i18n/i18n/hu.i18n.json +++ b/packages/rocketchat-i18n/i18n/hu.i18n.json @@ -1848,7 +1848,6 @@ "LDAP_Connect_Timeout": "Kapcsolódási idő (ms)", "LDAP_Default_Domain": "Alapértelmezett Domain", "LDAP_Default_Domain_Description": "Ha rendelkezésre áll, akkor az Alapértelmezett tartományt egyedi e-mailek létrehozására használják azon felhasználók számára, ahol az e-maileket nem importálták az LDAP-ból. Az e-mailt \"username @ default_domain\" vagy \"unique_id @ default_domain\" néven kell telepíteni.
Példa: `rocket.chat`", - "LDAP_Description": "Az LDAP hierarchikus adatbázis sok cég használja, hogy single sign on - a létesítmény megosztása egy jelszót a több oldalak és szolgáltatások. Speciális konfigurációs információkat és példákat, kérjük forduljon a wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Engedélyezve", "LDAP_Enable_Description": "Kísérlet, hogy kihasználja az LDAP hitelesítés.", "LDAP_Encryption": "Titkosítás", @@ -1890,14 +1889,10 @@ "LDAP_Sync_Now": "Háttér szinkronizálása most", "LDAP_Sync_Now_Description": "A ** Háttér-szinkronizálást ** ** futtatja, nem pedig a ** Szinkronizálási időtartamot ** akkor is, ha a ** Háttér-szinkronizálás ** hamis.
Ez a művelet aszinkron, kérjük, olvassa el a naplókat a folyamat", "LDAP_Sync_User_Avatar": "Szinkronizálás Avatar", - "LDAP_Sync_User_Data": "adatok szinkronizálása", - "LDAP_Sync_User_Data_Description": "Tartsa a felhasználói adatok szinkronban szerver login (pl: név, e-mail).", - "LDAP_Sync_User_Data_FieldMap": "Felhasználói adatok Field Térkép", - "LDAP_Sync_User_Data_FieldMap_Description": "Állítsd be, hogyan felhasználói fiók területeken (például e-mail) lakott egy rekordot LDAP (egyszer találtak).
Példaként `{\" cn \":\" name \",\" mail \":\" email \"}` fog választani egy személy olvasható név a cn attribútumot, és az e-mail a mail attribútumot.
Elérhető mezők közé `name` és` email`.", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "Channel Adminisztrátor", - "LDAP_Sync_User_Data_Groups_Filter": "Felhasználói csoport szűrő", - "LDAP_Sync_User_Data_GroupsMap": "Felhasználói adatcsoport térkép", - "LDAP_Test_Connection": "Kapcsolat tesztelése", + "LDAP_Sync_User_Data_Channels_Admin": "Channel Adminisztrátor", + "LDAP_Sync_User_Data_Channels_Filter": "Felhasználói csoport szűrő", + "LDAP_Sync_User_Data_Roles_Filter": "Felhasználói csoport szűrő", + "LDAP_Sync_User_Data_RolesMap": "Felhasználói adatcsoport térkép", "LDAP_Timeout": "Időzítés (ms)", "LDAP_Timeout_Description": "Hány mérföldes másodperc vár egy keresési eredményre, mielőtt hibát kap", "LDAP_Unique_Identifier_Field": "Egyedi azonosító mező", diff --git a/packages/rocketchat-i18n/i18n/id.i18n.json b/packages/rocketchat-i18n/i18n/id.i18n.json index f7da1ec733bc..96328a4ceaa2 100644 --- a/packages/rocketchat-i18n/i18n/id.i18n.json +++ b/packages/rocketchat-i18n/i18n/id.i18n.json @@ -1518,7 +1518,6 @@ "LDAP_Connect_Timeout": "Waktu Sambungan (ms)", "LDAP_Default_Domain": "default Domain", "LDAP_Default_Domain_Description": "Jika asalkan Domain Default akan digunakan untuk membuat email unik bagi pengguna yang emailnya tidak diimpor dari LDAP. Email akan dipasang sebagai `username @ default_domain` atau` unique_id @ default_domain`.
Contoh: `rocket.chat`", - "LDAP_Description": "LDAP adalah basis data hirarki yang banyak digunakan perusahaan untuk menyediakan fasilitas single sing on untuk berbagi satu kata sandi diantara beberapa situs dan services. Untuk informasi dan contoh konfigurasi lebih lanjut, silahkan berkonsultasi di wiki kami: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Hidupkan", "LDAP_Enable_Description": "Mencoba untuk memanfaatkan LDAP sebagai otentikasi.", "LDAP_Encryption": "enkripsi", @@ -1560,11 +1559,6 @@ "LDAP_Sync_Now": "Latar Belakang Sinkron Sekarang", "LDAP_Sync_Now_Description": "Akan menjalankan ** Background Sync ** sekarang daripada menunggu ** Sync Interval ** walaupun ** Background Sync ** salah.
Tindakan ini tidak sinkron, lihat log untuk informasi lebih lanjut tentang proses", "LDAP_Sync_User_Avatar": "Sinkronisasi Pengguna Avatar", - "LDAP_Sync_User_Data": "Sinkronisasi Data", - "LDAP_Sync_User_Data_Description": "Menjaga data pengguna tetap tersinkronasi dengan server saat login(seperti: nama, email).", - "LDAP_Sync_User_Data_FieldMap": "Peta Kolom Data User", - "LDAP_Sync_User_Data_FieldMap_Description": "Mengkonfigurasi bagaimana kolom akun pengguna(seperti email) yang akan diisi dari record dalam LDAP(sekali ditemukan).
Sebagai contoh, `{\"cn\":\"name\", \"mail\":\"email\"}` akan memilih nama yang dapat dibaca oleh manusia dari atribut cn, dan email mereka dari atribut mail.
Kolom yang tersedia meliputi `name`, and `email`.", - "LDAP_Test_Connection": "Tes koneksi", "LDAP_Timeout": "Waktu habis (ms)", "LDAP_Timeout_Description": "Berapa milimond menunggu hasil pencarian sebelum mengembalikan kesalahan", "LDAP_Unique_Identifier_Field": "Unique Identifier Bidang", diff --git a/packages/rocketchat-i18n/i18n/it.i18n.json b/packages/rocketchat-i18n/i18n/it.i18n.json index 96039a9515b8..36be030b74dc 100644 --- a/packages/rocketchat-i18n/i18n/it.i18n.json +++ b/packages/rocketchat-i18n/i18n/it.i18n.json @@ -1552,7 +1552,6 @@ "LDAP_Connect_Timeout": "Timeout Connessione (ms)", "LDAP_Default_Domain": "Dominio Predefinito", "LDAP_Default_Domain_Description": "Se fornito, il dominio predefinito verrà utilizzato per creare un'e-mail univoca per gli utenti in cui l'e-mail non è stata importata da LDAP. L'email verrà montata come `username@default_domain` o` unique_id@default_domain`.
Esempio: `rocket.chat`", - "LDAP_Description": "LDAP è un database gerarchico che molte aziende utilizzano per fornire single sign on - per la condivisione di una sola password tra più siti e servizi. Per informazioni sulla configurazione avanzata ed esempi, consulta il nostro wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Attivo", "LDAP_Enable_Description": "Tenta di utilizzare LDAP per l'autenticazione.", "LDAP_Encryption": "Crittografia", @@ -1594,11 +1593,6 @@ "LDAP_Sync_Now": "Sincronizzazione in background adesso", "LDAP_Sync_Now_Description": "Eseguirà **Sincronizzazione di sfondo** ora anziché attendere **Intervallo di sincronizzazione** anche se **Sincronizzazione in background** è False.
Questa azione è asincrona, consulta i registri per ulteriori informazioni sul processi", "LDAP_Sync_User_Avatar": "Sincronizzazione Avatar Utenti", - "LDAP_Sync_User_Data": "Sincronizzazione Dati", - "LDAP_Sync_User_Data_Description": "Conserva i dati degli utenti in sincro con il server di login (ad esempio: nome, email).", - "LDAP_Sync_User_Data_FieldMap": "Campo Utente Dati Mappa", - "LDAP_Sync_User_Data_FieldMap_Description": "Configura come i campi dell'account utente (come l'email) sono popolate da un record LDAP (una volta trovato).
A titolo di esempio, `{\" cn \":\" nome \",\" mail \":\" email \"}` sceglierà il nome di una persona umana dall'attributo cn, e la loro email dall'attributo mail. In aggiunta è possibile usare le variabili, per esempio: { \"#{givenName} #{sn}\": \"name\", \"mail\": \"email\" }` usa una combinazione di nome e cognome dell'utente per il campo `name` di rocket chat.
I campi disponibili in Rocket.Chat includono: `name` e `email`.", - "LDAP_Test_Connection": "Connessione di prova", "LDAP_Timeout": "Timeout (ms)", "LDAP_Timeout_Description": "Quanti chilometri quanti aspettano un risultato di ricerca prima di restituire un errore", "LDAP_Unique_Identifier_Field": "Campo Identificativo Univoco", diff --git a/packages/rocketchat-i18n/i18n/ja.i18n.json b/packages/rocketchat-i18n/i18n/ja.i18n.json index edad205ecec1..b97306a5fb37 100644 --- a/packages/rocketchat-i18n/i18n/ja.i18n.json +++ b/packages/rocketchat-i18n/i18n/ja.i18n.json @@ -2262,12 +2262,8 @@ "LDAP_Connect_Timeout": "接続タイムアウト (ミリ秒)", "LDAP_Default_Domain": "既定ドメイン", "LDAP_Default_Domain_Description": "指定されている場合は、デフォルトドメインを使用して、電子メールがLDAPからインポートされなかったユーザーの固有の電子メールを作成します。電子メールは `username @ default_domain` または `unique_id @ default_domain` としてマウントされます。
例: `rocket.chat`", - "LDAP_Default_Role_To_User": "ユーザーへのデフォルトの役割", - "LDAP_Default_Role_To_User_Description": "ユーザーにマッピングされていないLDAPロールがある場合にユーザーに適用されるデフォルトのRCロール。", - "LDAP_Description": "LDAP は、多くの企業でシングルサインオンを提供する為に使用している階層構造データベースで、 1 つのパスワードを複数サイトやサービスで共有できる手法です。高度な設定情報や例示は、私達の wiki で相談してください: https://rocket.chat/docs/administrator-guides/authentication/ldap/", "LDAP_Enable": "有効にする", "LDAP_Enable_Description": "LDAP による認証を試行するようになります。", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "LDAPからRocket.Chatへのロールマッピングを有効にする", "LDAP_Encryption": "暗号化", "LDAP_Encryption_Description": "LDAP サーバーとセキュアに通信するため、暗号化機能を使用します。例えば `plain` (暗号化なし) 、 `SSL/LDAPS` (開始から暗号化) や `StartTLS` (一度接続したら暗号化通信へアップグレード) を使用できます。", "LDAP_Find_User_After_Login": "ログイン後にユーザーを検索する", @@ -2296,15 +2292,11 @@ "LDAP_Merge_Existing_Users_Description": "*注意!* LDAPからユーザーをインポートするときに、同じユーザー名を持つユーザーが既に存在する場合は、LDAP情報とパスワードが既存のユーザーに設定されます。", "LDAP_Port": "ポート", "LDAP_Port_Description": "LDAP アクセスするポート番号。例: `389` や `636` ( LDAPS 用 )", - "LDAP_Query_To_Get_User_Groups": "ユーザーグループを取得するためのLDAPクエリ", - "LDAP_Query_To_Get_User_Groups_Description": "ユーザーが属するLDAPグループを取得するためのLDAPクエリ。", "LDAP_Query_To_Get_User_Teams": "ユーザーグループを取得するためのLDAPクエリ", "LDAP_Reconnect": "再接続します", "LDAP_Reconnect_Description": "操作の実行中に何らかの理由で接続が中断された場合、自動的に再接続を試みる", "LDAP_Reject_Unauthorized": "認証できなければ拒否する", "LDAP_Reject_Unauthorized_Description": "検証できない証明書を許可するには、このオプションを無効にします。通常、自己署名証明書では、このオプションを無効にする必要があります", - "LDAP_Roles_To_Rocket_Chat_Roles": "LDAPからRocket.Chatへのロールマッピング。", - "LDAP_Roles_To_Rocket_Chat_Roles_Description": "オブジェクトキーがLDAPロールであり、オブジェクト値がRCロールの配列である必要があるオブジェクト形式のロールマッピング。例:{ 'ldapRole': ['rcRole', 'anotherRCRole'] }", "LDAP_Search_Page_Size": "検索ページサイズ", "LDAP_Search_Page_Size_Description": "各結果ページが処理されるために返すエントリの最大数", "LDAP_Search_Size_Limit": "検索サイズ制限", @@ -2317,29 +2309,28 @@ "LDAP_Sync_User_Active_State_Disable": "ユーザーを無効にする", "LDAP_Sync_User_Active_State_Nothing": "何もしない", "LDAP_Sync_User_Avatar": "ユーザーのアバターを同期する", - "LDAP_Sync_User_Data": "データを同期する", - "LDAP_Sync_User_Data_Description": "ログインする時に、ユーザーデータを同期します (例: 名前, メールアドレス)", - "LDAP_Sync_User_Data_FieldMap": "ユーザーデータのフィールドマップ", - "LDAP_Sync_User_Data_FieldMap_Description": "どのようにユーザーアカウントのフィールド (メールアドレスなど) を LDAP にあるレコードから調整するか。
例えば、 `{\"cn\":\"name\", \"mail\":\"email\"}` では、人間が読める名前を cn 属性とし、メールアドレスを mail 属性から取得します。
使用できるは、 `名前` と `メールアドレス` を含むものです。", - "LDAP_Sync_User_Data_Groups": "LDAPグループの同期", - "LDAP_Sync_User_Data_Groups_AutoChannels": "LDAPグループをChannelに自動同期", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "Channel管理者", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin_Description": "同期中に存在しないチャネルが自動作成されると、このユーザーは自動的にチャネルの管理者になります。", - "LDAP_Sync_User_Data_Groups_AutoChannels_Description": "この機能を有効にすると、LDAPグループに基づいてユーザーが自動的にチャンネルに追加されます。ユーザーをチャンネルからも削除する場合は、ユーザーの自動削除に関する以下のオプションを参照してください。", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap": "LDAPグループChannelマップ", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Default": "// 上記のChannelへのLDAPグループの自動同期を有効にします", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Description": "LDAPグループをRocket.Chatチャネルにマップします。
例として、 `{\"employee\":\"general\"}` は従業員LDAPグループのすべてのユーザーを一般チャンネルに追加します。", - "LDAP_Sync_User_Data_Groups_AutoRemove": "ユーザーロールの自動削除", - "LDAP_Sync_User_Data_Groups_AutoRemove_Description": "**注意**:これを有効にすると、LDAPで割り当てられていないユーザーはロールから自動的に削除されます! これにより、以下のユーザーデータグループマップで設定されているロールのみが自動的に削除されます。", - "LDAP_Sync_User_Data_Groups_BaseDN": "LDAPグループ BaseDN", - "LDAP_Sync_User_Data_Groups_BaseDN_Description": "ユーザーの検索に使用されるLDAP BaseDN。", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels": "Channelからのユーザーの自動削除", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels_Description": "**注意**:これを有効にすると、対応するLDAPグループを持たないチャンネルのユーザーが削除されます! 何をしているのかわかっている場合にのみ、これを有効にしてください。", - "LDAP_Sync_User_Data_Groups_Filter": "ユーザーグループフィルター", - "LDAP_Sync_User_Data_Groups_Filter_Description": "ユーザーがグループに属しているかどうかを確認するために使用されるLDAP検索フィルター。", - "LDAP_Sync_User_Data_GroupsMap": "ユーザーデータグループマップ", - "LDAP_Sync_User_Data_GroupsMap_Description": "LDAPグループをRocket.Chatユーザーロールにマップする
例として、 `{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}`は rocket-admin LDAPグループをRocket.Chatのadminロールにマップします。", - "LDAP_Test_Connection": "接続テスト", + "LDAP_Sync_User_Data_Roles": "LDAPグループの同期", + "LDAP_Sync_User_Data_Channels": "LDAPグループをChannelに自動同期", + "LDAP_Sync_User_Data_Channels_Admin": "Channel管理者", + "LDAP_Sync_User_Data_Channels_Admin_Description": "同期中に存在しないチャネルが自動作成されると、このユーザーは自動的にチャネルの管理者になります。", + "LDAP_Sync_User_Data_Channels_BaseDN": "LDAPグループ BaseDN", + "LDAP_Sync_User_Data_Channels_BaseDN_Description": "ユーザーの検索に使用されるLDAP BaseDN。", + "LDAP_Sync_User_Data_Channels_Description": "この機能を有効にすると、LDAPグループに基づいてユーザーが自動的にチャンネルに追加されます。ユーザーをチャンネルからも削除する場合は、ユーザーの自動削除に関する以下のオプションを参照してください。", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels": "Channelからのユーザーの自動削除", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels_Description": "**注意**:これを有効にすると、対応するLDAPグループを持たないチャンネルのユーザーが削除されます! 何をしているのかわかっている場合にのみ、これを有効にしてください。", + "LDAP_Sync_User_Data_Channels_Filter": "ユーザーグループフィルター", + "LDAP_Sync_User_Data_Channels_Filter_Description": "ユーザーがグループに属しているかどうかを確認するために使用されるLDAP検索フィルター。", + "LDAP_Sync_User_Data_ChannelsMap": "LDAPグループChannelマップ", + "LDAP_Sync_User_Data_ChannelsMap_Default": "// 上記のChannelへのLDAPグループの自動同期を有効にします", + "LDAP_Sync_User_Data_ChannelsMap_Description": "LDAPグループをRocket.Chatチャネルにマップします。
例として、 `{\"employee\":\"general\"}` は従業員LDAPグループのすべてのユーザーを一般チャンネルに追加します。", + "LDAP_Sync_User_Data_Roles_AutoRemove": "ユーザーロールの自動削除", + "LDAP_Sync_User_Data_Roles_AutoRemove_Description": "**注意**:これを有効にすると、LDAPで割り当てられていないユーザーはロールから自動的に削除されます! これにより、以下のユーザーデータグループマップで設定されているロールのみが自動的に削除されます。", + "LDAP_Sync_User_Data_Roles_BaseDN": "LDAPグループ BaseDN", + "LDAP_Sync_User_Data_Roles_BaseDN_Description": "ユーザーの検索に使用されるLDAP BaseDN。", + "LDAP_Sync_User_Data_Roles_Filter": "ユーザーグループフィルター", + "LDAP_Sync_User_Data_Roles_Filter_Description": "ユーザーがグループに属しているかどうかを確認するために使用されるLDAP検索フィルター。", + "LDAP_Sync_User_Data_RolesMap": "ユーザーデータグループマップ", + "LDAP_Sync_User_Data_RolesMap_Description": "LDAPグループをRocket.Chatユーザーロールにマップする
例として、 `{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}`は rocket-admin LDAPグループをRocket.Chatのadminロールにマップします。", "LDAP_Timeout": "タイムアウト (ミリ秒)", "LDAP_Timeout_Description": "エラーを返す前に検索結果を待つ時間は何マイル秒か", "LDAP_Unique_Identifier_Field": "一意性を識別するフィールド", @@ -2352,8 +2343,6 @@ "LDAP_Username_Field": "ユーザー名フィールド", "LDAP_Username_Field_Description": "どのフィールドを新しいユーザーの *ユーザー名* として使用するのか。ログインページのユーザー名を利用する場合は、空にしてください。
テンプレートタグとして `#{givenName}.#{sn}` といった記述も使用できます。
既定値は、 `sAMAccountName` です", "LDAP_Validate_Teams_For_Each_Login": "各ログインのマッピングを検証する", - "LDAP_Validate_Roles_For_Each_Login": "各ログインのマッピングを検証する", - "LDAP_Validate_Roles_For_Each_Login_Description": "各ログインで検証を行う必要がある場合(この設定は各ログインでユーザーロールを上書きするため、注意してください。そうでない場合、ユーザーの作成時にのみ検証されます)。", "Lead_capture_email_regex": "リードキャプチャ電子メールの正規表現", "Lead_capture_phone_regex": "リードキャプチャ電話の正規表現", "Leave": "退出", diff --git a/packages/rocketchat-i18n/i18n/ka-GE.i18n.json b/packages/rocketchat-i18n/i18n/ka-GE.i18n.json index 3fc0c3d111f4..745fec20ec70 100644 --- a/packages/rocketchat-i18n/i18n/ka-GE.i18n.json +++ b/packages/rocketchat-i18n/i18n/ka-GE.i18n.json @@ -2040,12 +2040,8 @@ "LDAP_Connect_Timeout": "კავშირის ხანგრძლივობა (ms)", "LDAP_Default_Domain": "დეფაულტ დომეინი", "LDAP_Default_Domain_Description": "თუ გათვალისწინებულია, დეფაულტ დომეინი იქნება გამოყენებული მომხმარებლებისთვის უნიკალური ელ.ფოსტის შესაქმნელად როდესაც ელ.ფოსტა არ იყო იმპორტირებული LDAP-დან. ელ.ფოსტა მიმაგრდება შემდეგნაირად: `username@default_domain` or `unique_id@default_domain`.
Example: `rocket.chat`", - "LDAP_Default_Role_To_User": "ნაგულისხმევი(default) როლი მომხმარებლისთვის", - "LDAP_Default_Role_To_User_Description": "RC– ის ნაგულისხმევი როლი უნდა იქნას გამოყენებული მომხმარებლისთვის, თუ მომხმარებელს აქვს LDAP– ის გარკვეული როლი, რომელიც არ არის მიბმული.", - "LDAP_Description": "LDAP არის იერარქიული მონაცემთა ბაზა, რომელსაც მრავალი კომპანია იყენებს ერთი ავტორიზაციის შესაქმნელად - ერთი პაროლი სხვადასხვა მომსახურება და საიტებისთვის. კონფიგურაციის შესახებ ინფორმაციის და მაგალითებისთვის მიმართეთ ჩვენს ვიკებს: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "ჩართვა", "LDAP_Enable_Description": "LDAP-ის ავტორიზაციისთვის გამოყენების მცდელობა", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "ჩართეთ როლის მიბმა LDAP- დან Rocket.Chat-ში", "LDAP_Encryption": "დაშიფვრა", "LDAP_Encryption_Description": "დაშიფვრის მეთოდი, რომელიც გამოიყენება LDAP სერვერზე კომუნიკაციის უზრუნველსაყოფად. მაგალითებში მოცემულია `უბრალო ((დაშიფვრა), SS SSL / LDAPS` (დაშიფრული თავიდანვე) და` StartTLS` (დაშიფრული კავშირი დაკავშირებისთანავე).", "LDAP_Find_User_After_Login": "იპოვნეთ მომხმარებელი შესვლის შემდეგ", @@ -2074,15 +2070,11 @@ "LDAP_Merge_Existing_Users_Description": "ყურადღება! LDAP-დან მომხმარებლის იმპორტისას როდესაც მომხმარებელი ასეთი სახელით უკვე არსებობს LDAP ინფო და პაროლი მიენიჭება უკვე არსებულ მომხმარებელს", "LDAP_Port": "პორტი", "LDAP_Port_Description": "პორტი LDAP– ზე შესასვლელად. მაგალითად: `389` ან` 636` LDAPS– სთვის", - "LDAP_Query_To_Get_User_Groups": "LDAP მოთხოვნა, რომ მიიღოთ მომხმარებელთა ჯგუფები", - "LDAP_Query_To_Get_User_Groups_Description": "LDAP მოთხოვნა მიიღოთ LDAP ჯგუფები, რომელთა წევრიც არის მომხმარებელი.", "LDAP_Query_To_Get_User_Teams": "LDAP მოთხოვნა, რომ მიიღოთ მომხმარებელთა ჯგუფები", "LDAP_Reconnect": "თავიდან დაკავშირება", "LDAP_Reconnect_Description": "სცადეთ ხელახლა ავტომატურად დაკავშირება როდესაც კავშირი წყდება რაიმე მიზეზის გამო ოპერაციის შესრულებისას", "LDAP_Reject_Unauthorized": "არავტორიზებულის უარყოფა", "LDAP_Reject_Unauthorized_Description": "გამორთეთ ეს ვარიანტი, რომ დაუშვან სერთიფიკატები, რომელთა გადამოწმება შეუძლებელია. როგორც წესი, თვითმოწერილი სერთიფიკატები მოითხოვს ამ პარამეტრის გამორთვას", - "LDAP_Roles_To_Rocket_Chat_Roles": "როლის მიბმა LDAP- დან Rocket.Chat-ზე", - "LDAP_Roles_To_Rocket_Chat_Roles_Description": "როლის მობმა ობიექტის ფორმატში, სადაც ობიექტის გასაღები უნდა იყოს LDAP როლი და ობიექტის მნიშვნელობა უნდა იყოს RC როლების მასივი. მაგალითი: { 'ldapRole': ['rcRole', 'anotherRCRole'] }", "LDAP_Search_Page_Size_Description": "ცანაწერების მაქსიმალური რაოდენობა, რომელსაც შედეგების გვერდი დააბრუნებს", "LDAP_Search_Size_Limit_Description": "დასაბრუნებელი ცანაწერების მაქსიმალური რაოდენობა
ყურადღება! ეს რიცხვი უნდა იყოს **Search Page Size**-ზე დიდი", "LDAP_Sync_Now": "ფონის სინქრონიზაცია ახლა", @@ -2093,29 +2085,28 @@ "LDAP_Sync_User_Active_State_Disable": "მომხმარებლების გამორთვა", "LDAP_Sync_User_Active_State_Nothing": "Არაფრის კეთება", "LDAP_Sync_User_Avatar": "მომხმარებლის ავატარის სინქრონიზაცია", - "LDAP_Sync_User_Data": "მომხმარებლის მონაცემთა სინქრონიზაცია", - "LDAP_Sync_User_Data_Description": "დატოვეთ მომხმარებლის მონაცემები სინქრონში სერვერთან **login** ან **background sync** (მაგ: სახელი, ელ.ფოსტა)", - "LDAP_Sync_User_Data_FieldMap": "მომხმარებლის მონაცემების ველის რუკა", - "LDAP_Sync_User_Data_FieldMap_Description": "დააკონფიგურირეთ როგორ არის შევსებული მომხმარებლის ანგარიშის ველები (მაგ: ელ.ფოსტა) LDAP ანგარიშიდან (ასეთის პოვნის შემთხვევაში).
მაგალითად, {\"cn\":\"name\", \"mail\":\"email\"} აირჩევს პიროვნების წაკითხვად სახელს ატრიბუტებიდან, და მათ ელ. ფოსტას ელ.ფოსტის ველიდან. დამატებით შესაძლებელია ცვლადების გამოყენება, მაგალითად: `{ \"#{givenName} #{sn}\": \"name\", \"mail\": \"email\" } იყენებს მომხმარებლის სახელის და გვარის კომბინაციას, rocket chat-ის სახელის ველში.
ხელმისაწვდომი ველები Rocket.Chat-ში: 'სახელი', 'ელ.ფოსტა', და 'ქასთომ ველები'.", - "LDAP_Sync_User_Data_Groups": "LDAP ჯგუფების სინქრონიზაცია", - "LDAP_Sync_User_Data_Groups_AutoChannels": "LDAP ჯგუფების არხებთან ავტომატური სინქრონიზაცია", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "არხის ადმინი", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin_Description": "არხები რომლებიც ავტომატურად იქმნება და არ არსებობს სინქრონიზაციის დროს, ეს მომხმარებელი ავტომატურად გახდება ამ არხის ადმინი", - "LDAP_Sync_User_Data_Groups_AutoChannels_Description": "ჩართეთ ეს ფუნქცია რათა ავტომატურად დაამატოთ მომხმარებლები არხზე, მათი LDAP ჯგუფის საფუძველზე. თუ გსურთ ასევე ამოიღოთ მომხმარებლები არხიდან, იხილეთ ქვემოთ მოცემული პარამეტრები მომხმარებლების ავტომატური მოცილების შესახებ.", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap": "LDAP ჯგუფი Channel რუკა", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Default": "ზემოხსენებულ არხებში LDAP ჯგუფების ავტო სინქრონიზაციის ჩართვა", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Description": "LDAP ჯგუფების დატანა Rocket.Chat არხებში.
მაგ: {\"employee\":\"general\"} დაამატებს LDAP ჯგუფის ნებისმიერ მომხმარებელს ძირითად არხზე.", - "LDAP_Sync_User_Data_Groups_AutoRemove": "მომხმარებლის რომელის ავტომატური წაშლა", - "LDAP_Sync_User_Data_Groups_AutoRemove_Description": "** ყურადღება **: ამის ჩართვა ავტომატურად მოაცილებს მომხმარებელს როლს თუ ისინი არ არიან მიმაგრებული LDAP-ში! ეს მოაცილებს მხოლოდ როლებს რომლებიც ქვემოტ მომხმარებელთა მონაცემების ჯგუფშია", - "LDAP_Sync_User_Data_Groups_BaseDN": "LDAP ჯგუფიის BaseDN", - "LDAP_Sync_User_Data_Groups_BaseDN_Description": "LDAP BaseDN გამოყენებულ იქნა მომხმარებლების საძიებლად.", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels": "მომხმარებლის არხებიდან ავტომატურად წაშლა", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels_Description": "** ყურადღება **: ამის ჩართვა წაშლის ყველა მომხმარებელს არხში რომლებსაც არ აქვთ შესაბამისი LDAP ჯგუფი! გააქტიურეთ ეს ფუნქცია მხოლოდ იმ შემთხვევაში თუ ზუსტად იცით რას აკეთებთ", - "LDAP_Sync_User_Data_Groups_Filter": "მომხმარებელთა ჯგუფის ფილტრი", - "LDAP_Sync_User_Data_Groups_Filter_Description": "LDAP საძიებო ფილტრი გამოიყენება იმის შესამოწმებლად, თუ მომხმარებელი ჯგუფშია.", - "LDAP_Sync_User_Data_GroupsMap": "მომხმარებელთა მონაცემთა ჯგუფის რუკა", - "LDAP_Sync_User_Data_GroupsMap_Description": "LDAP ჯგუფების დატანა Rocket.Chat-ის მომხმარებელთა როლებზე
მაგალითად, {\"rocket-admin\":\"admin\", \"tech-support\":\"support\"} დაიტანს rocket-admin LDAP ჯგუფს Rocket's-ის ადმინის როლად", - "LDAP_Test_Connection": "კავშირის შემოწმება", + "LDAP_Sync_User_Data_Roles": "LDAP ჯგუფების სინქრონიზაცია", + "LDAP_Sync_User_Data_Channels": "LDAP ჯგუფების არხებთან ავტომატური სინქრონიზაცია", + "LDAP_Sync_User_Data_Channels_Admin": "არხის ადმინი", + "LDAP_Sync_User_Data_Channels_Admin_Description": "არხები რომლებიც ავტომატურად იქმნება და არ არსებობს სინქრონიზაციის დროს, ეს მომხმარებელი ავტომატურად გახდება ამ არხის ადმინი", + "LDAP_Sync_User_Data_Channels_BaseDN": "LDAP ჯგუფიის BaseDN", + "LDAP_Sync_User_Data_Channels_BaseDN_Description": "LDAP BaseDN გამოყენებულ იქნა მომხმარებლების საძიებლად.", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels": "მომხმარებლის არხებიდან ავტომატურად წაშლა", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels_Description": "** ყურადღება **: ამის ჩართვა წაშლის ყველა მომხმარებელს არხში რომლებსაც არ აქვთ შესაბამისი LDAP ჯგუფი! გააქტიურეთ ეს ფუნქცია მხოლოდ იმ შემთხვევაში თუ ზუსტად იცით რას აკეთებთ", + "LDAP_Sync_User_Data_Channels_Filter": "მომხმარებელთა ჯგუფის ფილტრი", + "LDAP_Sync_User_Data_Channels_Filter_Description": "LDAP საძიებო ფილტრი გამოიყენება იმის შესამოწმებლად, თუ მომხმარებელი ჯგუფშია.", + "LDAP_Sync_User_Data_Channels_Description": "ჩართეთ ეს ფუნქცია რათა ავტომატურად დაამატოთ მომხმარებლები არხზე, მათი LDAP ჯგუფის საფუძველზე. თუ გსურთ ასევე ამოიღოთ მომხმარებლები არხიდან, იხილეთ ქვემოთ მოცემული პარამეტრები მომხმარებლების ავტომატური მოცილების შესახებ.", + "LDAP_Sync_User_Data_ChannelsMap": "LDAP ჯგუფი Channel რუკა", + "LDAP_Sync_User_Data_ChannelsMap_Default": "ზემოხსენებულ არხებში LDAP ჯგუფების ავტო სინქრონიზაციის ჩართვა", + "LDAP_Sync_User_Data_ChannelsMap_Description": "LDAP ჯგუფების დატანა Rocket.Chat არხებში.
მაგ: {\"employee\":\"general\"} დაამატებს LDAP ჯგუფის ნებისმიერ მომხმარებელს ძირითად არხზე.", + "LDAP_Sync_User_Data_Roles_AutoRemove": "მომხმარებლის რომელის ავტომატური წაშლა", + "LDAP_Sync_User_Data_Roles_AutoRemove_Description": "** ყურადღება **: ამის ჩართვა ავტომატურად მოაცილებს მომხმარებელს როლს თუ ისინი არ არიან მიმაგრებული LDAP-ში! ეს მოაცილებს მხოლოდ როლებს რომლებიც ქვემოტ მომხმარებელთა მონაცემების ჯგუფშია", + "LDAP_Sync_User_Data_Roles_BaseDN": "LDAP ჯგუფიის BaseDN", + "LDAP_Sync_User_Data_Roles_BaseDN_Description": "LDAP BaseDN გამოყენებულ იქნა მომხმარებლების საძიებლად.", + "LDAP_Sync_User_Data_Roles_Filter": "მომხმარებელთა ჯგუფის ფილტრი", + "LDAP_Sync_User_Data_Roles_Filter_Description": "LDAP საძიებო ფილტრი გამოიყენება იმის შესამოწმებლად, თუ მომხმარებელი ჯგუფშია.", + "LDAP_Sync_User_Data_RolesMap": "მომხმარებელთა მონაცემთა ჯგუფის რუკა", + "LDAP_Sync_User_Data_RolesMap_Description": "LDAP ჯგუფების დატანა Rocket.Chat-ის მომხმარებელთა როლებზე
მაგალითად, {\"rocket-admin\":\"admin\", \"tech-support\":\"support\"} დაიტანს rocket-admin LDAP ჯგუფს Rocket's-ის ადმინის როლად", "LDAP_Timeout": "ტაიმაუტი (მილიწამები)", "LDAP_Timeout_Description": "რამდენი მილიწამი დაელოდოს ძიების შედეგს სანამ შეცდომას დააბრუნებს", "LDAP_Unique_Identifier_Field": "უნიკალური საიდენტიფიკაციო ველი", @@ -2127,8 +2118,6 @@ "LDAP_User_Search_Scope": "სფერო", "LDAP_Username_Field": "მომხმარებლის სახელის ველი", "LDAP_Validate_Teams_For_Each_Login": "მიბმის დადასტურება თითოეული შესვლისთვის", - "LDAP_Validate_Roles_For_Each_Login": "მიბმის დადასტურება თითოეული შესვლისთვის", - "LDAP_Validate_Roles_For_Each_Login_Description": "თუ დადასტურება უნდა მოხდეს თითოეული შესვლისთვის (ფრთხილად იყავით ამ პარამეტრთან, რადგან ის გადაწერს მომხმარებლის როლებს ყოველი შესვლისას, წინააღმდეგ შემთხვევაში, ეს შემოწმდება მხოლოდ მომხმარებლის შექმნის მომენტში).", "Leave": "დატოვე", "Leave_a_comment": "დატოვე კომენტარი", "Leave_Group_Warning": "დარწმუნებული ხართ, რომ გსურთ დატოვოთ ჯგუფი \"%s\"?", diff --git a/packages/rocketchat-i18n/i18n/km.i18n.json b/packages/rocketchat-i18n/i18n/km.i18n.json index 073d83cadea0..c5c74ddadaa8 100644 --- a/packages/rocketchat-i18n/i18n/km.i18n.json +++ b/packages/rocketchat-i18n/i18n/km.i18n.json @@ -1797,12 +1797,8 @@ "LDAP_Connect_Timeout": "អស់ពេលការតភ្ជាប់ (ms)", "LDAP_Default_Domain": "ដែនលំនាំដើម", "LDAP_Default_Domain_Description": "ប្រសិនបើបានបញ្ចូល Default Domain នោះវានឹងត្រូវបានប្រើប្រាស់ ដើម្បីបង្កើតអ៊ីមែលតែ១គត់ សម្រាប់អ្នកប្រើប្រាស់ទាំងអស់ ដែលអ៊ីមែលនោះមិនមែននាំចូលពី LDAP។ អ៊ីមែលនឹងត្រូវបានភ្ជាប់ជា `username@default_domain` or `unique_id@default_domain`។
ឧទាហរណ៍៖ `rocket.chat`", - "LDAP_Default_Role_To_User": "តួនាទីលំនាំដើមសម្រាប់អ្នកប្រើប្រាស់", - "LDAP_Default_Role_To_User_Description": "តួនាទី RC លំនាំដើមដែលត្រូវអនុវត្តចំពោះអ្នកប្រើប្រាស់ប្រសិនបើអ្នកប្រើប្រាស់មានតួនាទី LDAP មួយចំនួនដែលមិនត្រូវបានគូស។", - "LDAP_Description": "LDAP គឺជាលំដាប់ក្នុងទូផ្ទុកទិន្នន័យដែលផ្ទុកព័ត៌មានក្រុមហ៊ុនជាច្រើនដែលប្រើប្រាស់ដើម្បីធ្វើការ Authentication ដោយប្រើប្រាស់ Username និង Password រវាង Site ជាច្រើន និងសេវាកម្មផ្សេងៗ។ ព័ត៌មានអំពីការកំណត់កម្រិតខ្ពស់ និងឧទាហរណ៍សូមចូលទៅកាន់វីគី https://rocket.chat/docs/administrator-guides/authentication/ldap/", "LDAP_Enable": "អនុញ្ញាតិ LDAP", "LDAP_Enable_Description": "ព្យាយាមប្រើប្រាស់ LDAP ក្នុងការផ្ទៀងផ្ទាត់គណនី", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "បើកដំណើរការគូសផែនទីពី LDAP ទៅ Rocket.Chat", "LDAP_Encryption": "ការអ៊ីនគ្រីប", "LDAP_Encryption_Description": "វិធីសាស្រ្តក្នុងការអ៊ិនគ្រីបបានប្រើដើម្បីទទួលបានទំនាក់ទំនងទៅកាន់ម៉ាស៊ីនបម្រើ LDAP ។ ឧទហរណ៍រួមបញ្ចូលទាំងការ `plain` (ការអ៊ិនគ្រីបទេ): SSL / LDAPS` (ដែលបានអ៊ិនគ្រីបពីចាប់ផ្តើម) និង` StartTLS` (ធ្វើឱ្យប្រសើរឡើងទំនាក់ទំនងដែលបានអ៊ិនគ្រីបបានភ្ជាប់ម្តង) ។", "LDAP_Find_User_After_Login": "ស្វែងរកអ្នកប្រើបន្ទាប់ពីចូល", @@ -1831,15 +1827,11 @@ "LDAP_Merge_Existing_Users_Description": "* ការប្រុងប្រយ័ត្ន! * នៅពេលដែលនាំចូលអ្នកប្រើប្រាស់ពី LDAP និងអ្នកប្រើដែលមានឈ្មោះអ្នកប្រើដូចគ្នារួចហើយព័ត៌មាន LDAP និងពាក្យសម្ងាត់នឹងត្រូវបានកំណត់ទៅក្នុងអ្នកប្រើប្រាស់ដែលមានស្រាប់។", "LDAP_Port": "ច្រក LDAP", "LDAP_Port_Description": "ផែដើម្បីចូលទៅកាន់ LDAP ត្រង់លេខ; ឧទាហរណ៍៖ 389 ", - "LDAP_Query_To_Get_User_Groups": "សំណួរ LDAP ដើម្បីទទួលបានក្រុមអ្នកប្រើប្រាស់", - "LDAP_Query_To_Get_User_Groups_Description": "សំណួរអិលឌីភីដើម្បីទទួលបានក្រុមអិល។ ឌី។ ភី។ ដែលអ្នកប្រើជាសមាជិក។", "LDAP_Query_To_Get_User_Teams": "សំណួរ LDAP ដើម្បីទទួលបានក្រុមអ្នកប្រើប្រាស់", "LDAP_Reconnect": "ភ្ជាប់ឡើងវិញ", "LDAP_Reconnect_Description": "ព្យាយាមភ្ជាប់ឡើងវិញដោយស្វ័យប្រវត្តិនៅពេលការភ្ជាប់ត្រូវបានរំខានដោយមូលហេតុខ្លះនៅពេលកំពុងប្រតិបត្តិការ", "LDAP_Reject_Unauthorized": "បដិសេធចោលដោយគ្មានការអនុញ្ញាត", "LDAP_Reject_Unauthorized_Description": "បិទជម្រើសនេះដើម្បីអនុញ្ញាតវិញ្ញាបនប័ត្រដែលមិនអាចផ្ទៀងផ្ទាត់បាន។ ជាទូទៅវិញ្ញាបនបត្រចុះហត្ថលេខាផ្ទាល់ខ្លួននឹងតម្រូវឱ្យជម្រើសនេះត្រូវបានបិទដំណើរការ", - "LDAP_Roles_To_Rocket_Chat_Roles": "ការគូសផែនទីពីតួនាទីពីអិល។ ឌី។ អេ។ ទៅរ៉ក់ឌឺ។", - "LDAP_Roles_To_Rocket_Chat_Roles_Description": "ការគូសផែនទីតួនាទីជាទ្រង់ទ្រាយវត្ថុដែលកូនសោវត្ថុត្រូវតែជាតួនាទីរបស់ LDAP ហើយតម្លៃវត្ថុត្រូវតែជាតួនាទីរបស់ RC ។ ឧទាហរណ៍ៈ { 'ldapRole': ['rcRole', 'anotherRCRole'] }", "LDAP_Search_Page_Size": "ស្វែងរកទំហំទំព័រ", "LDAP_Search_Page_Size_Description": "ចំនួនធាតុអតិបរមានៃទំព័រលទ្ធផលនីមួយៗនឹងត្រូវត្រលប់មកវិញ", "LDAP_Search_Size_Limit": "ស្វែងរកទំហំកំណត់", @@ -1847,11 +1839,6 @@ "LDAP_Sync_Now": "ធ្វើសមកាលកម្មផ្ទៃខាងក្រោយឥឡូវនេះ", "LDAP_Sync_Now_Description": "នឹងអនុវត្ត ** ផ្ទៃខាងក្រោយសមកាលកម្ម ** ឥឡូវនេះជាជាងរង់ចាំ ** ចន្លោះពេលសមកាលកម្ម ** ទោះបី ** ផ្ទៃខាងក្រោយសមូហភាព ** មិនពិត។
សកម្មភាពនេះមិនសមកាលកម្មសូមមើលកំណត់ហេតុសម្រាប់ព័ត៌មានបន្ថែមអំពី ដំណើរការ", "LDAP_Sync_User_Avatar": "ធ្វើសមកាលកម្ម Avatar របស់អ្នកប្រើប្រាស់", - "LDAP_Sync_User_Data": "រក្សាទិន្នន័យ User ដោយ Sync ជាមួយ Server", - "LDAP_Sync_User_Data_Description": "រក្សាទិន្នន័យអ្នកប្រើប្រាស់ក្នុងការ Sync ជាមួយម៉ាស៊ីនមេក្នុងការ Login (eg: name, email)។", - "LDAP_Sync_User_Data_FieldMap": "ចំណុចចងភ្ជាប់ទិន្នន័យអ្នកប្រើប្រាស់", - "LDAP_Sync_User_Data_FieldMap_Description": "ការកំណត់ចន្លោះគណនីអ្នកប្រើប្រាស់ (ដូចជាអ៊ីមែល) គឺត្រូវបានទាញទិន្នន័យចេញពី LDAP (ពេលដែលរកឃើញ)។
ឧទាហរណ៍៖ `{\"cn\":\"ឈ្មោះ\", \"mail\":\"អ៊ីមែល\"}` នឹងត្រូវបានជ្រើសយកឈ្មោះមនុស្សពីធាតុ cn ហើយអ៊ីមែលរបស់ពួកគេទាញចេញពីធាតុ email។
ចន្លោះទំនេររាប់បញ្ចូលទាំង `ឈ្មោះ` និង `អ៊ីមែល`។", - "LDAP_Test_Connection": "សាកល្បងការតភ្ជាប់", "LDAP_Timeout": "អស់ពេល (នាទី)", "LDAP_Timeout_Description": "តើប៉ុន្មានវិនាទីរង់ចាំលទ្ធផលស្វែងរកមុនពេលត្រឡប់កំហុស", "LDAP_Unique_Identifier_Field": "មានតែមួយគត់សម្គាល់វាល", @@ -1864,8 +1851,6 @@ "LDAP_Username_Field": "ឈ្មោះអ្នកប្រើវាល", "LDAP_Username_Field_Description": "វាលនេះដែលនឹងត្រូវបានប្រើជា * សម្រាប់អ្នកប្រើឈ្មោះអ្នកប្រើ * ថ្មី។ ទុកឱ្យទទេដើម្បីប្រើឈ្មោះអ្នកប្រើដែលបានជូនដំណឹងនៅលើទំព័រចូល។
អ្នកអាចប្រើស្លាកពុម្ពផងដែរ, ដូចជា `#{givenName}.#{sn}` ។
តម្លៃលំនាំដើមគឺ `sAMAccountName` ។", "LDAP_Validate_Teams_For_Each_Login": "ធ្វើឱ្យផែនទីមានសុពលភាពសម្រាប់ការចូលនីមួយៗ", - "LDAP_Validate_Roles_For_Each_Login": "ធ្វើឱ្យផែនទីមានសុពលភាពសម្រាប់ការចូលនីមួយៗ", - "LDAP_Validate_Roles_For_Each_Login_Description": "ប្រសិនបើសុពលភាពគួរតែកើតឡើងសម្រាប់រាល់ការចូល (សូមប្រយ័ត្នជាមួយការកំណត់នេះព្រោះវានឹងសរសេរជាន់តួនាទីអ្នកប្រើក្នុងការចូលនីមួយៗបើមិនដូច្នេះទេវានឹងមានសុពលភាពតែនៅពេលបង្កើតអ្នកប្រើ) ។", "Lead_capture_email_regex": "នាំយកអ៊ីមែល regex", "Lead_capture_phone_regex": "នាំយកការហៅទូរស័ព្ទ regex", "Leave": "ចេញ​ពីបន្ទប់", diff --git a/packages/rocketchat-i18n/i18n/ko.i18n.json b/packages/rocketchat-i18n/i18n/ko.i18n.json index 73582fd9d736..9cf43169fd05 100644 --- a/packages/rocketchat-i18n/i18n/ko.i18n.json +++ b/packages/rocketchat-i18n/i18n/ko.i18n.json @@ -2208,12 +2208,8 @@ "LDAP_Connect_Timeout": "연결 시간 초과 (밀리 초)", "LDAP_Default_Domain": "기본 도메인", "LDAP_Default_Domain_Description": "제공되는 경우 기본 도메인은 LDAP에서 전자 메일을 가져 오지 않은 사용자의 고유 한 전자 메일을 만드는 데 사용됩니다. 전자 메일은`username @ default_domain` 또는`unique_id @ default_domain`으로 마운트됩니다.
예 :`rocket.chat`", - "LDAP_Default_Role_To_User": "사용자의 기본 역할", - "LDAP_Default_Role_To_User_Description": "사용자에게 매핑되지 않은 LDAP 역할이 있는 경우, 사용자에게 적용 되는 기본 RC역할.", - "LDAP_Description": "LDAP는 많은 기업들이 SSO을 제공하기 위해 사용하는 계층적인 데이터베이스입니다. 여러 사이트와 서비스 간에 하나의 비밀번호를 공유하기 위한 기능입니다. 자세한 정보는 위키를 참고하세요: https://github.com/RocketChat/Rocket.Chat/wiki/LDAP", "LDAP_Enable": "LDAP 사용", "LDAP_Enable_Description": "인증을 위해 LDAP를 사용하려고 합니다.", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "LDAP에서 Rocket으로 역할 맵핑 사용", "LDAP_Encryption": "암호화", "LDAP_Encryption_Description": "LDAP 서버 통신을 보호하는 데사용되는 암호화 방법. 예를 들면`plain`(암호화없음), `SSL/LDAPS`(시작부터 암호화됨), 그리고`StartTLS`(연결되면 암호화 통신으로 업그레이드) 등이 있습니다.", "LDAP_Find_User_After_Login": "로그인 후 사용자 찾기", @@ -2242,15 +2238,11 @@ "LDAP_Merge_Existing_Users_Description": "*주의! * LDAP에서 사용자를 가져올 때 동일한 사용자명을 가진 사용자가 이미 존재하면 LDAP 정보와 암호가 기존 사용자로 설정됩니다.", "LDAP_Port": "LDAP 포트", "LDAP_Port_Description": "LDAP에 액세스하기위한 포트. 예) LDAPS의 경우 `389` 또는 `636`", - "LDAP_Query_To_Get_User_Groups": "사용자 그룹을 가져오기 위한 LDAP 쿼리", - "LDAP_Query_To_Get_User_Groups_Description": "사용자가 속한 LDAP 그룹을 가져오기 위한 LDAP 쿼리.", "LDAP_Query_To_Get_User_Teams": "사용자 그룹을 가져오기 위한 LDAP 쿼리", "LDAP_Reconnect": "다시 연결", "LDAP_Reconnect_Description": "작업을 실행하는 동안 어떤 이유로 연결이 중단되면 자동으로 다시 연결을 시도하십시오.", "LDAP_Reject_Unauthorized": "미인증 거부", "LDAP_Reject_Unauthorized_Description": "확인할 수없는 인증서를 허용하려면이 옵션을 사용중지하십시오. 일반적으로 자체 서명 인증서를 사용하려면이 옵션을 사용하지 않도록 설정해야합니다.", - "LDAP_Roles_To_Rocket_Chat_Roles": "LDAP에서 Rocket.Chat으로 역할 맵핑", - "LDAP_Roles_To_Rocket_Chat_Roles_Description": "오브젝트 키가 LDAP 역할이고 오브젝트 값이 RC 역할의 배열이어야하는 오브젝트 형식의 역할 맵핑. 예 : { 'ldapRole': ['rcRole', 'anotherRCRole'] }", "LDAP_Search_Page_Size": "검색 페이지 크기", "LDAP_Search_Page_Size_Description": "각 결과 페이지가 처리되기 위해 반환 할 최대 항목 수", "LDAP_Search_Size_Limit": "검색 크기 제한", @@ -2263,29 +2255,28 @@ "LDAP_Sync_User_Active_State_Disable": "사용자 비활성화", "LDAP_Sync_User_Active_State_Nothing": "없음", "LDAP_Sync_User_Avatar": "사용자 아바타 동기화", - "LDAP_Sync_User_Data": "데이터 동기화", - "LDAP_Sync_User_Data_Description": "**로그인** 또는 **백그라운드 동기화** (예 : 이름, 이메일)로 서버와 사용자 데이터를 동기화하십시오.", - "LDAP_Sync_User_Data_FieldMap": "사용자 데이터 필드 맵", - "LDAP_Sync_User_Data_FieldMap_Description": "LDAP와 같은 사용자 계정 필드(예 : 이메일)가 LDAP의 레코드에서 채워지는 방식을 구성합니다.
예를 들어`{\"cn\":\"name\", \"mail\": \"email\"}` cn 속성은 사람이 읽을 수 있는 이름과 mail 속성은 이메일을 선택합니다. `{ \"#{givenName} #{sn}\":\"name\", \"mail\":\"email\"}` Rocket.Chat의 `name`에서 사용자의 이름과 성을 나누어 사용.
Rocket.Chat에서 사용할 수 있는 필드 :`name`,`email` 및`customFields`.", - "LDAP_Sync_User_Data_Groups": "LDAP 그룹 동기화", - "LDAP_Sync_User_Data_Groups_AutoChannels": "Channel 에 LDAP 그룹 자동 동기화", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "Channel 관리자", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin_Description": "동기화 중에 존재하지 않는 채널이 자동 생성되면이 사용자는 자동으로 채널의 관리자가됩니다.", - "LDAP_Sync_User_Data_Groups_AutoChannels_Description": "LDAP 그룹을 기반으로 사용자를 채널에 자동으로 추가하려면이 기능을 사용하십시오. 채널에서 사용자를 제거하려면 사용자 자동 제거에 대한 아래 옵션을 참조하십시오.", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap": "LDAP 그룹 Channel 배치", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Default": "// 위의 Channel에 LDAP 그룹 자동 동기화를 사용하도록 설정", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Description": "LDAP 그룹을 Rocket.Chat 채널에 맵핑하십시오.
예를 들어, [{\"employee\":\"general\"}`은 LDAP 그룹 직원의 모든 사용자를 일반 채널에 추가합니다.", - "LDAP_Sync_User_Data_Groups_AutoRemove": "사용자 역할 자동 제거", - "LDAP_Sync_User_Data_Groups_AutoRemove_Description": "**주의 ** :이 기능을 활성화하면 사용자가 LDAP에 할당되지 않은 경우 역할에서 자동으로 제거됩니다! 아래의 사용자 데이터 그룹 배치에서 설정된 역할만 자동으로 제거됩니다.", - "LDAP_Sync_User_Data_Groups_BaseDN": "LDAP 그룹 BaseDN", - "LDAP_Sync_User_Data_Groups_BaseDN_Description": "사용자를 찾는 데 사용되는 LDAP BaseDN입니다.", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels": "Channel 에서 사용자 자동 제거", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels_Description": "**주의 ** : 이 기능을 활성화하면 LDAP 그룹이 없는 채널의 모든 사용자가 제거됩니다! 수행중인 작업을 확인하고 기능을 활성화하십시오.", - "LDAP_Sync_User_Data_Groups_Filter": "사용자 그룹 필터", - "LDAP_Sync_User_Data_Groups_Filter_Description": "사용자가 그룹에 존재하는지 확인하는 데 사용되는 LDAP 검색 필터입니다.", - "LDAP_Sync_User_Data_GroupsMap": "사용자 데이터 그룹 배치", - "LDAP_Sync_User_Data_GroupsMap_Description": "LDAP 그룹을 Rocket에 매핑합니다. 채팅 사용자 역할
예를 들어, [{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}`은 rocket-admin LDAP 그룹을 Rocket의 \"admin\"역할에 매핑합니다.", - "LDAP_Test_Connection": "연결 테스트", + "LDAP_Sync_User_Data_Roles": "LDAP 그룹 동기화", + "LDAP_Sync_User_Data_Channels": "Channel 에 LDAP 그룹 자동 동기화", + "LDAP_Sync_User_Data_Channels_Admin": "Channel 관리자", + "LDAP_Sync_User_Data_Channels_Admin_Description": "동기화 중에 존재하지 않는 채널이 자동 생성되면이 사용자는 자동으로 채널의 관리자가됩니다.", + "LDAP_Sync_User_Data_Channels_BaseDN": "LDAP 그룹 BaseDN", + "LDAP_Sync_User_Data_Channels_BaseDN_Description": "사용자를 찾는 데 사용되는 LDAP BaseDN입니다.", + "LDAP_Sync_User_Data_Channels_Description": "LDAP 그룹을 기반으로 사용자를 채널에 자동으로 추가하려면이 기능을 사용하십시오. 채널에서 사용자를 제거하려면 사용자 자동 제거에 대한 아래 옵션을 참조하십시오.", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels": "Channel 에서 사용자 자동 제거", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels_Description": "**주의 ** : 이 기능을 활성화하면 LDAP 그룹이 없는 채널의 모든 사용자가 제거됩니다! 수행중인 작업을 확인하고 기능을 활성화하십시오.", + "LDAP_Sync_User_Data_Channels_Filter": "사용자 그룹 필터", + "LDAP_Sync_User_Data_Channels_Filter_Description": "사용자가 그룹에 존재하는지 확인하는 데 사용되는 LDAP 검색 필터입니다.", + "LDAP_Sync_User_Data_ChannelsMap": "LDAP 그룹 Channel 배치", + "LDAP_Sync_User_Data_ChannelsMap_Default": "// 위의 Channel에 LDAP 그룹 자동 동기화를 사용하도록 설정", + "LDAP_Sync_User_Data_ChannelsMap_Description": "LDAP 그룹을 Rocket.Chat 채널에 맵핑하십시오.
예를 들어, [{\"employee\":\"general\"}`은 LDAP 그룹 직원의 모든 사용자를 일반 채널에 추가합니다.", + "LDAP_Sync_User_Data_Roles_AutoRemove": "사용자 역할 자동 제거", + "LDAP_Sync_User_Data_Roles_AutoRemove_Description": "**주의 ** :이 기능을 활성화하면 사용자가 LDAP에 할당되지 않은 경우 역할에서 자동으로 제거됩니다! 아래의 사용자 데이터 그룹 배치에서 설정된 역할만 자동으로 제거됩니다.", + "LDAP_Sync_User_Data_Roles_BaseDN": "LDAP 그룹 BaseDN", + "LDAP_Sync_User_Data_Roles_BaseDN_Description": "사용자를 찾는 데 사용되는 LDAP BaseDN입니다.", + "LDAP_Sync_User_Data_Roles_Filter": "사용자 그룹 필터", + "LDAP_Sync_User_Data_Roles_Filter_Description": "사용자가 그룹에 존재하는지 확인하는 데 사용되는 LDAP 검색 필터입니다.", + "LDAP_Sync_User_Data_RolesMap": "사용자 데이터 그룹 배치", + "LDAP_Sync_User_Data_RolesMap_Description": "LDAP 그룹을 Rocket에 매핑합니다. 채팅 사용자 역할
예를 들어, [{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}`은 rocket-admin LDAP 그룹을 Rocket의 \"admin\"역할에 매핑합니다.", "LDAP_Timeout": "제한 시간 (밀리 초)", "LDAP_Timeout_Description": "오류를 반환하기 전에 검색 결과를 기다리는 시간 (mileeconds)", "LDAP_Unique_Identifier_Field": "고유 식별자 필드", @@ -2298,8 +2289,6 @@ "LDAP_Username_Field": "사용자명 필드", "LDAP_Username_Field_Description": "어떤 필드는 새로운 사용자를 위해 *사용자명*으로 사용될 것입니다. 로그인 페이지에서 입력된 사용자명을 사용하려면 비워 두세요.
'#{givenName}.#{sn}'처럼 템플릿 태그도 사용할 수 있습니다.
기본값은 'sAMAccountName'입니다.", "LDAP_Validate_Teams_For_Each_Login": "각 로그인에 대한 매핑 확인", - "LDAP_Validate_Roles_For_Each_Login": "각 로그인에 대한 매핑 확인", - "LDAP_Validate_Roles_For_Each_Login_Description": "각 로그인에 대해 유효성 검사가 수행되어야하는 경우 (이 설정은 각 로그인에서 사용자 역할을 덮어 쓰므로 주의해야합니다. 그렇지 않으면 사용자 생성 시점에서만 유효성이 검사됩니다).", "Lead_capture_email_regex": "리드 캡쳐 이메일 정규식", "Lead_capture_phone_regex": "리드 캡처 전화 정규식", "Leave": "나가기", diff --git a/packages/rocketchat-i18n/i18n/ku.i18n.json b/packages/rocketchat-i18n/i18n/ku.i18n.json index 17b8413ca50a..aed896fec590 100644 --- a/packages/rocketchat-i18n/i18n/ku.i18n.json +++ b/packages/rocketchat-i18n/i18n/ku.i18n.json @@ -1512,7 +1512,6 @@ "LDAP_Connect_Timeout": "Connection Timeout (ms)", "LDAP_Default_Domain": "Default Domain", "LDAP_Default_Domain_Description": "Ger pêşkêşî Default Domain dê ji bo bikarhênerên ku e-mail ji LDAP ve nehatiye veguhestin an e-nameyek taybet ava bikin. E-nameyê wekî navê bikarhêner 'default_domain` or `unique_id @ default_domain`.
mînak:` rocket.chat`", - "LDAP_Description": "hesanîyekî ji bo parvekirina yek nasnavê di navbera sites û xizmetên piralî - LDAP a nav HTMLê da heye hiyerarşîk ku gelek kompaniyên bi kar ji bo ne yek nîşanek li ser e. https://rocket.chat/docs/administrator-guides/authentication/ldap/: Ji bo agahiyên Mîhengên pêşketî û wergerandî, ji kerema xwe ve wiki me bişêwirin.", "LDAP_Enable": "Bikêrkirin", "LDAP_Enable_Description": "Hewldana ji bo dozeke LDAP bo piştrastkirinê.", "LDAP_Encryption": "Şîfrekirin,", @@ -1554,11 +1553,6 @@ "LDAP_Sync_Now": "Syngra Now Now", "LDAP_Sync_Now_Description": "Ma dê li benda dora ** Dema ku li benda benda bisekine, ji hêla sibê ve bikişîne ** bêtir li benda * Navnîşa Navneteweyî ** heger ** Navnîşa paşdewletî * Nehat e.
Ev çalakiyek asynchronous e, ji kerema xwe re bêtir agahdariyên der barê agahdariyên li ser doz", "LDAP_Sync_User_Avatar": "Syncê User Avatar", - "LDAP_Sync_User_Data": "Syncê Data", - "LDAP_Sync_User_Data_Description": "Keep welat user di synchê bi server li ser login (wek nimûne: name, email).", - "LDAP_Sync_User_Data_FieldMap": "Bikarhêner Data Map Field", - "LDAP_Sync_User_Data_FieldMap_Description": "Mîheng bikî ka zeviyên Hesabê bikarhêner (wek email) bi ji qeyda li LDAP dijîn (cih).
Wek nimûne, `{\" cn \":\" name \",\" mail \":\" email \"}` ê bi navê mirovekî mirovan xwendin ji bikarbar cn, û email xwe ji taybetiyê mail hilbijêre.
zeviyên Available de `name`, û` email`.", - "LDAP_Test_Connection": "Connection test", "LDAP_Timeout": "Timeout (ms)", "LDAP_Timeout_Description": "Berî ku çend xerîbên ji bo vegerandina çewtiya encama lêgerînê digerin", "LDAP_Unique_Identifier_Field": "Krom Field", diff --git a/packages/rocketchat-i18n/i18n/lo.i18n.json b/packages/rocketchat-i18n/i18n/lo.i18n.json index 1c46aca23191..a5b34e23e3f6 100644 --- a/packages/rocketchat-i18n/i18n/lo.i18n.json +++ b/packages/rocketchat-i18n/i18n/lo.i18n.json @@ -1553,12 +1553,8 @@ "LDAP_Connect_Timeout": "ເວລາການເຊື່ອມຕໍ່ (ms)", "LDAP_Default_Domain": "Domain ມາດຕະຖານ", "LDAP_Default_Domain_Description": "ຖ້າສະຫນອງໃຫ້ Domain Default ຈະຖືກນໍາໃຊ້ເພື່ອສ້າງອີເມວເປັນເອກະລັກສໍາລັບຜູ້ໃຊ້ທີ່ອີເມວບໍ່ຖືກນໍາເຂົ້າຈາກ LDAP. ອີເມວຈະຖືກຕິດຕັ້ງເປັນ `ຊື່ຜູ້ໃຊ້ @ default_domain 'ຫຼື` unique_id @ default_domain `.
ຕົວຢ່າງ:` rocket.chat `", - "LDAP_Default_Role_To_User": "ຄ່າເລີ່ມຕົ້ນຂອງຜູ້ໃຊ້", - "LDAP_Default_Role_To_User_Description": "ຄ່າເລີ່ມຕົ້ນສິດທິຂອງ RC ທີ່ຈະໃຊ້ກັບຜູ້ໃຊ້ ຖ້າຜຸ້ໃຊ້ມີສິດທິ LDAP ບາງຕົວທີ່ບໍ່ຖືກລວມເຂົ້າກັນ", - "LDAP_Description": "LDAP ເປັນຖານຂໍ້ມູນລໍາດັບຊັ້ນທີ່ຫຼາຍບໍລິສັດນໍາໃຊ້ເພື່ອສະຫນອງການເຂົ້າສູ່ລະບົບໃນ - ສະຖານທີ່ສໍາລັບການແລກປ່ຽນລະຫັດຜ່ານຫນຶ່ງລະຫວ່າງສະຖານທີ່ແລະບໍລິການທີ່ຫຼາກຫຼາຍ. ສໍາລັບຂໍ້ມູນການຕັ້ງຄ່າຂັ້ນສູງແລະຕົວຢ່າງ, ກະລຸນາປືກສາຫາລື wiki ຂອງພວກເຮົາ: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "ເຮັດໃຫ້ສາມາດ", "LDAP_Enable_Description": "ພະຍາຍາມທີ່ຈະນໍາໃຊ້ LDAP ສໍາລັບການກວດສອບ.", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "ເປີດການໃຊ້ງານບົດບາດການເຊື່ອມເຂົ້າກັນຈາກ LDAP ໄປຍັງ Rocket.Chat", "LDAP_Encryption": "ການເຂົ້າລະຫັດ", "LDAP_Encryption_Description": "ວິທີການເຂົ້າລະຫັດທີ່ໃຊ້ໃນການຮັບປະກັນການສື່ສານກັບເຄື່ອງແມ່ຂ່າຍຂອງ LDAP. ຕົວຢ່າງລວມມີ `plain` (ບໍ່ມີການເຂົ້າລະຫັດ),` SSL / LDAPS` (ການເຂົ້າລະຫັດຈາກການເລີ່ມຕົ້ນ), ແລະ `StartTLS` (ຍົກລະດັບການສື່ສານເຂົ້າລະຫັດເຊື່ອມຕໍ່ດຽວ).", "LDAP_Find_User_After_Login": "ຊອກຫາຜູ້ໃຊ້ຫຼັງຈາກເຂົ້າສູ່ລະບົບ", @@ -1598,11 +1594,6 @@ "LDAP_Sync_Now": "Background Sync Now", "LDAP_Sync_Now_Description": "ຈະປະຕິບັດ ** Background Sync ** ໃນປັດຈຸບັນແທນທີ່ຈະລໍຖ້າ ** Sync Interval ** ເຖິງແມ່ນວ່າ ** Background Sync ** ແມ່ນບໍ່ຖືກຕ້ອງ.
ປະຕິບັດງານນີ້ແມ່ນບໍ່ຖືກຕ້ອງ, ກະລຸນາເບິ່ງບັນທຶກສໍາລັບຂໍ້ມູນເພີ່ມເຕີມກ່ຽວກັບ ຂະບວນການ", "LDAP_Sync_User_Avatar": "Sync User Avatar", - "LDAP_Sync_User_Data": "Sync ຂໍ້ມູນ", - "LDAP_Sync_User_Data_Description": "ໃຫ້ເກັບຮັກສາຂໍ້ມູນຜູ້ໃຊ້ໃນ sync ກັບເຄື່ອງແມ່ຂ່າຍຂອງກ່ຽວກັບການເຂົ້າສູ່ລະບົບ (ເຊັ່ນ: ຊື່, ອີເມວ).", - "LDAP_Sync_User_Data_FieldMap": "ຜູ້ໃຊ້ຂໍ້ມູນພາກສະຫນາມແຜນທີ່", - "LDAP_Sync_User_Data_FieldMap_Description": "ກໍາຫນົດຄ່າວິທີຂົງເຂດບັນຊີຜູ້ໃຊ້ (ເຊັ່ນ: ອີ) ມີປະຊາກອນຈາກການບັນທຶກໃນ LDAP ເປັນ (ພົບເທື່ອດຽວ).
ໃນຖານະເປັນຕົວຢ່າງ, `{\" cn \":\" ຊື່ \",\" ຈົດຫມາຍ \":\" ອີເມລ໌ \"}` ຈະເລືອກເອົາຊື່ຂອງບຸກຄົນມະນຸດສາມາດອ່ານໄດ້ຈາກ cn ເຫດຜົນ, ແລະອີເມລຂອງເຂົາເຈົ້າຈາກເຫດຜົນ mail ໄດ້.
ທົ່ງນາທີ່ມີປະກອບມີ `name`, ແລະ` email`.", - "LDAP_Test_Connection": "ການເຊື່ອມຕໍ່ການທົດສອບ", "LDAP_Timeout": "ເວລາ (ms)", "LDAP_Timeout_Description": "ວິທີການຈໍານວນຫລາຍ mileseconds ລໍຖ້າສໍາລັບຜົນການຄົ້ນຫາກ່ອນທີ່ຈະກັບຄືນຂໍ້ຜິດພາດ", "LDAP_Unique_Identifier_Field": "ເປັນເອກະລັກ Identifier ພາກສະຫນາມ", diff --git a/packages/rocketchat-i18n/i18n/lt.i18n.json b/packages/rocketchat-i18n/i18n/lt.i18n.json index ed431f00e741..2c2426be1a3a 100644 --- a/packages/rocketchat-i18n/i18n/lt.i18n.json +++ b/packages/rocketchat-i18n/i18n/lt.i18n.json @@ -1519,7 +1519,6 @@ "LDAP_Connect_Timeout": "Prisijungimo laikas (ms)", "LDAP_Default_Domain": "Numatytasis domenas", "LDAP_Default_Domain_Description": "Jei numatytas numatytasis domenas bus naudojamas norint sukurti unikalų el. Pašto adresą naudotojams, kurių el. Paštas nebuvo importuotas iš LDAP. El. Laiškas bus pridėtas kaip \"username @ default_domain\" arba \"unique_id @ default_domain\".
Pavyzdys: `rocket.chat`", - "LDAP_Description": "LDAP yra hierarchinė duomenų bazė, kurią daugelis kompanijų naudoja vieninteliam prisijungimui - tai galimybė dalintis vienu slaptažodžiu tarp kelių svetainių ir paslaugų. Išsamesnės konfigūracijos informacijos ir pavyzdžių rasite mūsų wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Įgalinti", "LDAP_Enable_Description": "Bandymas naudoti LDAP autentifikavimui.", "LDAP_Encryption": "Šifravimas", @@ -1561,11 +1560,6 @@ "LDAP_Sync_Now": "Fono sinchronizavimas dabar", "LDAP_Sync_Now_Description": "Bus vykdoma ** Background Sync ** dabar, o ne laukti ** Sync Interval **, net jei ** Background Sync ** yra klaidinga.
Šis veiksmas yra asinchroniškas, daugiau informacijos ieškokite žurnaluose. procesas", "LDAP_Sync_User_Avatar": "Sync User Avatar", - "LDAP_Sync_User_Data": "Sinchronizuoti naudotojo duomenis", - "LDAP_Sync_User_Data_Description": "Suteikite naudotojo duomenis sinchronizuojant su serveriu ** prisijungimo ** arba ** fono sinchronizavimo ** (pvz .: vardas, el. Paštas).", - "LDAP_Sync_User_Data_FieldMap": "Vartotojo duomenų lauko žemėlapis", - "LDAP_Sync_User_Data_FieldMap_Description": "Konfigūruokite, kaip vartotojo abonemento laukai (pvz., El. Paštas) užpildomi LDAP įraše (kai rastas).
Pavyzdžiui, \"{\" cn \":\" name \",\" mail \":\" email \"}` pasirinks asmens žmogaus skaitomą vardą iš cn atributo ir jų el. Laišką iš pašto atributo. Be to, galima naudoti kintamuosius, pavyzdžiui: `{\" # {givenName} # {sn} \":\" vardas \",\" paštas \":\" el. Paštas \"}` naudoja vartotojo vardą ir pavardę raketų pokalbis \"pavadinimas\".
Galimi laukai Rocket.Chat: \"name\", \"email\" ir \"customFields\".", - "LDAP_Test_Connection": "Bandymo jungtis", "LDAP_Timeout": "Laikas (ms)", "LDAP_Timeout_Description": "Kiek leidimo rezultatas laukia paieškos rezultatų, kol bus grąžinta klaida", "LDAP_Unique_Identifier_Field": "Unikalus identifikatoriaus laukas", diff --git a/packages/rocketchat-i18n/i18n/lv.i18n.json b/packages/rocketchat-i18n/i18n/lv.i18n.json index c015ef27ff9f..52d2dc0e7ab8 100644 --- a/packages/rocketchat-i18n/i18n/lv.i18n.json +++ b/packages/rocketchat-i18n/i18n/lv.i18n.json @@ -1528,9 +1528,6 @@ "LDAP_Connect_Timeout": "Savienojuma beigu laiks (ms)", "LDAP_Default_Domain": "Noklusējuma domēns", "LDAP_Default_Domain_Description": "Ja tiek nodrošināts, noklusējuma domēns tiks izmantots, lai izveidotu unikālu e-pasta adresi lietotājiem, kur e-pasts netika importēts no LDAP. E-pasts tiks uzstādīts kā `lietotājvārds @ default_domain` vai` unique_id @ default_domain`.
Piemērs: `rocket.chat`", - "LDAP_Default_Role_To_User": "Lietotāja loma pēc noklusējuma", - "LDAP_Default_Role_To_User_Description": "Noklusētā RC loma, kas tiks piešķirta lietotājam, ja lietotājam ir kāda LDAP loma, kas nav kartēta.", - "LDAP_Description": "LDAP ir hierarhiska datu bāze, ko daudzi uzņēmumi izmanto, lai nodrošinātu vienotu pieteikšanos - telpu kur dalties ar vienu paroli starp vairākām vietnēm un pakalpojumiem. Papildu konfigurācijas informācijai un piemēriem, lūdzu skatiet mūsu wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Iespējot", "LDAP_Enable_Description": "Mēģinājums izmantot LDAP autentifikācijai.", "LDAP_Encryption": "Šifrēšana", @@ -1572,11 +1569,6 @@ "LDAP_Sync_Now": "Tultēja fona sinhronizācija", "LDAP_Sync_Now_Description": "Izpildīs ** Fona sinhronizācija ** tagad, nevis gaidīt ** Sinhronizācijas intervāls **, pat ja ** Fona sinhronizācija ** ir False.
Šī darbība ir asinhrona, lūdzu, skatiet žurnālus, lai iegūtu plašāku informāciju par procesu", "LDAP_Sync_User_Avatar": "Sinhronizēt lietotāja avatāru", - "LDAP_Sync_User_Data": "Sinhronizēt lietotāja datus", - "LDAP_Sync_User_Data_Description": "Saglabāt lietotāja datus sinhronizācijā ar serveri pie ** pieteikšanās ** vai pie** fona sinhronizācijas ** (piem.: vārds, e-pasts).", - "LDAP_Sync_User_Data_FieldMap": "Lietotāja datu lauka karte", - "LDAP_Sync_User_Data_FieldMap_Description": "Konfigurējiet, kā lietotāja konta lauki (piemēram, e-pasts) tiek aizpildīti no LDAP ieraksta (kad atrasts).
Piemēram, `{\" cn \":\" vārds \",\" pasts \":\" e-pasts \"}` izvēlas personas cilvēka vārdu no cn atribūta un e-pastu no pasta atribūta. Turklāt var izmantot mainīgos lielumus, piemēram: `{\" # {givenName} # {sn} \":\" vārds \",\" pasts \":\" e-pasts \"}` izmanto lietotāja vārda un uzvārda kombināciju rocket chat laukā \"vārds\".
Pieejamie lauki Rocket.Chat: `vārds`,` e-pastsl`and `pielāgotielauki`.", - "LDAP_Test_Connection": "Testa savienojums", "LDAP_Timeout": "Taimauts (ms)", "LDAP_Timeout_Description": "Cik milisekundes gaida meklēšanas rezultātu pirms atgriešanās kļūdas", "LDAP_Unique_Identifier_Field": "Unikāls identifikācijas lauks", diff --git a/packages/rocketchat-i18n/i18n/mn.i18n.json b/packages/rocketchat-i18n/i18n/mn.i18n.json index 0a061e07667c..7d43e6bf300b 100644 --- a/packages/rocketchat-i18n/i18n/mn.i18n.json +++ b/packages/rocketchat-i18n/i18n/mn.i18n.json @@ -1513,7 +1513,6 @@ "LDAP_Connect_Timeout": "Холболтын хугацаа (ms)", "LDAP_Default_Domain": "Анхдагч домэйн", "LDAP_Default_Domain_Description": "LDAP-аас имэйлийг импортлоодоггүй хэрэглэгчид зориулсан цахим захидал үүсгэхийн тулд Default Domain-ийг ашиглах болно. Имэйлийг 'username @ default_domain` эсвэл `unique_id @ default_domain` гэж дуудах болно.
Жишээ:` rocket.chat`", - "LDAP_Description": "LDAP нь олон компаниуд сайтууд болон үйлчилгээнүүдийн хооронд нэг нууц үг солилцох боломжийг олгодог шаталбар бүхий өгөгдлийн сан юм. Нэмэлт тохиргооны мэдээлэл болон жишээнүүдийн хувьд манай викитэй холбогдоно уу: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Бататгах", "LDAP_Enable_Description": "Нэвтрэлтийг баталгаажуулахын тулд LDAP-ийг ашиглахыг оролдсон.", "LDAP_Encryption": "Шифрлэлт", @@ -1555,11 +1554,6 @@ "LDAP_Sync_Now": "Үндсэн синх", "LDAP_Sync_Now_Description": "** Үндсэн синхрон ** худал байсан ч ** Үндсэн синхрон ** одоо ** Синхрон интервал ** ажиллуулах боломжтой.
Энэ үйлдэл нь асинхрон бус, энэ талаархи дэлгэрэнгүй мэдээллийг log -г үзнэ үү. үйл явц", "LDAP_Sync_User_Avatar": "Хэрэглэгчийн Хагалгийг синк хийх", - "LDAP_Sync_User_Data": "Хэрэглэгчийн мэдээллийг синк хийх", - "LDAP_Sync_User_Data_Description": "** нэвтрэх ** дээр серверийн синхрончлолд байлгах эсвэл ** арын синк ** дээр (жнь: нэр, имэйл) дээр байлгах.", - "LDAP_Sync_User_Data_FieldMap": "Хэрэглэгчийн өгөгдлийн хээрийн газрын зураг", - "LDAP_Sync_User_Data_FieldMap_Description": "LDAP дахь хэрэглэгчийн дансны талбарууд (имэйлтэй адил) нь хэрхэн бүртгэгдсэнийг тохируулах боломжтой (нэг удаа олдсон).
Жишээ нь `{\" cn \":\" нэр \",\" мэйл \":\" имэйл \"} нь хүний хүний уншигдах нэрийг cn шинж чанараас нь, мөн тэдний имэйл шинж чанарын имэйлийг сонгоно. Түүнээс гадна хувьсагчдыг ашиглах боломжтой. Жишээ нь: {{## givenName} # {sn} \":\" name \",\" mail \":\" email \"} нь хэрэглэгчийн нэр болон овог пуужингийн чатын нэр` талбар.
Рокет дотор боломжтой талбарууд.Анхаар: `нэр`,` имэйл` болон `customFields`.", - "LDAP_Test_Connection": "Туршилтын холболт", "LDAP_Timeout": "Цаг хугацаа (ms)", "LDAP_Timeout_Description": "Аливаа алдааг буцаахаас өмнө хайлтын үр дүнг хэдэн миллекунд хүлээх хэрэгтэй", "LDAP_Unique_Identifier_Field": "Онцгой таних талбар", diff --git a/packages/rocketchat-i18n/i18n/ms-MY.i18n.json b/packages/rocketchat-i18n/i18n/ms-MY.i18n.json index 4f61e5119e2b..371071990285 100644 --- a/packages/rocketchat-i18n/i18n/ms-MY.i18n.json +++ b/packages/rocketchat-i18n/i18n/ms-MY.i18n.json @@ -1513,7 +1513,6 @@ "LDAP_Connect_Timeout": "Waktu Sambungan (ms)", "LDAP_Default_Domain": "Domain lalai", "LDAP_Default_Domain_Description": "Jika disediakan Domain Lalai akan digunakan untuk membuat e-mel unik untuk pengguna di mana e-mel tidak diimport dari LDAP. E-mel akan dipasang sebagai `username @ default_domain` atau` unique_id @ default_domain`.
Contoh: `rocket.chat`", - "LDAP_Description": "LDAP adalah pangkalan data hierarki bahawa banyak syarikat gunakan untuk menyediakan single sign on - kemudahan untuk berkongsi satu kata laluan antara beberapa tapak dan perkhidmatan. Untuk maklumat konfigurasi lanjutan dan contoh, sila rujuk wiki kami: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "membolehkan", "LDAP_Enable_Description": "Cuba untuk menggunakan LDAP untuk pengesahan.", "LDAP_Encryption": "penyulitan", @@ -1555,11 +1554,6 @@ "LDAP_Sync_Now": "Penyegerakan Latar Belakang Sekarang", "LDAP_Sync_Now_Description": "Akan melaksanakan ** Latar Belakang Sync ** sekarang daripada tunggu ** Interval Sync ** walaupun ** Latar Belakang Sync ** adalah Palsu.
Tindakan ini tidak segerak, sila lihat log untuk maklumat lebih lanjut mengenai proses", "LDAP_Sync_User_Avatar": "Sync Pengguna Avatar", - "LDAP_Sync_User_Data": "Sync Data", - "LDAP_Sync_User_Data_Description": "Menyimpan data pengguna dalam penyegerakan dengan pelayan pada login (contohnya: nama, e-mel).", - "LDAP_Sync_User_Data_FieldMap": "Pengguna Data Field Peta", - "LDAP_Sync_User_Data_FieldMap_Description": "Konfigur berapa bidang akaun pengguna (seperti e-mel) adalah penduduk dari satu rekod dalam LDAP (sekali dijumpai).
Sebagai contoh, `{\" cn \":\" nama \",\" mel \":\" e-mel \"}` akan memilih nama seseorang manusia boleh dibaca dari atribut cn, dan e-mel mereka dari sifat mel.
bidang termasuk `name`, dan` email`.", - "LDAP_Test_Connection": "Test Connection", "LDAP_Timeout": "Waktu tunggu (ms)", "LDAP_Timeout_Description": "Berapa batu miles menunggu hasil carian sebelum mengembalikan ralat", "LDAP_Unique_Identifier_Field": "Pengecam Unik Field", diff --git a/packages/rocketchat-i18n/i18n/nl.i18n.json b/packages/rocketchat-i18n/i18n/nl.i18n.json index b928c476583d..93a4199b07e7 100644 --- a/packages/rocketchat-i18n/i18n/nl.i18n.json +++ b/packages/rocketchat-i18n/i18n/nl.i18n.json @@ -2433,12 +2433,8 @@ "LDAP_Connect_Timeout": "Time-out verbinding (ms)", "LDAP_Default_Domain": "Standaard domein", "LDAP_Default_Domain_Description": "Indien aanwezig, wordt het standaarddomein gebruikt om een unieke e-mail te maken voor gebruikers waarbij e-mail niet is geïmporteerd vanuit LDAP. De e-mail wordt aangekoppeld als `gebruikersnaam@standaard_domein` of `unieke_id@standaard_domein`.
Voorbeeld: `rocket.chat`", - "LDAP_Default_Role_To_User": "Standaardrol voor gebruiker", - "LDAP_Default_Role_To_User_Description": "De standaard RC-rol die op de gebruiker moet worden toegepast als de gebruiker een LDAP-rol heeft die niet is toegewezen.", - "LDAP_Description": "LDAP is een hiërarchische database die door veel bedrijven wordt voor eenmalige aanmelding - een mogelijkheid om één wachtwoord te delen tussen meerdere sites en services. Raadpleeg onze wiki voor geavanceerde configuratie-informatie en voorbeelden: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Inschakelen", "LDAP_Enable_Description": "Probeer LDAP te gebruiken voor authenticatie.", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "Schakel roltoewijzing van LDAP naar Rocket.Chat in", "LDAP_Enable_LDAP_Groups_To_RC_Teams": "Schakel teammapping van LDAP naar Rocket.Chat in", "LDAP_Encryption": "Versleuteling", "LDAP_Encryption_Description": "De versleutelingsmethode die wordt gebruikt om de communicatiememt de LDAP-server te beveiligen. Voorbeelden zijn `plain` (geen codering), `SSL/LDAPS` (vanaf het begin gecodeerd), en `StartTLS` (upgrade naar gecodeerde communicatie zodra verbinding is gemaakt).", @@ -2469,15 +2465,11 @@ "LDAP_Merge_Existing_Users_Description": "*Let op!* Bij het importen van een gebruiker uit LDAP en er bestaat al een gebruiker met dezelfde gebruikersnaam, dan worden de LDAP-info en het wachtwoord ingesteld op de bestaande gebruiker.", "LDAP_Port": "Poort", "LDAP_Port_Description": "Poort voor toegang tot LDAP. Bijv. `389` of `636` voor LDAPS", - "LDAP_Query_To_Get_User_Groups": "LDAP-query om gebruikersgroepen op te halen", - "LDAP_Query_To_Get_User_Groups_Description": "LDAP-query om de LDAP-groepen op te halen waarvan de gebruiker deel uitmaakt.", "LDAP_Query_To_Get_User_Teams": "LDAP-query om gebruikersgroepen op te halen", "LDAP_Reconnect": "Verbinding opnieuw maken", "LDAP_Reconnect_Description": "Probeer automatisch opnieuw verbinding te maken wanneer de verbinding om een of andere reden wordt onderbroken tijdens het uitvoeren van bewerkingen", "LDAP_Reject_Unauthorized": "Ongeautoriseerde weigeren", "LDAP_Reject_Unauthorized_Description": "Schakel deze optie uit om certificaten toe te staan die niet kunnen worden geverifieerd. Meestal vereist een zelfondertekend certificaat dat deze optie uitgeschakeld is om te werken", - "LDAP_Roles_To_Rocket_Chat_Roles": "Roltoewijzing van LDAP naar Rocket.Chat.", - "LDAP_Roles_To_Rocket_Chat_Roles_Description": "Roltoewijzing in objectindeling waarbij de objectsleutel de LDAP-rol moet zijn en de objectwaarde een array van RC-rollen. Voorbeeld: { 'ldapRole': ['rcRole', 'anotherRCRole'] }", "LDAP_Search_Page_Size": "Zoekpaginaformaat", "LDAP_Search_Page_Size_Description": "Het maximale aantal items dat elke resultaatpagina zal terugsturen om te verwerken", "LDAP_Search_Size_Limit": "Limiet voor zoekgrootte", @@ -2490,29 +2482,28 @@ "LDAP_Sync_User_Active_State_Disable": "Schakel gebruikers uit", "LDAP_Sync_User_Active_State_Nothing": "Niets doen", "LDAP_Sync_User_Avatar": "Synchroniseer gebruikersavatar", - "LDAP_Sync_User_Data": "Gebruikersgegevens synchroniseren", - "LDAP_Sync_User_Data_Description": "Houd gebruikersgegevens gesynchroniseerd met de server bij **inloggen** of bij **achtergrondsynchronisatie** (bijvoorbeeld: naam, e-mail).", - "LDAP_Sync_User_Data_FieldMap": "Gebruikersgegevensveldkaart", - "LDAP_Sync_User_Data_FieldMap_Description": "Configureer hoe gebruikersaccountvelden (zoals e-mail) worden ingevuld vanuit een record in LDAP (eenmaal gevonden).
Als voorbeeld, `{\"cn\":\"name\", \"mail\":\"email\"}` zal de door mensen leesbare naam van een persoon kiezen uit het cn-attribuut en hun e-mailadres uit het mailattribuut. Bovendien is het mogelijk om variabelen te gebruiken, bijvoorbeeld: `{ \"#{givenName} # {sn} \": \"name\", \"mail\": \"email\"}` gebruikt een combinatie van de voor- en achternaam van de gebruiker voor de rocket chat `naam` veld.
Beschikbare velden in Rocket.Chat:`name`, `email` en `customFields`.", - "LDAP_Sync_User_Data_Groups": "Synchroniseer LDAP-groepen", - "LDAP_Sync_User_Data_Groups_AutoChannels": "LDAP-groepen automatisch synchroniseren met kanalen", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "Kanaalbeheerder", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin_Description": "Als er automatisch kanalen worden aangemaakt die niet bestaan tijdens een synchronisatie, wordt deze gebruiker automatisch de beheerder van het kanaal.", - "LDAP_Sync_User_Data_Groups_AutoChannels_Description": "Schakel deze functie in om automatisch gebruikers aan een kanaal toe te voegen op basis van hun LDAP-groep. Als je ook gebruikers van een kanaal wilt verwijderen, bekijk dan de onderstaande optie over het automatisch verwijderen van gebruikers.", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap": "Kanaaloverzicht LDAP-groep", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Default": "// Schakel LDAP-groepen automatische synchronisatie in voor de kanalen hierboven", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Description": "Wijs LDAP-groepen toe aan Rocket.Chat-kanalen.
Als voorbeeld: `{\"employee\":\"general\"}` zal elke gebruiker in de LDAP-groep employee toevoegen aan het algemene kanaal.", - "LDAP_Sync_User_Data_Groups_AutoRemove": "Automatisch gebruikersrollen verwijderen", - "LDAP_Sync_User_Data_Groups_AutoRemove_Description": "**Let op**: als u dit inschakelt, worden gebruikers automatisch uit een rol verwijderd als ze niet zijn toegewezen in LDAP! HIermee worden alleen automatisch rollen verwijderd die zijn ingesteld onder de gebruikersgegevensgroepkaart hieronder.", - "LDAP_Sync_User_Data_Groups_BaseDN": "LDAP groep BaseDN", - "LDAP_Sync_User_Data_Groups_BaseDN_Description": "De LDAP BaseDN die gebruikt wordt om gebruikers op te zoeken.", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels": "Gebruikers automatisch verwijderen uit kanalen", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels_Description": "**Opgelet**: als u dit inschakelt, worden alle gebruikers in een kanaal verwijderd die niet de bijhorende LDAP-groep hebben! Schakel dit alleen in wanneer u weet wat u doet.", - "LDAP_Sync_User_Data_Groups_Filter": "Gebruikersgroepfilter", - "LDAP_Sync_User_Data_Groups_Filter_Description": "Het LDAP-zoekfilter dat wordt gebruikt om te controleren of een gebruiker deel uitmaakt van een groep.", - "LDAP_Sync_User_Data_GroupsMap": "User Data Group Map", - "LDAP_Sync_User_Data_GroupsMap_Description": "Wijs LDAP-groepen toe aan Rocket.Chat-gebruikersrollen
Als voorbeeld zal `{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}` de rocket-admin LDAP-groep toewijzen aan Rocket's rol \"admin\".", - "LDAP_Test_Connection": "Test verbinding", + "LDAP_Sync_User_Data_Roles": "Synchroniseer LDAP-groepen", + "LDAP_Sync_User_Data_Channels": "LDAP-groepen automatisch synchroniseren met kanalen", + "LDAP_Sync_User_Data_Channels_Admin": "Kanaalbeheerder", + "LDAP_Sync_User_Data_Channels_Admin_Description": "Als er automatisch kanalen worden aangemaakt die niet bestaan tijdens een synchronisatie, wordt deze gebruiker automatisch de beheerder van het kanaal.", + "LDAP_Sync_User_Data_Channels_BaseDN": "LDAP groep BaseDN", + "LDAP_Sync_User_Data_Channels_BaseDN_Description": "De LDAP BaseDN die gebruikt wordt om gebruikers op te zoeken.", + "LDAP_Sync_User_Data_Channels_Description": "Schakel deze functie in om automatisch gebruikers aan een kanaal toe te voegen op basis van hun LDAP-groep. Als je ook gebruikers van een kanaal wilt verwijderen, bekijk dan de onderstaande optie over het automatisch verwijderen van gebruikers.", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels": "Gebruikers automatisch verwijderen uit kanalen", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels_Description": "**Opgelet**: als u dit inschakelt, worden alle gebruikers in een kanaal verwijderd die niet de bijhorende LDAP-groep hebben! Schakel dit alleen in wanneer u weet wat u doet.", + "LDAP_Sync_User_Data_Channels_Filter": "Gebruikersgroepfilter", + "LDAP_Sync_User_Data_Channels_Filter_Description": "Het LDAP-zoekfilter dat wordt gebruikt om te controleren of een gebruiker deel uitmaakt van een groep.", + "LDAP_Sync_User_Data_ChannelsMap": "Kanaaloverzicht LDAP-groep", + "LDAP_Sync_User_Data_ChannelsMap_Default": "// Schakel LDAP-groepen automatische synchronisatie in voor de kanalen hierboven", + "LDAP_Sync_User_Data_ChannelsMap_Description": "Wijs LDAP-groepen toe aan Rocket.Chat-kanalen.
Als voorbeeld: `{\"employee\":\"general\"}` zal elke gebruiker in de LDAP-groep employee toevoegen aan het algemene kanaal.", + "LDAP_Sync_User_Data_Roles_AutoRemove": "Automatisch gebruikersrollen verwijderen", + "LDAP_Sync_User_Data_Roles_AutoRemove_Description": "**Let op**: als u dit inschakelt, worden gebruikers automatisch uit een rol verwijderd als ze niet zijn toegewezen in LDAP! HIermee worden alleen automatisch rollen verwijderd die zijn ingesteld onder de gebruikersgegevensgroepkaart hieronder.", + "LDAP_Sync_User_Data_Roles_BaseDN": "LDAP groep BaseDN", + "LDAP_Sync_User_Data_Roles_BaseDN_Description": "De LDAP BaseDN die gebruikt wordt om gebruikers op te zoeken.", + "LDAP_Sync_User_Data_Roles_Filter": "Gebruikersgroepfilter", + "LDAP_Sync_User_Data_Roles_Filter_Description": "Het LDAP-zoekfilter dat wordt gebruikt om te controleren of een gebruiker deel uitmaakt van een groep.", + "LDAP_Sync_User_Data_RolesMap": "User Data Group Map", + "LDAP_Sync_User_Data_RolesMap_Description": "Wijs LDAP-groepen toe aan Rocket.Chat-gebruikersrollen
Als voorbeeld zal `{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}` de rocket-admin LDAP-groep toewijzen aan Rocket's rol \"admin\".", "LDAP_Timeout": "Time-out (ms)", "LDAP_Timeout_Description": "Hoeveel milliseconden wachten op een zoekresultaat voordat een fout wordt geretourneerd", "LDAP_Unique_Identifier_Field": "Uniek identificatieveld", @@ -2526,8 +2517,6 @@ "LDAP_Username_Field_Description": "Welk veld wordt gebruikt als *gebruikersnaam* voor nieuwe gebruikers. Laat leeg om de gebruikersnaam te gebruiken die op de inlogpagina wordt vermeld.
U kunt sjabloontags gebruiken, zoals `#{givenName}.#{sn}`.
De standaardwaarde is `sAMAccountName`.", "LDAP_Validate_Teams_For_Each_Login": "Valideer de mapping voor elke login", "LDAP_Validate_Teams_For_Each_Login_Description": "Bepaal of de teams van gebruikers moeten bijgewerkt worden elke keer dat ze op Rocket.Chat inloggen. Als dit is uitgeschakeld, wordt het enkel bij de eerste login geladen.", - "LDAP_Validate_Roles_For_Each_Login": "Valideer de mapping voor elke login", - "LDAP_Validate_Roles_For_Each_Login_Description": "Als de validatie voor elke login moet plaatsvinden (wees voorzichtig met deze instelling, want hierdoor worden de gebruikersrollen bij elke login overschreven, anders wordt dit pas gevalideerd op het moment dat de gebruiker wordt aangemaakt).", "Lead_capture_email_regex": "Regex voor e-mailregistratie voor leads", "Lead_capture_phone_regex": "Lead capture telefoon regex", "Leave": "Verlaten", diff --git a/packages/rocketchat-i18n/i18n/no.i18n.json b/packages/rocketchat-i18n/i18n/no.i18n.json index 3020c76ba585..b2ad8ef26e97 100644 --- a/packages/rocketchat-i18n/i18n/no.i18n.json +++ b/packages/rocketchat-i18n/i18n/no.i18n.json @@ -1592,11 +1592,8 @@ "LDAP_Connect_Timeout": "Tilkoblingstidsavbrudd (ms)", "LDAP_Default_Domain": "Standard domenenavn", "LDAP_Default_Domain_Description": "Hvis det leveres, vil standarddomenet brukes til å lage en unik e-post for brukere der e-post ikke ble importert fra LDAP. E-posten vil bli montert som `brukernavn@default_domai` eller`unique_id@default_domain`.
Eksempel: `rocket.chat`", - "LDAP_Default_Role_To_User": "Standardrolle for bruker", - "LDAP_Description": "LDAP er en hierarkisk database som mange bedrifter bruker til å gi et enkelt tegn på - et anlegg for å dele ett passord mellom flere nettsteder og tjenester. For avansert konfigurasjonsinformasjon og eksempler, vennligst se vår wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Aktiver", "LDAP_Enable_Description": "Forsøk å bruke LDAP for autentisering.", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "Aktivér rolletilknytning gjennom LDAP til Rocket.Chat", "LDAP_Encryption": "kryptering", "LDAP_Encryption_Description": "Krypteringsmetoden brukes til å sikre kommunikasjon til LDAP-serveren. Eksempler er \"plain\" (ingen kryptering), `SSL / LDAPS` (kryptert fra starten) og` StartTLS` (oppgradering til kryptert kommunikasjon når den er tilkoblet).", "LDAP_Find_User_After_Login": "Finn bruker etter innlogging", @@ -1625,14 +1622,11 @@ "LDAP_Merge_Existing_Users_Description": "* Forsiktig! * Når du importerer en bruker fra LDAP, og en bruker med samme brukernavn allerede eksisterer, blir LDAP-info og passord satt inn i den eksisterende brukeren.", "LDAP_Port": "Havn", "LDAP_Port_Description": "Port for å få tilgang til LDAP. f.eks .: `389` eller` 636` for LDAPS", - "LDAP_Query_To_Get_User_Groups": "LDAP-spørring for å få brukergrupper", - "LDAP_Query_To_Get_User_Groups_Description": "LDAP-spørring for å få LDAP-gruppene en bruker er med i.", "LDAP_Query_To_Get_User_Teams": "LDAP-spørring for å få brukergrupper", "LDAP_Reconnect": "koble", "LDAP_Reconnect_Description": "Prøv å koble til igjen automatisk når tilkoblingen avbrytes av en eller annen grunn mens du utfører operasjoner", "LDAP_Reject_Unauthorized": "Avvis Uautorisert", "LDAP_Reject_Unauthorized_Description": "Deaktiver dette alternativet for å tillate sertifikater som ikke kan verifiseres. Vanligvis vil selvsignerte sertifikater kreve at dette alternativet er deaktivert for å fungere", - "LDAP_Roles_To_Rocket_Chat_Roles": "Kobling for roller fra LDAP til Rocket.Chat.", "LDAP_Search_Page_Size": "Søkeformat", "LDAP_Search_Page_Size_Description": "Maksimalt antall innføringer hver resultatside vil returnere for å bli behandlet", "LDAP_Search_Size_Limit": "Søk størrelsesgrense", @@ -1640,11 +1634,6 @@ "LDAP_Sync_Now": "Bakgrunnssynkronisering nå", "LDAP_Sync_Now_Description": "Vil utføre **Background Sync** nå i stedet for å vente **Sync Interval** selv om **Bakgrunnssynkronisering** er False.
Denne handlingen er asynkron, se loggene for mer informasjon om prosess", "LDAP_Sync_User_Avatar": "Synkroniser User Avatar", - "LDAP_Sync_User_Data": "Synkroniser brukerdata", - "LDAP_Sync_User_Data_Description": "Hold brukerdata synkronisert med serveren på ** pålogging ** eller på ** bakgrunnssynkronisering ** (f.eks: navn, e-post).", - "LDAP_Sync_User_Data_FieldMap": "Brukerdatafeltkart", - "LDAP_Sync_User_Data_FieldMap_Description": "Konfigurer hvordan brukerkontofelt (som e-post) er fylt ut fra en post i LDAP (en gang funnet).
Som et eksempel vil `{\"cn\":\"navn\", \"mail\":\"e-post\"}` velge en persons menneskelige lesbare navn fra cn-attributtet og deres e-post fra postattributtet. I tillegg er det mulig å bruke variabler, for eksempel: `{\"#{givenName}#{sn}\":\"navn\", \"mail\":\"email\"}` bruker en kombinasjon av brukerens fornavn og etternavn for rocket chat `name`-feltet.
Tilgjengelige felt i Rocket.Chat:`name`, `email` og `customFields`.", - "LDAP_Test_Connection": "Testforbindelse", "LDAP_Timeout": "Timeout (ms)", "LDAP_Timeout_Description": "Hvor mange milesekunder venter på et søkeresultat før du returnerer en feil", "LDAP_Unique_Identifier_Field": "Unikt identifikasjonsfelt", diff --git a/packages/rocketchat-i18n/i18n/pl.i18n.json b/packages/rocketchat-i18n/i18n/pl.i18n.json index e0abd7dd4577..b149b7de1bb5 100644 --- a/packages/rocketchat-i18n/i18n/pl.i18n.json +++ b/packages/rocketchat-i18n/i18n/pl.i18n.json @@ -2430,12 +2430,8 @@ "LDAP_Connect_Timeout": "Limit czasu połączenia (ms)", "LDAP_Default_Domain": "Domyślna domena", "LDAP_Default_Domain_Description": "Jeśli zostanie podana, domyślna domena będzie używana do tworzenia unikatowych wiadomości e-mail dla użytkowników, których poczta e-mail nie została zaimportowana z LDAP. Wiadomość e-mail zostanie zamontowana jako \"nazwa_użytkownika @ domyślna_domena\" lub \"unikalny_domyślny @ domyślna_domena\".
Przykład: `rocket.chat`", - "LDAP_Default_Role_To_User": "Domyślna rola dla użytkownika", - "LDAP_Default_Role_To_User_Description": "Zostanie użyta domyślna rola RC jeżeli użytkownik ma jakąś rolę LDAP która nie jest zamapowana.", - "LDAP_Description": "LDAP to hierarchiczna baza danych wykorzystywana przez wiele firm w celu udostępniania pojedynczej usługi autoryzacji użytkowników pomiędzy wieloma serwisami. Aby uzyskać dodatkowe informacje i przykłady konfiguracji, odwiedź nasze wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Włącz LDAP", "LDAP_Enable_Description": "Włącza LDAP podczas uwierzytelniania.", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "Włącz mapowanie ról z LDAP do Rocket.Chat", "LDAP_Enable_LDAP_Groups_To_RC_Teams": "Włącz mapowanie zespołów z LDAP do Rocket.Chat", "LDAP_Encryption": "Szyfrowanie", "LDAP_Encryption_Description": "Metoda szyfrowania wykorzystywany do zabezpieczenia komunikacji z serwerem LDAP. Przykłady obejmują `plain` (bez szyfrowania),` SSL / LDAPS` (zaszyfrowany od początku) i `StartTLS` (upgrade do szyfrowanej komunikacji po podłączeniu).", @@ -2466,15 +2462,11 @@ "LDAP_Merge_Existing_Users_Description": "* Uwaga! * Gdy importowanie użytkownika z serwera LDAP i użytkownika o tej samej nazwie już istnieje, informacje LDAP i hasło zostaną ustawione na istniejącego użytkownika.", "LDAP_Port": "Port LDAP", "LDAP_Port_Description": "Port dla LDAP, np: `389`lub `636` dla LDAPS", - "LDAP_Query_To_Get_User_Groups": "Zapytanie LDAP do pobrania grup użytkownika", - "LDAP_Query_To_Get_User_Groups_Description": "Zapytanie LDAP do pobrania grup w których uczestniczy użytkownik", "LDAP_Query_To_Get_User_Teams": "Zapytanie LDAP do pobrania grup użytkownika", "LDAP_Reconnect": "Podłącz", "LDAP_Reconnect_Description": "Spróbuj ponownie połączyć się automatycznie, gdy połączenie zostanie przerwane z jakiegoś powodu podczas wykonywania operacji", "LDAP_Reject_Unauthorized": "Odrzuć nieautoryzowane", "LDAP_Reject_Unauthorized_Description": "Wyłącz tę opcję, aby zezwolić na certyfikaty, których nie można zweryfikować. Zazwyczaj certyfikaty z własnym podpisem wymagają wyłączenia tej opcji", - "LDAP_Roles_To_Rocket_Chat_Roles": "Mapowanie ról z LDAP do Rocket.Chat", - "LDAP_Roles_To_Rocket_Chat_Roles_Description": "Odwzorowanie ról w formacie obiektowym, w którym kluczem obiektu musi być rola LDAP, a wartością obiektu musi być tablica ról RC. Example: { 'ldapRole': ['rcRole', 'anotherRCRole'] }", "LDAP_Search_Page_Size": "Rozmiar strony wyszukiwania", "LDAP_Search_Page_Size_Description": "Maksymalna liczba wpisów na stronie wyników będzie zwracana do przetworzenia", "LDAP_Search_Size_Limit": "Ogranicz rozmiar wyszukiwania", @@ -2487,29 +2479,28 @@ "LDAP_Sync_User_Active_State_Disable": "Dezaktywuj użytkowników", "LDAP_Sync_User_Active_State_Nothing": "Nic nie rób", "LDAP_Sync_User_Avatar": "Synchronizacja User Avatar", - "LDAP_Sync_User_Data": "Synchronizuj dane", - "LDAP_Sync_User_Data_Description": "Utrzymuj dane (np: nazwa, email) w synchronizacji z serwerem podczas logowania", - "LDAP_Sync_User_Data_FieldMap": "Mapa pól użytkownika", - "LDAP_Sync_User_Data_FieldMap_Description": "Konfigurowanie sposobu w jaki pola kont (np. email) są uzupełniane z rekordów LDAP (gdy takowe zostaną znalezione).
Na przykład podając `{\"cn\":\"name\", \"mail\":\"email\"}` system wybierze wyświetlaną nazwę użytkownika z pola cn i jego adres email z pola email.
Dostępne pola to: `name`, `email`.", - "LDAP_Sync_User_Data_Groups": "Synchronizuj grupy LDAP", - "LDAP_Sync_User_Data_Groups_AutoChannels": "Automatyczna synchronizacja grup LDAP do kanałów", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "Channel Admin", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin_Description": "Kiedy kanały są automatycznie tworzone ponieważ nie istnieją podczas synchronizacji, użytkownik ten automatycznie staje się administratorem kanału.", - "LDAP_Sync_User_Data_Groups_AutoChannels_Description": "Włączenie tej funkcji umożliwia automatyczne dodawanie użytkowników do kanału w oparciu o ich grupę LDAP. Jeśli chcesz także usunąć użytkowników z kanału, zobacz poniższą opcję dotyczącą automatycznego usuwania użytkowników.", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap": "Mapa grup LDAP kanału Channel", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Default": "// Włączyć Auto Sync LDAP Groups do Channels powyżej", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Description": "Mapuj grupy LDAP do kanałów Rocket.Chat.
Jako przykład, `{\"employee\":\"general\"}` doda dowolnego użytkownika w grupie LDAP employee, do ogólnego kanału.", - "LDAP_Sync_User_Data_Groups_AutoRemove": "Automatyczne usuwanie roli użytkownika", - "LDAP_Sync_User_Data_Groups_AutoRemove_Description": "**Uwaga** Włączenie tego spowoduje automatyczne usunięcie użytkowników z roli, jeśli nie są oni przypisani w LDAP! Spowoduje to automatyczne usunięcie tylko tych ról, które są ustawione dla user data group map poniżej.", - "LDAP_Sync_User_Data_Groups_BaseDN": "LDAP Group BaseDN", - "LDAP_Sync_User_Data_Groups_BaseDN_Description": "LDAP BaseDN do wyszukiwania użytkowników.", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels": "Automatyczne usuwanie użytkowników z kanałów", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels_Description": "**Uwaga** Włączenie tej funkcji spowoduje usunięcie wszystkich użytkowników z kanału, który nie posiada odpowiadającej im grupy LDAP! Włączaj to tylko wtedy, gdy wiesz, co robisz.", - "LDAP_Sync_User_Data_Groups_Filter": "Filtr grupy użytkowników", - "LDAP_Sync_User_Data_Groups_Filter_Description": "Filtr wyszukiwania LDAP służy do sprawdzania, czy użytkownik znajduje się w grupie.", - "LDAP_Sync_User_Data_GroupsMap": "User Data Group Map", - "LDAP_Sync_User_Data_GroupsMap_Description": "Mapuj grupy LDAP do ról użytkownika Rocket.Chat
Na przykład, `{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}` zmapuje grupę LDAP \"rocket-admin\" do roli \"admin\" Rocketa.", - "LDAP_Test_Connection": "Testuj połączenie", + "LDAP_Sync_User_Data_Roles": "Synchronizuj grupy LDAP", + "LDAP_Sync_User_Data_Channels": "Automatyczna synchronizacja grup LDAP do kanałów", + "LDAP_Sync_User_Data_Channels_Admin": "Channel Admin", + "LDAP_Sync_User_Data_Channels_Admin_Description": "Kiedy kanały są automatycznie tworzone ponieważ nie istnieją podczas synchronizacji, użytkownik ten automatycznie staje się administratorem kanału.", + "LDAP_Sync_User_Data_Channels_BaseDN": "LDAP Group BaseDN", + "LDAP_Sync_User_Data_Channels_BaseDN_Description": "LDAP BaseDN do wyszukiwania użytkowników.", + "LDAP_Sync_User_Data_Channels_Description": "Włączenie tej funkcji umożliwia automatyczne dodawanie użytkowników do kanału w oparciu o ich grupę LDAP. Jeśli chcesz także usunąć użytkowników z kanału, zobacz poniższą opcję dotyczącą automatycznego usuwania użytkowników.", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels": "Automatyczne usuwanie użytkowników z kanałów", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels_Description": "**Uwaga** Włączenie tej funkcji spowoduje usunięcie wszystkich użytkowników z kanału, który nie posiada odpowiadającej im grupy LDAP! Włączaj to tylko wtedy, gdy wiesz, co robisz.", + "LDAP_Sync_User_Data_Channels_Filter": "Filtr grupy użytkowników", + "LDAP_Sync_User_Data_Channels_Filter_Description": "Filtr wyszukiwania LDAP służy do sprawdzania, czy użytkownik znajduje się w grupie.", + "LDAP_Sync_User_Data_ChannelsMap": "Mapa grup LDAP kanału Channel", + "LDAP_Sync_User_Data_ChannelsMap_Default": "// Włączyć Auto Sync LDAP Groups do Channels powyżej", + "LDAP_Sync_User_Data_ChannelsMap_Description": "Mapuj grupy LDAP do kanałów Rocket.Chat.
Jako przykład, `{\"employee\":\"general\"}` doda dowolnego użytkownika w grupie LDAP employee, do ogólnego kanału.", + "LDAP_Sync_User_Data_Roles_AutoRemove": "Automatyczne usuwanie roli użytkownika", + "LDAP_Sync_User_Data_Roles_AutoRemove_Description": "**Uwaga** Włączenie tego spowoduje automatyczne usunięcie użytkowników z roli, jeśli nie są oni przypisani w LDAP! Spowoduje to automatyczne usunięcie tylko tych ról, które są ustawione dla user data group map poniżej.", + "LDAP_Sync_User_Data_Roles_BaseDN": "LDAP Group BaseDN", + "LDAP_Sync_User_Data_Roles_BaseDN_Description": "LDAP BaseDN do wyszukiwania użytkowników.", + "LDAP_Sync_User_Data_Roles_Filter": "Filtr grupy użytkowników", + "LDAP_Sync_User_Data_Roles_Filter_Description": "Filtr wyszukiwania LDAP służy do sprawdzania, czy użytkownik znajduje się w grupie.", + "LDAP_Sync_User_Data_RolesMap": "User Data Group Map", + "LDAP_Sync_User_Data_RolesMap_Description": "Mapuj grupy LDAP do ról użytkownika Rocket.Chat
Na przykład, `{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}` zmapuje grupę LDAP \"rocket-admin\" do roli \"admin\" Rocketa.", "LDAP_Timeout": "Limit czasu (ms)", "LDAP_Timeout_Description": "Ile milisekund czeka na wynik wyszukiwania, zanim zwróci błąd", "LDAP_Unique_Identifier_Field": "Unikalny Identyfikator Pole", @@ -2523,8 +2514,6 @@ "LDAP_Username_Field_Description": "Które pole będzie używany jako nazwa użytkownika * * Dla nowych użytkowników. Zostaw puste, aby użyć nazwy użytkownika informować na stronie logowania.
Można używać znaczników szablonów też, podobnie jak `#{givenName}.#{sn}`.
 Domyślną wartością jest `sAMAccountName`.", "LDAP_Validate_Teams_For_Each_Login": "Zweryfikuj mapowanie przy każdym logowaniu", "LDAP_Validate_Teams_For_Each_Login_Description": "Określ, czy zespoły użytkowników powinny być aktualizowane za każdym razem, gdy zalogują się do Rocket.Chat. Jeśli ta opcja jest wyłączona, zespół będzie ładowany tylko przy pierwszym logowaniu.", - "LDAP_Validate_Roles_For_Each_Login": "Zweryfikuj mapowanie przy każdym logowaniu", - "LDAP_Validate_Roles_For_Each_Login_Description": "Jeśli sprawdzanie poprawności powinno nastąpić przy każdym logowaniu (należy zachować ostrożność przy tym ustawieniu, ponieważ spowoduje to zastąpienie ról użytkownika przy każdym logowaniu, w przeciwnym razie zostanie to zatwierdzone tylko w momencie tworzenia użytkownika).", "Lead_capture_email_regex": "Lead capture email regex", "Lead_capture_phone_regex": "Lead capture phone regex", "Leave": "Opuść", diff --git a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json index 3c7ca58518b8..3dd2e0870bc8 100644 --- a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json +++ b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json @@ -2431,12 +2431,8 @@ "LDAP_Connect_Timeout": "Tempo limite de conexão (ms)", "LDAP_Default_Domain": "Domínio Padrão", "LDAP_Default_Domain_Description": "Se fornecido, o Domínio Padrão será usado para criar um e-mail exclusivo para usuários onde o e-mail não foi importado do LDAP. O e-mail será montado como `username@default_domain` ou` unique_id@default_domain`.
Exemplo: `rocket.chat`", - "LDAP_Default_Role_To_User": "Papel padrão para o usuário", - "LDAP_Default_Role_To_User_Description": "Papel padrão par ser aplicado ao usuário, caso ele tenha algum papel do LDAP que não esteja mapeado.", - "LDAP_Description": "LDAP é um banco de dados hierárquico que muitas empresas usam para fornecer single sign on - uma facilidade para compartilhar uma senha entre múltiplos sites e serviços. Para exemplos e informações de configurações avançadas, por favor consulte nosso wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/", "LDAP_Enable": "Ativar", "LDAP_Enable_Description": "Tente utilizar LDAP para autenticação", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "Habilitar o mapeamento de papéis do LDAP para o Rocket.Chat", "LDAP_Enable_LDAP_Groups_To_RC_Teams": "Mapeia mapeamento de equipes do LDAP para o LDAP to Rocket.Chat", "LDAP_Encryption": "Criptografia", "LDAP_Encryption_Description": "O método de criptografia usado para proteger as comunicações com o servidor LDAP. Exemplos incluem `plain` (sem criptografia),` SSL / LDAPS` (criptografados desde o início), e `StartTLS` (upgrade para comunicação criptografada uma vez conectado).", @@ -2467,15 +2463,11 @@ "LDAP_Merge_Existing_Users_Description": "* Cuidado! * Ao importar um usuário do LDAP e um usuário com o mesmo nome de usuário já existe, as informações LDAP e a senha serão definidas no usuário existente.", "LDAP_Port": "Porta", "LDAP_Port_Description": "Porta para acessar o LDAP. Ex.: `389` ou `636` para LDAPS", - "LDAP_Query_To_Get_User_Groups": "Consulta LDAP para pegar os grupos de usuários", - "LDAP_Query_To_Get_User_Groups_Description": "Consulta para pegar os grupos em que o usuário faz parte.", "LDAP_Query_To_Get_User_Teams": "Consulta LDAP para pegar os grupos de usuários", "LDAP_Reconnect": "Reconectar", "LDAP_Reconnect_Description": "Tente reconectar-se automaticamente quando a conexão for interrompida por algum motivo durante a execução das operações", "LDAP_Reject_Unauthorized": "Rejeitar Não Autorizados", "LDAP_Reject_Unauthorized_Description": "Desative esta opção para permitir certificados que não podem ser verificados. Normalmente, Certificados autenticados exigirão que esta opção seja desativada para funcionar", - "LDAP_Roles_To_Rocket_Chat_Roles": "Mapeamento dos papéis do LDAP para o Rocket.Chat", - "LDAP_Roles_To_Rocket_Chat_Roles_Description": "Mapeamento dos papéis que deve ser em formato de objeto onde a chave do objeto precisa ser o nome do papel LDAP e o valor deve ser um array de papéis Rocket.Chat. Exemplo: { 'ldapRole': ['rcRole', 'anotherRCRole'] }", "LDAP_Search_Page_Size": "Tamanho da página de pesquisa", "LDAP_Search_Page_Size_Description": "O número máximo de entradas que cada página de resultados retornará para ser processado", "LDAP_Search_Size_Limit": "Limite de tamanho de pesquisa", @@ -2488,29 +2480,27 @@ "LDAP_Sync_User_Active_State_Disable": "Desabilitar Usuários", "LDAP_Sync_User_Active_State_Nothing": "Não Fazer Nada", "LDAP_Sync_User_Avatar": "Sincronizar Avatar dos Usuários", - "LDAP_Sync_User_Data": "Manter dados dos usuários sincronizados", - "LDAP_Sync_User_Data_Description": "Mantenha seus dados de usuário em sincronia logando no servidor (ex.: nome, email).", - "LDAP_Sync_User_Data_FieldMap": "Mapeamento de campos do usuário", - "LDAP_Sync_User_Data_FieldMap_Description": "Configure como os campos da conta de usuário (tipo email) serão populados no LDAP (quando encontrados).
Por exemplo, `{\"cn\":\"name\", \"mail\":\"email\"}` irá selecionar o nome do usuário do atributo cn, e o seu e-mail do atributo mail.
Os campos disponíveis incluem `name`, `email` e `customFields`.", - "LDAP_Sync_User_Data_Groups": "Sincronizar Grupos LDAP", - "LDAP_Sync_User_Data_Groups_AutoChannels": "Sincronizar automaticamente Grupos LDAP para Canais", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "Administrador do Canal", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin_Description": "Quando canais são auto-criados e não existem durante a sincronização, este usuário se tornará automaticamente o administrador do canal.", - "LDAP_Sync_User_Data_Groups_AutoChannels_Description": "Habilite esta funcionalidade para incluir automaticamente usuários a um canal baseado no seu grupo LDAP. Se você também gostaria de remover usuários de um canal, veja a opção abaixo sobre a auto-remoção de usuários.", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap": "Mapeamento do Canal / Grupo LDAP", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Default": "// Habilitar Auto Sincronização de Grupos LDAP para Canais acima", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Description": "Mapeie grupos LDAP para canais Rocket.Chat.
Por exemplo, `{\"funcionario\":\"geral\"}` irá incluir qualquer usuário do grupo LDAP funcionario ao canal geral.", - "LDAP_Sync_User_Data_Groups_AutoRemove": "Auto Remover Papéis de Usuário", - "LDAP_Sync_User_Data_Groups_AutoRemove_Description": "**Atenção**: Habilitando isso removerá automaticamente usuário de um papel se eles não são atribuídos no LDAP! Só serão removidos automaticamente papéis que são definidos no mapeamento de dados de usuário abaixo", - "LDAP_Sync_User_Data_Groups_BaseDN": "BaseDN do Grupo LDAP", - "LDAP_Sync_User_Data_Groups_BaseDN_Description": "A BaseDN LDAP usada para procurar usuários.", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels": "Remover Automaticamente Usuários de Canais", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels_Description": "**Atenção**: Habilitando isso, irá remover quaisquer usuários em um canal que não possui o grupo LDAP correspondente! Habilite apenas se você sabe o que está fazendo.", - "LDAP_Sync_User_Data_Groups_Filter": "Filtro de Grupo de Usuário", - "LDAP_Sync_User_Data_Groups_Filter_Description": "O filtro de busca LDAP usado para verificar se um usuário está em um grupo.", - "LDAP_Sync_User_Data_GroupsMap": "Mapeamento de Grupo de Dados de Usuário", - "LDAP_Sync_User_Data_GroupsMap_Description": "Mapeia grupos LDAP para papeis de usuário Rocket.Chat
Por exemplo, `{\"rocket-admin\":\"admin\", \"suporte-tecnico\":\"suporte\"}` irá mapear o grupo LDAP rocket-admin para o papel \"admin\" do Rocket.Chat.", - "LDAP_Test_Connection": "Testar Conexão", + "LDAP_Sync_User_Data_Channels": "Sincronizar automaticamente Grupos LDAP para Canais", + "LDAP_Sync_User_Data_Channels_Description": "Habilite esta funcionalidade para incluir automaticamente usuários a um canal baseado no seu grupo LDAP. Se você também gostaria de remover usuários de um canal, veja a opção abaixo sobre a auto-remoção de usuários.", + "LDAP_Sync_User_Data_Channels_Admin": "Administrador do Canal", + "LDAP_Sync_User_Data_Channels_Admin_Description": "Quando canais são auto-criados e não existem durante a sincronização, este usuário se tornará automaticamente o administrador do canal.", + "LDAP_Sync_User_Data_Channels_BaseDN": "BaseDN do Grupo LDAP", + "LDAP_Sync_User_Data_Channels_BaseDN_Description": "A BaseDN LDAP usada para procurar usuários.", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels": "Remover Automaticamente Usuários de Canais", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels_Description": "**Atenção**: Habilitando isso, irá remover quaisquer usuários em um canal que não possui o grupo LDAP correspondente! Habilite apenas se você sabe o que está fazendo.", + "LDAP_Sync_User_Data_Channels_Filter": "Filtro de Grupo de Usuário", + "LDAP_Sync_User_Data_Channels_Filter_Description": "O filtro de busca LDAP usado para verificar se um usuário está em um grupo.", + "LDAP_Sync_User_Data_ChannelsMap": "Mapeamento do Canal / Grupo LDAP", + "LDAP_Sync_User_Data_ChannelsMap_Description": "Mapeie grupos LDAP para canais Rocket.Chat.
Por exemplo, `{\"funcionario\":\"geral\"}` irá incluir qualquer usuário do grupo LDAP funcionario ao canal geral.", + "LDAP_Sync_User_Data_Roles": "Sincronizar Grupos LDAP", + "LDAP_Sync_User_Data_Roles_AutoRemove": "Auto Remover Papéis de Usuário", + "LDAP_Sync_User_Data_Roles_AutoRemove_Description": "**Atenção**: Habilitando isso removerá automaticamente usuário de um papel se eles não são atribuídos no LDAP! Só serão removidos automaticamente papéis que são definidos no mapeamento de dados de usuário abaixo", + "LDAP_Sync_User_Data_Roles_BaseDN": "BaseDN do Grupo LDAP", + "LDAP_Sync_User_Data_Roles_BaseDN_Description": "A BaseDN LDAP usada para procurar usuários.", + "LDAP_Sync_User_Data_Roles_Filter": "Filtro de Grupo de Usuário", + "LDAP_Sync_User_Data_Roles_Filter_Description": "O filtro de busca LDAP usado para verificar se um usuário está em um grupo.", + "LDAP_Sync_User_Data_RolesMap": "Mapeamento de Grupo de Dados de Usuário", + "LDAP_Sync_User_Data_RolesMap_Description": "Mapeia grupos LDAP para papeis de usuário Rocket.Chat
Por exemplo, `{\"rocket-admin\":\"admin\", \"suporte-tecnico\":\"suporte\"}` irá mapear o grupo LDAP rocket-admin para o papel \"admin\" do Rocket.Chat.", "LDAP_Timeout": "Tempo limite (ms)", "LDAP_Timeout_Description": "Qual tempo limite esperar por um resultado de pesquisa antes de retornar um erro", "LDAP_Unique_Identifier_Field": "Campo Identificador Único", @@ -2524,8 +2514,6 @@ "LDAP_Username_Field_Description": "O campo que será usado como nome de usuário ( *username* ) para novos usuários. Deixe em branco para usar o nome de usuário informado na página de login.
Você pode usar tags de template também, como `#{givenName}.#{sn}`.
O valor padrão é `sAMAccountName`.", "LDAP_Validate_Teams_For_Each_Login": "Validar o mapeamento em cada login", "LDAP_Validate_Teams_For_Each_Login_Description": "Determina se equipes de usuários devem ser atualizados toda vez que eles autenticam no Rocket.Chat. Se isso for desligado, a equipe será carregada apenas no seu primeiro login", - "LDAP_Validate_Roles_For_Each_Login": "Validar o mapeamento em cada login", - "LDAP_Validate_Roles_For_Each_Login_Description": " Se a validação deve ser feita a cada login(Tenha cuidado com essa configuração, pois ela vai sobrescrever os papéis de usuário a cada login, caso esteja desabilitado, a validação será feita apenas no momento da criação do usuário).", "Lead_capture_email_regex": "Regex de e-mail de captura de lead", "Lead_capture_phone_regex": "Regex de telefone de captura de lead", "Leave": "Sair", diff --git a/packages/rocketchat-i18n/i18n/pt.i18n.json b/packages/rocketchat-i18n/i18n/pt.i18n.json index d89425b3fe2c..d8064be604e9 100644 --- a/packages/rocketchat-i18n/i18n/pt.i18n.json +++ b/packages/rocketchat-i18n/i18n/pt.i18n.json @@ -1790,7 +1790,6 @@ "LDAP_Connect_Timeout": "Tempo limite de conexão (ms)", "LDAP_Default_Domain": "Domínio Padrão", "LDAP_Default_Domain_Description": "Se fornecido, o Domínio Padrão será usado para criar um e-mail exclusivo para utilizadores onde o e-mail não foi importado do LDAP. O e-mail será montado como `username @ default_domain` ou` unique_id @ default_domain`.
Exemplo: `rocket.chat`", - "LDAP_Description": "LDAP é um banco de dados hierárquico que muitas empresas usam para fornecer single sign on - uma facilidade para compartilhar uma senha entre múltiplos sites e serviços. Para exemplos e informações de configurações avançadas, por favor consulte nosso wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/", "LDAP_Enable": "Habilitar", "LDAP_Enable_Description": "Tente utilizar LDAP para autenticação", "LDAP_Encryption": "Criptografia", @@ -1832,11 +1831,6 @@ "LDAP_Sync_Now": "Sincronização de fundo agora", "LDAP_Sync_Now_Description": "Executa o ** Sincronização de fundo ** agora em vez de aguardar o ** Intervalo de sincronização ** mesmo se ** Sincronização de fundo ** for Falso.
Esta ação é assíncrona, veja os logs para obter mais informações sobre o processo", "LDAP_Sync_User_Avatar": "Sincronizar Avatar dos Utilizadores", - "LDAP_Sync_User_Data": "Manter dados dos utilizadores sincronizados", - "LDAP_Sync_User_Data_Description": "Mantenha seus dados de utilizador em sincronia logando no servidor (ex.: nome, email).", - "LDAP_Sync_User_Data_FieldMap": "Mapeamento de campos do utilizador", - "LDAP_Sync_User_Data_FieldMap_Description": "Configure como os campos da conta de utilizador (tipo email) serão populados no LDAP (quando encontrados).
Por exemplo, `{\"cn\":\"name\", \"mail\":\"email\"}` irá selecionar o nome do utilizador do atributo cn, e o seu e-mail do atributo mail.
Os campos disponíveis incluem `name`, `email` e `customFields`.", - "LDAP_Test_Connection": "Testar Conexão", "LDAP_Timeout": "Tempo limite (ms)", "LDAP_Timeout_Description": "Quantos quilómetros de milhas esperam por um resultado de pesquisa antes de retornar um erro", "LDAP_Unique_Identifier_Field": "Campo Identificador Único", diff --git a/packages/rocketchat-i18n/i18n/ro.i18n.json b/packages/rocketchat-i18n/i18n/ro.i18n.json index c9f87b0e5c2f..f7be4ab0d7e6 100644 --- a/packages/rocketchat-i18n/i18n/ro.i18n.json +++ b/packages/rocketchat-i18n/i18n/ro.i18n.json @@ -1517,7 +1517,6 @@ "LDAP_Connect_Timeout": "Timp de conectare (ms)", "LDAP_Default_Domain": "Domeniu implicit", "LDAP_Default_Domain_Description": "Dacă este furnizat, Domeniul implicit va fi utilizat pentru a crea un e-mail unic pentru utilizatorii în care e-mailul nu a fost importat din LDAP. Emailul va fi montat ca \"username @ default_domain\" sau \"unique_id @ default_domain\".
Exemplu: `rocket.chat`", - "LDAP_Description": "LDAP este o bază de date ierarhică pe care multe companii o folosesc pentru a oferi osingură  parolă pe mai multe site-uri și servicii. Pentru informații și exemple de configurare avansate, vă rugăm să consultați wiki nostru: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Activați", "LDAP_Enable_Description": "Încearcă să utilizezi LDAP pentru autentificare.", "LDAP_Encryption": "Encriptare", @@ -1559,11 +1558,6 @@ "LDAP_Sync_Now": "Background Sync Now", "LDAP_Sync_Now_Description": "Va executa ** Sincronizarea de fundal ** acum, mai degrabă decât să așteptați ** Intervalul de sincronizare ** chiar dacă ** Sincronizarea de fundal ** este Falsă.
Această acțiune este asincronă, vă rugăm să consultați jurnalele pentru mai multe informații despre proces", "LDAP_Sync_User_Avatar": "Sincronizare Avatar utilizator", - "LDAP_Sync_User_Data": "Sync Data", - "LDAP_Sync_User_Data_Description": "Păstrați datele utilizatorului în sincron cu serverul de autentificare (de exemplu: nume, e-mail).", - "LDAP_Sync_User_Data_FieldMap": "User Data Field Map", - "LDAP_Sync_User_Data_FieldMap_Description": "Configurați modul în care detalii ale contului de utilizator (cum ar fi e-mail-ul) sunt populate de o înregistrare LDAP (odată găsită).
De exemplu, {\"cn\": \"Numele\", \"e-mail\": \"e-mail\"} va alege numele unei persoane ce poate fi citit de la atributul cn, și e-mail lor de atributul e-mail.
Detaliile disponibile includ numele și e-mail.", - "LDAP_Test_Connection": "Test conexiune", "LDAP_Timeout": "Timeout (ms)", "LDAP_Timeout_Description": "Câte milesecunde așteaptă un rezultat al căutării înainte de a reveni la o eroare", "LDAP_Unique_Identifier_Field": "Identificator unic câmp", diff --git a/packages/rocketchat-i18n/i18n/ru.i18n.json b/packages/rocketchat-i18n/i18n/ru.i18n.json index 5eadac8ddbc7..7713aa32bc4e 100644 --- a/packages/rocketchat-i18n/i18n/ru.i18n.json +++ b/packages/rocketchat-i18n/i18n/ru.i18n.json @@ -2431,12 +2431,8 @@ "LDAP_Connect_Timeout": "Таймаут соединения (мсек)", "LDAP_Default_Domain": "Домен по умолчанию", "LDAP_Default_Domain_Description": "Если при условии, что домен по умолчанию будет использоваться для создания уникального письма для пользователей, где электронная почта не была импортирована из LDAP. Электронная почта будет установлена как `username @ default_domain` или` unique_id @ default_domain`.
Пример: `rocket.chat`", - "LDAP_Default_Role_To_User": "Роль по умолчанию для пользователя", - "LDAP_Default_Role_To_User_Description": "Роль RC по умолчанию, которая будет применяться к пользователю, если у пользователя есть какая-то не сопоставленная LDAP роль.", - "LDAP_Description": "Протокол LDAP - это иерархическая база данных, которую используют многие компании для обеспечения единой регистрации - средство для совместного использования одного пароля для разных сайтов и сервисов. Для подробной информации по конфигурации читайте нашу wiki-страницу: https://rocket.chat/docs/administrator-guides/authentication/ldap/ ", "LDAP_Enable": "Включить LDAP", "LDAP_Enable_Description": "Попытка использовать LDAP для аутентификации.", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "Включение сопоставления ролей из LDAP в Rocket.Chat", "LDAP_Enable_LDAP_Groups_To_RC_Teams": "Включение сопоставления команды из LDAP в Rocket.Chat", "LDAP_Encryption": "Шифрование", "LDAP_Encryption_Description": "Метод шифрования, используемый для обеспечения связи с сервером LDAP. Примеры включают в себя «plain» (без шифрования), «SSL / LDAPS» (зашифрованные с самого начала) и «StartTLS» (обновление до зашифрованной связи после подключения).", @@ -2467,15 +2463,11 @@ "LDAP_Merge_Existing_Users_Description": "*Внимание!* При импорте пользователя из LDAP, если пользователь с таким логином уже существует, данные из LDAP и пароль будут установлены уже существующему пользователю.", "LDAP_Port": "LDAP порт", "LDAP_Port_Description": "Порт для доступа LDAP. Пример: `389` или `636` для LDAPS", - "LDAP_Query_To_Get_User_Groups": "LDAP запрос для получения групп пользователей", - "LDAP_Query_To_Get_User_Groups_Description": "LDAP запрос для получения LDAP групп, членом которых является пользователь.", "LDAP_Query_To_Get_User_Teams": "LDAP запрос для получения групп пользователей", "LDAP_Reconnect": "Переподключение", "LDAP_Reconnect_Description": "Пробовать переподключаться автоматически, когда соединение прервано по каким-то причинам во время выполнения операций", "LDAP_Reject_Unauthorized": "Отклонить неавторизованных", "LDAP_Reject_Unauthorized_Description": "Отключите эту опцию, чтобы разрешить сертификаты, которые не могут быть проверены. Обычно для работы с самоподписанными сертификатами требуется отключение это опции", - "LDAP_Roles_To_Rocket_Chat_Roles": "Сопоставление ролей из LDAP в Rocket.Chat.", - "LDAP_Roles_To_Rocket_Chat_Roles_Description": "Сопоставление ролей в формате объектов, где ключ объекта должен быть LDAP ролью, а значение объекта должно быть массивом RC ролей. Пример: { 'ldapRole': ['rcRole', 'anotherRCRole'] }", "LDAP_Search_Page_Size": "Размер страницы поиска", "LDAP_Search_Page_Size_Description": "Максимальное количество записей, которое отображается на странице", "LDAP_Search_Size_Limit": "Ограничение размера поиска", @@ -2488,29 +2480,28 @@ "LDAP_Sync_User_Active_State_Disable": "Отключить пользователей", "LDAP_Sync_User_Active_State_Nothing": "Ничего не делать", "LDAP_Sync_User_Avatar": "Синхронизация пользовательских аватаров", - "LDAP_Sync_User_Data": "Синхронизация пользовательских данных", - "LDAP_Sync_User_Data_Description": "Синхронизировать пользовательские данные с сервером при входе (например: имя, адрес электронной почты).", - "LDAP_Sync_User_Data_FieldMap": "Карта пользовательских данных", - "LDAP_Sync_User_Data_FieldMap_Description": "Настраивайте то, как будут заполняться поля аккаунта пользователя (такие как адрес электронной почты) из записи в LDAP (как только будет найден).
Например `{\"cn\":\"name\", \"mail\":\"email\"}` выберет человекочитаемое имя человека из атрибута \"cn\", и его адрес электронной почты – из атрибута \"mail\". Дополнительно возможно использовать переменные, например: `{ \"#{givenName} #{sn}\": \"name\", \"mail\": \"email\" }` использует комбинацию имени и фамилии пользователя для поля `name` в Rocket.Chat.
В Rocket.Chat доступны поля `name` и `email`.", - "LDAP_Sync_User_Data_Groups": "Синхронизация групп LDAP", - "LDAP_Sync_User_Data_Groups_AutoChannels": "Автоматическая синхронизация групп LDAP с Channelами", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "Channel Администратор", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin_Description": "Когда автоматически создаются каналы, которые не существуют во время синхронизации, этот пользователь автоматически становится администратором канала.", - "LDAP_Sync_User_Data_Groups_AutoChannels_Description": "Включите эту функцию, чтобы автоматически добавлять пользователей в канал на основе их группы LDAP. Если вы также хотите удалить пользователей из канала, см. Параметр ниже об автоматическом удалении пользователей.", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap": "Карта группы LDAP Channel", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Default": "// Автоматическая синхронизация групп LDAP с Channelами выше", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Description": "Сопоставьте группы LDAP с каналами Rocket.Chat.
Например, `{\"employee\":\"general\"}` добавит любого пользователя из группы сотрудников LDAP в общий канал.", - "LDAP_Sync_User_Data_Groups_AutoRemove": "Автоматическое удаление пользовательских ролей", - "LDAP_Sync_User_Data_Groups_AutoRemove_Description": "** Внимание **: Включение этого автоматически удалит пользователей из роли, если они не назначены в LDAP! Это приведет к автоматическому удалению только тех ролей, которые установлены под картой группы пользовательских данных ниже.", - "LDAP_Sync_User_Data_Groups_BaseDN": "LDAP Группы BaseDN", - "LDAP_Sync_User_Data_Groups_BaseDN_Description": "LDAP BaseDN используется для поиска пользователей.", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels": "Автоматическое удаление пользователей из Channelов", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels_Description": "** Внимание **: Включение этого удалит всех пользователей в канале, у которых нет соответствующей группы LDAP! Включите это, только если вы знаете, что делаете.", - "LDAP_Sync_User_Data_Groups_Filter": "Фильтр Группы Пользователей", - "LDAP_Sync_User_Data_Groups_Filter_Description": "Фильтр поиска LDAP используется для проверки того, входит ли пользователь в группу.", - "LDAP_Sync_User_Data_GroupsMap": "Карта группы пользовательских данных", - "LDAP_Sync_User_Data_GroupsMap_Description": "Сопоставьте группы LDAP с ролями пользователей Rocket.Chat
В качестве примера `{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}` сопоставит группу LDAP rocket-admin с ролью \"admin\" в Rocket Chat.", - "LDAP_Test_Connection": "Протестировать соединение", + "LDAP_Sync_User_Data_Roles": "Синхронизация групп LDAP", + "LDAP_Sync_User_Data_Channels": "Автоматическая синхронизация групп LDAP с Channelами", + "LDAP_Sync_User_Data_Channels_Admin": "Channel Администратор", + "LDAP_Sync_User_Data_Channels_Admin_Description": "Когда автоматически создаются каналы, которые не существуют во время синхронизации, этот пользователь автоматически становится администратором канала.", + "LDAP_Sync_User_Data_Channels_BaseDN": "LDAP Группы BaseDN", + "LDAP_Sync_User_Data_Channels_BaseDN_Description": "LDAP BaseDN используется для поиска пользователей.", + "LDAP_Sync_User_Data_Channels_Description": "Включите эту функцию, чтобы автоматически добавлять пользователей в канал на основе их группы LDAP. Если вы также хотите удалить пользователей из канала, см. Параметр ниже об автоматическом удалении пользователей.", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels": "Автоматическое удаление пользователей из Channelов", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels_Description": "** Внимание **: Включение этого удалит всех пользователей в канале, у которых нет соответствующей группы LDAP! Включите это, только если вы знаете, что делаете.", + "LDAP_Sync_User_Data_Channels_Filter": "Фильтр Группы Пользователей", + "LDAP_Sync_User_Data_Channels_Filter_Description": "Фильтр поиска LDAP используется для проверки того, входит ли пользователь в группу.", + "LDAP_Sync_User_Data_ChannelsMap": "Карта группы LDAP Channel", + "LDAP_Sync_User_Data_ChannelsMap_Default": "// Автоматическая синхронизация групп LDAP с Channelами выше", + "LDAP_Sync_User_Data_ChannelsMap_Description": "Сопоставьте группы LDAP с каналами Rocket.Chat.
Например, `{\"employee\":\"general\"}` добавит любого пользователя из группы сотрудников LDAP в общий канал.", + "LDAP_Sync_User_Data_Roles_AutoRemove": "Автоматическое удаление пользовательских ролей", + "LDAP_Sync_User_Data_Roles_AutoRemove_Description": "** Внимание **: Включение этого автоматически удалит пользователей из роли, если они не назначены в LDAP! Это приведет к автоматическому удалению только тех ролей, которые установлены под картой группы пользовательских данных ниже.", + "LDAP_Sync_User_Data_Roles_BaseDN": "LDAP Группы BaseDN", + "LDAP_Sync_User_Data_Roles_BaseDN_Description": "LDAP BaseDN используется для поиска пользователей.", + "LDAP_Sync_User_Data_Roles_Filter": "Фильтр Группы Пользователей", + "LDAP_Sync_User_Data_Roles_Filter_Description": "Фильтр поиска LDAP используется для проверки того, входит ли пользователь в группу.", + "LDAP_Sync_User_Data_RolesMap": "Карта группы пользовательских данных", + "LDAP_Sync_User_Data_RolesMap_Description": "Сопоставьте группы LDAP с ролями пользователей Rocket.Chat
В качестве примера `{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}` сопоставит группу LDAP rocket-admin с ролью \"admin\" в Rocket Chat.", "LDAP_Timeout": "Тайм-аут (мс)", "LDAP_Timeout_Description": "Сколько миллисекунд ждать результата поиска, прежде чем вернуть ошибку", "LDAP_Unique_Identifier_Field": "Поле уникального идентификатора", @@ -2524,8 +2515,6 @@ "LDAP_Username_Field_Description": "Какое поле будет устанавливаться в качестве логина для новых пользователей. Оставьте поле пустым, чтобы использовать логин, введенный на странице входа.
Вы также можете использовать теги шаблонов, например `#{givenName}.#{sn}`.
Значение по умолчанию - `sAMAccountName`.", "LDAP_Validate_Teams_For_Each_Login": "Проверка соответствия для каждого входа", "LDAP_Validate_Teams_For_Each_Login_Description": "Определите, следует ли обновлять команды пользователей при каждом входе в Rocket.Chat. Если эта функция отключена, то команда будет загружаться только при первом входе в систему.", - "LDAP_Validate_Roles_For_Each_Login": "Проверка соответствия для каждого входа", - "LDAP_Validate_Roles_For_Each_Login_Description": "Если проверка должна происходить для каждого входа в систему (Будьте осторожны с этой настройкой, потому что она будет перезаписывать роли пользователя при каждом входе в систему, в противном случае проверка будет производиться только в момент создания пользователя).", "Lead_capture_email_regex": "Регулярное перемещение по электронной почте", "Lead_capture_phone_regex": "Повторное использование", "Leave": "Покинуть", diff --git a/packages/rocketchat-i18n/i18n/sk-SK.i18n.json b/packages/rocketchat-i18n/i18n/sk-SK.i18n.json index 817518070318..4573634c40a0 100644 --- a/packages/rocketchat-i18n/i18n/sk-SK.i18n.json +++ b/packages/rocketchat-i18n/i18n/sk-SK.i18n.json @@ -1529,7 +1529,6 @@ "LDAP_Connect_Timeout": "Časový limit pripojenia (ms)", "LDAP_Default_Domain": "Predvolená doména", "LDAP_Default_Domain_Description": "Ak je predvolená doména použitá na vytvorenie jedinečného e-mailu pre používateľov, ktorých e-mail nebol importovaný z LDAP. E-mail bude pripojený ako \"username @ default_domain\" alebo \"unique_id @ default_domain\".
Príklad: `rocket.chat`", - "LDAP_Description": "LDAP je hierarchická databáza, ktorú mnohé spoločnosti používajú na poskytovanie jednotného prihlásenia - zariadenie na zdieľanie jedného hesla medzi viacerými webmi a službami. Podrobnejšie informácie o konfigurácii a príklady nájdete v našom wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "umožniť", "LDAP_Enable_Description": "Pokúste sa použiť protokol LDAP na autentifikáciu.", "LDAP_Encryption": "šifrovanie", @@ -1571,11 +1570,6 @@ "LDAP_Sync_Now": "Synchronizácia pozadia teraz", "LDAP_Sync_Now_Description": "Spustí sa ** Synchronizácia pozadia ** namiesto toho, aby sa počkať ** Interval synchronizácie **, aj keď ** Synchronizácia pozadia ** je nepravdivá.
Táto akcia je asynchrónna, viac informácií nájdete v protokoloch proces", "LDAP_Sync_User_Avatar": "Synchronizovať používateľa Avatar", - "LDAP_Sync_User_Data": "Synchronizácia používateľských údajov", - "LDAP_Sync_User_Data_Description": "Uchovávajte používateľské dáta v synchronizácii so serverom ** pri prihlasovaní ** alebo ** pri synchronizácii pozadia ** (napr .: meno, e-mail).", - "LDAP_Sync_User_Data_FieldMap": "Mapová mapa používateľských údajov", - "LDAP_Sync_User_Data_FieldMap_Description": "Nakonfigurujte, ako sa polia používateľských kont (ako e-mail) vyplnia z záznamu v LDAP (akonáhle sa nájde).
Napríklad meno `` `cn ':' name ',' mail ':' email '}` si vyberie ľudské čitateľné meno z atribútu cn a jeho e-mail z atribútu mail. Okrem toho je možné použiť premenné, napríklad: \"{\" # {givenName} # {sn} \":\" name \",\" mail \":\" email \"} používa kombináciu mena a priezviska používateľa raketový chat `meno 'pole.
Dostupné polia v Rocket.Chat:` name`, `email` a` customFields`.", - "LDAP_Test_Connection": "Test pripojenia", "LDAP_Timeout": "Časový limit (ms)", "LDAP_Timeout_Description": "Koľko kilometrov za sekundu čaká na výsledok vyhľadávania pred vrátením chyby", "LDAP_Unique_Identifier_Field": "Jedinečné pole identifikátora", diff --git a/packages/rocketchat-i18n/i18n/sl-SI.i18n.json b/packages/rocketchat-i18n/i18n/sl-SI.i18n.json index 4d5c8552a786..a2a3af5fdcfe 100644 --- a/packages/rocketchat-i18n/i18n/sl-SI.i18n.json +++ b/packages/rocketchat-i18n/i18n/sl-SI.i18n.json @@ -1509,7 +1509,6 @@ "LDAP_Connect_Timeout": "Časovna omejitev povezave (ms)", "LDAP_Default_Domain": "Privzeta domena", "LDAP_Default_Domain_Description": "Če boste s privzeto domeno, ki je na voljo, uporabnikom ustvarili enolični e-poštni naslov, pri čemer e-poštni naslov ni uvožen iz protokola LDAP. Ta e-poštni naslov bo ustvarjen kot `username@default_domain` ali `unique_id@default_domain`.
Primer: `rocket.chat`", - "LDAP_Description": "Protokol LDAP je hierarhična zbirka podatkov, ki jo številna podjetja uporabljajo, da zagotovijo možnost enega vpisa – možnost, ki omogoča, da si različne spletne strani in storitve delijo eno geslo. Za dodatne informacije o konfiguraciji in primere, si oglejte: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Omogoči", "LDAP_Enable_Description": "Poskus izkoriščanja LDAP za preverjanje pristnosti.", "LDAP_Encryption": "Šifriranje", @@ -1551,11 +1550,6 @@ "LDAP_Sync_Now": "Sinhroniziraj v ozadju zdaj", "LDAP_Sync_Now_Description": "Boste izvedli ** Background Sync ** zdaj, namesto da počakate ** sinhronizacijski interval **, tudi če je ** sinhronizacija v ozadju ** napačna.
To dejanje je asinhrono, prosimo, preglejte dnevnike za več informacij o procesu", "LDAP_Sync_User_Avatar": "Sinhroniziraj uporabniškega avatarja", - "LDAP_Sync_User_Data": "Sinhroniziraj uporabniške podatke", - "LDAP_Sync_User_Data_Description": "Ohranite uporabniške podatke v sinhronizaciji s strežnikom na ** login ** ali na ** sinhronizaciji ozadja ** (npr. Ime, e-pošta).", - "LDAP_Sync_User_Data_FieldMap": "Polje uporabniških podatkov", - "LDAP_Sync_User_Data_FieldMap_Description": "Konfigurirajte, kako so polja z uporabniškim računom (na primer e-poštni naslov) naseljena iz zapisa v LDAP (ko je bilo najdeno).
Na primer, `{\" cn \":\" ime \",\" pošta \":\" e-pošta \"}} bo izbrala človeško berljivo ime iz atributa cn in njihovo e-pošto iz atributa pošte. Poleg tega je mogoče uporabiti spremenljivke, na primer: \"{\" # {givenName} # {sn} \":\" ime \",\" pošta \":\" e-pošta \"}\" uporablja kombinacijo uporabniškega imena in priimka za raketni klepet `ime` polje.
Razpoložljiva polja v Rocket.Chat:` name`, `email` in` customFields`.", - "LDAP_Test_Connection": "Preveri povezavo", "LDAP_Timeout": "Časovna omejitev (ms)", "LDAP_Timeout_Description": "Koliko milisekunde počaka na rezultat iskanja, preden vrne napako", "LDAP_Unique_Identifier_Field": "Polje enoličnega identifikatorja", diff --git a/packages/rocketchat-i18n/i18n/sq.i18n.json b/packages/rocketchat-i18n/i18n/sq.i18n.json index cc2d1a95d60f..5112033f08c1 100644 --- a/packages/rocketchat-i18n/i18n/sq.i18n.json +++ b/packages/rocketchat-i18n/i18n/sq.i18n.json @@ -1516,7 +1516,6 @@ "LDAP_Connect_Timeout": "Koha e lidhjes (ms)", "LDAP_Default_Domain": "Domain Default", "LDAP_Default_Domain_Description": "Nëse jepet Domaini i Parazgjedhur do të përdoret për të krijuar një email të veçantë për përdoruesit ku nuk u importua email nga LDAP. Emaili do të instalohet si `username @ default_domain` ose` unique_id @ default_domain`.
Shembull: `rocket.chat`", - "LDAP_Description": "LDAP është një bazë të dhënash hierarkike se shumë kompani përdorin për të dhënë shenjë të vetme në - një strukturë për të ndarë një fjalëkalim në mes të vendeve të shumta dhe të shërbimeve. Për informacion të avancuara konfigurimi dhe shembuj, ju lutem konsultoni wiki tonë: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "mundësoj", "LDAP_Enable_Description": "Përpjekje për të shfrytëzuar LDAP për autentikim.", "LDAP_Encryption": "encryption", @@ -1558,11 +1557,6 @@ "LDAP_Sync_Now": "Historiku i sinkronizimit tani", "LDAP_Sync_Now_Description": "Do të ekzekutojë ** Sync Historiku ** tani, në vend se të presë ** Sync Interval ** edhe nëse ** Sinkronizimi i Historikut ** është i Falsifikuar.
Ky Aksion është asinkron, ju lutem shihni shkrimet për më shumë informacion rreth proces", "LDAP_Sync_User_Avatar": "Sync User Avatar", - "LDAP_Sync_User_Data": "Sync Të dhënat", - "LDAP_Sync_User_Data_Description": "Të mbajtur të dhënat e përdoruesit në sync me server në hyrje (p.sh: emri, email).", - "LDAP_Sync_User_Data_FieldMap": "User Data Map Field", - "LDAP_Sync_User_Data_FieldMap_Description": "Konfiguro si fusha e llogarisë përdoruesit (si email) janë të populluar nga një rekord në LDAP (sapo gjetur).
Si një shembull, `{\" cn \":\" Emri \",\" postë \":\" email \"} 'do të zgjedhë emrin e një personi njerëzor lexueshëm nga atribut cn dhe adresën e tyre nga postës atribut.
Fushat e vlefshme përfshijnë `name`, dhe` email`.", - "LDAP_Test_Connection": "Test Connection", "LDAP_Timeout": "Kohëzgjatja (ms)", "LDAP_Timeout_Description": "Sa milje milje prisni për një rezultat kërkimi para se të ktheheni një gabim", "LDAP_Unique_Identifier_Field": "Unique Identifier Field", diff --git a/packages/rocketchat-i18n/i18n/sr.i18n.json b/packages/rocketchat-i18n/i18n/sr.i18n.json index 267fa0735035..e76fbbe64f1c 100644 --- a/packages/rocketchat-i18n/i18n/sr.i18n.json +++ b/packages/rocketchat-i18n/i18n/sr.i18n.json @@ -1268,7 +1268,6 @@ "LDAP_Connect_Timeout": "Временска конекција (мс)", "LDAP_Default_Domain": "Уобичајено Домен", "LDAP_Default_Domain_Description": "Ако се подразумева, подразумевани домен ће се користити за креирање јединственог е-поште за кориснике у којима е-пошта није увезена из ЛДАП-а. Е-маил ће бити постављен као `усернаме @ дефаулт_домаин` или` уникуе_ид @ дефаулт_домаин`.
Пример: `роцкет.цхат`", - "LDAP_Description": "ЛДАП је хијерархијска база података која многе компаније користе да би обезбедили јединствени знак на - објекат за размену једну лозинку између више локација и услуга. За напредне информације о конфигурацији и примере, погледајте наш вики: хттпс://гитхуб.цом/РоцкетЦхат/Роцкет.Цхат/вики/ЛДАП-Аутхентицатион.", "LDAP_Enable": "омогућити", "LDAP_Enable_Description": "Покушај да се користе ЛДАП за потврду идентитета.", "LDAP_Encryption": "Шифровање", @@ -1306,8 +1305,6 @@ "LDAP_Sync_Now": "Синхронизација позадине сада", "LDAP_Sync_Now_Description": "Хоће ли извршити ** Бацкгроунд Синц ** сада уместо да чека ** Интервал синхронизације ** чак и ако је ** Бацкгроунд Синц ** неисправан.
Ова акција је асинхроно, молимо погледајте дневнике за више информација о процес", "LDAP_Sync_User_Avatar": "Синхронизуј корисничке аватаре", - "LDAP_Sync_User_Data": "Синхронизуј корисничке податке", - "LDAP_Test_Connection": "Тестирај везу", "LDAP_Timeout": "Тимеоут (мс)", "LDAP_Timeout_Description": "Колико милесецондс чека резултат претраге пре повратка грешке", "LDAP_Unique_Identifier_Field": "Јединствени идентификатор Поље", diff --git a/packages/rocketchat-i18n/i18n/sv.i18n.json b/packages/rocketchat-i18n/i18n/sv.i18n.json index f7039d7f6124..ce06db4d70dc 100644 --- a/packages/rocketchat-i18n/i18n/sv.i18n.json +++ b/packages/rocketchat-i18n/i18n/sv.i18n.json @@ -1590,7 +1590,6 @@ "LDAP_Connect_Timeout": "Connection Timeout (ms)", "LDAP_Default_Domain": "Standarddomän", "LDAP_Default_Domain_Description": "Om det tillhandahålls kommer Default Domain att användas för att skapa ett unikt e-postmeddelande för användare där e-post inte importerades från LDAP. E-postmeddelandet kommer att monteras som `användarnamn @ default_domain` eller` unique_id @ default_domain`.
Exempel: `rocket.chat`", - "LDAP_Description": "LDAP är en hierarkisk databas som många företag använder för att tillhandahålla enkel inloggning - ett sätt att dela ett lösenord mellan flera webbplatser och tjänster. För avancerad konfiguration. information och exempel, titta i vår wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Aktivera", "LDAP_Enable_Description": "Försök att använda LDAP för autentisering.", "LDAP_Encryption": "kryptering", @@ -1632,11 +1631,6 @@ "LDAP_Sync_Now": "Bakgrundssynkronisering nu", "LDAP_Sync_Now_Description": "Kommer att utföra ** Bakgrundssynkronisering ** nu istället för att vänta på ** Sync Interval ** även om ** Bakgrundssynkronisering ** är Falsk.
Denna åtgärd är asynkron, se loggarna för mer information om bearbeta", "LDAP_Sync_User_Avatar": "Sync User Avatar", - "LDAP_Sync_User_Data": "Synka data", - "LDAP_Sync_User_Data_Description": "Håll användardata i synk med servern vid inloggning ( t.ex. namn, e-post ).", - "LDAP_Sync_User_Data_FieldMap": "Användardatafält Karta", - "LDAP_Sync_User_Data_FieldMap_Description": "Konfigurera hur användarkonto fält (som e-post) fylls från en post i LDAP (en gång hittade).
Som ett exempel, `{\" cn \":\" namn \",\" post \":\" email \"} 'kommer att välja en persons mänskligt läsbar namn från cn attribut och deras e-post från e-postattribut.
Tillgängliga fält inkluderar `name` och` email`.", - "LDAP_Test_Connection": "Testa anslutning", "LDAP_Timeout": "Timeout (ms)", "LDAP_Timeout_Description": "Hur många mileseconds väntar på ett sökresultat innan ett fel returneras", "LDAP_Unique_Identifier_Field": "Unique Identifier Field", diff --git a/packages/rocketchat-i18n/i18n/ta-IN.i18n.json b/packages/rocketchat-i18n/i18n/ta-IN.i18n.json index c9b4f4efc254..23e2142fae94 100644 --- a/packages/rocketchat-i18n/i18n/ta-IN.i18n.json +++ b/packages/rocketchat-i18n/i18n/ta-IN.i18n.json @@ -1516,7 +1516,6 @@ "LDAP_Connect_Timeout": "இணைப்பு காலம் கடந்தது (ms)", "LDAP_Default_Domain": "இயல்புநிலை களப்", "LDAP_Default_Domain_Description": "LDAP இலிருந்து மின்னஞ்சல் இறக்குமதி செய்யப்படாத பயனர்களுக்கான ஒரு தனிப்பட்ட மின்னஞ்சலை உருவாக்க இயல்புநிலை டொமைன் வழங்கப்பட்டிருந்தால். மின்னஞ்சல் பயனர்பெயர் @ default_domain` அல்லது `unique_id @ default_domain` என ஏற்றப்படும்.
உதாரணம்:` rocket.chat`", - "LDAP_Description": "பல தளங்கள் மற்றும் சேவைகள் இடையே ஒரு கடவுச்சொல்லை பகிர்ந்து ஒரு வசதி - LDAP, பல நிறுவனங்கள் ஒற்றை அடையாளம் வழங்க பயன்படுத்த என்று ஒரு படிநிலை தரவுத்தள உள்ளது. https://rocket.chat/docs/administrator-guides/authentication/ldap/: மேம்பட்ட கட்டமைப்பு தகவல் மற்றும் உதாரணங்கள், எங்கள் விக்கி கலந்தாலோசிக்கவும்.", "LDAP_Enable": "இயக்கு", "LDAP_Enable_Description": "அங்கீகார க்கான LDAP பயன்படுத்த முயற்சிக்கும்.", "LDAP_Encryption": "குறியாக்க", @@ -1558,11 +1557,6 @@ "LDAP_Sync_Now": "பின்புல ஒத்திசைவு", "LDAP_Sync_Now_Description": "** ஒத்திசைவு இடைவேளை ** பின்னணி ஒத்திசைவு ** காத்திருக்காமல் ** பின்னணி ஒத்திசைவை ** நிறைவேற்றும் ** பின்னணி ஒத்திசைவு ** தவறானது.
இந்தச் செயல் ஒத்திசையற்றது, மேலும் செயல்முறை", "LDAP_Sync_User_Avatar": "ஒத்திசைவு பதிவர்", - "LDAP_Sync_User_Data": "ஒத்திசைவு தரவு", - "LDAP_Sync_User_Data_Description": "உள்நுழைவு சர்வர் ஒத்திசைந்து பயனர் தரவை வைத்திருக்கவும் (எ.கா.: பெயர், மின்னஞ்சல்).", - "LDAP_Sync_User_Data_FieldMap": "பயனர் தகவல்கள் களம் வரைபடம்", - "LDAP_Sync_User_Data_FieldMap_Description": "பயனர் கணக்கு துறைகள் (மின்னஞ்சல் போன்ற) LDAP இல் ஒரு சாதனை இருந்து மக்கள் எப்படி கட்டமைக்க (ஒரு முறை காணப்படுகிறது).
உதாரணமாக, `{\" cn \"என்பது:\" பெயர் \",\" மெயில் \":\" மின்னஞ்சல் \"}: CN பண்பு இருந்து ஒரு நபரின் மனித வாசிக்கக்கூடிய பெயர், மற்றும் மெயில் பண்பு தங்கள் மின்னஞ்சல் தேர்வு செய்யும்.
கிடைக்க துறைகள் name`, மற்றும் `email` அடங்கும்:.", - "LDAP_Test_Connection": "சோதனை இணைப்பு", "LDAP_Timeout": "நேரம் (மி)", "LDAP_Timeout_Description": "ஒரு பிழை திரும்பும் முன் எத்தனை Mileseconds ஒரு தேடல் முடிவு காத்திருக்கிறது", "LDAP_Unique_Identifier_Field": "தனித்துவ அடையாளங்காட்டி களம்", diff --git a/packages/rocketchat-i18n/i18n/th-TH.i18n.json b/packages/rocketchat-i18n/i18n/th-TH.i18n.json index 95b09c8cd479..c530a39c2886 100644 --- a/packages/rocketchat-i18n/i18n/th-TH.i18n.json +++ b/packages/rocketchat-i18n/i18n/th-TH.i18n.json @@ -1513,7 +1513,6 @@ "LDAP_Connect_Timeout": "หมดเวลาการเชื่อมต่อ (มิลลิวินาที)", "LDAP_Default_Domain": "โดเมนเริ่มต้น", "LDAP_Default_Domain_Description": "หากระบุโดเมนเริ่มต้นจะใช้เพื่อสร้างอีเมลที่ไม่ซ้ำกันสำหรับผู้ใช้ที่ไม่ได้นำเข้าอีเมลจาก LDAP อีเมลจะได้รับการติดตั้งเป็น `username @ default_domain` หรือ` unique_id @ default_domain`.
ตัวอย่าง: `rocket.chat`", - "LDAP_Description": "LDAP เป็นฐานข้อมูลแบบลำดับชั้นที่หลาย บริษัท ใช้ในการจัดเตรียมการลงชื่อเพียงครั้งเดียวเพื่ออำนวยความสะดวกในการแชร์รหัสผ่านระหว่างเว็บไซต์และบริการต่างๆ สำหรับข้อมูลการกำหนดค่าขั้นสูงและตัวอย่างโปรดปรึกษาวิกิของเราที่ https://rocket.chat/docs/administrator-guides/authentication/ldap/", "LDAP_Enable": "ทำให้สามารถ", "LDAP_Enable_Description": "พยายามใช้ LDAP เพื่อการตรวจสอบสิทธิ์", "LDAP_Encryption": "การเข้ารหัสลับ", @@ -1555,11 +1554,6 @@ "LDAP_Sync_Now": "พื้นหลังซิงค์เดี๋ยวนี้", "LDAP_Sync_Now_Description": "จะใช้งาน ** Background Sync ** แทนรอ ** Sync Interval ** แม้ว่า ** Background Sync ** จะเป็นเท็จ
แอ็คชันนี้ไม่ตรงกันโปรดดูบันทึกสำหรับข้อมูลเพิ่มเติมเกี่ยวกับ กระบวนการ", "LDAP_Sync_User_Avatar": "ซิงค์ Avatar ผู้ใช้", - "LDAP_Sync_User_Data": "ซิงค์ข้อมูลผู้ใช้", - "LDAP_Sync_User_Data_Description": "เก็บข้อมูลผู้ใช้ให้ตรงกันกับเซิร์ฟเวอร์ใน ** login ** หรือ ** sync พื้นหลัง ** (เช่นชื่ออีเมล)", - "LDAP_Sync_User_Data_FieldMap": "แผนที่ช่องข้อมูลผู้ใช้", - "LDAP_Sync_User_Data_FieldMap_Description": "กำหนดค่าฟิลด์ผู้ใช้ของบัญชีผู้ใช้ (เช่นอีเมล) จากระเบียนใน LDAP (พบครั้งเดียว)
ตัวอย่างเช่น `{'cn\": \"name\", \"mail\": \"email\"} `จะเลือกชื่อที่มนุษย์สามารถอ่านได้จากแอตทริบิวต์ cn และอีเมลจากแอตทริบิวต์ mail นอกจากนี้คุณยังสามารถใช้ตัวแปรเช่น `{\" # {givenName} # {sn} \":\" name \",\" mail \":\" email \"}` ใช้ชื่อและนามสกุลของผู้ใช้สำหรับ จรวดแชทชื่อ `field.
ช่องที่มีใน Rocket.Chat:` name`, `email` และ` customFields`", - "LDAP_Test_Connection": "ทดสอบการเชื่อมต่อ", "LDAP_Timeout": "หมดเวลา (มิลลิวินาที)", "LDAP_Timeout_Description": "ไมล์สะสมเท่าไหร่รอผลการค้นหาก่อนที่จะส่งข้อผิดพลาด", "LDAP_Unique_Identifier_Field": "ฟิลด์ตัวระบุที่ไม่ซ้ำ", diff --git a/packages/rocketchat-i18n/i18n/tr.i18n.json b/packages/rocketchat-i18n/i18n/tr.i18n.json index c8f809a5db62..f9a3fcc1376e 100644 --- a/packages/rocketchat-i18n/i18n/tr.i18n.json +++ b/packages/rocketchat-i18n/i18n/tr.i18n.json @@ -1818,7 +1818,6 @@ "LDAP_Connect_Timeout": "Bağlantı Zaman Aşımı (ms)", "LDAP_Default_Domain": "Varsayılan Alan Adı", "LDAP_Default_Domain_Description": "Varsayılan Etki Alanı, e-postanın LDAP'den içe aktarılmadığı kullanıcılar için benzersiz bir e-posta oluşturmak üzere kullanılacaktır. E-posta `username @ default_domain` veya 'unique_id @ default_domain` olarak bağlanacaktır.
Örnek:` rocket.chat`", - "LDAP_Description": "Birden çok site ve hizmetler arasında bir parola paylaşımı için bir tesis - LDAP birçok şirket üzerinde tek oturum sağlamak için kullanmak hiyerarşik veritabanı. https://rocket.chat/docs/administrator-guides/authentication/ldap/: gelişmiş yapılandırma bilgi ve örnekler için, bizim wiki danışın.", "LDAP_Enable": "Etkinleştir", "LDAP_Enable_Description": "Kimlik doğrulama için LDAP kullanmak için deneyin.", "LDAP_Encryption": "Şifreleme", @@ -1860,12 +1859,7 @@ "LDAP_Sync_Now": "Arka Plan Senkronize Edilsin", "LDAP_Sync_Now_Description": "** Arka Plan Senkronizasyonu ** yanlış olsa bile ** Eşzamanlı Aralığı ** beklemek yerine şu an ** Arka Plan Senkronizasyonu ** uygulayacaktır.
Bu İşlem eşzamansızdır, lütfen bu işlem hakkında daha fazla bilgi için günlüklere bakın. süreç", "LDAP_Sync_User_Avatar": "Kullanıcı Avatarını Senkronize Et", - "LDAP_Sync_User_Data": "Verileri Senkronize Et", - "LDAP_Sync_User_Data_Description": "girişte sunucu ile senkronize kullanıcı verilerini tutmak (örneğin: isim, e-posta).", - "LDAP_Sync_User_Data_FieldMap": "Kullanıcı Veri Alanı Haritası", - "LDAP_Sync_User_Data_Groups": "LDAP", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "Kanal Yöneticisi", - "LDAP_Test_Connection": "Test Bağlantısı", + "LDAP_Sync_User_Data_Channels_Admin": "Kanal Yöneticisi", "LDAP_Timeout": "Zaman aşımı (ms)", "LDAP_Timeout_Description": "Bir hata döndürmeden önce bir arama sonucunu kaç dakika bekleyecektir?", "LDAP_Unique_Identifier_Field": "Benzersiz Tanımlayıcı Alan", diff --git a/packages/rocketchat-i18n/i18n/ug.i18n.json b/packages/rocketchat-i18n/i18n/ug.i18n.json index 5be663a91469..8d505891675a 100644 --- a/packages/rocketchat-i18n/i18n/ug.i18n.json +++ b/packages/rocketchat-i18n/i18n/ug.i18n.json @@ -597,7 +597,6 @@ "LDAP_BaseDN_Description": ".تىكى يۇقىرى دەرىجىلىك مۇندەرىجىنى ئاساسىي تورنامى قىلىپ ئىشلىتىشنى تەكلىپ قىلىمىز .تۆۋەنكى 'بەلگىلەنگەن تورنامى ئىزدەش'تاللاش شەرتىگە ئاساسەن ئەزا چەكلەش ئېلىپ بېرىڭ. .LDAP .ئاستىدىكى ئەزانىلا ئىزدىيەلەيدۇ.DNنىڭ ئاساسىي تور نامى بولىشىنى ئەگەر سىز چەكلىگەن بولسىڭىز بۇ ۋاقىتتا پەقەت بۇ DN.نى سىز كۆپرەپ قاتسىڭىز بولىدۇ لېكىن گۇرۇپپا ۋە گۇرۇپپا ئىچىدە ئەزا نامى چوقۇم بىر تورنامى ئاستىدا بولىشى كېرەك DN .نىڭ تارماق دەرىخى ئىچىدىن ئەزا ۋە گۇرۇپ ئىزدىشىگە قولايلىق بولىدۇ .LDAP نىڭ DNبۇنداق بولغاندا (Domain Base)نى تولدۇرۇپ ئۇنى ئاساسى توربەت نامىد قىددلىڭ ،DNئىناۋەتلىك", "LDAP_CA_Cert": "CA گۇۋاھنامىسى", "LDAP_Default_Domain": "بەلگىلەنگەن تور نامى", - "LDAP_Description": "ئادەتتە شىركەتلەر تەرىپىدىن ئاددىي نۇقتا كىرىش مېخانىزىمى قىلىپ قوللىنىدۇ .بۇ خىلمېخانىزىم بىر ئەزانى ئوخشاش بىر يۈرۈش ھېسابات نومۇرى ۋە مەخپىي نومۇر ئارقىلىق كۆپلىگەن تور بەت ۋەمۇلازىمەتكە كىرگىلى بولىدۇ.كۆپلىگەن LDAPگۇۋاھنامىسىنى تەڭشەش ۋە مىساللىرىنى ئىچكىرى چۈشەنمەكچى بولسىڭىز بىزنىڭ wikiتور بېتىمىزدىن پايدىلانسىڭىز بولىدۇ https://rocket.chat/docs/administrator-guides/authentication/ldap/ (ېنىك مۇندەرىجىنى زىيارەت قىلىش كېلىشىمى)LDAP", "LDAP_Enable": "قوزغىتىش", "LDAP_Enable_Description": "ئارقىلىق سالاھىيەتنى تەكشۈرۈشنى سىناش.LDAP", "LDAP_Encryption": "مەخپىيلەشتۈرۈش ئۇسۇلى", @@ -608,11 +607,6 @@ "LDAP_Port_Description": "`389` ياكى `636`ئېغىزى . مەسلەن :LDAP", "LDAP_Reject_Unauthorized": "ھوقۇق بېرىلمىگىنىنى رەت قىلىش", "LDAP_Sync_User_Avatar": "ئەزا باش سۈرئەتنى قەدەملەشتۈرۈش", - "LDAP_Sync_User_Data": "سانلىق مەلۇماتنى قەدەملەشتۈرۈش", - "LDAP_Sync_User_Data_Description": "(مەسىلەن ، ئىسىم فامىلە ، ئىلخەت ئادرېس.) كىرگەندە ئەزانىڭ سانلىق مەلۇماتى بىلەن مۇلازىمىتېرنى قەدەملەشتۈرۈش", - "LDAP_Sync_User_Data_FieldMap": "ئەزانىڭ سانلىق مەلۇمات بۆلىكىنى قايتۇرما ئەكس ئېتىش", - "LDAP_Sync_User_Data_FieldMap_Description": "设置用户数据字段(比如 E-mail)来自 LDAP 何处(如果能找到)。
;例如:`{\"cn\":\"name\", \"mail\":\"email\"}` 会从属性 cn 中取出名字字段,从 mail 属性中取出 email 字段。
有效字段包括 `name` 和 `email`。", - "LDAP_Test_Connection": "ئۇلاشنى سىناش", "LDAP_Unique_Identifier_Field": "بىردىنبىر تونۇيدىغان خەت بۆلىكى", "LDAP_Unique_Identifier_Field_Description": "`objectGUID,ibm-entryUUID,GUID,dominoUNID,nsuniqueId,uidNumber` بەلگىلەنگەن قىممتى بولسا :
تىكى ئەزا ئۇچۇرىنى ئۇلاش Rocket.Chat ۋە LDAPقايسى خەت بۆلىكىنى ئىشلىتىپ", "LDAP_User_Search_Field_Description": "نى ئىشلەتسە بولىدۇ .`sAMAccountName,mail` مەسلەن بىر ۋاقىتتا ئوخشاش ئەزا نامى ۋە ئىلخەت ئادرېسىنى دەللىلەش ھېسابات نومۇرى قىلسا،
ئەگەر بىر ۋاقىتتا كۆپ خىل دەلىللەش ئىشلىتىلسە ، پەش ئارقىلىق خەت بۆلەك ئىسمىنى ئايرىپ تۇرسا بولىدۇ .
خەت بۆلىكىنى ئىشلىتىشى مۇمكىن .`uid` بولسا OpenLDAP ھەل قىلىش پىلانلىرى مەسلەن LDAPخەت بۆلىكى ئىشلىتىدۇ .لېكىن باشقا `sAMAccountName` نى ئېلىپ ئېيتقاندا ، كۆپ ئەھۋالدا Windows AD خۇسۇسىيتى كىرگۈچىنىڭ خەت بۆلىكىنى تونۇشقا ئىشلىتىلىدۇ.LDAPبۇ", diff --git a/packages/rocketchat-i18n/i18n/uk.i18n.json b/packages/rocketchat-i18n/i18n/uk.i18n.json index 65ba3bd6e5b9..9057d2d5f636 100644 --- a/packages/rocketchat-i18n/i18n/uk.i18n.json +++ b/packages/rocketchat-i18n/i18n/uk.i18n.json @@ -1986,8 +1986,6 @@ "LDAP_Connect_Timeout": "Час очікування з'єднання (мс)", "LDAP_Default_Domain": "Домен за замовчуванням", "LDAP_Default_Domain_Description": "Якщо надано, Domain Default буде використовуватися для створення унікальної електронної пошти для користувачів, де електронна пошта не була імпортована з LDAP. Електронна пошта буде встановлена як `ім'якористувача@default_domain` або`unique_id@default_domain`.
Приклад: `rocket.chat`", - "LDAP_Default_Role_To_User": "Роль користувача за замовчуванням", - "LDAP_Description": "LDAP є ієрархічною базу даних, що багато компаній використовують для забезпечення єдиного входу - об'єкта для спільного використання одного пароля між декількома сайтами і послугами. Для отримання попередньої інформації про конфігурацію і приклади, будь ласка, зверніться до нашої вікі: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "включити", "LDAP_Enable_Description": "Спроба використовувати LDAP для аутентифікації.", "LDAP_Encryption": "шифрування", @@ -2029,20 +2027,16 @@ "LDAP_Sync_Now": "Фонова синхронізація зараз", "LDAP_Sync_Now_Description": "Буде виконано **Background Sync**, а не очікувати **Sync Interval**, навіть якщо **Background Sync** є False.
Цей захід є асинхронним, перегляньте журнали для отримання додаткової інформації про процес", "LDAP_Sync_User_Avatar": "Синхронізація Аватар користувача", - "LDAP_Sync_User_Data": "Синхронізація даних", - "LDAP_Sync_User_Data_Description": "Зберігати дані користувача в синхронізації з сервером при вході в систему (наприклад: ім'я, адреса електронної пошти).", - "LDAP_Sync_User_Data_FieldMap": "Дані користувача Карта Поле", - "LDAP_Sync_User_Data_FieldMap_Description": "Налаштування, як поля облікових записів користувачів (наприклад, електронної пошти) заповнюються із запису в LDAP (колись знайшла).
Як приклад, `{\" сп \":\" ім'я \",\" пошта \":\" електронна пошта \"}` буде вибрати удобочитаем ім'я людини з атрибута CN, і їх електронну пошту від атрибута пошти.
Доступні поля включають `name` і` email`.", - "LDAP_Sync_User_Data_Groups": "Синхронізація груп LDAP", - "LDAP_Sync_User_Data_Groups_AutoChannels": "Автоматична синхронізація груп LDAP до Channel", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "Адміністратор Channel", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin_Description": "При автоматичному створенні каналів, які не існують під час синхронізації, цей користувач автоматично стає адміністратором каналу.", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Description": "Позначити групи LDAP на каналах Rocket.Chat.
Як приклад, `{\"employee\":\"general\"}` додасть будь-якого користувача, LDAP групи employee, до каналу general", - "LDAP_Sync_User_Data_Groups_AutoRemove": "Автоматичне видалення ролей користувача", - "LDAP_Sync_User_Data_Groups_AutoRemove_Description": "** Увага **: Увімкнення, автоматично видалить користувачів із ролі, якщо вони не призначені в LDAP! Це видалить лише автоматичні ролі, які встановлені нижче на карті групи даних користувачів.", - "LDAP_Sync_User_Data_Groups_Filter": "Фільтр груп користувачів", - "LDAP_Sync_User_Data_GroupsMap": "Карта групи даних користувачів", - "LDAP_Test_Connection": "Тестове підключення", + "LDAP_Sync_User_Data_Roles": "Синхронізація груп LDAP", + "LDAP_Sync_User_Data_Channels": "Автоматична синхронізація груп LDAP до Channel", + "LDAP_Sync_User_Data_Channels_Admin": "Адміністратор Channel", + "LDAP_Sync_User_Data_Channels_Admin_Description": "При автоматичному створенні каналів, які не існують під час синхронізації, цей користувач автоматично стає адміністратором каналу.", + "LDAP_Sync_User_Data_Channels_Filter": "Фільтр груп користувачів", + "LDAP_Sync_User_Data_ChannelsMap_Description": "Позначити групи LDAP на каналах Rocket.Chat.
Як приклад, `{\"employee\":\"general\"}` додасть будь-якого користувача, LDAP групи employee, до каналу general", + "LDAP_Sync_User_Data_Roles_AutoRemove": "Автоматичне видалення ролей користувача", + "LDAP_Sync_User_Data_Roles_AutoRemove_Description": "** Увага **: Увімкнення, автоматично видалить користувачів із ролі, якщо вони не призначені в LDAP! Це видалить лише автоматичні ролі, які встановлені нижче на карті групи даних користувачів.", + "LDAP_Sync_User_Data_Roles_Filter": "Фільтр груп користувачів", + "LDAP_Sync_User_Data_RolesMap": "Карта групи даних користувачів", "LDAP_Timeout": "Тайм-аут (мс)", "LDAP_Timeout_Description": "Скільки миль-секунд чекає результат пошуку перед тим, як повернути помилку", "LDAP_Unique_Identifier_Field": "Поле унікального ідентифікатора", diff --git a/packages/rocketchat-i18n/i18n/vi-VN.i18n.json b/packages/rocketchat-i18n/i18n/vi-VN.i18n.json index 95a091741f2b..149f8024cb3d 100644 --- a/packages/rocketchat-i18n/i18n/vi-VN.i18n.json +++ b/packages/rocketchat-i18n/i18n/vi-VN.i18n.json @@ -1507,7 +1507,6 @@ "LDAP_Connect_Timeout": "Thời gian chờ kết nối (ms)", "LDAP_Default_Domain": "Tên miền mặc định", "LDAP_Default_Domain_Description": "Nếu được cung cấp Tên miền Mặc định sẽ được sử dụng để tạo một email duy nhất cho người dùng khi email không được nhập từ LDAP. Email sẽ được gắn kết dưới dạng `username @ default_domain` hoặc` unique_id @ default_domain`.
Ví dụ: `rocket.chat`", - "LDAP_Description": "LDAP là một cơ sở dữ liệu có thứ bậc mà nhiều công ty sử dụng để cung cấp single sign on - một cơ sở để chia sẻ một mật khẩu giữa nhiều trang web và dịch vụ. Để biết thông tin cấu hình nâng cao và các ví dụ, vui lòng tham khảo wiki của chúng tôi: https://rocket.chat/docs/administrator-guides/authentication/ldap/.", "LDAP_Enable": "Bật", "LDAP_Enable_Description": "Cố gắng sử dụng LDAP để xác thực.", "LDAP_Encryption": "Mã hóa", @@ -1549,11 +1548,6 @@ "LDAP_Sync_Now": "Đồng bộ hóa ngay bây giờ", "LDAP_Sync_Now_Description": "Sẽ thực hiện **Background Sync** thay vì chờ **Sync Interval** ngay cả khi **Background Sync** là Sai.
Tác vụ này không đồng bộ, vui lòng xem nhật ký để biết thêm thông tin về quá trình", "LDAP_Sync_User_Avatar": "Đồng bộ hóa Hình đại diện Người dùng", - "LDAP_Sync_User_Data": "Đồng bộ hóa dữ liệu người dùng", - "LDAP_Sync_User_Data_Description": "Giữ dữ liệu người dùng đồng bộ với máy chủ trên ** đăng nhập ** hoặc trên ** nền đồng bộ ** (ví dụ: tên, email).", - "LDAP_Sync_User_Data_FieldMap": "FieldMap dữ liệu người dùng", - "LDAP_Sync_User_Data_FieldMap_Description": "Cấu hình cách các trường tài khoản người dùng (như email) được populate từ một bản ghi trong LDAP (khi tìm thấy).
Ví dụ: `{\" cn \":\" tên \",\" mail \":\" email \"}` sẽ chọn tên người có thể đọc được của một người từ thuộc tính cn và email của họ từ thuộc tính mail. Ngoài ra, có thể sử dụng các biến, ví dụ: `{\" # {givenName} # {sn} \":\" tên \",\" mail \":\" email \"}` sử dụng kết hợp tên và họ của người dùng cho tên Rocket.Chat.
Các trường có sẵn trong Rocket.Chat: `name`,` email` và `customFields`.", - "LDAP_Test_Connection": "Kiểm tra kết nối", "LDAP_Timeout": "Thời gian chờ (ms)", "LDAP_Timeout_Description": "Bao lâu mili giây chờ đợi cho một kết quả tìm kiếm trước khi trả về lỗi", "LDAP_Unique_Identifier_Field": "Trường nhận dạng duy nhất", diff --git a/packages/rocketchat-i18n/i18n/zh-HK.i18n.json b/packages/rocketchat-i18n/i18n/zh-HK.i18n.json index 402ae60efcb5..17434b84a6c0 100644 --- a/packages/rocketchat-i18n/i18n/zh-HK.i18n.json +++ b/packages/rocketchat-i18n/i18n/zh-HK.i18n.json @@ -1537,7 +1537,6 @@ "LDAP_Connect_Timeout": "连接超时(毫秒)", "LDAP_Default_Domain": "默认域", "LDAP_Default_Domain_Description": "如果提供了默认域,将用于为未从LDAP导入电子邮件的用户创建唯一的电子邮件。该电子邮件将被安装为“username @ default_domain”或“unique_id @ default_domain”。
示例:`rocket.chat`", - "LDAP_Description": "LDAP是许多公司用来提供单点登录的分层数据库 - 用于在多个站点和服务之间共享一个密码的工具。有关高级配置信息和示例,请参阅我们的wiki:https://rocket.chat/docs/administrator-guides/authentication/ldap/。", "LDAP_Enable": "启用", "LDAP_Enable_Description": "尝试使用LDAP进行身份验证。", "LDAP_Encryption": "加密", @@ -1579,11 +1578,6 @@ "LDAP_Sync_Now": "后台立即同步", "LDAP_Sync_Now_Description": "将立即执行**后台同步**,而不是等待** Sync Interval **,即使**后台同步**为假。
此操作是异步的,请参阅日志以获取有关处理", "LDAP_Sync_User_Avatar": "同步用户头像", - "LDAP_Sync_User_Data": "同步用户数据", - "LDAP_Sync_User_Data_Description": "保持用户数据与**登录**或**后台同步**(例如:姓名,电子邮件)服务器同步。", - "LDAP_Sync_User_Data_FieldMap": "用户数据字段映射", - "LDAP_Sync_User_Data_FieldMap_Description": "配置用户帐户字段(如电子邮件)如何从LDAP中的记录填充(一旦找到)。
举例来说,`{“cn”:“name”,“mail”:“email”}`将从cn属性中选择一个人的可读名称,并从mail属性中选择他们的电子邮件。此外,还可以使用变量,例如:`{“#{givenName}#{sn}”:“name”,“mail”:“email”}`使用用户的名字和姓氏的组合火箭聊天`name`字段。
Rocket.Chat中的可用字段:`name`,`email`和`customFields`。", - "LDAP_Test_Connection": "测试连接", "LDAP_Timeout": "超时(ms)", "LDAP_Timeout_Description": "在返回错误之前等待搜索结果多少英里", "LDAP_Unique_Identifier_Field": "唯一标识符字段", diff --git a/packages/rocketchat-i18n/i18n/zh-TW.i18n.json b/packages/rocketchat-i18n/i18n/zh-TW.i18n.json index eb81399b764f..4ee53566f3cb 100644 --- a/packages/rocketchat-i18n/i18n/zh-TW.i18n.json +++ b/packages/rocketchat-i18n/i18n/zh-TW.i18n.json @@ -2366,12 +2366,8 @@ "LDAP_Connect_Timeout": "連接超時(毫秒)", "LDAP_Default_Domain": "預設網域", "LDAP_Default_Domain_Description": "如果提供了預設網域,將用於為未從LDAP導入電子郵件的用戶建立唯一的電子郵件。該電子郵件將被安裝為 “username@default_domain” 或 “unique_id@default_domain”。
例如:`rocket.chat`", - "LDAP_Default_Role_To_User": "給使用者的預設角色", - "LDAP_Default_Role_To_User_Description": "如果使用者具有某些未對應的 LDAP 身份,則將套用於使用者的預設 RC 身份。", - "LDAP_Description": "LDAP 是一個分層資料庫,許多公司使用它來提供單點登入 - 一種在多個站點和服務之間共享一個密碼的工具。有關進階設定資訊跟範例,請參閱我們的wiki:https://rocket.chat/docs/administrator-guides/authentication/ldap/。", "LDAP_Enable": "啟用", "LDAP_Enable_Description": "試著使用 LDAP 進行身份驗證。", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "啟用從 LDAP 到 Rocket.Chat 的對應身份", "LDAP_Enable_LDAP_Groups_To_RC_Teams": "啟用從 LDAP 到 Rocket.Chat 的團隊映射", "LDAP_Encryption": "加密", "LDAP_Encryption_Description": "用來保護通信到 LDAP 伺服器的加密方法。例如包括`plain`(不加密),`SSL / LDAPS`(從一開始加密)和`StartTLS`(升級到一旦連結就加密通信)。", @@ -2402,15 +2398,11 @@ "LDAP_Merge_Existing_Users_Description": "*警告!*當從 LDAP 匯入使用者並且具有相同使用者名稱的使用者已經存在時,LDAP 訊息和密碼將被設置到現有使用者中。", "LDAP_Port": "連接埠", "LDAP_Port_Description": "LDAP 連接埠。例如:\"389\" 或 \"636\"", - "LDAP_Query_To_Get_User_Groups": "LDAP 查詢以取得使用者群組", - "LDAP_Query_To_Get_User_Groups_Description": "LDAP 查詢以取得使用者所屬的 LDAP 群組。", "LDAP_Query_To_Get_User_Teams": "LDAP 查詢以取得使用者群組", "LDAP_Reconnect": "重新連接", "LDAP_Reconnect_Description": "嘗試在執行操作時由於某種原因中斷連接時自動重新連接", "LDAP_Reject_Unauthorized": "拒絕未經授權", "LDAP_Reject_Unauthorized_Description": "禁用此選項以允許無法驗證的證書。通常,自簽名證書將要求禁用此選項才能工作", - "LDAP_Roles_To_Rocket_Chat_Roles": "從 LDAP 到 Rocket.Chat 的對應身份。", - "LDAP_Roles_To_Rocket_Chat_Roles_Description": "對象格式的對應身份,其中對象鍵必須是 LDAP 身份,並且對象值必須是 RC 身份群組。例如:{ 'ldapRole': ['rcRole', 'anotherRCRole'] }", "LDAP_Search_Page_Size": "搜尋頁面大小", "LDAP_Search_Page_Size_Description": "每個結果頁面的最大條目數將返回進行處理", "LDAP_Search_Size_Limit": "搜尋大小限制", @@ -2423,29 +2415,28 @@ "LDAP_Sync_User_Active_State_Disable": "停用使用者", "LDAP_Sync_User_Active_State_Nothing": "不做任何事", "LDAP_Sync_User_Avatar": "同步使用者大頭貼", - "LDAP_Sync_User_Data": "同步使用者資料", - "LDAP_Sync_User_Data_Description": "在登入時保持與伺服器的使用者資料同步。(例如姓名或電子郵件)", - "LDAP_Sync_User_Data_FieldMap": "使用者資料欄位對應", - "LDAP_Sync_User_Data_FieldMap_Description": "配置如何從LDAP中的記錄(一旦找到)填充用戶帳戶字段(如電子郵件)。
例如,`{\"cn\":\"name\", \"mail\":\"email\"}`將從cn屬性中選擇一個人的可讀名稱,並從mail屬性中選擇他們的電子郵件。此外,可以使用變量,例如:`{ \"#{givenName}#{sn}“:”name“,”mail“:”email“}`使用使用者的名字和姓氏的組合進行Rocket.Chat` name`字段。
Rocket.Chat中的可用字段:`name`,`email`和`customFields`。", - "LDAP_Sync_User_Data_Groups": "同步 LDAP 群組", - "LDAP_Sync_User_Data_Groups_AutoChannels": "自動同步 LDAP 群組到 Channel", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "Channel 管理員", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin_Description": "當自動建立在同步期間不存在的頻道時,此使用者將自動成為頻道的管理員。", - "LDAP_Sync_User_Data_Groups_AutoChannels_Description": "啟用此功能可根據使用者的 LDAP 群組自動將群組增加到頻道。如果您還要從頻道中刪除使用者,請參閱下面有關自動刪除使用者的選項。", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap": "LDAP 群組 Channel 對應", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Default": "// 啟用自動同步LDAP組到上面的 Channel", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Description": "將 LDAP 群組對應到 Rocket.Chat 頻道。
例如,`{\"employee\":\"general\"}`會將 LDAP 群組員工中的任何使用者增加到標準頻道。", - "LDAP_Sync_User_Data_Groups_AutoRemove": "自動移除使用者角色", - "LDAP_Sync_User_Data_Groups_AutoRemove_Description": "**注意**:如果未在 LDAP 中分配使用者,啟用此功能將自動從角色中刪除使用者!這將僅自動刪除在下面的使用者資料群組對應下設置的角色。", - "LDAP_Sync_User_Data_Groups_BaseDN": "LDAP 群組 BaseDN", - "LDAP_Sync_User_Data_Groups_BaseDN_Description": "LDAP BaseDN 已使用在查詢使用者上。", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels": "自動從 Channel 移除使用者", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels_Description": "**注意**:啟用此功能將刪除頻道中沒有coorosponding LDAP 群組的所有使用者!只有在你知道自己在做什麼的情況下才能啟用它。", - "LDAP_Sync_User_Data_Groups_Filter": "使用者群組過濾", - "LDAP_Sync_User_Data_Groups_Filter_Description": "LDAP 搜尋過濾已使用在假如使用者在群組時檢查。", - "LDAP_Sync_User_Data_GroupsMap": "使用者資料群組對應", - "LDAP_Sync_User_Data_GroupsMap_Description": "將 LDAP 群組對應到 Rocket.Chat 使用者角色
例如,`{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}`將 rocket-admin LDAP 群組對應到Rocket 的 “admin” 角色。", - "LDAP_Test_Connection": "測試連線", + "LDAP_Sync_User_Data_Roles": "同步 LDAP 群組", + "LDAP_Sync_User_Data_Channels": "自動同步 LDAP 群組到 Channel", + "LDAP_Sync_User_Data_Channels_Admin": "Channel 管理員", + "LDAP_Sync_User_Data_Channels_Admin_Description": "當自動建立在同步期間不存在的頻道時,此使用者將自動成為頻道的管理員。", + "LDAP_Sync_User_Data_Channels_BaseDN": "LDAP 群組 BaseDN", + "LDAP_Sync_User_Data_Channels_BaseDN_Description": "LDAP BaseDN 已使用在查詢使用者上。", + "LDAP_Sync_User_Data_Channels_Description": "啟用此功能可根據使用者的 LDAP 群組自動將群組增加到頻道。如果您還要從頻道中刪除使用者,請參閱下面有關自動刪除使用者的選項。", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels": "自動從 Channel 移除使用者", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels_Description": "**注意**:啟用此功能將刪除頻道中沒有coorosponding LDAP 群組的所有使用者!只有在你知道自己在做什麼的情況下才能啟用它。", + "LDAP_Sync_User_Data_Channels_Filter": "使用者群組過濾", + "LDAP_Sync_User_Data_Channels_Filter_Description": "LDAP 搜尋過濾已使用在假如使用者在群組時檢查。", + "LDAP_Sync_User_Data_ChannelsMap": "LDAP 群組 Channel 對應", + "LDAP_Sync_User_Data_ChannelsMap_Default": "// 啟用自動同步LDAP組到上面的 Channel", + "LDAP_Sync_User_Data_ChannelsMap_Description": "將 LDAP 群組對應到 Rocket.Chat 頻道。
例如,`{\"employee\":\"general\"}`會將 LDAP 群組員工中的任何使用者增加到標準頻道。", + "LDAP_Sync_User_Data_Roles_AutoRemove": "自動移除使用者角色", + "LDAP_Sync_User_Data_Roles_AutoRemove_Description": "**注意**:如果未在 LDAP 中分配使用者,啟用此功能將自動從角色中刪除使用者!這將僅自動刪除在下面的使用者資料群組對應下設置的角色。", + "LDAP_Sync_User_Data_Roles_BaseDN": "LDAP 群組 BaseDN", + "LDAP_Sync_User_Data_Roles_BaseDN_Description": "LDAP BaseDN 已使用在查詢使用者上。", + "LDAP_Sync_User_Data_Roles_Filter": "使用者群組過濾", + "LDAP_Sync_User_Data_Roles_Filter_Description": "LDAP 搜尋過濾已使用在假如使用者在群組時檢查。", + "LDAP_Sync_User_Data_RolesMap": "使用者資料群組對應", + "LDAP_Sync_User_Data_RolesMap_Description": "將 LDAP 群組對應到 Rocket.Chat 使用者角色
例如,`{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}`將 rocket-admin LDAP 群組對應到Rocket 的 “admin” 角色。", "LDAP_Timeout": "逾時(毫秒)", "LDAP_Timeout_Description": "在返回錯誤之前等待搜尋結果要多少毫秒", "LDAP_Unique_Identifier_Field": "唯一標識欄位", @@ -2459,8 +2450,6 @@ "LDAP_Username_Field_Description": "這將被用於為*使用者名稱*為新使用者。留空使用的使用者名告知登錄頁面上。
您可以使用模板標籤太像`#{givenName}.#{sn}`。
預設值是`sAMAccountName`。", "LDAP_Validate_Teams_For_Each_Login": "驗證每個登入名的對應", "LDAP_Validate_Teams_For_Each_Login_Description": "確定是否應該在使用者每次登入 Rocket.Chat 時更新使用者的團隊。如果關閉此選項,團隊將僅在他們第一次登入時載入。", - "LDAP_Validate_Roles_For_Each_Login": "驗證每個登入名的對應", - "LDAP_Validate_Roles_For_Each_Login_Description": "如果每次登入都要進行驗證(請謹慎使用此設定,因為它將覆寫每次登入中的使用者身份,否則僅在建立使用者時進行驗證)。", "Lead_capture_email_regex": "最先抓取電子郵件正規表示法", "Lead_capture_phone_regex": "最先抓取手機號碼正規表示法", "Leave": "離開", diff --git a/packages/rocketchat-i18n/i18n/zh.i18n.json b/packages/rocketchat-i18n/i18n/zh.i18n.json index ecbc73616aa1..b310a29d5aaa 100644 --- a/packages/rocketchat-i18n/i18n/zh.i18n.json +++ b/packages/rocketchat-i18n/i18n/zh.i18n.json @@ -2246,12 +2246,8 @@ "LDAP_Connect_Timeout": "连接超时(ms)", "LDAP_Default_Domain": "默认域名", "LDAP_Default_Domain_Description": "如果提供了默认域,将用于为未从LDAP导入电子邮件的用户创建唯一的电子邮件。该电子邮件将被安装为“username@default_domain”或“unique_id@default_domain”。
示例:`rocket.chat`", - "LDAP_Default_Role_To_User": "用户默认角色", - "LDAP_Default_Role_To_User_Description": "如果用户拥有未映射的 LDAP 角色,则用户将会应用默认的 RC 角色。", - "LDAP_Description": "LDAP(轻量目录访问协议)是一种层次数据库,常被企业用于提供单点登录机制——该机制允许用户使用同一套帐号密码登录多个网站或服务。想要了解LDAP认证的设置及示例,可参考我们的wiki页: https://rocket.chat/docs/administrator-guides/authentication/ldap/", "LDAP_Enable": "启用", "LDAP_Enable_Description": "尝试使用 LDAP 进行身份验证。", - "LDAP_Enable_LDAP_Roles_To_RC_Roles": "启用由 LDAP 到 Rocket.Chat 的角色映射", "LDAP_Encryption": "加密", "LDAP_Encryption_Description": "请指定与 LDAP 服务器通信时,使用何种加密方法。可选方法包括:`不使用加密`,`SSL/LDAPS`(全程启用加密)和`StartTLS`(建立连接后启用加密)", "LDAP_Find_User_After_Login": "登录后找到用户", @@ -2280,15 +2276,11 @@ "LDAP_Merge_Existing_Users_Description": "*小心!* 当从 LDAP 导入和已经存在用户同名的用户时,会将 LDAP 信息和密码设置在已有用户上。", "LDAP_Port": "LDAP 端口", "LDAP_Port_Description": "LDAP 端口。比如:`389` 或 `636`", - "LDAP_Query_To_Get_User_Groups": "用于获取用户组的 LDAP 查询", - "LDAP_Query_To_Get_User_Groups_Description": "用于获取用户所属的LDAP用户组的 LDAP 查询", "LDAP_Query_To_Get_User_Teams": "用于获取用户组的 LDAP 查询", "LDAP_Reconnect": "重新连接", "LDAP_Reconnect_Description": "尝试在执行操作时由于某种原因中断连接时自动重新连接", "LDAP_Reject_Unauthorized": "拒绝未授权", "LDAP_Reject_Unauthorized_Description": "禁用此选项以允许无法验证的证书。通常,自签名证书将要求禁用此选项才能工作", - "LDAP_Roles_To_Rocket_Chat_Roles": "从 LDAP 到 Rocket.Chat 的角色映射。", - "LDAP_Roles_To_Rocket_Chat_Roles_Description": "在对象格式的角色映射中,其键必须为LDAP角色,其值必须为 RC 角色数组。例:{ 'ldapRole': ['rcRole', 'anotherRCRole'] }", "LDAP_Search_Page_Size": "搜索页面大小", "LDAP_Search_Page_Size_Description": "每个结果页面的最大条目数将返回进行处理", "LDAP_Search_Size_Limit": "搜索大小限制", @@ -2301,29 +2293,28 @@ "LDAP_Sync_User_Active_State_Disable": "禁用用户", "LDAP_Sync_User_Active_State_Nothing": "什么也不做", "LDAP_Sync_User_Avatar": "同步用户头像", - "LDAP_Sync_User_Data": "同步数据", - "LDAP_Sync_User_Data_Description": "登录时保持用户数据和服务器同步(例如:姓名、电子邮箱地址)。", - "LDAP_Sync_User_Data_FieldMap": "用户数据字段映射", - "LDAP_Sync_User_Data_FieldMap_Description": "设置用户数据字段(比如 E-mail)来自 LDAP 何处(如果能找到)。
;例如:`{\"cn\":\"name\", \"mail\":\"email\"}` 会从属性 cn 中取出名字字段,从 mail 属性中取出 email 字段。
有效字段包括 `name` 和 `email`。", - "LDAP_Sync_User_Data_Groups": "同步 LDAP 群组", - "LDAP_Sync_User_Data_Groups_AutoChannels": "自动同步 LDAP 组到频道", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin": "频道管理员", - "LDAP_Sync_User_Data_Groups_AutoChannels_Admin_Description": "当自动创建在同步过程中不存在的频道时,该用户将自动成为频道的管理员。", - "LDAP_Sync_User_Data_Groups_AutoChannels_Description": "启用此功能可以根据用户的 LDAP 组自动将用户添加到频道。如果您还想从频道中移除用户,请参阅以下有关自动移除用户的选项。", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap": "LDAP 组频道映射", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Default": "//启用自动同步 LDAP 组到上述频道", - "LDAP_Sync_User_Data_Groups_AutoChannelsMap_Description": "将 LDAP 组对应到 Rocket.Chat 频道
例如,`{\"employee\":\"general\"}`会将 LDAP employee 组的用户添加到 general 频道。", - "LDAP_Sync_User_Data_Groups_AutoRemove": "自动删除用户角色", - "LDAP_Sync_User_Data_Groups_AutoRemove_Description": "**注意**:如果未在LDAP中分配用户,启用此功能将自动从角色中删除用户!这只会自动删除在下面的用户数据组对应设置下的角色。", - "LDAP_Sync_User_Data_Groups_BaseDN": "LDAP组BaseDN", - "LDAP_Sync_User_Data_Groups_BaseDN_Description": "用于查找用户的LDAP BaseDN。", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels": "自动从频道中删除用户", - "LDAP_Sync_User_Data_Groups_Enforce_AutoChannels_Description": "**注意**:启用此选项将删除频道中没有对应 LDAP 组的所有用户!请谨慎使用。", - "LDAP_Sync_User_Data_Groups_Filter": "用户组过滤器", - "LDAP_Sync_User_Data_Groups_Filter_Description": "LDAP搜索过滤器,用于检查用户是否在组中。", - "LDAP_Sync_User_Data_GroupsMap": "用户数据群组对应", - "LDAP_Sync_User_Data_GroupsMap_Description": "将LDAP组对应到Rocket.Chat用户角色
例如,`{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}`会将rocket-admin LDAP组对应到Rocket.Chat的“管理员”角色。", - "LDAP_Test_Connection": "测试连接", + "LDAP_Sync_User_Data_Roles": "同步 LDAP 群组", + "LDAP_Sync_User_Data_Channels": "自动同步 LDAP 组到频道", + "LDAP_Sync_User_Data_Channels_Admin": "频道管理员", + "LDAP_Sync_User_Data_Channels_Admin_Description": "当自动创建在同步过程中不存在的频道时,该用户将自动成为频道的管理员。", + "LDAP_Sync_User_Data_Channels_BaseDN": "LDAP组BaseDN", + "LDAP_Sync_User_Data_Channels_BaseDN_Description": "用于查找用户的LDAP BaseDN。", + "LDAP_Sync_User_Data_Channels_Description": "启用此功能可以根据用户的 LDAP 组自动将用户添加到频道。如果您还想从频道中移除用户,请参阅以下有关自动移除用户的选项。", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels": "自动从频道中删除用户", + "LDAP_Sync_User_Data_Channels_Enforce_AutoChannels_Description": "**注意**:启用此选项将删除频道中没有对应 LDAP 组的所有用户!请谨慎使用。", + "LDAP_Sync_User_Data_Channels_Filter": "用户组过滤器", + "LDAP_Sync_User_Data_Channels_Filter_Description": "LDAP搜索过滤器,用于检查用户是否在组中。", + "LDAP_Sync_User_Data_ChannelsMap": "LDAP 组频道映射", + "LDAP_Sync_User_Data_ChannelsMap_Default": "//启用自动同步 LDAP 组到上述频道", + "LDAP_Sync_User_Data_ChannelsMap_Description": "将 LDAP 组对应到 Rocket.Chat 频道
例如,`{\"employee\":\"general\"}`会将 LDAP employee 组的用户添加到 general 频道。", + "LDAP_Sync_User_Data_Roles_AutoRemove": "自动删除用户角色", + "LDAP_Sync_User_Data_Roles_AutoRemove_Description": "**注意**:如果未在LDAP中分配用户,启用此功能将自动从角色中删除用户!这只会自动删除在下面的用户数据组对应设置下的角色。", + "LDAP_Sync_User_Data_Roles_BaseDN": "LDAP组BaseDN", + "LDAP_Sync_User_Data_Roles_BaseDN_Description": "用于查找用户的LDAP BaseDN。", + "LDAP_Sync_User_Data_Roles_Filter": "用户组过滤器", + "LDAP_Sync_User_Data_Roles_Filter_Description": "LDAP搜索过滤器,用于检查用户是否在组中。", + "LDAP_Sync_User_Data_RolesMap": "用户数据群组对应", + "LDAP_Sync_User_Data_RolesMap_Description": "将LDAP组对应到Rocket.Chat用户角色
例如,`{\"rocket-admin\":\"admin\", \"tech-support\":\"support\"}`会将rocket-admin LDAP组对应到Rocket.Chat的“管理员”角色。", "LDAP_Timeout": "超时(ms)", "LDAP_Timeout_Description": "在返回错误之前等待搜索结果多少英里", "LDAP_Unique_Identifier_Field": "唯一识别字段", @@ -2336,8 +2327,6 @@ "LDAP_Username_Field": "用户名字段", "LDAP_Username_Field_Description": "指定新用户登录时,使用 LDAP 中哪个字段的值作为*用户名*。若要使用登录页面所用的用户名,请留空。
可使用模版标签,比如 `#{givenName}.#{sn}`。
默认字段为 `sAMAccountName`。", "LDAP_Validate_Teams_For_Each_Login": "每次登录时验证映射", - "LDAP_Validate_Roles_For_Each_Login": "每次登录时验证映射", - "LDAP_Validate_Roles_For_Each_Login_Description": "如果每次登录都需要验证(请小心使用这个设置,它将会在每次登录时覆盖用户的角色,否则只会在创建用户时进行验证)。", "Lead_capture_email_regex": "领导捕获电子邮件正则表达式", "Lead_capture_phone_regex": "领导捕获手机正则表达式", "Leave": "离开", diff --git a/server/configuration/ldap.ts b/server/configuration/ldap.ts new file mode 100644 index 000000000000..7c170015108a --- /dev/null +++ b/server/configuration/ldap.ts @@ -0,0 +1,46 @@ +import { Accounts } from 'meteor/accounts-base'; +import { Promise } from 'meteor/promise'; + +import { callbacks } from '../../app/callbacks/server'; +import { LDAP } from '../sdk'; +import { settings } from '../../app/settings/server'; + +// Register ldap login handler +Accounts.registerLoginHandler('ldap', function(loginRequest: Record) { + if (!loginRequest.ldap || !loginRequest.ldapOptions) { + return undefined; + } + + return Promise.await(LDAP.loginRequest(loginRequest.username, loginRequest.ldapPass)); +}); + +// Prevent password logins by LDAP users when LDAP is enabled +let ldapEnabled: boolean; +settings.get('LDAP_Enable', (_key, value) => { + if (ldapEnabled === value) { + return; + } + ldapEnabled = value as boolean; + + if (!value) { + return callbacks.remove('beforeValidateLogin', 'validateLdapLoginFallback'); + } + + callbacks.add('beforeValidateLogin', (login: Record) => { + if (!login.allowed) { + return login; + } + + // The fallback setting should only block password logins, so users that have other login services can continue using them + if (login.type !== 'password') { + return login; + } + + // LDAP users can still login locally when login fallback is enabled + if (login.user.services?.ldap?.id) { + login.allowed = settings.get('LDAP_Login_Fallback') ?? false; + } + + return login; + }, callbacks.priority.MEDIUM, 'validateLdapLoginFallback'); +}); diff --git a/server/importPackages.js b/server/importPackages.js index ccaa796480ba..87b4aa33d7f5 100644 --- a/server/importPackages.js +++ b/server/importPackages.js @@ -40,7 +40,6 @@ import '../app/integrations/server'; import '../app/irc'; import '../app/issuelinks/server'; import '../app/katex/server'; -import '../app/ldap/server'; import '../app/lib'; import '../app/livestream/server'; import '../app/logger'; diff --git a/server/lib/ldap/Connection.ts b/server/lib/ldap/Connection.ts new file mode 100644 index 000000000000..d118508147b3 --- /dev/null +++ b/server/lib/ldap/Connection.ts @@ -0,0 +1,648 @@ +import ldapjs from 'ldapjs'; + +import { settings } from '../../../app/settings/server'; +import type { ILDAPConnectionOptions, LDAPEncryptionType, LDAPSearchScope } from '../../../definition/ldap/ILDAPOptions'; +import type { ILDAPEntry } from '../../../definition/ldap/ILDAPEntry'; +import type { ILDAPCallback, ILDAPPageCallback } from '../../../definition/ldap/ILDAPCallback'; +import { callbacks } from '../../../app/callbacks/server'; +import { logger, connLogger, searchLogger, authLogger } from './Logger'; +import { getLDAPConditionalSetting } from './getLDAPConditionalSetting'; + +interface ILDAPEntryCallback { + (entry: ldapjs.SearchEntry): T | undefined; +} + +interface ILDAPSearchEndCallback { + (error?: any): void; +} + +interface ILDAPSearchPageCallback { + (result: ldapjs.SearchEntry[]): void; +} + +interface ILDAPSearchAllCallbacks { + dataCallback?: ILDAPSearchPageCallback; + endCallback?: ILDAPSearchEndCallback; + entryCallback?: ILDAPEntryCallback; +} + +type ILDAPExtractedValue = string | Array; + +export class LDAPConnection { + public ldapjs: any; + + public connected: boolean; + + public options: ILDAPConnectionOptions; + + public client: ldapjs.Client; + + private _receivedResponse: boolean; + + private _connectionTimedOut: boolean; + + private _connectionCallback: ILDAPCallback; + + constructor() { + this.ldapjs = ldapjs; + + this.connected = false; + this._receivedResponse = false; + this._connectionTimedOut = false; + + this.options = { + host: settings.get('LDAP_Host') ?? '', + port: settings.get('LDAP_Port') ?? 389, + reconnect: settings.get('LDAP_Reconnect') ?? false, + timeout: settings.get('LDAP_Timeout') ?? 60000, + connectionTimeout: settings.get('LDAP_Connect_Timeout') ?? 1000, + idleTimeout: settings.get('LDAP_Idle_Timeout') ?? 1000, + encryption: settings.get('LDAP_Encryption') ?? 'plain', + caCert: settings.get('LDAP_CA_Cert'), + rejectUnauthorized: settings.get('LDAP_Reject_Unauthorized') || false, + baseDN: settings.get('LDAP_BaseDN') ?? '', + userSearchFilter: settings.get('LDAP_User_Search_Filter') ?? '', + userSearchScope: settings.get('LDAP_User_Search_Scope') ?? 'sub', + userSearchField: getLDAPConditionalSetting('LDAP_User_Search_Field') ?? '', + searchPageSize: settings.get('LDAP_Search_Page_Size') ?? 250, + searchSizeLimit: settings.get('LDAP_Search_Size_Limit') ?? 1000, + uniqueIdentifierField: settings.get('LDAP_Unique_Identifier_Field'), + groupFilterEnabled: settings.get('LDAP_Group_Filter_Enable') ?? false, + groupFilterObjectClass: settings.get('LDAP_Group_Filter_ObjectClass'), + groupFilterGroupIdAttribute: settings.get('LDAP_Group_Filter_Group_Id_Attribute'), + groupFilterGroupMemberAttribute: settings.get('LDAP_Group_Filter_Group_Member_Attribute'), + groupFilterGroupMemberFormat: settings.get('LDAP_Group_Filter_Group_Member_Format'), + groupFilterGroupName: settings.get('LDAP_Group_Filter_Group_Name'), + }; + + if (!this.options.host) { + logger.warn('LDAP Host is not configured.'); + } + if (!this.options.baseDN) { + logger.warn('LDAP Search BaseDN is not configured.'); + } + } + + public async connect(): Promise { + return new Promise((resolve, reject) => { + this.initializeConnection((error, result) => { + if (error) { + return reject(error); + } + + return resolve(result); + }); + }); + } + + public disconnect(): void { + this.connected = false; + connLogger.info('Disconnecting'); + + if (this.client) { + this.client.unbind(); + } + } + + public async testConnection(): Promise { + await this.connect(); + } + + public async searchByUsername(escapedUsername: string): Promise { + const searchOptions: ldapjs.SearchOptions = { + filter: this.getUserFilter(escapedUsername), + scope: this.options.userSearchScope || 'sub', + sizeLimit: this.options.searchSizeLimit, + }; + + if (this.options.searchPageSize > 0) { + searchOptions.paged = { + pageSize: this.options.searchPageSize, + pagePause: false, + }; + } + + searchLogger.info({ msg: 'Searching by username', username: escapedUsername, baseDN: this.options.baseDN, searchOptions }); + return this.search(this.options.baseDN, searchOptions); + } + + public async findOneByUsername(username: string): Promise { + const results = await this.searchByUsername(username); + + if (results.length === 1) { + return results[0]; + } + } + + public async searchById(id: string, attribute?: string): Promise { + const searchOptions: ldapjs.SearchOptions = { + scope: this.options.userSearchScope || 'sub', + attributes: ['*', '+'], + }; + + if (attribute) { + searchOptions.filter = new this.ldapjs.filters.EqualityFilter({ + attribute, + value: Buffer.from(id, 'hex'), + }); + } else if (this.options.uniqueIdentifierField) { + // If we don't know what attribute the id came from, we have to look for all of them. + const possibleFields = this.options.uniqueIdentifierField.split(',').concat(this.options.userSearchField.split(',')); + const filters = []; + for (const field of possibleFields) { + if (!field) { + continue; + } + + filters.push(new this.ldapjs.filters.EqualityFilter({ + attribute: field, + value: Buffer.from(id, 'hex'), + })); + } + searchOptions.filter = new this.ldapjs.filters.OrFilter({ filters }); + } else { + searchLogger.warn('Unique Identifier Field is not configured.'); + } + + searchLogger.info({ msg: 'Searching by id', id }); + searchLogger.debug({ msg: 'search filter', searchOptions, baseDN: this.options.baseDN }); + + return this.search(this.options.baseDN, searchOptions); + } + + public async findOneById(id: string, attribute?: string): Promise { + const results = await this.searchById(id, attribute); + if (results.length === 1) { + return results[0]; + } + } + + public async searchAllUsers({ dataCallback, endCallback, entryCallback }: ILDAPSearchAllCallbacks): Promise { + searchLogger.info('Searching all users'); + + const searchOptions: ldapjs.SearchOptions = { + filter: this.getUserFilter('*'), + scope: this.options.userSearchScope || 'sub', + sizeLimit: this.options.searchSizeLimit, + }; + + if (this.options.searchPageSize > 0) { + let count = 0; + await this.doPagedSearch(this.options.baseDN, searchOptions, this.options.searchPageSize, (error, entries: ldapjs.SearchEntry[], { end, next } = { end: false, next: undefined }) => { + if (error) { + endCallback && endCallback(error); + return; + } + + count += entries.length; + dataCallback && dataCallback(entries); + if (end) { + endCallback && endCallback(); + } + + if (next) { + next(count); + } + }, entryCallback); + return; + } + + await this.doAsyncSearch(this.options.baseDN, searchOptions, (error, result) => { + dataCallback && dataCallback(result); + endCallback && endCallback(error); + }, entryCallback); + } + + public async authenticate(dn: string, password: string): Promise { + authLogger.info({ msg: 'Authenticating', dn }); + + try { + await this.bindDN(dn, password); + + authLogger.info({ msg: 'Authenticated', dn }); + return true; + } catch (error) { + authLogger.info({ msg: 'Not authenticated', dn }); + authLogger.debug({ msg: 'error', error }); + return false; + } + } + + public async search(baseDN: string, searchOptions: ldapjs.SearchOptions): Promise { + return this.doCustomSearch(baseDN, searchOptions, (entry) => this.extractLdapEntryData(entry)); + } + + public async searchRaw(baseDN: string, searchOptions: ldapjs.SearchOptions): Promise { + return this.doCustomSearch(baseDN, searchOptions, (entry) => entry); + } + + public async searchAndCount(baseDN: string, searchOptions: ldapjs.SearchOptions): Promise { + let count = 0; + await this.doCustomSearch(baseDN, searchOptions, () => { + count++; + }); + + return count; + } + + public extractLdapAttribute(value: Buffer | Buffer[] | string): ILDAPExtractedValue { + if (Array.isArray(value)) { + return value.map((item) => this.extractLdapAttribute(item)); + } + + if (value instanceof Buffer) { + return value.toString(); + } + + return value; + } + + public extractLdapEntryData(entry: ldapjs.SearchEntry): ILDAPEntry { + const values: ILDAPEntry = { + _raw: entry.raw, + }; + + Object.keys(values._raw).forEach((key) => { + values[key] = this.extractLdapAttribute(values._raw[key]); + }); + + return values; + } + + public async doCustomSearch(baseDN: string, searchOptions: ldapjs.SearchOptions, entryCallback: ILDAPEntryCallback): Promise { + await this.runBeforeSearch(searchOptions); + + if (!searchOptions.scope) { + searchOptions.scope = this.options.userSearchScope || 'sub'; + } + searchLogger.debug({ msg: 'searchOptions', searchOptions, baseDN }); + + let realEntries = 0; + + return new Promise((resolve, reject) => { + this.client.search(baseDN, searchOptions, (error, res: ldapjs.SearchCallbackResponse) => { + if (error) { + searchLogger.error(error); + reject(error); + return; + } + + res.on('error', (error) => { + searchLogger.error(error); + reject(error); + }); + + const entries: T[] = []; + + res.on('searchEntry', (entry) => { + const result = entryCallback(entry); + if (result) { + entries.push(result as T); + } + realEntries++; + }); + + res.on('end', () => { + searchLogger.info(`LDAP Search found ${ realEntries } entries and loaded the data of ${ entries.length }.`); + resolve(entries); + }); + }); + }); + } + + /* + Create an LDAP search filter based on the username + */ + public getUserFilter(username: string): string { + const filter: string[] = []; + + this.addUserFilters(filter, username); + + const usernameFilter = this.options.userSearchField.split(',').map((item) => `(${ item }=${ username })`); + + if (usernameFilter.length === 0) { + logger.error('LDAP_LDAP_User_Search_Field not defined'); + } else if (usernameFilter.length === 1) { + filter.push(`${ usernameFilter[0] }`); + } else { + filter.push(`(|${ usernameFilter.join('') })`); + } + + return `(&${ filter.join('') })`; + } + + public async isUserAcceptedByGroupFilter(username: string, userdn: string): Promise { + if (!this.options.groupFilterEnabled) { + return true; + } + + const filter = ['(&']; + + if (this.options.groupFilterObjectClass) { + filter.push(`(objectclass=${ this.options.groupFilterObjectClass })`); + } + + if (this.options.groupFilterGroupMemberAttribute) { + filter.push(`(${ this.options.groupFilterGroupMemberAttribute }=${ this.options.groupFilterGroupMemberFormat })`); + } + + if (this.options.groupFilterGroupIdAttribute) { + filter.push(`(${ this.options.groupFilterGroupIdAttribute }=${ this.options.groupFilterGroupName })`); + } + filter.push(')'); + + const searchOptions: ldapjs.SearchOptions = { + filter: filter.join('').replace(/#{username}/g, username).replace(/#{userdn}/g, userdn), + scope: 'sub', + }; + + searchLogger.debug({ msg: 'Group filter LDAP:', filter: searchOptions.filter }); + + const result = await this.searchRaw(this.options.baseDN, searchOptions); + + if (!Array.isArray(result) || result.length === 0) { + return false; + } + return true; + } + + protected addUserFilters(filters: string[], _username: string): void { + const { userSearchFilter } = this.options; + + if (userSearchFilter !== '') { + if (userSearchFilter[0] === '(') { + filters.push(`${ userSearchFilter }`); + } else { + filters.push(`(${ userSearchFilter })`); + } + } + } + + public async bindDN(dn: string, password: string): Promise { + await new Promise((resolve, reject) => { + try { + this.client.bind(dn, password, (error) => { + if (error) { + return reject(error); + } + + resolve(); + }); + } catch (error) { + reject(error); + } + }); + } + + private async doAsyncSearch(baseDN: string, searchOptions: ldapjs.SearchOptions, callback: ILDAPCallback, entryCallback?: ILDAPEntryCallback): Promise { + await this.runBeforeSearch(searchOptions); + + searchLogger.debug({ msg: 'searchOptions', searchOptions, baseDN }); + + this.client.search(baseDN, searchOptions, (error: ldapjs.Error | null, res: ldapjs.SearchCallbackResponse): void => { + if (error) { + searchLogger.error(error); + callback(error); + return; + } + + res.on('error', (error) => { + searchLogger.error(error); + callback(error); + }); + + const entries: T[] = []; + + res.on('searchEntry', (entry) => { + const result = entryCallback ? entryCallback(entry) : entry; + entries.push(result as T); + }); + + res.on('end', () => { + searchLogger.info({ msg: 'Search result count', count: entries.length }); + callback(null, entries); + }); + }); + } + + private processSearchPage({ entries, title, end, next }: {entries: T[]; title: string; end: boolean; next?: Function}, callback: ILDAPPageCallback): void { + searchLogger.info(title); + // Force LDAP idle to wait the record processing + this._updateIdle(true); + + callback(null, entries, { end, + next: () => { + // Reset idle timer + this._updateIdle(); + next && next(); + } }); + } + + private async doPagedSearch(baseDN: string, searchOptions: ldapjs.SearchOptions, pageSize: number, callback: ILDAPPageCallback, entryCallback?: ILDAPEntryCallback): Promise { + searchOptions.paged = { + pageSize, + pagePause: true, + }; + + await this.runBeforeSearch(searchOptions); + + searchLogger.debug({ msg: 'searchOptions', searchOptions, baseDN }); + + this.client.search(baseDN, searchOptions, (error: ldapjs.Error | null, res: ldapjs.SearchCallbackResponse): void => { + if (error) { + searchLogger.error(error); + callback(error); + return; + } + + res.on('error', (error) => { + searchLogger.error(error); + callback(error); + }); + + let entries: T[] = []; + const internalPageSize = pageSize * 2; + + res.on('searchEntry', (entry) => { + const result = entryCallback ? entryCallback(entry) : entry; + entries.push(result as T); + + if (entries.length >= internalPageSize) { + this.processSearchPage({ + entries, + title: 'Internal Page', + end: false, + }, callback); + entries = []; + } + }); + + res.on('page', (_result, next) => { + if (!next) { + this._updateIdle(true); + this.processSearchPage({ + entries, + title: 'Final Page', + end: true, + }, callback); + entries = []; + } else if (entries.length) { + this.processSearchPage({ + entries, + title: 'Page', + end: false, + next, + }, callback); + entries = []; + } + }); + + res.on('end', () => { + if (entries.length) { + this.processSearchPage({ + entries, + title: 'Final Page', + end: true, + }, callback); + entries = []; + } + }); + }); + } + + private _updateIdle(override?: boolean): void { + // @ts-ignore calling a private method + this.client._updateIdle(override); + } + + protected async runBeforeSearch(searchOptions: ldapjs.SearchOptions): Promise { + callbacks.run('beforeLDAPSearch', searchOptions, this); + } + + /* + Get list of options to initialize a new ldapjs Client + */ + private getClientOptions(): { clientOptions: ldapjs.ClientOptions; tlsOptions: Record } { + const clientOptions: ldapjs.ClientOptions = { + url: `${ this.options.host }:${ this.options.port }`, + timeout: this.options.timeout, + connectTimeout: this.options.connectionTimeout, + idleTimeout: this.options.idleTimeout, + reconnect: this.options.reconnect, + log: connLogger, + }; + + const tlsOptions: Record = { + rejectUnauthorized: this.options.rejectUnauthorized, + }; + + if (this.options.caCert) { + // Split CA cert into array of strings + const chainLines = this.options.caCert.split('\n'); + let cert: string[] = []; + const ca: string[] = []; + chainLines.forEach((line) => { + cert.push(line); + if (line.match(/-END CERTIFICATE-/)) { + ca.push(cert.join('\n')); + cert = []; + } + }); + tlsOptions.ca = ca; + } + + if (this.options.encryption === 'ssl') { + clientOptions.url = `ldaps://${ clientOptions.url }`; + clientOptions.tlsOptions = tlsOptions; + } else { + clientOptions.url = `ldap://${ clientOptions.url }`; + } + + return { + clientOptions, + tlsOptions, + }; + } + + private handleConnectionResponse(error: any, response?: any): void { + if (!this._receivedResponse) { + this._receivedResponse = true; + this._connectionCallback(error, response); + return; + } + + if (this._connectionTimedOut && !error) { + connLogger.info('Received a response after the connection timedout.'); + } else { + logger.debug('Ignored error/response:'); + } + + if (error) { + connLogger.debug(error); + } else { + connLogger.debug(response); + } + } + + private initializeConnection(callback: ILDAPCallback): void { + connLogger.info('Init Setup'); + this._receivedResponse = false; + this._connectionTimedOut = false; + this._connectionCallback = callback; + + const { clientOptions, tlsOptions } = this.getClientOptions(); + connLogger.info({ msg: 'Connecting', url: clientOptions.url }); + connLogger.debug({ msg: 'clientOptions', clientOptions }); + + this.client = ldapjs.createClient(clientOptions); + + this.client.on('error', (error) => { + connLogger.error(error); + this.handleConnectionResponse(error, null); + }); + + this.client.on('idle', () => { + searchLogger.info('Idle'); + this.disconnect(); + }); + + this.client.on('close', () => { + searchLogger.info('Closed'); + }); + + if (this.options.encryption === 'tls') { + // Set host parameter for tls.connect which is used by ldapjs starttls. This may not be needed anymore + // https://github.com/RocketChat/Rocket.Chat/issues/2035 + // https://github.com/mcavage/node-ldapjs/issues/349 + tlsOptions.host = this.options.host; + + connLogger.info('Starting TLS'); + connLogger.debug({ msg: 'tlsOptions', tlsOptions }); + + this.client.starttls(tlsOptions, null, (error, response) => { + if (error) { + connLogger.error({ msg: 'TLS connection', error }); + return this.handleConnectionResponse(error, null); + } + + connLogger.info('TLS connected'); + this.connected = true; + this.handleConnectionResponse(null, response); + }); + } else { + this.client.on('connect', (response) => { + connLogger.info('LDAP connected'); + this.connected = true; + this.handleConnectionResponse(null, response); + }); + } + + setTimeout(() => { + if (!this._receivedResponse) { + connLogger.error({ msg: 'connection time out', timeout: clientOptions.connectTimeout }); + this.handleConnectionResponse(new Error('Timeout')); + this._connectionTimedOut = true; + } + }, clientOptions.connectTimeout); + } +} diff --git a/server/lib/ldap/DataConverter.ts b/server/lib/ldap/DataConverter.ts new file mode 100644 index 000000000000..5b8a1036a645 --- /dev/null +++ b/server/lib/ldap/DataConverter.ts @@ -0,0 +1,42 @@ +import { VirtualDataConverter } from '../../../app/importer/server/classes/VirtualDataConverter'; +import { IImportUser } from '../../../definition/IImportUser'; +import type { IUser } from '../../../definition/IUser'; +import type { IConverterOptions } from '../../../app/importer/server/classes/ImportDataConverter'; +import { Logger } from '../logger/Logger'; +import { Users } from '../../../app/models/server/raw'; +import { settings } from '../../../app/settings/server'; + +const logger = new Logger('LDAP Data Converter'); + +export class LDAPDataConverter extends VirtualDataConverter { + private mergeExistingUsers: boolean; + + constructor(virtual = true, options?: IConverterOptions) { + super(virtual, options); + this.setLogger(logger); + + this.mergeExistingUsers = settings.get('LDAP_Merge_Existing_Users') ?? true; + } + + findExistingUser(data: IImportUser): IUser | undefined { + if (data.services?.ldap?.id) { + const importedUser = Promise.await(Users.findOneByLDAPId(data.services.ldap.id, data.services.ldap.idAttribute)); + if (importedUser) { + return importedUser; + } + } + + if (!this.mergeExistingUsers) { + return; + } + + // Search by email and username + return super.findExistingUser(data); + } + + static convertSingleUser(userData: IImportUser, options?: IConverterOptions): void { + const converter = new LDAPDataConverter(true, options); + converter.addUser(userData); + converter.convertUsers(); + } +} diff --git a/server/lib/ldap/Logger.ts b/server/lib/ldap/Logger.ts new file mode 100644 index 000000000000..14bdc80af4e2 --- /dev/null +++ b/server/lib/ldap/Logger.ts @@ -0,0 +1,7 @@ +import { Logger } from '../logger/Logger'; + +export const logger = new Logger('LDAP'); +export const connLogger = logger.section('Connection'); +export const bindLogger = logger.section('Bind'); +export const searchLogger = logger.section('Search'); +export const authLogger = logger.section('Auth'); diff --git a/server/lib/ldap/Manager.ts b/server/lib/ldap/Manager.ts new file mode 100644 index 000000000000..a8bfabadaa8a --- /dev/null +++ b/server/lib/ldap/Manager.ts @@ -0,0 +1,413 @@ +import limax from 'limax'; +// #ToDo: #TODO: Remove Meteor dependencies +import { SHA256 } from 'meteor/sha'; +import { Meteor } from 'meteor/meteor'; +import { Accounts } from 'meteor/accounts-base'; +import ldapEscape from 'ldap-escape'; +import _ from 'underscore'; + +import { ILDAPEntry } from '../../../definition/ldap/ILDAPEntry'; +import { LDAPLoginResult } from '../../../definition/ldap/ILDAPLoginResult'; +import { ILDAPUniqueIdentifierField } from '../../../definition/ldap/ILDAPUniqueIdentifierField'; +import { IUser, /* IUserEmail,*/ LoginUsername } from '../../../definition/IUser'; +import { IImportUser } from '../../../definition/IImportUser'; +import { settings } from '../../../app/settings/server'; +import { Users as UsersRaw } from '../../../app/models/server/raw'; +import { LDAPConnection } from './Connection'; +import { LDAPDataConverter } from './DataConverter'; +import { getLDAPConditionalSetting } from './getLDAPConditionalSetting'; +import { logger, authLogger, connLogger } from './Logger'; +import type { IConverterOptions } from '../../../app/importer/server/classes/ImportDataConverter'; +import { callbacks } from '../../../app/callbacks/server'; +import { setUserAvatar } from '../../../app/lib/server/functions'; + +export class LDAPManager { + public static async login(username: string, password: string): Promise { + logger.debug({ msg: 'Init LDAP login', username }); + + if (settings.get('LDAP_Enable') !== true) { + return this.fallbackToDefaultLogin(username, password); + } + + let ldapUser: ILDAPEntry | undefined; + + const ldap = this.getNewConnection(); + try { + try { + await ldap.connect(); + ldapUser = await this.findUser(ldap, username, password); + } catch (error) { + logger.error(error); + } + + if (ldapUser === undefined) { + return this.fallbackToDefaultLogin(username, password); + } + + const slugifiedUsername = this.slugifyUsername(ldapUser, username); + const user = await this.findExistingUser(ldapUser, slugifiedUsername); + + if (user) { + return await this.loginExistingUser(ldap, user, ldapUser, password); + } + + return await this.loginNewUserFromLDAP(slugifiedUsername, password, ldapUser, ldap); + } finally { + ldap.disconnect(); + } + } + + public static getNewConnection(): LDAPConnection { + const ClassRef = callbacks.run('getLDAPConnectionClass') || LDAPConnection; + + return new ClassRef(); + } + + public static async testConnection(): Promise { + try { + const ldap = LDAPManager.getNewConnection(); + try { + await ldap.testConnection(); + } finally { + ldap.disconnect(); + } + } catch (error) { + connLogger.error(error); + throw error; + } + } + + // This method will only find existing users that are already linked to LDAP + protected static async findExistingLDAPUser(ldapUser: ILDAPEntry): Promise { + const uniqueIdentifierField = this.getLdapUserUniqueID(ldapUser); + + if (uniqueIdentifierField) { + logger.debug({ msg: 'Querying user', uniqueId: uniqueIdentifierField.value }); + return UsersRaw.findOneByLDAPId(uniqueIdentifierField.value, uniqueIdentifierField.attribute); + } + } + + protected static getConverterOptions(): IConverterOptions { + return { + flagEmailsAsVerified: settings.get('Accounts_Verify_Email_For_External_Accounts') ?? false, + }; + } + + protected static mapUserData(ldapUser: ILDAPEntry, usedUsername?: string | undefined): IImportUser { + const uniqueId = this.getLdapUserUniqueID(ldapUser); + if (!uniqueId) { + throw new Error('Failed to generate unique identifier for ldap entry'); + } + + const { attribute: idAttribute, value: id } = uniqueId; + const username = this.getLdapUsername(ldapUser) || usedUsername || id || undefined; + const emails = this.getLdapEmails(ldapUser, username); + const name = this.getLdapName(ldapUser) || undefined; + + const userData: IImportUser = { + type: 'user', + emails, + importIds: [ldapUser.dn], + username, + name, + services: { + ldap: { + idAttribute, + id, + }, + }, + }; + + this.onMapUserData(ldapUser, userData); + return userData; + } + + private static onMapUserData(ldapUser: ILDAPEntry, userData: IImportUser): void { + callbacks.run('mapLDAPUserData', userData, ldapUser); + } + + private static async findUser(ldap: LDAPConnection, username: string, password: string): Promise { + const escapedUsername = ldapEscape.filter`${ username }`; + + try { + const users = await ldap.searchByUsername(escapedUsername); + + if (users.length !== 1) { + logger.debug(`Search returned ${ users.length } records for ${ escapedUsername }`); + throw new Error('User not found'); + } + + const [ldapUser] = users; + if (!await ldap.authenticate(ldapUser.dn, password)) { + logger.debug(`Wrong password for ${ escapedUsername }`); + } + + if (settings.get('LDAP_Find_User_After_Login')) { + // Do a search as the user and check if they have any result + authLogger.debug('User authenticated successfully, performing additional search.'); + if (await ldap.searchAndCount(ldapUser.dn, {}) === 0) { + authLogger.debug(`Bind successful but user ${ ldapUser.dn } was not found via search`); + } + } + + if (!await ldap.isUserAcceptedByGroupFilter(escapedUsername, ldapUser.dn)) { + throw new Error('User not in a valid group'); + } + + return ldapUser; + } catch (error) { + logger.error(error); + } + } + + private static async loginNewUserFromLDAP(slugifiedUsername: string, ldapPass: string, ldapUser: ILDAPEntry, ldap: LDAPConnection): Promise { + logger.debug({ msg: 'User does not exist, creating', username: slugifiedUsername }); + + let username: string | undefined; + + if (getLDAPConditionalSetting('LDAP_Username_Field') !== '') { + username = slugifiedUsername; + } + + // Create new user + return this.addLdapUser(ldapUser, username, ldapPass, ldap); + } + + private static async addLdapUser(ldapUser: ILDAPEntry, username: string | undefined, password: string | undefined, ldap: LDAPConnection): Promise { + const user = await this.syncUserForLogin(ldapUser, undefined, username); + + this.onLogin(ldapUser, user, password, ldap); + if (user) { + return { + userId: user._id, + }; + } + } + + private static onLogin(ldapUser: ILDAPEntry, user: IUser | undefined, password: string | undefined, ldap: LDAPConnection): void { + logger.debug('running onLDAPLogin'); + + if (user) { + if (settings.get('LDAP_Login_Fallback') && typeof password === 'string' && password.trim() !== '') { + Accounts.setPassword(user._id, password, { logout: false }); + } + + this.syncUserAvatar(user, ldapUser); + } + + callbacks.run('onLDAPLogin', { user, ldapUser }, ldap); + } + + private static async loginExistingUser(ldap: LDAPConnection, user: IUser, ldapUser: ILDAPEntry, password: string): Promise { + if (user.ldap !== true && settings.get('LDAP_Merge_Existing_Users') !== true) { + logger.debug('User exists without "ldap: true"'); + throw new Meteor.Error('LDAP-login-error', `LDAP Authentication succeeded, but there's already an existing user with provided username [${ user.username }] in Mongo.`); + } + + const syncData = settings.get('LDAP_Update_Data_On_Login') ?? false; + logger.debug({ msg: 'Logging user in', syncData }); + const updatedUser = (syncData && await this.syncUserForLogin(ldapUser, user)) || user; + + this.onLogin(ldapUser, updatedUser, password, ldap); + return { + userId: user._id, + }; + } + + private static async syncUserForLogin(ldapUser: ILDAPEntry, existingUser?: IUser, usedUsername?: string | undefined): Promise { + logger.debug({ msg: 'Syncing user data', ldapUser, user: { ...existingUser && { email: existingUser.emails, _id: existingUser._id } } }); + + const userData = this.mapUserData(ldapUser, usedUsername); + const options = this.getConverterOptions(); + LDAPDataConverter.convertSingleUser(userData, options); + + return existingUser || this.findExistingLDAPUser(ldapUser); + } + + private static getLdapUserUniqueID(ldapUser: ILDAPEntry): ILDAPUniqueIdentifierField | undefined { + let uniqueIdentifierField: string | string[] | undefined = settings.get('LDAP_Unique_Identifier_Field'); + + if (uniqueIdentifierField) { + uniqueIdentifierField = uniqueIdentifierField.replace(/\s/g, '').split(','); + } else { + uniqueIdentifierField = []; + } + + let userSearchField: string | string[] | undefined = getLDAPConditionalSetting('LDAP_User_Search_Field'); + + if (userSearchField) { + userSearchField = userSearchField.replace(/\s/g, '').split(','); + } else { + userSearchField = []; + } + + uniqueIdentifierField = uniqueIdentifierField.concat(userSearchField); + if (!uniqueIdentifierField.length) { + uniqueIdentifierField.push('dn'); + } + + const key = uniqueIdentifierField.find((field) => !_.isEmpty(ldapUser._raw[field])); + if (key) { + return { + attribute: key, + value: ldapUser._raw[key].toString('hex'), + }; + } + + connLogger.warn('Failed to generate unique identifier for ldap entry'); + connLogger.debug(ldapUser); + } + + private static ldapKeyExists(ldapUser: ILDAPEntry, key: string): boolean { + return !_.isEmpty(ldapUser[key.trim()]); + } + + private static getLdapString(ldapUser: ILDAPEntry, key: string): string { + return ldapUser[key.trim()]; + } + + private static getLdapDynamicValue(ldapUser: ILDAPEntry, attributeSetting: string | undefined): string | undefined { + if (!attributeSetting) { + return; + } + + // If the attribute setting is a template, then convert the variables in it + if (attributeSetting.includes('#{')) { + return attributeSetting.replace(/#{(.+?)}/g, (_match, field) => { + const key = field.trim(); + + if (this.ldapKeyExists(ldapUser, key)) { + return this.getLdapString(ldapUser, key); + } + + return ''; + }); + } + + // If it's not a template, then treat the setting as a CSV list of possible attribute names and return the first valid one. + const attributeList: string[] = attributeSetting.replace(/\s/g, '').split(','); + const key = attributeList.find((field) => this.ldapKeyExists(ldapUser, field)); + if (key) { + return this.getLdapString(ldapUser, key); + } + } + + private static getLdapName(ldapUser: ILDAPEntry): string | undefined { + const nameAttributes = getLDAPConditionalSetting('LDAP_Name_Field'); + return this.getLdapDynamicValue(ldapUser, nameAttributes); + } + + private static getLdapEmails(ldapUser: ILDAPEntry, username?: string): string[] { + const emailAttributes = getLDAPConditionalSetting('LDAP_Email_Field'); + if (emailAttributes) { + const attributeList: string[] = emailAttributes.replace(/\s/g, '').split(','); + const key = attributeList.find((field) => this.ldapKeyExists(ldapUser, field)); + + const emails: string[] = [].concat(key ? ldapUser[key.trim()] : []); + const filteredEmails = emails.filter((email) => email.includes('@')); + + if (filteredEmails.length) { + return filteredEmails; + } + } + + if (settings.get('LDAP_Default_Domain') !== '' && username) { + return [`${ username }@${ settings.get('LDAP_Default_Domain') }`]; + } + + if (ldapUser.mail && ldapUser.mail.includes('@')) { + return [ldapUser.mail]; + } + + logger.debug(ldapUser); + throw new Error('Failed to get email address from LDAP user'); + } + + private static slugify(text: string): string { + if (settings.get('UTF8_Names_Slugify') !== true) { + return text; + } + + text = limax(text, { replacement: '.' }); + return text.replace(/[^0-9a-z-_.]/g, ''); + } + + private static slugifyUsername(ldapUser: ILDAPEntry, requestUsername: string): string { + if (getLDAPConditionalSetting('LDAP_Username_Field') !== '') { + const username = this.getLdapUsername(ldapUser); + if (username) { + return this.slugify(username); + } + } + + return this.slugify(requestUsername); + } + + private static getLdapUsername(ldapUser: ILDAPEntry): string | undefined { + const usernameField = getLDAPConditionalSetting('LDAP_Username_Field') as string; + return this.getLdapDynamicValue(ldapUser, usernameField); + } + + // This method will find existing users by LDAP id or by username. + private static async findExistingUser(ldapUser: ILDAPEntry, slugifiedUsername: string): Promise { + const user = await this.findExistingLDAPUser(ldapUser); + if (user) { + return user; + } + + return UsersRaw.findOneByUsername(slugifiedUsername); + } + + private static fallbackToDefaultLogin(username: LoginUsername, password: string): LDAPLoginResult { + if (typeof username === 'string') { + if (username.indexOf('@') === -1) { + username = { username }; + } else { + username = { email: username }; + } + } + + logger.debug({ msg: 'Fallback to default account system', username }); + + const loginRequest = { + user: username, + password: { + digest: SHA256(password), + algorithm: 'sha-256', + }, + }; + + return Accounts._runLoginHandlers(this, loginRequest); + } + + private static getAvatarFromUser(ldapUser: ILDAPEntry): any | undefined { + const avatarField = String(settings.get('LDAP_Avatar_Field') || '').trim(); + if (avatarField && ldapUser._raw[avatarField]) { + return ldapUser._raw[avatarField]; + } + + if (ldapUser._raw.thumbnailPhoto) { + return ldapUser._raw.thumbnailPhoto; + } + + if (ldapUser._raw.jpegPhoto) { + return ldapUser._raw.jpegPhoto; + } + } + + private static syncUserAvatar(user: IUser, ldapUser: ILDAPEntry): void { + if (!user?._id || settings.get('LDAP_Sync_User_Avatar') !== true) { + return; + } + + const avatar = this.getAvatarFromUser(ldapUser); + if (!avatar) { + return; + } + + logger.debug('Syncing user avatar'); + // #ToDo: Remove Meteor references here + // runAsUser is needed for now because the UploadFS class rejects files if there's no userId + Meteor.defer(() => Meteor.runAsUser(user._id, () => setUserAvatar(user, avatar, 'image/jpeg', 'rest'))); + } +} diff --git a/server/lib/ldap/getLDAPConditionalSetting.ts b/server/lib/ldap/getLDAPConditionalSetting.ts new file mode 100644 index 000000000000..198847bd9692 --- /dev/null +++ b/server/lib/ldap/getLDAPConditionalSetting.ts @@ -0,0 +1,8 @@ +import { settings } from '../../../app/settings/server'; +import type { SettingValue } from '../../../definition/ISetting'; + +export function getLDAPConditionalSetting(settingName: string): T | undefined { + const isActiveDirectory = settings.get('LDAP_Server_Type') === 'ad'; + const key = isActiveDirectory ? settingName.replace('LDAP_', 'LDAP_AD_') : settingName; + return settings.get(key); +} diff --git a/server/main.d.ts b/server/main.d.ts index 532da7dc8783..74635273891d 100644 --- a/server/main.d.ts +++ b/server/main.d.ts @@ -25,6 +25,8 @@ declare module 'meteor/accounts-base' { function insertUserDoc(options: Record, user: Record): string; function _generateStampedLoginToken(): {token: string; when: Date}; + + function _runLoginHandlers(methodInvocation: Function, loginRequest: Record): Record | undefined; } } diff --git a/server/main.js b/server/main.js index f806c978ef7e..50dab8a48d82 100644 --- a/server/main.js +++ b/server/main.js @@ -16,6 +16,7 @@ import './startup/presence'; import './startup/serverRunning'; import './startup/coreApps'; import './configuration/accounts_meld'; +import './configuration/ldap'; import './methods/OEmbedCacheCleanup'; import './methods/addAllUserToRoom'; import './methods/addRoomLeader'; @@ -78,5 +79,6 @@ import './publications/subscription'; import './routes/avatar'; import './stream/stdout'; import './stream/streamBroadcast'; +import './settings/index'; import './features/EmailInbox/index'; diff --git a/server/sdk/index.ts b/server/sdk/index.ts index 1b5c18b04057..298caae6e5e3 100644 --- a/server/sdk/index.ts +++ b/server/sdk/index.ts @@ -14,6 +14,7 @@ import { INPSService } from './types/INPSService'; import { ITeamService } from './types/ITeamService'; import { IRoomService } from './types/IRoomService'; import { IMediaService } from './types/IMediaService'; +import { ILDAPService } from './types/ILDAPService'; // TODO think in a way to not have to pass the service name to proxify here as well export const Authorization = proxifyWithWait('authorization'); @@ -27,6 +28,7 @@ export const NPS = proxifyWithWait('nps'); export const Team = proxifyWithWait('team'); export const Room = proxifyWithWait('room'); export const Media = proxifyWithWait('media'); +export const LDAP = proxifyWithWait('ldap'); // Calls without wait. Means that the service is optional and the result may be an error // of service/method not available diff --git a/server/sdk/types/ILDAPService.ts b/server/sdk/types/ILDAPService.ts new file mode 100644 index 000000000000..e321db4c056a --- /dev/null +++ b/server/sdk/types/ILDAPService.ts @@ -0,0 +1,6 @@ +import type { LDAPLoginResult } from '../../../definition/ldap/ILDAPLoginResult'; + +export interface ILDAPService { + loginRequest(username: string, password: string): Promise; + testConnection(): Promise; +} diff --git a/server/services/ldap/service.ts b/server/services/ldap/service.ts new file mode 100644 index 000000000000..087713e28381 --- /dev/null +++ b/server/services/ldap/service.ts @@ -0,0 +1,16 @@ +import { LDAPManager } from '../../lib/ldap/Manager'; +import { ILDAPService } from '../../sdk/types/ILDAPService'; +import { ServiceClass } from '../../sdk/types/ServiceClass'; +import { LDAPLoginResult } from '../../../definition/ldap/ILDAPLoginResult'; + +export class LDAPService extends ServiceClass implements ILDAPService { + protected name = 'ldap'; + + async loginRequest(username: string, password: string): Promise { + return LDAPManager.login(username, password); + } + + async testConnection(): Promise { + return LDAPManager.testConnection(); + } +} diff --git a/server/services/startup.ts b/server/services/startup.ts index e2757c0fab50..bee2dd61df0b 100644 --- a/server/services/startup.ts +++ b/server/services/startup.ts @@ -9,6 +9,7 @@ import { RoomService } from './room/service'; import { TeamService } from './team/service'; import { UiKitCoreApp } from './uikit-core-app/service'; import { MediaService } from './image/service'; +import { LDAPService } from './ldap/service'; const { db } = MongoInternals.defaultRemoteCollectionDriver().mongo; @@ -20,3 +21,4 @@ api.registerService(new NPSService(db)); api.registerService(new RoomService(db)); api.registerService(new TeamService(db)); api.registerService(new MediaService()); +api.registerService(new LDAPService()); diff --git a/server/settings/index.ts b/server/settings/index.ts new file mode 100644 index 000000000000..4a5af30485e1 --- /dev/null +++ b/server/settings/index.ts @@ -0,0 +1 @@ +import './ldap'; diff --git a/server/settings/ldap.ts b/server/settings/ldap.ts new file mode 100644 index 000000000000..6582db256a2d --- /dev/null +++ b/server/settings/ldap.ts @@ -0,0 +1,376 @@ +import { settings } from '../../app/settings/server'; + +settings.addGroup('LDAP', function() { + const enableQuery = { _id: 'LDAP_Enable', value: true }; + const adOnly = { _id: 'LDAP_Server_Type', value: 'ad' }; + const ldapOnly = { _id: 'LDAP_Server_Type', value: '' }; + + this.set({ tab: 'LDAP_Connection' }, function() { + this.add('LDAP_Enable', false, { type: 'boolean', public: true }); + + this.add('LDAP_Server_Type', 'ad', { + type: 'select', + public: true, + enableQuery, + values: [ + { key: 'ad', i18nLabel: 'LDAP_Server_Type_AD' }, + { key: '', i18nLabel: 'LDAP_Server_Type_Other' }, + ], + }); + + this.add('LDAP_Host', '', { type: 'string', enableQuery }); + this.add('LDAP_Port', '389', { type: 'int', enableQuery }); + this.add('LDAP_Reconnect', false, { type: 'boolean', enableQuery }); + + this.add('LDAP_Login_Fallback', false, { type: 'boolean', enableQuery }); + + this.section('LDAP_Connection_Encryption', function() { + this.add('LDAP_Encryption', 'plain', { + type: 'select', + values: [ + { key: 'plain', i18nLabel: 'No_Encryption' }, + { key: 'tls', i18nLabel: 'StartTLS' }, + { key: 'ssl', i18nLabel: 'SSL/LDAPS' }, + ], + enableQuery, + }); + + const enableTLSQuery = [ + enableQuery, + { _id: 'LDAP_Encryption', value: { $in: ['tls', 'ssl'] } }, + ]; + + this.add('LDAP_CA_Cert', '', { type: 'string', multiline: true, enableQuery: enableTLSQuery, secret: true }); + this.add('LDAP_Reject_Unauthorized', true, { type: 'boolean', enableQuery: enableTLSQuery }); + }); + + this.section('LDAP_Connection_Timeouts', function() { + this.add('LDAP_Timeout', 60000, { type: 'int', enableQuery }); + this.add('LDAP_Connect_Timeout', 1000, { type: 'int', enableQuery }); + this.add('LDAP_Idle_Timeout', 1000, { type: 'int', enableQuery }); + }); + }); + + this.set({ tab: 'LDAP_UserSearch' }, function() { + this.add('LDAP_Find_User_After_Login', true, { type: 'boolean', enableQuery }); + + this.section('LDAP_UserSearch_Filter', function() { + this.add('LDAP_BaseDN', '', { + type: 'string', + enableQuery, + }); + + this.add('LDAP_User_Search_Filter', '(objectclass=*)', { + type: 'string', + enableQuery, + }); + + this.add('LDAP_User_Search_Scope', 'sub', { + type: 'string', + enableQuery, + }); + + this.add('LDAP_AD_User_Search_Field', 'sAMAccountName', { + i18nLabel: 'LDAP_User_Search_Field', + i18nDescription: 'LDAP_User_Search_Field_Description', + type: 'string', + enableQuery, + displayQuery: adOnly, + }); + this.add('LDAP_User_Search_Field', 'uid', { + type: 'string', + enableQuery, + displayQuery: ldapOnly, + }); + this.add('LDAP_Search_Page_Size', 250, { + type: 'int', + enableQuery, + }); + + this.add('LDAP_Search_Size_Limit', 1000, { + type: 'int', + enableQuery, + }); + }); + + this.section('LDAP_UserSearch_GroupFilter', function() { + const groupFilterQuery = [ + enableQuery, + { _id: 'LDAP_Group_Filter_Enable', value: true }, + ]; + + this.add('LDAP_Group_Filter_Enable', false, { type: 'boolean', enableQuery }); + this.add('LDAP_Group_Filter_ObjectClass', 'groupOfUniqueNames', { type: 'string', enableQuery: groupFilterQuery }); + this.add('LDAP_Group_Filter_Group_Id_Attribute', 'cn', { type: 'string', enableQuery: groupFilterQuery }); + this.add('LDAP_Group_Filter_Group_Member_Attribute', 'uniqueMember', { type: 'string', enableQuery: groupFilterQuery }); + this.add('LDAP_Group_Filter_Group_Member_Format', 'uniqueMember', { type: 'string', enableQuery: groupFilterQuery }); + this.add('LDAP_Group_Filter_Group_Name', 'ROCKET_CHAT', { type: 'string', enableQuery: groupFilterQuery }); + }); + }); + + this.set({ tab: 'LDAP_DataSync' }, function() { + this.add('LDAP_Unique_Identifier_Field', 'objectGUID,ibm-entryUUID,GUID,dominoUNID,nsuniqueId,uidNumber,uid', { + type: 'string', + enableQuery, + }); + + this.add('LDAP_Merge_Existing_Users', false, { + type: 'boolean', + enableQuery, + }); + + this.add('LDAP_Update_Data_On_Login', false, { + type: 'boolean', + enableQuery, + }); + + this.add('LDAP_Default_Domain', '', { + type: 'string', + enableQuery, + }); + + this.section('LDAP_DataSync_DataMap', function() { + this.add('LDAP_AD_Username_Field', 'sAMAccountName', { + type: 'string', + enableQuery, + i18nLabel: 'LDAP_Username_Field', + i18nDescription: 'LDAP_Username_Field_Description', + displayQuery: adOnly, + }); + + this.add('LDAP_Username_Field', 'uid', { + type: 'string', + enableQuery, + displayQuery: ldapOnly, + }); + + this.add('LDAP_AD_Email_Field', 'mail', { + i18nLabel: 'LDAP_Email_Field', + i18nDescription: 'LDAP_Email_Field_Description', + type: 'string', + enableQuery, + displayQuery: adOnly, + }); + + this.add('LDAP_Email_Field', 'mail', { + type: 'string', + enableQuery, + displayQuery: ldapOnly, + }); + + this.add('LDAP_AD_Name_Field', 'cn', { + i18nLabel: 'LDAP_Name_Field', + i18nDescription: 'LDAP_Name_Field_Description', + type: 'string', + enableQuery, + displayQuery: adOnly, + }); + + this.add('LDAP_Name_Field', 'cn', { + type: 'string', + enableQuery, + displayQuery: ldapOnly, + }); + }); + + this.section('LDAP_DataSync_Avatar', function() { + this.add('LDAP_Sync_User_Avatar', true, { + type: 'boolean', + enableQuery, + }); + + this.add('LDAP_Avatar_Field', '', { + type: 'string', + enableQuery, + }); + }); + }); + + this.set({ + tab: 'LDAP_Enterprise', + enterprise: true, + modules: ['ldap-enterprise'], + }, function() { + this.section('LDAP_Connection_Authentication', function() { + const enableAuthentication = [ + enableQuery, + { _id: 'LDAP_Authentication', value: true }, + ]; + + this.add('LDAP_Authentication', false, { type: 'boolean', enableQuery, invalidValue: false }); + this.add('LDAP_Authentication_UserDN', '', { type: 'string', enableQuery: enableAuthentication, secret: true, invalidValue: '' }); + this.add('LDAP_Authentication_Password', '', { type: 'password', enableQuery: enableAuthentication, secret: true, invalidValue: '' }); + }); + + this.section('LDAP_DataSync_BackgroundSync', function() { + this.add('LDAP_Background_Sync', false, { + type: 'boolean', + enableQuery, + invalidValue: false, + }); + + const backgroundSyncQuery = [ + enableQuery, + { _id: 'LDAP_Background_Sync', value: true }, + ]; + + this.add('LDAP_Background_Sync_Interval', 'Every 24 hours', { + type: 'string', + enableQuery: backgroundSyncQuery, + invalidValue: 'Every 24 hours', + }); + + this.add('LDAP_Background_Sync_Import_New_Users', true, { + type: 'boolean', + enableQuery: backgroundSyncQuery, + invalidValue: true, + }); + + this.add('LDAP_Background_Sync_Keep_Existant_Users_Updated', true, { + type: 'boolean', + enableQuery: backgroundSyncQuery, + invalidValue: true, + }); + }); + + this.section('LDAP_DataSync_ActiveState', function() { + this.add('LDAP_Sync_User_Active_State', 'disable', { + type: 'select', + values: [ + { key: 'none', i18nLabel: 'LDAP_Sync_User_Active_State_Nothing' }, + { key: 'disable', i18nLabel: 'LDAP_Sync_User_Active_State_Disable' }, + { key: 'both', i18nLabel: 'LDAP_Sync_User_Active_State_Both' }, + ], + i18nDescription: 'LDAP_Sync_User_Active_State_Description', + enableQuery: { _id: 'LDAP_Enable', value: true }, + enterprise: true, + invalidValue: 'none', + }); + }); + + this.section('LDAP_DataSync_CustomFields', function() { + this.add('LDAP_Sync_Custom_Fields', false, { + type: 'boolean', + enableQuery, + invalidValue: false, + }); + + this.add('LDAP_CustomFieldMap', '{}', { + type: 'code', + multiline: true, + enableQuery: [ + enableQuery, + { _id: 'LDAP_Sync_Custom_Fields', value: true }, + ], + invalidValue: '{}', + }); + }); + + this.section('LDAP_DataSync_Roles', function() { + this.add('LDAP_Sync_User_Data_Roles', false, { + type: 'boolean', + enableQuery, + invalidValue: false, + }); + const syncRolesQuery = [ + enableQuery, + { _id: 'LDAP_Sync_User_Data_Roles', value: true }, + ]; + this.add('LDAP_Sync_User_Data_Roles_AutoRemove', false, { + type: 'boolean', + enableQuery: syncRolesQuery, + invalidValue: false, + }); + + this.add('LDAP_Sync_User_Data_Roles_Filter', '(&(cn=#{groupName})(memberUid=#{username}))', { + type: 'string', + enableQuery: syncRolesQuery, + invalidValue: '', + }); + + this.add('LDAP_Sync_User_Data_Roles_BaseDN', '', { + type: 'string', + enableQuery: syncRolesQuery, + invalidValue: '', + }); + + this.add('LDAP_Sync_User_Data_RolesMap', '{\n\t"rocket-admin": "admin",\n\t"tech-support": "support"\n}', { + type: 'code', + multiline: true, + public: false, + code: 'application/json', + enableQuery: syncRolesQuery, + invalidValue: '', + }); + }); + + this.section('LDAP_DataSync_Channels', function() { + this.add('LDAP_Sync_User_Data_Channels', false, { + type: 'boolean', + enableQuery, + invalidValue: false, + }); + + const syncChannelsQuery = [ + enableQuery, + { _id: 'LDAP_Sync_User_Data_Channels', value: true }, + ]; + + this.add('LDAP_Sync_User_Data_Channels_Admin', 'rocket.cat', { + type: 'string', + enableQuery: syncChannelsQuery, + invalidValue: 'rocket.cat', + }); + + this.add('LDAP_Sync_User_Data_Channels_Filter', '(&(cn=#{groupName})(memberUid=#{username}))', { + type: 'string', + enableQuery: syncChannelsQuery, + invalidValue: '', + }); + + this.add('LDAP_Sync_User_Data_Channels_BaseDN', '', { + type: 'string', + enableQuery: syncChannelsQuery, + invalidValue: '', + }); + + this.add('LDAP_Sync_User_Data_ChannelsMap', '{\n\t"employee": "general",\n\t"techsupport": [\n\t\t"helpdesk",\n\t\t"support"\n\t]\n}', { + type: 'code', + multiline: true, + public: false, + code: 'application/json', + enableQuery: syncChannelsQuery, + invalidValue: '', + }); + + this.add('LDAP_Sync_User_Data_Channels_Enforce_AutoChannels', false, { + type: 'boolean', + enableQuery: syncChannelsQuery, + invalidValue: false, + }); + }); + + this.section('LDAP_DataSync_Teams', function() { + this.add('LDAP_Enable_LDAP_Groups_To_RC_Teams', false, { + type: 'boolean', + enableQuery: { _id: 'LDAP_Enable', value: true }, + invalidValue: false, + }); + this.add('LDAP_Groups_To_Rocket_Chat_Teams', '{}', { + type: 'code', + enableQuery: { _id: 'LDAP_Enable_LDAP_Groups_To_RC_Teams', value: true }, + invalidValue: '{}', + }); + this.add('LDAP_Validate_Teams_For_Each_Login', false, { + type: 'boolean', + enableQuery: { _id: 'LDAP_Enable_LDAP_Groups_To_RC_Teams', value: true }, + invalidValue: false, + }); + this.add('LDAP_Query_To_Get_User_Teams', '(&(ou=*)(uniqueMember=uid=#{username},dc=example,dc=com))', { + type: 'string', + enableQuery: { _id: 'LDAP_Enable_LDAP_Groups_To_RC_Teams', value: true }, + invalidValue: '(&(ou=*)(uniqueMember=uid=#{username},dc=example,dc=com))', + }); + }); + }); +}); diff --git a/server/startup/migrations/index.js b/server/startup/migrations/index.js index 1f541c39cedd..c0e0d64b6302 100644 --- a/server/startup/migrations/index.js +++ b/server/startup/migrations/index.js @@ -233,4 +233,5 @@ import './v233'; import './v234'; import './v235'; import './v236'; +import './v237'; import './xrun'; diff --git a/server/startup/migrations/v237.ts b/server/startup/migrations/v237.ts new file mode 100644 index 000000000000..ec1b68fee71c --- /dev/null +++ b/server/startup/migrations/v237.ts @@ -0,0 +1,110 @@ +import { Migrations } from '../../../app/migrations/server'; +import { settings } from '../../../app/settings/server'; +import { Settings } from '../../../app/models/server'; +import { isEnterprise } from '../../../ee/app/license/server'; + +function copySettingValue(newName: string, oldName: string): void { + const value = settings.get(oldName); + if (value === undefined) { + return; + } + + Settings.upsert({ _id: newName }, { $set: { value } }); +} + +Migrations.add({ + version: 237, + up() { + const isEE = isEnterprise(); + + // Override AD defaults with the previously configured values + copySettingValue('LDAP_AD_User_Search_Field', 'LDAP_User_Search_Field'); + copySettingValue('LDAP_AD_Username_Field', 'LDAP_Username_Field'); + + // If we're sure the server is AD, then select it - otherwise keep it as generic ldap + const useAdDefaults = settings.get('LDAP_User_Search_Field') === 'sAMAccountName'; + Settings.upsert({ _id: 'LDAP_Server_Type' }, { $set: { value: useAdDefaults ? 'ad' : '' } }); + + // The setting to use the field map also determined if the user data was updated on login or not + copySettingValue('LDAP_Update_Data_On_Login', 'LDAP_Sync_User_Data'); + + let fieldMap; + try { + fieldMap = JSON.parse(settings.get('LDAP_Sync_User_Data_FieldMap') ?? ''); + } catch (_error) { + // Ignore any parsing errors; + } + + if (fieldMap) { + const newObject: Record = {}; + + for (const key in fieldMap) { + if (!fieldMap.hasOwnProperty(key)) { + continue; + } + + if (fieldMap[key] === 'name') { + Settings.upsert({ _id: 'LDAP_Name_Field' }, { $set: { value: key } }); + Settings.upsert({ _id: 'LDAP_AD_Name_Field' }, { $set: { value: key } }); + continue; + } + + if (fieldMap[key] === 'email') { + Settings.upsert({ _id: 'LDAP_Email_Field' }, { $set: { value: key } }); + Settings.upsert({ _id: 'LDAP_AD_Email_Field' }, { $set: { value: key } }); + continue; + } + + newObject[fieldMap[key]] = key; + } + + if (isEE) { + const newJson = JSON.stringify(newObject); + Settings.upsert({ _id: 'LDAP_CustomFieldMap' }, { $set: { value: newJson } }); + + const syncCustomFields = Object.keys(newObject).length > 0 && settings.get('LDAP_Sync_User_Data'); + Settings.upsert({ _id: 'LDAP_Sync_Custom_Fields' }, { $set: { value: syncCustomFields } }); + } + } + + copySettingValue('LDAP_Sync_User_Data_Roles', 'LDAP_Sync_User_Data_Groups'); + copySettingValue('LDAP_Sync_User_Data_Roles_AutoRemove', 'LDAP_Sync_User_Data_Groups_AutoRemove'); + copySettingValue('LDAP_Sync_User_Data_Roles_Filter', 'LDAP_Sync_User_Data_Groups_Filter'); + copySettingValue('LDAP_Sync_User_Data_Roles_BaseDN', 'LDAP_Sync_User_Data_Groups_BaseDN'); + copySettingValue('LDAP_Sync_User_Data_RolesMap', 'LDAP_Sync_User_Data_GroupsMap'); + copySettingValue('LDAP_Sync_User_Data_Channels', 'LDAP_Sync_User_Data_Groups_AutoChannels'); + copySettingValue('LDAP_Sync_User_Data_Channels_Admin', 'LDAP_Sync_User_Data_Groups_AutoChannels_Admin'); + copySettingValue('LDAP_Sync_User_Data_ChannelsMap', 'LDAP_Sync_User_Data_Groups_AutoChannelsMap'); + copySettingValue('LDAP_Sync_User_Data_Channels_Enforce_AutoChannels', 'LDAP_Sync_User_Data_Groups_Enforce_AutoChannels'); + + copySettingValue('LDAP_Sync_User_Data_Channels_Filter', 'LDAP_Sync_User_Data_Groups_Filter'); + copySettingValue('LDAP_Sync_User_Data_Channels_BaseDN', 'LDAP_Sync_User_Data_Groups_BaseDN'); + + Settings.remove({ + _id: { + $in: [ + 'LDAP_Sync_Now', + 'LDAP_Test_Connection', + 'LDAP_Sync_CustomFields', + 'LDAP_Sync_User_Data', + 'LDAP_Sync_User_Data_FieldMap', + 'LDAP_Enable_LDAP_Roles_To_RC_Roles', + 'LDAP_Roles_To_Rocket_Chat_Roles', + 'LDAP_Validate_Roles_For_Each_Login', + 'LDAP_Default_Role_To_User', + 'LDAP_Query_To_Get_User_Groups', + 'LDAP_Sync_User_Data_Groups', + 'LDAP_Sync_User_Data_Groups_AutoRemove', + 'LDAP_Sync_User_Data_Groups_Filter', + 'LDAP_Sync_User_Data_Groups_BaseDN', + 'LDAP_Sync_User_Data_GroupsMap', + 'LDAP_Sync_User_Data_Groups_AutoChannels', + 'LDAP_Sync_User_Data_Groups_AutoChannels_Admin', + 'LDAP_Sync_User_Data_Groups_AutoChannelsMap', + 'LDAP_Sync_User_Data_Groups_Enforce_AutoChannels', + 'LDAP_Internal_Log_Level', + ], + }, + }); + }, +});