diff --git a/app/api/server/api.js b/app/api/server/api.js index 34d34aadf09b..c492b1a6e81b 100644 --- a/app/api/server/api.js +++ b/app/api/server/api.js @@ -7,21 +7,15 @@ import { Restivus } from 'meteor/nimble:restivus'; import { RateLimiter } from 'meteor/rate-limit'; import _ from 'underscore'; -import { Logger } from '../../logger'; -import { settings } from '../../settings'; -import { metrics } from '../../metrics'; -import { hasPermission, hasAllPermission } from '../../authorization'; +import { Logger } from '../../../server/lib/logger/Logger'; +import { getRestPayload } from '../../../server/lib/logger/logPayloads'; +import { settings } from '../../settings/server'; +import { metrics } from '../../metrics/server'; +import { hasPermission, hasAllPermission } from '../../authorization/server'; import { getDefaultUserFields } from '../../utils/server/functions/getDefaultUserFields'; import { checkCodeForUser } from '../../2fa/server/code'; -const logger = new Logger('API', {}); - -const { - LOG_REST_PAYLOAD = 'false', - LOG_REST_METHOD_PAYLOADS = 'false', -} = process.env; - -const addPayloadToLog = LOG_REST_PAYLOAD !== 'false' || LOG_REST_METHOD_PAYLOADS !== 'false'; +const logger = new Logger('API'); const rateLimiterDictionary = {}; export const defaultRateLimiterOptions = { @@ -134,8 +128,6 @@ export class APIClass extends Restivus { body: result, }; - logger.debug('Success', result); - return result; } @@ -167,8 +159,6 @@ export class APIClass extends Restivus { body: result, }; - logger.debug('Failure', result); - return result; } @@ -359,10 +349,26 @@ export class APIClass extends Restivus { }); this.requestIp = getRequestIP(this.request); + + const startTime = Date.now(); + + const log = logger.logger.child({ + method: this.request.method, + url: this.request.url, + userId: this.request.headers['x-user-id'], + userAgent: this.request.headers['user-agent'], + length: this.request.headers['content-length'], + host: this.request.headers.host, + referer: this.request.headers.referer, + remoteIP: this.requestIp, + ...getRestPayload(this.request.body), + }); + const objectForRateLimitMatch = { IPAddr: this.requestIp, route: `${ this.request.route }${ this.request.method.toLowerCase() }`, }; + let result; const connection = { @@ -397,25 +403,29 @@ export class APIClass extends Restivus { api.processTwoFactor({ userId: this.userId, request: this.request, invocation, options: _options.twoFactorOptions, connection }); } - result = DDP._CurrentInvocation.withValue(invocation, () => originalAction.apply(this)); - } catch (e) { - logger.debug(`${ method } ${ route } threw an error:`, e.stack); + result = DDP._CurrentInvocation.withValue(invocation, () => originalAction.apply(this)) || API.v1.success(); + log.http({ + status: result.statusCode, + responseTime: Date.now() - startTime, + }); + } catch (e) { const apiMethod = { 'error-too-many-requests': 'tooManyRequests', 'error-unauthorized': 'unauthorized', }[e.error] || 'failure'; result = API.v1[apiMethod](typeof e === 'string' ? e : e.message, e.error, process.env.TEST_MODE ? e.stack : undefined, e); + + log.http({ + err: e, + status: result.statusCode, + responseTime: Date.now() - startTime, + }); } finally { delete Accounts._accountData[connection.id]; } - const dateTime = new Date().toISOString(); - logger.info(() => `${ this.requestIp } - ${ this.userId } [${ dateTime }] "${ this.request.method } ${ this.request.url }" ${ result.statusCode } - "${ this.request.headers.referer }" "${ this.request.headers['user-agent'] }" | ${ addPayloadToLog ? JSON.stringify(this.request.body) : '' }`); - - result = result || API.v1.success(); - rocketchatRestApiEnd({ status: result.statusCode, }); diff --git a/app/api/server/v1/misc.js b/app/api/server/v1/misc.js index 01376658e4eb..57f88df0a6b5 100644 --- a/app/api/server/v1/misc.js +++ b/app/api/server/v1/misc.js @@ -15,7 +15,7 @@ import { API } from '../api'; import { getDefaultUserFields } from '../../../utils/server/functions/getDefaultUserFields'; import { getURL } from '../../../utils/lib/getURL'; import { StdOut } from '../../../logger/server/streamer'; -import { SystemLogger } from '../../../logger/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; // DEPRECATED diff --git a/app/apps/server/bridges/scheduler.ts b/app/apps/server/bridges/scheduler.ts index 0676178c84de..698931a25be2 100644 --- a/app/apps/server/bridges/scheduler.ts +++ b/app/apps/server/bridges/scheduler.ts @@ -1,4 +1,5 @@ import Agenda from 'agenda'; +import { ObjectID } from 'bson'; import { MongoInternals } from 'meteor/mongo'; import { StartupType, @@ -10,13 +11,15 @@ import { SchedulerBridge } from '@rocket.chat/apps-engine/server/bridges/Schedul import { AppServerOrchestrator } from '../orchestrator'; -function _callProcessor(processor: Function): (job: { attrs?: { data: object } }) => void { +function _callProcessor(processor: Function): (job: Agenda.Job) => void { return (job): void => { const data = job?.attrs?.data || {}; // This field is for internal use, no need to leak to app processor delete (data as any).appId; + data.jobId = job.attrs._id.toString(); + return processor(data); }; } @@ -68,10 +71,10 @@ export class AppSchedulerBridge extends SchedulerBridge { * @param {Array.} processors An array of processors * @param {string} appId * - * @returns Promise + * @returns {string[]} List of task ids run at startup, or void no startup run is set */ - protected async registerProcessors(processors: Array = [], appId: string): Promise { - const runAfterRegister: Promise[] = []; + protected async registerProcessors(processors: Array = [], appId: string): Promise> { + const runAfterRegister: Promise[] = []; this.orch.debugLog(`The App ${ appId } is registering job processors`, processors); processors.forEach(({ id, processor, startupSetting }: IProcessor) => { this.scheduler.define(id, _callProcessor(processor)); @@ -82,10 +85,10 @@ export class AppSchedulerBridge extends SchedulerBridge { switch (startupSetting.type) { case StartupType.ONETIME: - runAfterRegister.push(this.scheduleOnceAfterRegister({ id, when: startupSetting.when, data: startupSetting.data }, appId)); + runAfterRegister.push(this.scheduleOnceAfterRegister({ id, when: startupSetting.when, data: startupSetting.data }, appId) as Promise); break; case StartupType.RECURRING: - runAfterRegister.push(this.scheduleRecurring({ id, interval: startupSetting.interval, skipImmediate: startupSetting.skipImmediate, data: startupSetting.data }, appId)); + runAfterRegister.push(this.scheduleRecurring({ id, interval: startupSetting.interval, skipImmediate: startupSetting.skipImmediate, data: startupSetting.data }, appId) as Promise); break; default: this.orch.getRocketChatLogger().error(`Invalid startup setting type (${ String((startupSetting as any).type) }) for the processor ${ id }`); @@ -94,7 +97,7 @@ export class AppSchedulerBridge extends SchedulerBridge { }); if (runAfterRegister.length) { - await Promise.all(runAfterRegister); + return Promise.all(runAfterRegister) as Promise>; } } @@ -107,22 +110,23 @@ export class AppSchedulerBridge extends SchedulerBridge { * @param {Object} [job.data] An optional object that is passed to the processor * @param {string} appId * - * @returns Promise + * @returns {string} taskid */ - protected async scheduleOnce(job: IOnetimeSchedule, appId: string): Promise { - this.orch.debugLog(`The App ${ appId } is scheduling an onetime job`, job); + protected async scheduleOnce({ id, when, data }: IOnetimeSchedule, appId: string): Promise { + this.orch.debugLog(`The App ${ appId } is scheduling an onetime job (processor ${ id })`); try { await this.startScheduler(); - await this.scheduler.schedule(job.when, job.id, this.decorateJobData(job.data, appId)); + const job = await this.scheduler.schedule(when, id, this.decorateJobData(data, appId)); + return job.attrs._id.toString(); } catch (e) { this.orch.getRocketChatLogger().error(e); } } - private async scheduleOnceAfterRegister(job: IOnetimeSchedule, appId: string): Promise { + private async scheduleOnceAfterRegister(job: IOnetimeSchedule, appId: string): Promise { const scheduledJobs = await this.scheduler.jobs({ name: job.id, type: 'normal' }); if (!scheduledJobs.length) { - await this.scheduleOnce(job, appId); + return this.scheduleOnce(job, appId); } } @@ -136,13 +140,14 @@ export class AppSchedulerBridge extends SchedulerBridge { * @param {Object} [job.data] An optional object that is passed to the processor * @param {string} appId * - * @returns Promise + * @returns {string} taskid */ - protected async scheduleRecurring({ id, interval, skipImmediate = false, data }: IRecurringSchedule, appId: string): Promise { - this.orch.debugLog(`The App ${ appId } is scheduling a recurring job`, id); + protected async scheduleRecurring({ id, interval, skipImmediate = false, data }: IRecurringSchedule, appId: string): Promise { + this.orch.debugLog(`The App ${ appId } is scheduling a recurring job (processor ${ id })`); try { await this.startScheduler(); - await this.scheduler.every(interval, id, this.decorateJobData(data, appId), { skipImmediate }); + const job = await this.scheduler.every(interval, id, this.decorateJobData(data, appId), { skipImmediate }); + return job.attrs._id.toString(); } catch (e) { this.orch.getRocketChatLogger().error(e); } @@ -159,8 +164,17 @@ export class AppSchedulerBridge extends SchedulerBridge { protected async cancelJob(jobId: string, appId: string): Promise { this.orch.debugLog(`The App ${ appId } is canceling a job`, jobId); await this.startScheduler(); + + let cancelQuery; + try { + cancelQuery = { _id: new ObjectID(jobId.split('_')[0]) }; + } catch (jobDocIdError) { + // it is not a valid objectid, so it won't try to cancel by document id + cancelQuery = { name: jobId }; + } + try { - await this.scheduler.cancel({ name: jobId }); + await this.scheduler.cancel(cancelQuery); } catch (e) { this.orch.getRocketChatLogger().error(e); } diff --git a/app/apps/server/communication/uikit.js b/app/apps/server/communication/uikit.js index d86aa6b8fb4c..4abc6b992ab3 100644 --- a/app/apps/server/communication/uikit.js +++ b/app/apps/server/communication/uikit.js @@ -263,7 +263,6 @@ const appsRoutes = (orch) => (req, res) => { res.sendStatus(200); } catch (e) { - console.error(e); res.status(500).send(e.message); } break; @@ -297,6 +296,10 @@ const appsRoutes = (orch) => (req, res) => { } break; } + + default: { + res.status(500).send({ error: 'Unknown action' }); + } } // TODO: validate payloads per type diff --git a/app/apps/server/communication/websockets.js b/app/apps/server/communication/websockets.js index fd9360dce473..f5eadf281d97 100644 --- a/app/apps/server/communication/websockets.js +++ b/app/apps/server/communication/websockets.js @@ -1,5 +1,6 @@ import { AppStatusUtils } from '@rocket.chat/apps-engine/definition/AppStatus'; +import { SystemLogger } from '../../../../server/lib/logger/system'; import notifications from '../../../notifications/server/lib/Notifications'; export const AppEvents = Object.freeze({ @@ -49,10 +50,10 @@ export class AppServerListener { this.received.set(`${ AppEvents.APP_STATUS_CHANGE }_${ appId }`, { appId, status, when: new Date() }); if (AppStatusUtils.isEnabled(status)) { - await this.orch.getManager().enable(appId).catch(console.error); + await this.orch.getManager().enable(appId).catch(SystemLogger.error); this.clientStreamer.emitWithoutBroadcast(AppEvents.APP_STATUS_CHANGE, { appId, status }); } else if (AppStatusUtils.isDisabled(status)) { - await this.orch.getManager().disable(appId, status, true).catch(console.error); + await this.orch.getManager().disable(appId, status, true).catch(SystemLogger.error); this.clientStreamer.emitWithoutBroadcast(AppEvents.APP_STATUS_CHANGE, { appId, status }); } } diff --git a/app/authentication/server/lib/logLoginAttempts.ts b/app/authentication/server/lib/logLoginAttempts.ts index 699c7c00ddd0..ed73cf395e6d 100644 --- a/app/authentication/server/lib/logLoginAttempts.ts +++ b/app/authentication/server/lib/logLoginAttempts.ts @@ -1,5 +1,6 @@ import { ILoginAttempt } from '../ILoginAttempt'; import { settings } from '../../../settings/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; export const logFailedLoginAttempts = (login: ILoginAttempt): void => { if (!settings.get('Login_Logs_Enabled')) { @@ -25,5 +26,5 @@ export const logFailedLoginAttempts = (login: ILoginAttempt): void => { if (!settings.get('Login_Logs_UserAgent')) { userAgent = '-'; } - console.log('Failed login detected - Username[%s] ClientAddress[%s] ForwardedFor[%s] XRealIp[%s] UserAgent[%s]', user, clientAddress, forwardedFor, realIp, userAgent); + SystemLogger.info(`Failed login detected - Username[${ user }] ClientAddress[${ clientAddress }] ForwardedFor[${ forwardedFor }] XRealIp[${ realIp }] UserAgent[${ userAgent }]`); }; diff --git a/app/authentication/server/lib/restrictLoginAttempts.ts b/app/authentication/server/lib/restrictLoginAttempts.ts index a746d6e7938e..d62f090b1364 100644 --- a/app/authentication/server/lib/restrictLoginAttempts.ts +++ b/app/authentication/server/lib/restrictLoginAttempts.ts @@ -16,7 +16,6 @@ const logger = new Logger('LoginProtection'); export const notifyFailedLogin = async (ipOrUsername: string, blockedUntil: Date, failedAttempts: number): Promise => { const channelToNotify = settings.get('Block_Multiple_Failed_Logins_Notify_Failed_Channel'); if (!channelToNotify) { - /* @ts-expect-error */ logger.error('Cannot notify failed logins: channel provided is invalid'); return; } @@ -24,7 +23,6 @@ export const notifyFailedLogin = async (ipOrUsername: string, blockedUntil: Date // to avoid issues when "fname" is presented in the UI, check if the name matches it as well const room = await Rooms.findOneByNameOrFname(channelToNotify); if (!room) { - /* @ts-expect-error */ logger.error('Cannot notify failed logins: channel provided doesn\'t exists'); return; } diff --git a/app/autotranslate/server/deeplTranslate.js b/app/autotranslate/server/deeplTranslate.js index 91145470cf55..b45500602a3b 100644 --- a/app/autotranslate/server/deeplTranslate.js +++ b/app/autotranslate/server/deeplTranslate.js @@ -7,7 +7,7 @@ import { HTTP } from 'meteor/http'; import _ from 'underscore'; import { TranslationProviderRegistry, AutoTranslate } from './autotranslate'; -import { SystemLogger } from '../../logger/server'; +import { SystemLogger } from '../../../server/lib/logger/system'; import { settings } from '../../settings'; /** diff --git a/app/autotranslate/server/googleTranslate.js b/app/autotranslate/server/googleTranslate.js index b2463718e6f5..88c5403e550b 100644 --- a/app/autotranslate/server/googleTranslate.js +++ b/app/autotranslate/server/googleTranslate.js @@ -7,7 +7,7 @@ import { HTTP } from 'meteor/http'; import _ from 'underscore'; import { AutoTranslate, TranslationProviderRegistry } from './autotranslate'; -import { SystemLogger } from '../../logger/server'; +import { SystemLogger } from '../../../server/lib/logger/system'; import { settings } from '../../settings'; /** diff --git a/app/autotranslate/server/logger.js b/app/autotranslate/server/logger.js index 8f104e75e88c..70ca0cbf97b6 100644 --- a/app/autotranslate/server/logger.js +++ b/app/autotranslate/server/logger.js @@ -1,9 +1,5 @@ -import { Logger } from '../../logger'; +import { Logger } from '../../logger/server'; -export const logger = new Logger('AutoTranslate', { - sections: { - google: 'Google', - deepl: 'DeepL', - microsoft: 'Microsoft', - }, -}); +const logger = new Logger('AutoTranslate'); + +export const msLogger = logger.section('Microsoft'); diff --git a/app/autotranslate/server/msTranslate.js b/app/autotranslate/server/msTranslate.js index a71d450fa72d..1c3da27e6c29 100644 --- a/app/autotranslate/server/msTranslate.js +++ b/app/autotranslate/server/msTranslate.js @@ -7,7 +7,7 @@ import { HTTP } from 'meteor/http'; import _ from 'underscore'; import { TranslationProviderRegistry, AutoTranslate } from './autotranslate'; -import { logger } from './logger'; +import { msLogger } from './logger'; import { settings } from '../../settings'; /** @@ -137,7 +137,7 @@ class MsAutoTranslate extends AutoTranslate { try { return this._translate(msgs, targetLanguages); } catch (e) { - logger.microsoft.error('Error translating message', e); + msLogger.error({ err: e, msg: 'Error translating message' }); } return {}; } @@ -155,7 +155,7 @@ class MsAutoTranslate extends AutoTranslate { Text: attachment.description || attachment.text, }], targetLanguages); } catch (e) { - logger.microsoft.error('Error translating message attachment', e); + msLogger.error({ err: e, msg: 'Error translating message attachment' }); } return {}; } diff --git a/app/bigbluebutton/server/bigbluebutton-api.js b/app/bigbluebutton/server/bigbluebutton-api.js index b90424914736..f1c8c471027f 100644 --- a/app/bigbluebutton/server/bigbluebutton-api.js +++ b/app/bigbluebutton/server/bigbluebutton-api.js @@ -7,15 +7,11 @@ var BigBlueButtonApi, filterCustomParameters, include, noChecksumMethods, BigBlueButtonApi = (function () { function BigBlueButtonApi(url, salt, debug, opts) { var _base; - if (debug == null) { - debug = false; - } if (opts == null) { opts = {}; } this.url = url; this.salt = salt; - this.debug = debug; this.opts = opts; if ((_base = this.opts).shaType == null) { _base.shaType = 'sha1'; @@ -82,9 +78,7 @@ BigBlueButtonApi = (function () { if (filter == null) { filter = true; } - if (this.debug) { - console.log("Generating URL for", method); - } + SystemLogger.debug("Generating URL for", method); if (filter) { params = this.filterParams(params, method); } else { @@ -132,9 +126,7 @@ BigBlueButtonApi = (function () { BigBlueButtonApi.prototype.checksum = function (method, query) { var c, shaObj, str; query || (query = ""); - if (this.debug) { - console.log("- Calculating the checksum using: '" + method + "', '" + query + "', '" + this.salt + "'"); - } + SystemLogger.debug("- Calculating the checksum using: '" + method + "', '" + query + "', '" + this.salt + "'"); str = method + query + this.salt; if (this.opts.shaType === 'sha256') { shaObj = crypto.createHash('sha256', "TEXT") @@ -143,9 +135,7 @@ BigBlueButtonApi = (function () { } shaObj.update(str); c = shaObj.digest('hex'); - if (this.debug) { - console.log("- Checksum calculated:", c); - } + SystemLogger.debug("- Checksum calculated:", c); return c; }; diff --git a/app/blockstack/server/loginHandler.js b/app/blockstack/server/loginHandler.js index de00f0d1ccf4..53756efe8891 100644 --- a/app/blockstack/server/loginHandler.js +++ b/app/blockstack/server/loginHandler.js @@ -44,7 +44,7 @@ Accounts.registerLoginHandler('blockstack', (loginRequest) => { }); } } catch (e) { - console.error(e); + logger.error(e); } } diff --git a/app/callbacks/lib/callbacks.js b/app/callbacks/lib/callbacks.js index 525d869e191b..5def1fcfb9bd 100644 --- a/app/callbacks/lib/callbacks.js +++ b/app/callbacks/lib/callbacks.js @@ -16,7 +16,7 @@ if (Meteor.isClient) { } if (Meteor.isServer) { - const { Logger } = require('../../logger/server/server'); + const { Logger } = require('../../../server/lib/logger/Logger'); logger = new Logger('Callbacks'); } diff --git a/app/cas/server/cas_rocketchat.js b/app/cas/server/cas_rocketchat.js index 47dd4b405e25..6e4fea97c122 100644 --- a/app/cas/server/cas_rocketchat.js +++ b/app/cas/server/cas_rocketchat.js @@ -4,7 +4,7 @@ import { ServiceConfiguration } from 'meteor/service-configuration'; import { Logger } from '../../logger'; import { settings } from '../../settings'; -export const logger = new Logger('CAS', {}); +export const logger = new Logger('CAS'); Meteor.startup(function() { settings.addGroup('CAS', function() { diff --git a/app/chatpal-search/server/provider/index.js b/app/chatpal-search/server/provider/index.js index 4195805d53b7..9a3ad7c56f75 100644 --- a/app/chatpal-search/server/provider/index.js +++ b/app/chatpal-search/server/provider/index.js @@ -29,13 +29,13 @@ class Backend { const response = HTTP.call('POST', `${ this._options.baseurl }${ this._options.updatepath }`, options); if (response.statusCode >= 200 && response.statusCode < 300) { - ChatpalLogger.debug(`indexed ${ docs.length } documents`, JSON.stringify(response.data, null, 2)); + ChatpalLogger.debug({ msg: `indexed ${ docs.length } documents`, data: response.data }); } else { throw new Error(response); } } catch (e) { // TODO how to deal with this - ChatpalLogger.error('indexing failed', JSON.stringify(e, null, 2)); + ChatpalLogger.error({ msg: 'indexing failed', err: e }); return false; } } @@ -83,7 +83,7 @@ class Backend { ...this._options.httpOptions, }; - ChatpalLogger.debug('query: ', JSON.stringify(options, null, 2)); + ChatpalLogger.debug({ query: options }); try { if (callback) { @@ -101,7 +101,7 @@ class Backend { throw new Error(response); } } catch (e) { - ChatpalLogger.error('query failed', JSON.stringify(e, null, 2)); + ChatpalLogger.error({ msg: 'query failed', err: e }); throw e; } } diff --git a/app/chatpal-search/server/provider/provider.js b/app/chatpal-search/server/provider/provider.js index ff8e6fb3bc1c..e60d9c507aff 100644 --- a/app/chatpal-search/server/provider/provider.js +++ b/app/chatpal-search/server/provider/provider.js @@ -286,8 +286,8 @@ class ChatpalProvider extends SearchProvider { this._stats = server.stats; - ChatpalLogger.debug('config:', JSON.stringify(this._indexConfig, null, 2)); - ChatpalLogger.debug('stats:', JSON.stringify(this._stats, null, 2)); + ChatpalLogger.debug({ config: this._indexConfig }); + ChatpalLogger.debug({ stats: this._stats }); this.index = new Index(this._indexConfig, this.indexFail || clear, this._stats.message.oldest || new Date().valueOf()); diff --git a/app/chatpal-search/server/utils/logger.js b/app/chatpal-search/server/utils/logger.js index c1d75b806a2c..bfc73d4ecbc7 100644 --- a/app/chatpal-search/server/utils/logger.js +++ b/app/chatpal-search/server/utils/logger.js @@ -1,4 +1,4 @@ import { Logger } from '../../../logger'; -const ChatpalLogger = new Logger('Chatpal Logger', {}); +const ChatpalLogger = new Logger('Chatpal Logger'); export default ChatpalLogger; diff --git a/app/cloud/server/functions/connectWorkspace.js b/app/cloud/server/functions/connectWorkspace.js index 6e428803dc0c..974eb47d0668 100644 --- a/app/cloud/server/functions/connectWorkspace.js +++ b/app/cloud/server/functions/connectWorkspace.js @@ -6,6 +6,7 @@ import { retrieveRegistrationStatus } from './retrieveRegistrationStatus'; import { Settings } from '../../../models'; import { settings } from '../../../settings'; import { saveRegistrationData } from './saveRegistrationData'; +import { SystemLogger } from '../../../../server/lib/logger/system'; export function connectWorkspace(token) { const { connectToCloud } = retrieveRegistrationStatus(); @@ -38,9 +39,9 @@ export function connectWorkspace(token) { }); } catch (e) { if (e.response && e.response.data && e.response.data.error) { - console.error(`Failed to register with Rocket.Chat Cloud. Error: ${ e.response.data.error }`); + SystemLogger.error(`Failed to register with Rocket.Chat Cloud. Error: ${ e.response.data.error }`); } else { - console.error(e); + SystemLogger.error(e); } return false; diff --git a/app/cloud/server/functions/finishOAuthAuthorization.js b/app/cloud/server/functions/finishOAuthAuthorization.js index 5bf24cb9992b..60691ed20dce 100644 --- a/app/cloud/server/functions/finishOAuthAuthorization.js +++ b/app/cloud/server/functions/finishOAuthAuthorization.js @@ -5,6 +5,7 @@ import { getRedirectUri } from './getRedirectUri'; import { settings } from '../../../settings'; import { Users } from '../../../models'; import { userScopes } from '../oauthScopes'; +import { SystemLogger } from '../../../../server/lib/logger/system'; export function finishOAuthAuthorization(code, state) { if (settings.get('Cloud_Workspace_Registration_State') !== state) { @@ -32,9 +33,9 @@ export function finishOAuthAuthorization(code, state) { }); } catch (e) { if (e.response && e.response.data && e.response.data.error) { - console.error(`Failed to get AccessToken from Rocket.Chat Cloud. Error: ${ e.response.data.error }`); + SystemLogger.error(`Failed to get AccessToken from Rocket.Chat Cloud. Error: ${ e.response.data.error }`); } else { - console.error(e); + SystemLogger.error(e); } return false; diff --git a/app/cloud/server/functions/getUserCloudAccessToken.js b/app/cloud/server/functions/getUserCloudAccessToken.js index 3be0f726b121..f6a48a0ad63e 100644 --- a/app/cloud/server/functions/getUserCloudAccessToken.js +++ b/app/cloud/server/functions/getUserCloudAccessToken.js @@ -8,6 +8,7 @@ import { userLoggedOut } from './userLoggedOut'; import { Users } from '../../../models'; import { settings } from '../../../settings'; import { userScopes } from '../oauthScopes'; +import { SystemLogger } from '../../../../server/lib/logger/system'; export function getUserCloudAccessToken(userId, forceNew = false, scope = '', save = true) { const { connectToCloud, workspaceRegistered } = retrieveRegistrationStatus(); @@ -63,10 +64,10 @@ export function getUserCloudAccessToken(userId, forceNew = false, scope = '', sa }); } catch (e) { if (e.response && e.response.data && e.response.data.error) { - console.error(`Failed to get User AccessToken from Rocket.Chat Cloud. Error: ${ e.response.data.error }`); + SystemLogger.error(`Failed to get User AccessToken from Rocket.Chat Cloud. Error: ${ e.response.data.error }`); if (e.response.data.error === 'oauth_invalid_client_credentials') { - console.error('Server has been unregistered from cloud'); + SystemLogger.error('Server has been unregistered from cloud'); unregisterWorkspace(); } @@ -74,7 +75,7 @@ export function getUserCloudAccessToken(userId, forceNew = false, scope = '', sa userLoggedOut(userId); } } else { - console.error(e); + SystemLogger.error(e); } return ''; diff --git a/app/cloud/server/functions/getWorkspaceAccessTokenWithScope.js b/app/cloud/server/functions/getWorkspaceAccessTokenWithScope.js index f7ad77aa38d1..6acdbe8be039 100644 --- a/app/cloud/server/functions/getWorkspaceAccessTokenWithScope.js +++ b/app/cloud/server/functions/getWorkspaceAccessTokenWithScope.js @@ -6,6 +6,7 @@ import { retrieveRegistrationStatus } from './retrieveRegistrationStatus'; import { unregisterWorkspace } from './unregisterWorkspace'; import { settings } from '../../../settings'; import { workspaceScopes } from '../oauthScopes'; +import { SystemLogger } from '../../../../server/lib/logger/system'; export function getWorkspaceAccessTokenWithScope(scope = '') { const { connectToCloud, workspaceRegistered } = retrieveRegistrationStatus(); @@ -43,14 +44,14 @@ export function getWorkspaceAccessTokenWithScope(scope = '') { }); } catch (e) { if (e.response && e.response.data && e.response.data.error) { - console.error(`Failed to get AccessToken from Rocket.Chat Cloud. Error: ${ e.response.data.error }`); + SystemLogger.error(`Failed to get AccessToken from Rocket.Chat Cloud. Error: ${ e.response.data.error }`); if (e.response.data.error === 'oauth_invalid_client_credentials') { - console.error('Server has been unregistered from cloud'); + SystemLogger.error('Server has been unregistered from cloud'); unregisterWorkspace(); } } else { - console.error(e); + SystemLogger.error(e); } return tokenResponse; diff --git a/app/cloud/server/functions/getWorkspaceLicense.js b/app/cloud/server/functions/getWorkspaceLicense.js index 00916c9b93db..1483e04d3d16 100644 --- a/app/cloud/server/functions/getWorkspaceLicense.js +++ b/app/cloud/server/functions/getWorkspaceLicense.js @@ -5,6 +5,7 @@ import { settings } from '../../../settings'; import { Settings } from '../../../models'; import { callbacks } from '../../../callbacks'; import { LICENSE_VERSION } from '../license'; +import { SystemLogger } from '../../../../server/lib/logger/system'; export function getWorkspaceLicense() { const token = getWorkspaceAccessToken(); @@ -22,9 +23,9 @@ export function getWorkspaceLicense() { }); } catch (e) { if (e.response && e.response.data && e.response.data.error) { - console.error(`Failed to update license from Rocket.Chat Cloud. Error: ${ e.response.data.error }`); + SystemLogger.error(`Failed to update license from Rocket.Chat Cloud. Error: ${ e.response.data.error }`); } else { - console.error(e); + SystemLogger.error(e); } return { updated: false, license: '' }; diff --git a/app/cloud/server/functions/startRegisterWorkspace.js b/app/cloud/server/functions/startRegisterWorkspace.js index 84837dcdaf61..eba17c2649b1 100644 --- a/app/cloud/server/functions/startRegisterWorkspace.js +++ b/app/cloud/server/functions/startRegisterWorkspace.js @@ -5,6 +5,7 @@ import { syncWorkspace } from './syncWorkspace'; import { settings } from '../../../settings'; import { Settings } from '../../../models'; import { buildWorkspaceRegistrationData } from './buildRegistrationData'; +import { SystemLogger } from '../../../../server/lib/logger/system'; export function startRegisterWorkspace(resend = false) { @@ -28,9 +29,9 @@ export function startRegisterWorkspace(resend = false) { }); } catch (e) { if (e.response && e.response.data && e.response.data.error) { - console.error(`Failed to register with Rocket.Chat Cloud. ErrorCode: ${ e.response.data.error }`); + SystemLogger.error(`Failed to register with Rocket.Chat Cloud. ErrorCode: ${ e.response.data.error }`); } else { - console.error(e); + SystemLogger.error(e); } return false; diff --git a/app/cloud/server/functions/syncWorkspace.js b/app/cloud/server/functions/syncWorkspace.js index 360309c7cd5c..03f67acf4a4b 100644 --- a/app/cloud/server/functions/syncWorkspace.js +++ b/app/cloud/server/functions/syncWorkspace.js @@ -8,6 +8,7 @@ import { Settings } from '../../../models'; import { settings } from '../../../settings'; import { getAndCreateNpsSurvey } from '../../../../server/services/nps/getAndCreateNpsSurvey'; import { NPS, Banner } from '../../../../server/sdk'; +import { SystemLogger } from '../../../../server/lib/logger/system'; export function syncWorkspace(reconnectCheck = false) { const { workspaceRegistered, connectToCloud } = retrieveRegistrationStatus(); @@ -38,9 +39,9 @@ export function syncWorkspace(reconnectCheck = false) { getWorkspaceLicense(); } catch (e) { if (e.response && e.response.data && e.response.data.error) { - console.error(`Failed to sync with Rocket.Chat Cloud. Error: ${ e.response.data.error }`); + SystemLogger.error(`Failed to sync with Rocket.Chat Cloud. Error: ${ e.response.data.error }`); } else { - console.error(e); + SystemLogger.error(e); } return false; diff --git a/app/cloud/server/functions/userLogout.js b/app/cloud/server/functions/userLogout.js index 5dea9eb07815..405ab5bd0d73 100644 --- a/app/cloud/server/functions/userLogout.js +++ b/app/cloud/server/functions/userLogout.js @@ -4,6 +4,7 @@ import { userLoggedOut } from './userLoggedOut'; import { retrieveRegistrationStatus } from './retrieveRegistrationStatus'; import { Users } from '../../../models'; import { settings } from '../../../settings'; +import { SystemLogger } from '../../../../server/lib/logger/system'; export function userLogout(userId) { const { connectToCloud, workspaceRegistered } = retrieveRegistrationStatus(); @@ -41,9 +42,9 @@ export function userLogout(userId) { }); } catch (e) { if (e.response && e.response.data && e.response.data.error) { - console.error(`Failed to get Revoke refresh token to logout of Rocket.Chat Cloud. Error: ${ e.response.data.error }`); + SystemLogger.error(`Failed to get Revoke refresh token to logout of Rocket.Chat Cloud. Error: ${ e.response.data.error }`); } else { - console.error(e); + SystemLogger.error(e); } } } diff --git a/app/cors/server/cors.js b/app/cors/server/cors.js index b14d6b5588bb..9033d0b548f8 100644 --- a/app/cors/server/cors.js +++ b/app/cors/server/cors.js @@ -8,7 +8,7 @@ import { settings } from '../../settings'; import { Logger } from '../../logger'; -const logger = new Logger('CORS', {}); +const logger = new Logger('CORS'); // Deprecated setting let Support_Cordova_App = false; diff --git a/app/crowd/server/crowd.js b/app/crowd/server/crowd.js index a4cc46ca45ba..f2dd3acbaee9 100644 --- a/app/crowd/server/crowd.js +++ b/app/crowd/server/crowd.js @@ -11,7 +11,7 @@ import { settings } from '../../settings'; import { hasRole } from '../../authorization'; import { deleteUser } from '../../lib/server/functions'; -const logger = new Logger('CROWD', {}); +const logger = new Logger('CROWD'); function fallbackDefaultAccountSystem(bind, username, password) { if (typeof username === 'string') { diff --git a/app/custom-oauth/server/custom_oauth_server.js b/app/custom-oauth/server/custom_oauth_server.js index bd698fd90c2b..b8b49aafda93 100644 --- a/app/custom-oauth/server/custom_oauth_server.js +++ b/app/custom-oauth/server/custom_oauth_server.js @@ -190,7 +190,7 @@ export class CustomOAuth { data = JSON.parse(response.content); } - logger.debug('Identity response', JSON.stringify(data, null, 2)); + logger.debug({ msg: 'Identity response', data }); return this.normalizeIdentity(data); } catch (err) { diff --git a/app/custom-oauth/server/oauth_helpers.js b/app/custom-oauth/server/oauth_helpers.js index f00eea03b6b7..7520f041eb65 100644 --- a/app/custom-oauth/server/oauth_helpers.js +++ b/app/custom-oauth/server/oauth_helpers.js @@ -3,7 +3,7 @@ import { Roles, Rooms } from '../../models'; import { addUserToRoom, createRoom } from '../../lib/server/functions'; import { Logger } from '../../logger'; -export const logger = new Logger('OAuth', {}); +export const logger = new Logger('OAuth'); // Returns list of roles from SSO identity export function mapRolesFromSSO(identity, roleClaimName) { diff --git a/app/custom-sounds/server/startup/custom-sounds.js b/app/custom-sounds/server/startup/custom-sounds.js index 77a0d2c52b38..00349dfd706d 100644 --- a/app/custom-sounds/server/startup/custom-sounds.js +++ b/app/custom-sounds/server/startup/custom-sounds.js @@ -3,6 +3,7 @@ import { WebApp } from 'meteor/webapp'; import { RocketChatFile } from '../../../file/server'; import { settings } from '../../../settings/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; export let RocketChatFileCustomSoundsInstance; @@ -19,7 +20,7 @@ Meteor.startup(function() { throw new Error(`Invalid RocketChatStore type [${ storeType }]`); } - console.log(`Using ${ storeType } for custom sounds storage`.green); + SystemLogger.info(`Using ${ storeType } for custom sounds storage`); let path = '~/uploads'; if (settings.get('CustomSounds_FileSystemPath') != null) { diff --git a/app/emoji-custom/server/startup/emoji-custom.js b/app/emoji-custom/server/startup/emoji-custom.js index 8decb068ea1e..c7a83a0cf301 100644 --- a/app/emoji-custom/server/startup/emoji-custom.js +++ b/app/emoji-custom/server/startup/emoji-custom.js @@ -2,7 +2,8 @@ import { Meteor } from 'meteor/meteor'; import { WebApp } from 'meteor/webapp'; import _ from 'underscore'; -import { settings } from '../../../settings'; +import { settings } from '../../../settings/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; import { RocketChatFile } from '../../../file'; export let RocketChatFileEmojiCustomInstance; @@ -20,7 +21,7 @@ Meteor.startup(function() { throw new Error(`Invalid RocketChatStore type [${ storeType }]`); } - console.log(`Using ${ storeType } for custom emoji storage`.green); + SystemLogger.info(`Using ${ storeType } for custom emoji storage`); let path = '~/uploads'; if (settings.get('EmojiUpload_FileSystemPath') != null) { diff --git a/app/federation/server/endpoints/dispatch.js b/app/federation/server/endpoints/dispatch.js index d518505127c2..ae392ac8aac8 100644 --- a/app/federation/server/endpoints/dispatch.js +++ b/app/federation/server/endpoints/dispatch.js @@ -1,7 +1,7 @@ import { EJSON } from 'meteor/ejson'; import { API } from '../../../api/server'; -import { logger } from '../lib/logger'; +import { serverLogger } from '../lib/logger'; import { contextDefinitions, eventTypes } from '../../../models/server/models/FederationEvents'; import { FederationRoomEvents, FederationServers, @@ -134,7 +134,7 @@ const eventHandlers = { federationAltered = true; } } catch (ex) { - logger.server.debug(`unable to create subscription for user ( ${ user._id } ) in room (${ roomId })`); + serverLogger.debug(`unable to create subscription for user ( ${ user._id } ) in room (${ roomId })`); } // Refresh the servers list @@ -267,7 +267,7 @@ const eventHandlers = { notifyUsersOnMessage(denormalizedMessage, room); sendAllNotifications(denormalizedMessage, room); } catch (err) { - logger.server.debug(`Error on creating message: ${ message._id }`); + serverLogger.debug(`Error on creating message: ${ message._id }`); } } } @@ -463,7 +463,7 @@ API.v1.addRoute('federation.events.dispatch', { authRequired: false, rateLimiter // Convert from EJSON const { events } = EJSON.fromJSONValue(payload); - logger.server.debug(`federation.events.dispatch => events=${ events.map((e) => JSON.stringify(e, null, 2)) }`); + serverLogger.debug({ msg: 'federation.events.dispatch', events }); // Loop over received events for (const event of events) { @@ -478,14 +478,14 @@ API.v1.addRoute('federation.events.dispatch', { authRequired: false, rateLimiter // If there was an error handling the event, take action if (!eventResult || !eventResult.success) { try { - logger.server.debug(`federation.events.dispatch => Event has missing parents -> event=${ JSON.stringify(event, null, 2) }`); + serverLogger.debug({ msg: 'federation.events.dispatch => Event has missing parents', event }); requestEventsFromLatest(event.origin, getFederationDomain(), contextDefinitions.defineType(event), event.context, eventResult.latestEventIds); // And stop handling the events break; } catch (err) { - logger.server.error(() => `dispatch => event=${ JSON.stringify(event, null, 2) } eventResult=${ JSON.stringify(eventResult, null, 2) } error=${ err.toString() } ${ err.stack }`); + serverLogger.error({ msg: 'dispatch', event, eventResult, err }); throw err; } diff --git a/app/federation/server/endpoints/requestFromLatest.js b/app/federation/server/endpoints/requestFromLatest.js index 87917880229e..cac0168c8c12 100644 --- a/app/federation/server/endpoints/requestFromLatest.js +++ b/app/federation/server/endpoints/requestFromLatest.js @@ -1,7 +1,7 @@ import { EJSON } from 'meteor/ejson'; import { API } from '../../../api/server'; -import { logger } from '../lib/logger'; +import { serverLogger } from '../lib/logger'; import { FederationRoomEvents } from '../../../models/server'; import { decryptIfNeeded } from '../lib/crypt'; import { isFederationEnabled } from '../lib/isFederationEnabled'; @@ -25,7 +25,7 @@ API.v1.addRoute('federation.events.requestFromLatest', { authRequired: false }, const { fromDomain, contextType, contextQuery, latestEventIds } = EJSON.fromJSONValue(payload); - logger.server.debug(`federation.events.requestFromLatest => contextType=${ contextType } contextQuery=${ JSON.stringify(contextQuery, null, 2) } latestEventIds=${ latestEventIds.join(', ') }`); + serverLogger.debug({ msg: 'federation.events.requestFromLatest', contextType, contextQuery, latestEventIds }); let EventsModel; diff --git a/app/federation/server/endpoints/users.js b/app/federation/server/endpoints/users.js index d74cdae83248..7b92b0b5e509 100644 --- a/app/federation/server/endpoints/users.js +++ b/app/federation/server/endpoints/users.js @@ -1,7 +1,7 @@ import { API } from '../../../api/server'; import { Users } from '../../../models/server'; import { normalizers } from '../normalizers'; -import { logger } from '../lib/logger'; +import { serverLogger } from '../lib/logger'; import { isFederationEnabled } from '../lib/isFederationEnabled'; const userFields = { _id: 1, username: 1, type: 1, emails: 1, name: 1 }; @@ -14,7 +14,7 @@ API.v1.addRoute('federation.users.search', { authRequired: false }, { const { username, domain } = this.requestParams(); - logger.server.debug(`federation.users.search => username=${ username } domain=${ domain }`); + serverLogger.debug(`federation.users.search => username=${ username } domain=${ domain }`); const query = { type: 'user', @@ -41,7 +41,7 @@ API.v1.addRoute('federation.users.getByUsername', { authRequired: false }, { const { username } = this.requestParams(); - logger.server.debug(`federation.users.getByUsername => username=${ username }`); + serverLogger.debug(`federation.users.getByUsername => username=${ username }`); const query = { type: 'user', diff --git a/app/federation/server/handler/index.js b/app/federation/server/handler/index.js index 8ccb510194a5..7827ddf063a7 100644 --- a/app/federation/server/handler/index.js +++ b/app/federation/server/handler/index.js @@ -1,7 +1,7 @@ import qs from 'querystring'; import { disabled } from '../functions/errors'; -import { logger } from '../lib/logger'; +import { clientLogger } from '../lib/logger'; import { isFederationEnabled } from '../lib/isFederationEnabled'; import { federationRequestToPeer } from '../lib/http'; @@ -10,7 +10,7 @@ export function federationSearchUsers(query) { throw disabled('client.searchUsers'); } - logger.client.debug(() => `searchUsers => query=${ query }`); + clientLogger.debug({ msg: 'searchUsers', query }); const [username, peerDomain] = query.split('@'); @@ -26,7 +26,7 @@ export function getUserByUsername(query) { throw disabled('client.searchUsers'); } - logger.client.debug(() => `getUserByUsername => query=${ query }`); + clientLogger.debug({ msg: 'getUserByUsername', query }); const [username, peerDomain] = query.split('@'); @@ -42,7 +42,7 @@ export function requestEventsFromLatest(domain, fromDomain, contextType, context throw disabled('client.requestEventsFromLatest'); } - logger.client.debug(() => `requestEventsFromLatest => domain=${ domain } contextType=${ contextType } contextQuery=${ JSON.stringify(contextQuery, null, 2) } latestEventIds=${ latestEventIds.join(', ') }`); + clientLogger.debug({ msg: 'requestEventsFromLatest', domain, contextType, contextQuery, latestEventIds }); const uri = '/api/v1/federation.events.requestFromLatest'; @@ -57,7 +57,7 @@ export function dispatchEvents(domains, events) { domains = [...new Set(domains)]; - logger.client.debug(() => `dispatchEvents => domains=${ domains.join(', ') } events=${ events.map((e) => JSON.stringify(e, null, 2)) }`); + clientLogger.debug({ msg: 'dispatchEvents', domains, events }); const uri = '/api/v1/federation.events.dispatch'; diff --git a/app/federation/server/hooks/afterAddedToRoom.js b/app/federation/server/hooks/afterAddedToRoom.js index 1fd359504c5e..02f76297fcfd 100644 --- a/app/federation/server/hooks/afterAddedToRoom.js +++ b/app/federation/server/hooks/afterAddedToRoom.js @@ -1,4 +1,4 @@ -import { logger } from '../lib/logger'; +import { clientLogger } from '../lib/logger'; import { getFederatedRoomData, hasExternalDomain, isLocalUser, checkRoomType, checkRoomDomainsLength } from '../functions/helpers'; import { FederationRoomEvents, Subscriptions } from '../../../models/server'; import { normalizers } from '../normalizers'; @@ -16,7 +16,7 @@ async function afterAddedToRoom(involvedUsers, room) { return involvedUsers; } - logger.client.debug(() => `afterAddedToRoom => involvedUsers=${ JSON.stringify(involvedUsers, null, 2) } room=${ JSON.stringify(room, null, 2) }`); + clientLogger.debug({ msg: 'afterAddedToRoom', involvedUsers, room }); // If there are not federated users on this room, ignore it const { users, subscriptions } = getFederatedRoomData(room); @@ -73,7 +73,7 @@ async function afterAddedToRoom(involvedUsers, room) { // Remove the user subscription from the room Subscriptions.remove({ _id: subscription._id }); - logger.client.error('afterAddedToRoom => Could not add user:', err); + clientLogger.error({ msg: 'afterAddedToRoom => Could not add user:', err }); } return involvedUsers; diff --git a/app/federation/server/hooks/afterCreateDirectRoom.js b/app/federation/server/hooks/afterCreateDirectRoom.js index a0048fcb24a6..ac05794e1c2e 100644 --- a/app/federation/server/hooks/afterCreateDirectRoom.js +++ b/app/federation/server/hooks/afterCreateDirectRoom.js @@ -1,4 +1,4 @@ -import { logger } from '../lib/logger'; +import { clientLogger } from '../lib/logger'; import { FederationRoomEvents, Subscriptions } from '../../../models/server'; import { normalizers } from '../normalizers'; import { deleteRoom } from '../../../lib/server/functions'; @@ -7,7 +7,7 @@ import { dispatchEvents } from '../handler'; import { isFullyQualified } from '../functions/helpers'; async function afterCreateDirectRoom(room, extras) { - logger.client.debug(() => `afterCreateDirectRoom => room=${ JSON.stringify(room, null, 2) } extras=${ JSON.stringify(extras, null, 2) }`); + clientLogger.debug({ msg: 'afterCreateDirectRoom', room, extras }); // If the room is federated, ignore if (room.federation) { return room; } @@ -45,7 +45,7 @@ async function afterCreateDirectRoom(room, extras) { } catch (err) { await deleteRoom(room._id); - logger.client.error('afterCreateDirectRoom => Could not create federated room:', err); + clientLogger.error({ msg: 'afterCreateDirectRoom => Could not create federated room:', err }); } return room; diff --git a/app/federation/server/hooks/afterCreateRoom.js b/app/federation/server/hooks/afterCreateRoom.js index a58d40446c17..75dfeeac6575 100644 --- a/app/federation/server/hooks/afterCreateRoom.js +++ b/app/federation/server/hooks/afterCreateRoom.js @@ -1,4 +1,4 @@ -import { logger } from '../lib/logger'; +import { clientLogger } from '../lib/logger'; import { FederationRoomEvents, Subscriptions, Users } from '../../../models/server'; import { normalizers } from '../normalizers'; import { deleteRoom } from '../../../lib/server/functions'; @@ -80,13 +80,13 @@ async function afterCreateRoom(roomOwner, room) { throw new Error('Channels cannot be federated'); } - logger.client.debug(() => `afterCreateRoom => roomOwner=${ JSON.stringify(roomOwner, null, 2) } room=${ JSON.stringify(room, null, 2) }`); + clientLogger.debug({ msg: 'afterCreateRoom', roomOwner, room }); await doAfterCreateRoom(room, users, subscriptions); } catch (err) { deleteRoom(room._id); - logger.client.error('afterCreateRoom => Could not create federated room:', err); + clientLogger.error({ msg: 'afterCreateRoom => Could not create federated room:', err }); } return room; diff --git a/app/federation/server/hooks/afterDeleteMessage.js b/app/federation/server/hooks/afterDeleteMessage.js index 714de63a6e4d..6d070eafbac0 100644 --- a/app/federation/server/hooks/afterDeleteMessage.js +++ b/app/federation/server/hooks/afterDeleteMessage.js @@ -1,5 +1,5 @@ import { FederationRoomEvents, Rooms } from '../../../models/server'; -import { logger } from '../lib/logger'; +import { clientLogger } from '../lib/logger'; import { hasExternalDomain } from '../functions/helpers'; import { getFederationDomain } from '../lib/getFederationDomain'; import { dispatchEvent } from '../handler'; @@ -10,7 +10,7 @@ async function afterDeleteMessage(message) { // If there are not federated users on this room, ignore it if (!hasExternalDomain(room)) { return message; } - logger.client.debug(() => `afterDeleteMessage => message=${ JSON.stringify(message, null, 2) } room=${ JSON.stringify(room, null, 2) }`); + clientLogger.debug({ msg: 'afterDeleteMessage', message, room }); // Create the delete message event const event = await FederationRoomEvents.createDeleteMessageEvent(getFederationDomain(), room._id, message._id); diff --git a/app/federation/server/hooks/afterLeaveRoom.js b/app/federation/server/hooks/afterLeaveRoom.js index 5f1227df0a69..524d2078ae8a 100644 --- a/app/federation/server/hooks/afterLeaveRoom.js +++ b/app/federation/server/hooks/afterLeaveRoom.js @@ -1,6 +1,6 @@ import { FederationRoomEvents } from '../../../models/server'; import { getFederatedRoomData, hasExternalDomain, isLocalUser } from '../functions/helpers'; -import { logger } from '../lib/logger'; +import { clientLogger } from '../lib/logger'; import { normalizers } from '../normalizers'; import { getFederationDomain } from '../lib/getFederationDomain'; import { dispatchEvent } from '../handler'; @@ -13,7 +13,7 @@ async function afterLeaveRoom(user, room) { return user; } - logger.client.debug(() => `afterLeaveRoom => user=${ JSON.stringify(user, null, 2) } room=${ JSON.stringify(room, null, 2) }`); + clientLogger.debug({ msg: 'afterLeaveRoom', user, room }); const { users } = getFederatedRoomData(room); @@ -40,7 +40,7 @@ async function afterLeaveRoom(user, room) { // Dispatch the events dispatchEvent(domainsBeforeLeft, userLeftEvent); } catch (err) { - logger.client.error('afterLeaveRoom => Could not make user leave:', err); + clientLogger.error({ msg: 'afterLeaveRoom => Could not make user leave:', err }); } return user; diff --git a/app/federation/server/hooks/afterMuteUser.js b/app/federation/server/hooks/afterMuteUser.js index 4dba95ee4df7..6a53d204d0a8 100644 --- a/app/federation/server/hooks/afterMuteUser.js +++ b/app/federation/server/hooks/afterMuteUser.js @@ -1,5 +1,5 @@ import { FederationRoomEvents } from '../../../models/server'; -import { logger } from '../lib/logger'; +import { clientLogger } from '../lib/logger'; import { normalizers } from '../normalizers'; import { hasExternalDomain } from '../functions/helpers'; import { getFederationDomain } from '../lib/getFederationDomain'; @@ -9,7 +9,7 @@ async function afterMuteUser(involvedUsers, room) { // If there are not federated users on this room, ignore it if (!hasExternalDomain(room)) { return involvedUsers; } - logger.client.debug(() => `afterMuteUser => involvedUsers=${ JSON.stringify(involvedUsers, null, 2) } room=${ JSON.stringify(room, null, 2) }`); + clientLogger.debug({ msg: 'afterMuteUser', involvedUsers, room }); const { mutedUser } = involvedUsers; diff --git a/app/federation/server/hooks/afterRemoveFromRoom.js b/app/federation/server/hooks/afterRemoveFromRoom.js index c816f251982b..4c7509ec961e 100644 --- a/app/federation/server/hooks/afterRemoveFromRoom.js +++ b/app/federation/server/hooks/afterRemoveFromRoom.js @@ -1,6 +1,6 @@ import { FederationRoomEvents } from '../../../models/server'; import { getFederatedRoomData, hasExternalDomain, isLocalUser } from '../functions/helpers'; -import { logger } from '../lib/logger'; +import { clientLogger } from '../lib/logger'; import { normalizers } from '../normalizers'; import { getFederationDomain } from '../lib/getFederationDomain'; import { dispatchEvent } from '../handler'; @@ -15,7 +15,7 @@ async function afterRemoveFromRoom(involvedUsers, room) { return involvedUsers; } - logger.client.debug(() => `afterRemoveFromRoom => involvedUsers=${ JSON.stringify(involvedUsers, null, 2) } room=${ JSON.stringify(room, null, 2) }`); + clientLogger.debug({ msg: 'afterRemoveFromRoom', involvedUsers, room }); const { users } = getFederatedRoomData(room); @@ -42,7 +42,7 @@ async function afterRemoveFromRoom(involvedUsers, room) { // Dispatch the events dispatchEvent(domainsBeforeRemoval, removeUserEvent); } catch (err) { - logger.client.error('afterRemoveFromRoom => Could not remove user:', err); + clientLogger.error({ msg: 'afterRemoveFromRoom => Could not remove user:', err }); } return involvedUsers; diff --git a/app/federation/server/hooks/afterSaveMessage.js b/app/federation/server/hooks/afterSaveMessage.js index 5f72868a2323..7fdc128977b5 100644 --- a/app/federation/server/hooks/afterSaveMessage.js +++ b/app/federation/server/hooks/afterSaveMessage.js @@ -1,4 +1,4 @@ -import { logger } from '../lib/logger'; +import { clientLogger } from '../lib/logger'; import { FederationRoomEvents } from '../../../models/server'; import { normalizers } from '../normalizers'; import { hasExternalDomain } from '../functions/helpers'; @@ -9,7 +9,7 @@ async function afterSaveMessage(message, room) { // If there are not federated users on this room, ignore it if (!hasExternalDomain(room)) { return message; } - logger.client.debug(() => `afterSaveMessage => message=${ JSON.stringify(message, null, 2) } room=${ JSON.stringify(room, null, 2) }`); + clientLogger.debug({ msg: 'afterSaveMessage', message, room }); let event; diff --git a/app/federation/server/hooks/afterSetReaction.js b/app/federation/server/hooks/afterSetReaction.js index fec108dd91da..ce3d3d726394 100644 --- a/app/federation/server/hooks/afterSetReaction.js +++ b/app/federation/server/hooks/afterSetReaction.js @@ -1,7 +1,5 @@ -import _ from 'underscore'; - import { FederationRoomEvents, Rooms } from '../../../models/server'; -import { logger } from '../lib/logger'; +import { clientLogger } from '../lib/logger'; import { hasExternalDomain } from '../functions/helpers'; import { getFederationDomain } from '../lib/getFederationDomain'; import { dispatchEvent } from '../handler'; @@ -12,7 +10,7 @@ async function afterSetReaction(message, { user, reaction }) { // If there are not federated users on this room, ignore it if (!hasExternalDomain(room)) { return message; } - logger.client.debug(() => `afterSetReaction => message=${ JSON.stringify(_.pick(message, '_id', 'msg'), null, 2) } room=${ JSON.stringify(_.pick(room, '_id'), null, 2) } user=${ JSON.stringify(_.pick(user, 'username'), null, 2) } reaction=${ reaction }`); + clientLogger.debug({ msg: 'afterSetReaction', message, room, user, reaction }); // Create the event const event = await FederationRoomEvents.createSetMessageReactionEvent(getFederationDomain(), room._id, message._id, user.username, reaction); diff --git a/app/federation/server/hooks/afterUnmuteUser.js b/app/federation/server/hooks/afterUnmuteUser.js index 3578e08c97d0..e33ff80ac956 100644 --- a/app/federation/server/hooks/afterUnmuteUser.js +++ b/app/federation/server/hooks/afterUnmuteUser.js @@ -1,5 +1,5 @@ import { FederationRoomEvents } from '../../../models/server'; -import { logger } from '../lib/logger'; +import { clientLogger } from '../lib/logger'; import { normalizers } from '../normalizers'; import { hasExternalDomain } from '../functions/helpers'; import { getFederationDomain } from '../lib/getFederationDomain'; @@ -9,7 +9,7 @@ async function afterUnmuteUser(involvedUsers, room) { // If there are not federated users on this room, ignore it if (!hasExternalDomain(room)) { return involvedUsers; } - logger.client.debug(() => `afterUnmuteUser => involvedUsers=${ JSON.stringify(involvedUsers, null, 2) } room=${ JSON.stringify(room, null, 2) }`); + clientLogger.debug({ msg: 'afterUnmuteUser', involvedUsers, room }); const { unmutedUser } = involvedUsers; diff --git a/app/federation/server/hooks/afterUnsetReaction.js b/app/federation/server/hooks/afterUnsetReaction.js index 72c9259822c0..42d34091c80a 100644 --- a/app/federation/server/hooks/afterUnsetReaction.js +++ b/app/federation/server/hooks/afterUnsetReaction.js @@ -1,7 +1,5 @@ -import _ from 'underscore'; - import { FederationRoomEvents, Rooms } from '../../../models/server'; -import { logger } from '../lib/logger'; +import { clientLogger } from '../lib/logger'; import { hasExternalDomain } from '../functions/helpers'; import { getFederationDomain } from '../lib/getFederationDomain'; import { dispatchEvent } from '../handler'; @@ -12,7 +10,7 @@ async function afterUnsetReaction(message, { user, reaction }) { // If there are not federated users on this room, ignore it if (!hasExternalDomain(room)) { return message; } - logger.client.debug(() => `afterUnsetReaction => message=${ JSON.stringify(_.pick(message, '_id', 'msg'), null, 2) } room=${ JSON.stringify(_.pick(room, '_id'), null, 2) } user=${ JSON.stringify(_.pick(user, 'username'), null, 2) } reaction=${ reaction }`); + clientLogger.debug({ msg: 'afterUnsetReaction', message, room, user, reaction }); // Create the event const event = await FederationRoomEvents.createUnsetMessageReactionEvent(getFederationDomain(), room._id, message._id, user.username, reaction); diff --git a/app/federation/server/hooks/beforeDeleteRoom.js b/app/federation/server/hooks/beforeDeleteRoom.js index 0131e4692806..7e55887263df 100644 --- a/app/federation/server/hooks/beforeDeleteRoom.js +++ b/app/federation/server/hooks/beforeDeleteRoom.js @@ -1,4 +1,4 @@ -import { logger } from '../lib/logger'; +import { clientLogger } from '../lib/logger'; import { FederationRoomEvents, Rooms } from '../../../models/server'; import { hasExternalDomain } from '../functions/helpers'; import { getFederationDomain } from '../lib/getFederationDomain'; @@ -13,7 +13,7 @@ async function beforeDeleteRoom(roomId) { // If there are not federated users on this room, ignore it if (!hasExternalDomain(room)) { return roomId; } - logger.client.debug(() => `beforeDeleteRoom => room=${ JSON.stringify(room, null, 2) }`); + clientLogger.debug({ msg: 'beforeDeleteRoom', room }); try { // Create the message event @@ -22,7 +22,7 @@ async function beforeDeleteRoom(roomId) { // Dispatch event (async) dispatchEvent(room.federation.domains, event); } catch (err) { - logger.client.error('beforeDeleteRoom => Could not remove room:', err); + clientLogger.error({ msg: 'beforeDeleteRoom => Could not remove room:', err }); throw err; } diff --git a/app/federation/server/lib/crypt.js b/app/federation/server/lib/crypt.js index ce92cfd84059..7a231a13fb91 100644 --- a/app/federation/server/lib/crypt.js +++ b/app/federation/server/lib/crypt.js @@ -1,7 +1,7 @@ import { FederationKeys } from '../../../models/server'; import { getFederationDomain } from './getFederationDomain'; import { search } from './dns'; -import { logger } from './logger'; +import { cryptLogger } from './logger'; export function decrypt(data, peerKey) { // @@ -15,7 +15,7 @@ export function decrypt(data, peerKey) { // Decrypt with the local private key data = FederationKeys.getPrivateKey().decrypt(data); } catch (err) { - logger.crypt.error(err); + cryptLogger.error(err); throw new Error('Could not decrypt'); } @@ -60,7 +60,7 @@ export function encrypt(data, peerKey) { // Encrypt with the local private key return FederationKeys.getPrivateKey().encryptPrivate(data); } catch (err) { - logger.crypt.error(err); + cryptLogger.error(err); throw new Error('Could not encrypt'); } diff --git a/app/federation/server/lib/dns.js b/app/federation/server/lib/dns.js index 189b8fc18692..0c4e2f348e1b 100644 --- a/app/federation/server/lib/dns.js +++ b/app/federation/server/lib/dns.js @@ -4,7 +4,7 @@ import { Meteor } from 'meteor/meteor'; import mem from 'mem'; import * as federationErrors from '../functions/errors'; -import { logger } from './logger'; +import { dnsLogger } from './logger'; import { isFederationEnabled } from './isFederationEnabled'; import { federationRequest } from './http'; @@ -26,7 +26,7 @@ export function registerWithHub(peerDomain, url, publicKey) { return true; } catch (err) { - logger.dns.error(err); + dnsLogger.error(err); throw federationErrors.peerCouldNotBeRegisteredWithHub('dns.registerWithHub'); } @@ -34,19 +34,19 @@ export function registerWithHub(peerDomain, url, publicKey) { export function searchHub(peerDomain) { try { - logger.dns.debug(`searchHub: peerDomain=${ peerDomain }`); + dnsLogger.debug(`searchHub: peerDomain=${ peerDomain }`); // If there is no DNS entry for that, get from the Hub const { data: { peer } } = federationRequest('GET', `${ hubUrl }/api/v1/peers?search=${ peerDomain }`); if (!peer) { - logger.dns.debug(`searchHub: could not find peerDomain=${ peerDomain }`); + dnsLogger.debug(`searchHub: could not find peerDomain=${ peerDomain }`); throw federationErrors.peerCouldNotBeRegisteredWithHub('dns.registerWithHub'); } const { url, public_key: publicKey } = peer; - logger.dns.debug(`searchHub: found peerDomain=${ peerDomain } url=${ url }`); + dnsLogger.debug(`searchHub: found peerDomain=${ peerDomain } url=${ url }`); return { url, @@ -54,7 +54,7 @@ export function searchHub(peerDomain) { publicKey, }; } catch (err) { - logger.dns.error(err); + dnsLogger.error(err); throw federationErrors.peerNotFoundUsingDNS('dns.searchHub'); } @@ -65,14 +65,14 @@ export function search(peerDomain) { throw federationErrors.disabled('dns.search'); } - logger.dns.debug(`search: peerDomain=${ peerDomain }`); + dnsLogger.debug(`search: peerDomain=${ peerDomain }`); let srvEntries = []; let protocol = ''; // Search by HTTPS first try { - logger.dns.debug(`search: peerDomain=${ peerDomain } srv=_rocketchat._https.${ peerDomain }`); + dnsLogger.debug(`search: peerDomain=${ peerDomain } srv=_rocketchat._https.${ peerDomain }`); srvEntries = memoizedDnsResolveSRV(`_rocketchat._https.${ peerDomain }`); protocol = 'https'; } catch (err) { @@ -82,7 +82,7 @@ export function search(peerDomain) { // If there is not entry, try with http if (!srvEntries.length) { try { - logger.dns.debug(`search: peerDomain=${ peerDomain } srv=_rocketchat._http.${ peerDomain }`); + dnsLogger.debug(`search: peerDomain=${ peerDomain } srv=_rocketchat._http.${ peerDomain }`); srvEntries = memoizedDnsResolveSRV(`_rocketchat._http.${ peerDomain }`); protocol = 'http'; } catch (err) { @@ -93,12 +93,12 @@ export function search(peerDomain) { // If there is not entry, try with tcp if (!srvEntries.length) { try { - logger.dns.debug(`search: peerDomain=${ peerDomain } srv=_rocketchat._tcp.${ peerDomain }`); + dnsLogger.debug(`search: peerDomain=${ peerDomain } srv=_rocketchat._tcp.${ peerDomain }`); srvEntries = memoizedDnsResolveSRV(`_rocketchat._tcp.${ peerDomain }`); protocol = 'https'; // https is the default // Then, also try to get the protocol - logger.dns.debug(`search: peerDomain=${ peerDomain } txt=rocketchat-tcp-protocol.${ peerDomain }`); + dnsLogger.debug(`search: peerDomain=${ peerDomain } txt=rocketchat-tcp-protocol.${ peerDomain }`); protocol = memoizedDnsResolveSRV(`rocketchat-tcp-protocol.${ peerDomain }`); protocol = protocol[0].join(''); @@ -115,7 +115,7 @@ export function search(peerDomain) { // If there is no entry, throw error if (!srvEntry || !protocol) { - logger.dns.debug(`search: could not find valid SRV entry peerDomain=${ peerDomain } srvEntry=${ JSON.stringify(srvEntry) } protocol=${ protocol }`); + dnsLogger.debug({ msg: 'search: could not find valid SRV entry', peerDomain, srvEntry, protocol }); return searchHub(peerDomain); } @@ -123,7 +123,7 @@ export function search(peerDomain) { // Get the public key from the TXT record try { - logger.dns.debug(`search: peerDomain=${ peerDomain } txt=rocketchat-public-key.${ peerDomain }`); + dnsLogger.debug(`search: peerDomain=${ peerDomain } txt=rocketchat-public-key.${ peerDomain }`); const publicKeyTxtRecords = memoizedDnsResolveTXT(`rocketchat-public-key.${ peerDomain }`); // Join the TXT record, that might be split @@ -134,11 +134,11 @@ export function search(peerDomain) { // If there is no entry, throw error if (!publicKey) { - logger.dns.debug(`search: could not find TXT entry for peerDomain=${ peerDomain } - SRV entry found`); + dnsLogger.debug(`search: could not find TXT entry for peerDomain=${ peerDomain } - SRV entry found`); return searchHub(peerDomain); } - logger.dns.debug(`search: found peerDomain=${ peerDomain } srvEntry=${ srvEntry.name }:${ srvEntry.port } protocol=${ protocol }`); + dnsLogger.debug({ msg: 'search: found', peerDomain, srvEntry, protocol }); return { url: `${ protocol }://${ srvEntry.name }:${ srvEntry.port }`, diff --git a/app/federation/server/lib/http.js b/app/federation/server/lib/http.js index 52cb31480163..542a2d32ef9e 100644 --- a/app/federation/server/lib/http.js +++ b/app/federation/server/lib/http.js @@ -1,7 +1,7 @@ import { HTTP as MeteorHTTP } from 'meteor/http'; import { EJSON } from 'meteor/ejson'; -import { logger } from './logger'; +import { httpLogger } from './logger'; import { getFederationDomain } from './getFederationDomain'; import { search } from './dns'; import { encrypt } from './crypt'; @@ -17,7 +17,7 @@ export function federationRequest(method, url, body, headers, peerKey = null) { } } - logger.http.debug(`[${ method }] ${ url }`); + httpLogger.debug(`[${ method }] ${ url }`); return MeteorHTTP.call(method, url, { data, timeout: 2000, headers: { ...headers, 'x-federation-domain': getFederationDomain() } }); } @@ -37,11 +37,11 @@ export function federationRequestToPeer(method, peerDomain, uri, body, options = let result; try { - logger.http.debug(() => `federationRequestToPeer => url=${ baseUrl }${ uri }`); + httpLogger.debug({ msg: 'federationRequestToPeer', url: `${ baseUrl }${ uri }` }); result = federationRequest(method, `${ baseUrl }${ uri }`, body, options.headers || {}, peerKey); } catch (err) { - logger.http.error(`${ ignoreErrors ? '[IGNORED] ' : '' }Error ${ err }`); + httpLogger.error({ msg: `${ ignoreErrors ? '[IGNORED] ' : '' }Error`, err }); if (!ignoreErrors) { throw err; diff --git a/app/federation/server/lib/logger.js b/app/federation/server/lib/logger.js index f3e791a14bf8..9e66d33808b0 100644 --- a/app/federation/server/lib/logger.js +++ b/app/federation/server/lib/logger.js @@ -1,12 +1,10 @@ import { Logger } from '../../../logger/server'; -export const logger = new Logger('Federation', { - sections: { - client: 'client', - crypt: 'crypt', - dns: 'dns', - http: 'http', - server: 'server', - setup: 'Setup', - }, -}); +const logger = new Logger('Federation'); + +export const clientLogger = logger.section('client'); +export const cryptLogger = logger.section('crypt'); +export const dnsLogger = logger.section('dns'); +export const httpLogger = logger.section('http'); +export const serverLogger = logger.section('server'); +export const setupLogger = logger.section('Setup'); diff --git a/app/federation/server/startup/settings.js b/app/federation/server/startup/settings.js index 48213be78807..a94caaaeff25 100644 --- a/app/federation/server/startup/settings.js +++ b/app/federation/server/startup/settings.js @@ -7,7 +7,7 @@ import { getFederationDomain } from '../lib/getFederationDomain'; import { getFederationDiscoveryMethod } from '../lib/getFederationDiscoveryMethod'; import { registerWithHub } from '../lib/dns'; import { enableCallbacks, disableCallbacks } from '../lib/callbacks'; -import { logger } from '../lib/logger'; +import { setupLogger } from '../lib/logger'; import { FederationKeys } from '../../../models/server'; import { STATUS_ENABLED, STATUS_REGISTERING, STATUS_ERROR_REGISTERING, STATUS_DISABLED } from '../constants'; @@ -89,7 +89,7 @@ const updateSettings = debounce(Meteor.bindEnvironment(function() { }), 150); function enableOrDisable(key, value) { - logger.setup.info(`Federation is ${ value ? 'enabled' : 'disabled' }`); + setupLogger.info(`Federation is ${ value ? 'enabled' : 'disabled' }`); if (value) { updateSettings(); diff --git a/app/file-upload/server/config/AmazonS3.js b/app/file-upload/server/config/AmazonS3.js index fbbb3724ce1a..efbef8d05651 100644 --- a/app/file-upload/server/config/AmazonS3.js +++ b/app/file-upload/server/config/AmazonS3.js @@ -6,13 +6,14 @@ import _ from 'underscore'; import { settings } from '../../../settings'; import { FileUploadClass, FileUpload } from '../lib/FileUpload'; import '../../ufs/AmazonS3/server.js'; +import { SystemLogger } from '../../../../server/lib/logger/system'; const get = function(file, req, res) { const forceDownload = typeof req.query.download !== 'undefined'; this.store.getRedirectURL(file, forceDownload, (err, fileUrl) => { if (err) { - return console.error(err); + return SystemLogger.error(err); } if (!fileUrl) { diff --git a/app/file-upload/server/config/GoogleStorage.js b/app/file-upload/server/config/GoogleStorage.js index c8e11bfe1fb5..1717f38c4240 100644 --- a/app/file-upload/server/config/GoogleStorage.js +++ b/app/file-upload/server/config/GoogleStorage.js @@ -6,13 +6,14 @@ import _ from 'underscore'; import { FileUploadClass, FileUpload } from '../lib/FileUpload'; import { settings } from '../../../settings'; import '../../ufs/GoogleStorage/server.js'; +import { SystemLogger } from '../../../../server/lib/logger/system'; const get = function(file, req, res) { const forceDownload = typeof req.query.download !== 'undefined'; this.store.getRedirectURL(file, forceDownload, (err, fileUrl) => { if (err) { - return console.error(err); + return SystemLogger.error(err); } if (!fileUrl) { @@ -33,7 +34,7 @@ const get = function(file, req, res) { const copy = function(file, out) { this.store.getRedirectURL(file, false, (err, fileUrl) => { if (err) { - console.error(err); + SystemLogger.error(err); } if (fileUrl) { diff --git a/app/file-upload/server/config/Webdav.js b/app/file-upload/server/config/Webdav.js index 8c5382b6b77e..2386b40ae141 100644 --- a/app/file-upload/server/config/Webdav.js +++ b/app/file-upload/server/config/Webdav.js @@ -3,11 +3,12 @@ import _ from 'underscore'; import { FileUploadClass, FileUpload } from '../lib/FileUpload'; import { settings } from '../../../settings'; import '../../ufs/Webdav/server.js'; +import { SystemLogger } from '../../../../server/lib/logger/system'; const get = function(file, req, res) { this.store.getReadStream(file._id, file) .on('error', () => { - console.error('An error ocurred when fetching the file'); + SystemLogger.error('An error ocurred when fetching the file'); res.writeHead(503); res.end(); }) diff --git a/app/file-upload/server/config/_configUploadStorage.js b/app/file-upload/server/config/_configUploadStorage.js index 3fb54925db71..b0b656b5c468 100644 --- a/app/file-upload/server/config/_configUploadStorage.js +++ b/app/file-upload/server/config/_configUploadStorage.js @@ -1,7 +1,8 @@ import { UploadFS } from 'meteor/jalik:ufs'; import _ from 'underscore'; -import { settings } from '../../../settings'; +import { settings } from '../../../settings/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; import './AmazonS3.js'; import './FileSystem.js'; import './GoogleStorage.js'; @@ -12,7 +13,7 @@ const configStore = _.debounce(() => { const store = settings.get('FileUpload_Storage_Type'); if (store) { - console.log('Setting default file store to', store); + SystemLogger.info(`Setting default file store to ${ store }`); UploadFS.getStores().Avatars = UploadFS.getStore(`${ store }:Avatars`); UploadFS.getStores().Uploads = UploadFS.getStore(`${ store }:Uploads`); UploadFS.getStores().UserDataFiles = UploadFS.getStore(`${ store }:UserDataFiles`); diff --git a/app/file-upload/server/lib/FileUpload.js b/app/file-upload/server/lib/FileUpload.js index cc9fd2c9a6c3..22e1cfc210fb 100644 --- a/app/file-upload/server/lib/FileUpload.js +++ b/app/file-upload/server/lib/FileUpload.js @@ -28,6 +28,7 @@ import { isValidJWT, generateJWT } from '../../../utils/server/lib/JWTHelper'; import { Messages } from '../../../models/server'; import { AppEvents, Apps } from '../../../apps/server'; import { streamToBuffer } from './streamToBuffer'; +import { SystemLogger } from '../../../../server/lib/logger/system'; const cookie = new Cookies(); let maxFileSize = 0; @@ -235,7 +236,7 @@ export const FileUpload = { .then(Meteor.bindEnvironment(({ data, info }) => { fs.writeFile(tempFilePath, data, Meteor.bindEnvironment((err) => { if (err != null) { - console.error(err); + SystemLogger.error(err); } this.getCollection().direct.update({ _id: file._id }, { @@ -317,7 +318,7 @@ export const FileUpload = { const s = sharp(tmpFile); s.metadata(Meteor.bindEnvironment((err, metadata) => { if (err != null) { - console.error(err); + SystemLogger.error(err); return fut.return(); } @@ -344,7 +345,7 @@ export const FileUpload = { })); })); })).catch((err) => { - console.error(err); + SystemLogger.error(err); fut.return(); }); }; @@ -431,7 +432,7 @@ export const FileUpload = { getStoreByName(handlerName) { if (this.handlers[handlerName] == null) { - console.error(`Upload handler "${ handlerName }" does not exists`); + SystemLogger.error(`Upload handler "${ handlerName }" does not exists`); } return this.handlers[handlerName]; }, diff --git a/app/file-upload/server/lib/proxy.js b/app/file-upload/server/lib/proxy.js index 0921956d111a..2435df950b6d 100644 --- a/app/file-upload/server/lib/proxy.js +++ b/app/file-upload/server/lib/proxy.js @@ -19,7 +19,7 @@ WebApp.connectHandlers.stack.unshift({ return next(); } - logger.debug('Upload URL:', req.url); + logger.debug({ msg: 'Upload URL:', url: req.url }); if (req.method !== 'POST') { return next(); @@ -75,7 +75,7 @@ WebApp.connectHandlers.stack.unshift({ instance.extraInformation.host = 'localhost'; } - logger.debug('Wrong instance, proxing to:', `${ instance.extraInformation.host }:${ instance.extraInformation.port }`); + logger.debug(`Wrong instance, proxing to ${ instance.extraInformation.host }:${ instance.extraInformation.port }`); const options = { hostname: instance.extraInformation.host, @@ -84,7 +84,7 @@ WebApp.connectHandlers.stack.unshift({ method: 'POST', }; - console.warn('UFS proxy middleware is deprecated as this upload method is not being used by Web/Mobile Clients. See this: https://docs.rocket.chat/api/rest-api/methods/rooms/upload'); + logger.warn('UFS proxy middleware is deprecated as this upload method is not being used by Web/Mobile Clients. See this: https://docs.rocket.chat/api/rest-api/methods/rooms/upload'); const proxy = http.request(options, function(proxy_res) { proxy_res.pipe(res, { end: true, diff --git a/app/file-upload/server/methods/sendFileMessage.ts b/app/file-upload/server/methods/sendFileMessage.ts index 6dfeebd29e51..80dec7bca683 100644 --- a/app/file-upload/server/methods/sendFileMessage.ts +++ b/app/file-upload/server/methods/sendFileMessage.ts @@ -11,6 +11,7 @@ import { canAccessRoom } from '../../../authorization/server/functions/canAccess import { MessageAttachment } from '../../../../definition/IMessage/MessageAttachment/MessageAttachment'; import { FileAttachmentProps } from '../../../../definition/IMessage/MessageAttachment/Files/FileAttachmentProps'; import { IUser } from '../../../../definition/IUser'; +import { SystemLogger } from '../../../../server/lib/logger/system'; Meteor.methods({ async sendFileMessage(roomId, _store, file, msgData = {}) { @@ -82,7 +83,7 @@ Meteor.methods({ }); } } catch (e) { - console.error(e); + SystemLogger.error(e); } attachments.push(attachment); } else if (/^audio\/.+/.test(file.type)) { diff --git a/app/file-upload/ufs/AmazonS3/server.js b/app/file-upload/ufs/AmazonS3/server.js index fc6ab49ebd27..e5fb5f87709f 100644 --- a/app/file-upload/ufs/AmazonS3/server.js +++ b/app/file-upload/ufs/AmazonS3/server.js @@ -6,6 +6,8 @@ import { Random } from 'meteor/random'; import _ from 'underscore'; import S3 from 'aws-sdk/clients/s3'; +import { SystemLogger } from '../../../../server/lib/logger/system'; + /** * AmazonS3 store * @param options @@ -91,7 +93,7 @@ export class AmazonS3Store extends UploadFS.Store { s3.deleteObject(params, (err, data) => { if (err) { - console.error(err); + SystemLogger.error(err); } callback && callback(err, data); @@ -144,7 +146,7 @@ export class AmazonS3Store extends UploadFS.Store { }, (error) => { if (error) { - console.error(error); + SystemLogger.error(error); } writeStream.emit('real_finish'); diff --git a/app/file-upload/ufs/GoogleStorage/server.js b/app/file-upload/ufs/GoogleStorage/server.js index 47b384466549..f0fe78265ef7 100644 --- a/app/file-upload/ufs/GoogleStorage/server.js +++ b/app/file-upload/ufs/GoogleStorage/server.js @@ -3,6 +3,8 @@ import { UploadFS } from 'meteor/jalik:ufs'; import { Random } from 'meteor/random'; import { Storage } from '@google-cloud/storage'; +import { SystemLogger } from '../../../../server/lib/logger/system'; + /** * GoogleStorage store * @param options @@ -70,7 +72,7 @@ export class GoogleStorageStore extends UploadFS.Store { const file = this.getCollection().findOne({ _id: fileId }); this.bucket.file(this.getPath(file)).delete(function(err, data) { if (err) { - console.error(err); + SystemLogger.error(err); } callback && callback(err, data); diff --git a/app/file-upload/ufs/Webdav/server.js b/app/file-upload/ufs/Webdav/server.js index 59567fdb4645..3d5326e1f194 100644 --- a/app/file-upload/ufs/Webdav/server.js +++ b/app/file-upload/ufs/Webdav/server.js @@ -5,6 +5,7 @@ import { UploadFS } from 'meteor/jalik:ufs'; import { Random } from 'meteor/random'; import { WebdavClientAdapter } from '../../../webdav/server/lib/webdavClientAdapter'; +import { SystemLogger } from '../../../../server/lib/logger/system'; /** * WebDAV store * @param options @@ -72,7 +73,7 @@ export class WebdavStore extends UploadFS.Store { const file = this.getCollection().findOne({ _id: fileId }); client.deleteFile(this.getPath(file)).then((data) => { callback && callback(null, data); - }).catch(console.error); + }).catch(SystemLogger.error); }; /** diff --git a/app/google-vision/README.md b/app/google-vision/README.md deleted file mode 100644 index 75ada0a6d01b..000000000000 --- a/app/google-vision/README.md +++ /dev/null @@ -1,7 +0,0 @@ -For this to properly work, you need to have a Google Service Account; -https://console.cloud.google.com/apis/credentials - -Then you have to authorize that service account access to your buckets; -https://console.cloud.google.com/storage/browser -To do that, click on the ellipsis by your bucket's row and Edit object default permissions -Add user and paste the service account e-mail with owner privileges diff --git a/app/google-vision/client/googlevision.js b/app/google-vision/client/googlevision.js deleted file mode 100644 index a9f977eba4ff..000000000000 --- a/app/google-vision/client/googlevision.js +++ /dev/null @@ -1,70 +0,0 @@ -const getVisionAttributes = (attachment) => { - const attributes = {}; - const labels = []; - if (attachment.labels && attachment.labels.length > 0) { - attachment.labels.forEach((label) => { - labels.push({ label }); - }); - } - if (attachment.safeSearch && attachment.safeSearch && attachment.safeSearch.adult === true) { - labels.push({ label: 'NSFW', bgColor: 'red', fontColor: 'white' }); - } - if (attachment.safeSearch && attachment.safeSearch.violence === true) { - labels.push({ label: 'Violence', bgColor: 'red', fontColor: 'white' }); - } - if (attachment.colors && attachment.colors.length > 0) { - attributes.color = `#${ attachment.colors[0] }`; - } - if (attachment.logos && attachment.logos.length > 0) { - labels.push({ label: `Logo: ${ attachment.logos[0] }` }); - } - if (attachment.faces && attachment.faces.length > 0) { - let faceCount = 0; - attachment.faces.forEach((face) => { - const faceAttributes = []; - if (face.joy) { - faceAttributes.push('Joy'); - } - if (face.sorrow) { - faceAttributes.push('Sorrow'); - } - if (face.anger) { - faceAttributes.push('Anger'); - } - if (face.surprise) { - faceAttributes.push('Surprise'); - } - if (faceAttributes.length > 0) { - labels.push({ label: `Face ${ ++faceCount }: ${ faceAttributes.join(', ') }` }); - } - }); - } - if (labels.length > 0) { - attributes.labels = labels; - } - return attributes; -}; - -export const createGoogleVisionMessageRenderer = () => - (message) => { - if (!message.attachments?.length) { - return message; - } - - message.attachments = message.attachments.map((attachment) => - Object.assign(attachment, getVisionAttributes(attachment))); - - return message; - }; - -export const createGoogleVisionMessageStreamHandler = () => - (message) => { - if (!message.attachments?.length) { - return message; - } - - message.attachments = message.attachments.map((attachment) => - Object.assign(attachment, getVisionAttributes(attachment))); - - return message; - }; diff --git a/app/google-vision/client/index.js b/app/google-vision/client/index.js deleted file mode 100644 index da4b03a0d29c..000000000000 --- a/app/google-vision/client/index.js +++ /dev/null @@ -1,4 +0,0 @@ -export { - createGoogleVisionMessageRenderer, - createGoogleVisionMessageStreamHandler, -} from './googlevision'; diff --git a/app/google-vision/server/googlevision.js b/app/google-vision/server/googlevision.js deleted file mode 100644 index 69729c6c1ddb..000000000000 --- a/app/google-vision/server/googlevision.js +++ /dev/null @@ -1,159 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; - -import { settings } from '../../settings'; -import { callbacks } from '../../callbacks'; -import { Uploads, Settings, Users, Messages } from '../../models'; -import { FileUpload } from '../../file-upload'; -import { api } from '../../../server/sdk/api'; - -class GoogleVision { - constructor() { - this.storage = require('@google-cloud/storage'); - this.vision = require('@google-cloud/vision'); - this.storageClient = {}; - this.visionClient = {}; - this.enabled = settings.get('GoogleVision_Enable'); - this.serviceAccount = {}; - settings.get('GoogleVision_Enable', (key, value) => { - this.enabled = value; - }); - settings.get('GoogleVision_ServiceAccount', (key, value) => { - try { - this.serviceAccount = JSON.parse(value); - this.storageClient = this.storage({ credentials: this.serviceAccount }); - this.visionClient = this.vision({ credentials: this.serviceAccount }); - } catch (e) { - this.serviceAccount = {}; - } - }); - settings.get('GoogleVision_Block_Adult_Images', (key, value) => { - if (value) { - callbacks.add('beforeSaveMessage', this.blockUnsafeImages.bind(this), callbacks.priority.MEDIUM, 'googlevision-blockunsafe'); - } else { - callbacks.remove('beforeSaveMessage', 'googlevision-blockunsafe'); - } - }); - callbacks.add('afterFileUpload', this.annotate.bind(this), callbacks.priority.MEDIUM, 'GoogleVision'); - } - - incCallCount(count) { - const currentMonth = new Date().getMonth(); - const maxMonthlyCalls = settings.get('GoogleVision_Max_Monthly_Calls') || 0; - if (maxMonthlyCalls > 0) { - if (settings.get('GoogleVision_Current_Month') !== currentMonth) { - settings.set('GoogleVision_Current_Month', currentMonth); - if (count > maxMonthlyCalls) { - return false; - } - } else if (count + (settings.get('GoogleVision_Current_Month_Calls') || 0) > maxMonthlyCalls) { - return false; - } - } - Settings.update({ _id: 'GoogleVision_Current_Month_Calls' }, { $inc: { value: count } }); - return true; - } - - blockUnsafeImages(message) { - if (this.enabled && this.serviceAccount && message && message.file && message.file._id) { - const file = Uploads.findOne({ _id: message.file._id }); - if (file && file.type && file.type.indexOf('image') !== -1 && file.store === 'GoogleCloudStorage:Uploads' && file.GoogleStorage) { - if (this.incCallCount(1)) { - const bucket = this.storageClient.bucket(settings.get('FileUpload_GoogleStorage_Bucket')); - const bucketFile = bucket.file(file.GoogleStorage.path); - const results = Meteor.wrapAsync(this.visionClient.detectSafeSearch, this.visionClient)(bucketFile); - if (results && results.adult === true) { - FileUpload.getStore('Uploads').deleteById(file._id); - const user = Users.findOneById(message.u && message.u._id); - if (user) { - api.broadcast('notify.ephemeralMessage', user._id, message.rid, { - msg: TAPi18n.__('Adult_images_are_not_allowed', {}, user.language), - }); - } - throw new Meteor.Error('GoogleVisionError: Image blocked'); - } - } else { - console.error('Google Vision: Usage limit exceeded'); - } - return message; - } - } - } - - annotate({ message }) { - const visionTypes = []; - if (settings.get('GoogleVision_Type_Document')) { - visionTypes.push('document'); - } - if (settings.get('GoogleVision_Type_Faces')) { - visionTypes.push('faces'); - } - if (settings.get('GoogleVision_Type_Landmarks')) { - visionTypes.push('landmarks'); - } - if (settings.get('GoogleVision_Type_Labels')) { - visionTypes.push('labels'); - } - if (settings.get('GoogleVision_Type_Logos')) { - visionTypes.push('logos'); - } - if (settings.get('GoogleVision_Type_Properties')) { - visionTypes.push('properties'); - } - if (settings.get('GoogleVision_Type_SafeSearch')) { - visionTypes.push('safeSearch'); - } - if (settings.get('GoogleVision_Type_Similar')) { - visionTypes.push('similar'); - } - if (this.enabled && this.serviceAccount && visionTypes.length > 0 && message.file && message.file._id) { - const file = Uploads.findOne({ _id: message.file._id }); - if (file && file.type && file.type.indexOf('image') !== -1 && file.store === 'GoogleCloudStorage:Uploads' && file.GoogleStorage) { - if (this.incCallCount(visionTypes.length)) { - const bucket = this.storageClient.bucket(settings.get('FileUpload_GoogleStorage_Bucket')); - const bucketFile = bucket.file(file.GoogleStorage.path); - this.visionClient.detect(bucketFile, visionTypes, Meteor.bindEnvironment((error, results) => { - if (!error) { - Messages.setGoogleVisionData(message._id, this.getAnnotations(visionTypes, results)); - } else { - console.trace('GoogleVision error: ', error.stack); - } - })); - } else { - console.error('Google Vision: Usage limit exceeded'); - } - } - } - } - - getAnnotations(visionTypes, visionData) { - if (visionTypes.length === 1) { - const _visionData = {}; - _visionData[`${ visionTypes[0] }`] = visionData; - visionData = _visionData; - } - const results = {}; - for (const index in visionData) { - if (visionData.hasOwnProperty(index)) { - switch (index) { - case 'faces': - case 'landmarks': - case 'labels': - case 'similar': - case 'logos': - results[index] = (results[index] || []).concat(visionData[index] || []); - break; - case 'safeSearch': - results.safeSearch = visionData.safeSearch; - break; - case 'properties': - results.colors = visionData[index].colors; - break; - } - } - } - return results; - } -} - -export default new GoogleVision(); diff --git a/app/google-vision/server/index.js b/app/google-vision/server/index.js deleted file mode 100644 index 95ffc9e6e508..000000000000 --- a/app/google-vision/server/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import './settings'; -import './googlevision'; diff --git a/app/google-vision/server/settings.js b/app/google-vision/server/settings.js deleted file mode 100644 index efa0f446bc72..000000000000 --- a/app/google-vision/server/settings.js +++ /dev/null @@ -1,93 +0,0 @@ -import { Meteor } from 'meteor/meteor'; - -import { settings } from '../../settings'; - -Meteor.startup(function() { - settings.add('GoogleVision_Enable', false, { - type: 'boolean', - group: 'FileUpload', - section: 'Google Vision', - public: true, - enableQuery: { _id: 'FileUpload_Storage_Type', value: 'GoogleCloudStorage' }, - }); - settings.add('GoogleVision_ServiceAccount', '', { - type: 'string', - group: 'FileUpload', - section: 'Google Vision', - multiline: true, - enableQuery: { _id: 'GoogleVision_Enable', value: true }, - secret: true, - }); - settings.add('GoogleVision_Max_Monthly_Calls', 0, { - type: 'int', - group: 'FileUpload', - section: 'Google Vision', - enableQuery: { _id: 'GoogleVision_Enable', value: true }, - }); - settings.add('GoogleVision_Current_Month', 0, { - type: 'int', - group: 'FileUpload', - section: 'Google Vision', - hidden: true, - }); - settings.add('GoogleVision_Current_Month_Calls', 0, { - type: 'int', - group: 'FileUpload', - section: 'Google Vision', - blocked: true, - }); - settings.add('GoogleVision_Type_Document', false, { - type: 'boolean', - group: 'FileUpload', - section: 'Google Vision', - enableQuery: { _id: 'GoogleVision_Enable', value: true }, - }); - settings.add('GoogleVision_Type_Faces', false, { - type: 'boolean', - group: 'FileUpload', - section: 'Google Vision', - enableQuery: { _id: 'GoogleVision_Enable', value: true }, - }); - settings.add('GoogleVision_Type_Landmarks', false, { - type: 'boolean', - group: 'FileUpload', - section: 'Google Vision', - enableQuery: { _id: 'GoogleVision_Enable', value: true }, - }); - settings.add('GoogleVision_Type_Labels', false, { - type: 'boolean', - group: 'FileUpload', - section: 'Google Vision', - enableQuery: { _id: 'GoogleVision_Enable', value: true }, - }); - settings.add('GoogleVision_Type_Logos', false, { - type: 'boolean', - group: 'FileUpload', - section: 'Google Vision', - enableQuery: { _id: 'GoogleVision_Enable', value: true }, - }); - settings.add('GoogleVision_Type_Properties', false, { - type: 'boolean', - group: 'FileUpload', - section: 'Google Vision', - enableQuery: { _id: 'GoogleVision_Enable', value: true }, - }); - settings.add('GoogleVision_Type_SafeSearch', false, { - type: 'boolean', - group: 'FileUpload', - section: 'Google Vision', - enableQuery: { _id: 'GoogleVision_Enable', value: true }, - }); - settings.add('GoogleVision_Block_Adult_Images', false, { - type: 'boolean', - group: 'FileUpload', - section: 'Google Vision', - enableQuery: [{ _id: 'GoogleVision_Enable', value: true }, { _id: 'GoogleVision_Type_SafeSearch', value: true }], - }); - settings.add('GoogleVision_Type_Similar', false, { - type: 'boolean', - group: 'FileUpload', - section: 'Google Vision', - enableQuery: { _id: 'GoogleVision_Enable', value: true }, - }); -}); diff --git a/app/iframe-login/server/iframe_server.js b/app/iframe-login/server/iframe_server.js index 586bc8ee8558..95fd1d4cd50f 100644 --- a/app/iframe-login/server/iframe_server.js +++ b/app/iframe-login/server/iframe_server.js @@ -10,8 +10,6 @@ Accounts.registerLoginHandler('iframe', function(result) { check(result.token, String); - console.log('[Method] registerLoginHandler'); - const user = Meteor.users.findOne({ 'services.iframe.token': result.token, }); diff --git a/app/importer-csv/server/importer.js b/app/importer-csv/server/importer.js index 66cc086c1c1a..285f747e6193 100644 --- a/app/importer-csv/server/importer.js +++ b/app/importer-csv/server/importer.js @@ -35,7 +35,7 @@ export class CsvImporter extends Base { oldRate = rate; } } catch (e) { - console.error(e); + this.logger.error(e); } }; diff --git a/app/importer-hipchat-enterprise/server/importer.js b/app/importer-hipchat-enterprise/server/importer.js index 3f59b669e632..b5b2fc2e43b7 100644 --- a/app/importer-hipchat-enterprise/server/importer.js +++ b/app/importer-hipchat-enterprise/server/importer.js @@ -43,7 +43,7 @@ export class HipChatEnterpriseImporter extends Base { this.logger.debug('parsing file contents'); return JSON.parse(dataString); } catch (e) { - console.error(e); + this.logger.error(e); return false; } } diff --git a/app/importer-pending-avatars/server/importer.js b/app/importer-pending-avatars/server/importer.js index 7a8767ba582a..aa12266decf2 100644 --- a/app/importer-pending-avatars/server/importer.js +++ b/app/importer-pending-avatars/server/importer.js @@ -52,7 +52,6 @@ export class PendingAvatarImporter extends Base { Users.update({ _id }, { $unset: { _pendingAvatarUrl: '' } }); } catch (error) { this.logger.warn(`Failed to set ${ name }'s avatar from url ${ url }`); - console.log(`Failed to set ${ name }'s avatar from url ${ url }`); } }); } finally { @@ -65,7 +64,7 @@ export class PendingAvatarImporter extends Base { } catch (error) { // If the cursor expired, restart the method if (error && error.codeName === 'CursorNotFound') { - console.log('CursorNotFound'); + this.logger.info('CursorNotFound'); return this.startImport(); } diff --git a/app/importer-slack/server/importer.js b/app/importer-slack/server/importer.js index 7853b6d54e59..c913c77cbb1d 100644 --- a/app/importer-slack/server/importer.js +++ b/app/importer-slack/server/importer.js @@ -18,7 +18,7 @@ export class SlackImporter extends Base { this.logger.debug('parsing file contents'); return JSON.parse(dataString); } catch (e) { - console.error(e); + this.logger.error(e); return false; } } @@ -197,7 +197,7 @@ export class SlackImporter extends Base { oldRate = rate; } } catch (e) { - console.error(e); + this.logger.error(e); } }; @@ -290,7 +290,7 @@ export class SlackImporter extends Base { }); if (!_.isEmpty(missedTypes)) { - console.log('Missed import types:', missedTypes); + this.logger.info('Missed import types:', missedTypes); } } catch (e) { this.logger.error(e); diff --git a/app/importer/server/classes/ImporterBase.js b/app/importer/server/classes/ImporterBase.js index decfd093543f..75120f6965b9 100644 --- a/app/importer/server/classes/ImporterBase.js +++ b/app/importer/server/classes/ImporterBase.js @@ -54,7 +54,7 @@ export class Base { this.info = info; - this.logger = new Logger(`${ this.info.name } Importer`, {}); + this.logger = new Logger(`${ this.info.name } Importer`); this.converter.setLogger(this.logger); this.progress = new Progress(this.info.key, this.info.name); diff --git a/app/importer/server/startup/setImportsToInvalid.js b/app/importer/server/startup/setImportsToInvalid.js index a7ec86373222..431d4040ab79 100644 --- a/app/importer/server/startup/setImportsToInvalid.js +++ b/app/importer/server/startup/setImportsToInvalid.js @@ -1,6 +1,7 @@ import { Meteor } from 'meteor/meteor'; -import { Imports } from '../../../models'; +import { Imports } from '../../../models/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; import { RawImports } from '../models/RawImports'; import { ProgressStep } from '../../lib/ImporterProgressStep'; @@ -8,7 +9,7 @@ function runDrop(fn) { try { fn(); } catch (e) { - console.log('error', e); // TODO: Remove + SystemLogger.error('error', e); // TODO: Remove // ignored } } diff --git a/app/integrations/server/api/api.js b/app/integrations/server/api/api.js index 63d32c9be338..b1d1277b4f3d 100644 --- a/app/integrations/server/api/api.js +++ b/app/integrations/server/api/api.js @@ -10,7 +10,7 @@ import _ from 'underscore'; import s from 'underscore.string'; import moment from 'moment'; -import { logger } from '../logger'; +import { incomingLogger } from '../logger'; import { processWebhookMessage } from '../../../lib'; import { API, APIClass, defaultRateLimiterOptions } from '../../../api/server'; import * as Models from '../../../models'; @@ -63,8 +63,8 @@ function getIntegrationScript(integration) { const script = integration.scriptCompiled; const { sandbox, store } = buildSandbox(); try { - logger.incoming.info('Will evaluate script of Trigger', integration.name); - logger.incoming.debug(script); + incomingLogger.info({ msg: 'Will evaluate script of Trigger', name: integration.name }); + incomingLogger.debug(script); const vmScript = vm.createScript(script, 'script.js'); vmScript.runInNewContext(sandbox); @@ -77,23 +77,20 @@ function getIntegrationScript(integration) { return compiledScripts[integration._id].script; } - } catch ({ stack }) { - logger.incoming.error('[Error evaluating Script in Trigger', integration.name, ':]'); - logger.incoming.error(script.replace(/^/gm, ' ')); - logger.incoming.error('[Stack:]'); - logger.incoming.error(stack.replace(/^/gm, ' ')); + } catch (err) { + incomingLogger.error({ msg: 'Error evaluating Script in Trigger', name: integration.name, script, err }); throw API.v1.failure('error-evaluating-script'); } if (!sandbox.Script) { - logger.incoming.error('[Class "Script" not in Trigger', integration.name, ']'); + incomingLogger.error({ msg: 'Class "Script" not in Trigger', name: integration.name }); throw API.v1.failure('class-script-not-found'); } } function createIntegration(options, user) { - logger.incoming.info('Add integration', options.name); - logger.incoming.debug(options); + incomingLogger.info({ msg: 'Add integration', name: options.name }); + incomingLogger.debug(options); Meteor.runAsUser(user._id, function() { switch (options.event) { @@ -129,8 +126,8 @@ function createIntegration(options, user) { } function removeIntegration(options, user) { - logger.incoming.info('Remove integration'); - logger.incoming.debug(options); + incomingLogger.info('Remove integration'); + incomingLogger.debug(options); const integrationToRemove = Models.Integrations.findOne({ urls: options.target_url, @@ -142,9 +139,8 @@ function removeIntegration(options, user) { } function executeIntegrationRest() { - logger.incoming.info('Post integration:', this.integration.name); - logger.incoming.debug('@urlParams:', this.urlParams); - logger.incoming.debug('@bodyParams:', this.bodyParams); + incomingLogger.info({ msg: 'Post integration:', name: this.integration.name }); + incomingLogger.debug({ urlParams: this.urlParams, bodyParams: this.bodyParams }); if (this.integration.enabled !== true) { return { @@ -165,7 +161,7 @@ function executeIntegrationRest() { try { script = getIntegrationScript(this.integration); } catch (e) { - logger.incoming.warn(e); + incomingLogger.error(e); return API.v1.failure(e.message); } @@ -214,7 +210,7 @@ function executeIntegrationRest() { })).wait(); if (!result) { - logger.incoming.debug('[Process Incoming Request result of Trigger', this.integration.name, ':] No data'); + incomingLogger.debug({ msg: 'Process Incoming Request result of Trigger has no data', name: this.integration.name }); return API.v1.success(); } if (result && result.error) { return API.v1.failure(result.error); @@ -226,13 +222,9 @@ function executeIntegrationRest() { this.user = result.user; } - logger.incoming.debug('[Process Incoming Request result of Trigger', this.integration.name, ':]'); - logger.incoming.debug('result', this.bodyParams); - } catch ({ stack }) { - logger.incoming.error('[Error running Script in Trigger', this.integration.name, ':]'); - logger.incoming.error(this.integration.scriptCompiled.replace(/^/gm, ' ')); - logger.incoming.error('[Stack:]'); - logger.incoming.error(stack.replace(/^/gm, ' ')); + incomingLogger.debug({ msg: 'Process Incoming Request result of Trigger', name: this.integration.name, result: this.bodyParams }); + } catch (err) { + incomingLogger.error({ msg: 'Error running Script in Trigger', name: this.integration.name, script: this.integration.scriptCompiled, err }); return API.v1.failure('error-running-script'); } } @@ -253,7 +245,7 @@ function executeIntegrationRest() { } if (this.scriptResponse) { - logger.incoming.debug('response', this.scriptResponse); + incomingLogger.debug({ msg: 'response', response: this.scriptResponse }); } return API.v1.success(this.scriptResponse); @@ -271,7 +263,7 @@ function removeIntegrationRest() { } function integrationSampleRest() { - logger.incoming.info('Sample Integration'); + incomingLogger.info('Sample Integration'); return { statusCode: 200, body: [ @@ -308,7 +300,7 @@ function integrationSampleRest() { } function integrationInfoRest() { - logger.incoming.info('Info integration'); + incomingLogger.info('Info integration'); return { statusCode: 200, body: { @@ -387,7 +379,7 @@ const Api = new WebHookAPI({ }); if (!this.integration) { - logger.incoming.info('Invalid integration id', this.request.params.integrationId, 'or token', this.request.params.token); + incomingLogger.info(`Invalid integration id ${ this.request.params.integrationId } or token ${ this.request.params.token }`); return { error: { diff --git a/app/integrations/server/lib/triggerHandler.js b/app/integrations/server/lib/triggerHandler.js index a7cd0a682c4a..0c5afb6cbde8 100644 --- a/app/integrations/server/lib/triggerHandler.js +++ b/app/integrations/server/lib/triggerHandler.js @@ -12,7 +12,7 @@ import Future from 'fibers/future'; import * as Models from '../../../models'; import { settings } from '../../../settings'; import { getRoomByNameOrIdWithOptionToJoin, processWebhookMessage } from '../../../lib'; -import { logger } from '../logger'; +import { outgoingLogger } from '../logger'; import { integrations } from '../../lib/rocketchat'; export class RocketChatIntegrationHandler { @@ -26,17 +26,17 @@ export class RocketChatIntegrationHandler { } addIntegration(record) { - logger.outgoing.debug(`Adding the integration ${ record.name } of the event ${ record.event }!`); + outgoingLogger.debug(`Adding the integration ${ record.name } of the event ${ record.event }!`); let channels; if (record.event && !integrations.outgoingEvents[record.event].use.channel) { - logger.outgoing.debug('The integration doesnt rely on channels.'); + outgoingLogger.debug('The integration doesnt rely on channels.'); // We don't use any channels, so it's special ;) channels = ['__any']; } else if (_.isEmpty(record.channel)) { - logger.outgoing.debug('The integration had an empty channel property, so it is going on all the public channels.'); + outgoingLogger.debug('The integration had an empty channel property, so it is going on all the public channels.'); channels = ['all_public_channels']; } else { - logger.outgoing.debug('The integration is going on these channels:', record.channel); + outgoingLogger.debug('The integration is going on these channels:', record.channel); channels = [].concat(record.channel); } @@ -172,11 +172,11 @@ export class RocketChatIntegrationHandler { // If no room could be found, we won't be sending any messages but we'll warn in the logs if (!tmpRoom) { - logger.outgoing.warn(`The Integration "${ trigger.name }" doesn't have a room configured nor did it provide a room to send the message to.`); + outgoingLogger.warn(`The Integration "${ trigger.name }" doesn't have a room configured nor did it provide a room to send the message to.`); return; } - logger.outgoing.debug(`Found a room for ${ trigger.name } which is: ${ tmpRoom.name } with a type of ${ tmpRoom.t }`); + outgoingLogger.debug(`Found a room for ${ trigger.name } which is: ${ tmpRoom.name } with a type of ${ tmpRoom.t }`); message.bot = { i: trigger._id }; @@ -240,8 +240,8 @@ export class RocketChatIntegrationHandler { let vmScript; try { - logger.outgoing.info('Will evaluate script of Trigger', integration.name); - logger.outgoing.debug(script); + outgoingLogger.info({ msg: 'Will evaluate script of Trigger', name: integration.name }); + outgoingLogger.debug(script); vmScript = this.vm.createScript(script, 'script.js'); @@ -256,16 +256,13 @@ export class RocketChatIntegrationHandler { return this.compiledScripts[integration._id].script; } - } catch (e) { - logger.outgoing.error(`Error evaluating Script in Trigger ${ integration.name }:`); - logger.outgoing.error(script.replace(/^/gm, ' ')); - logger.outgoing.error('Stack Trace:'); - logger.outgoing.error(e.stack.replace(/^/gm, ' ')); + } catch (err) { + outgoingLogger.error({ msg: 'Error evaluating Script in Trigger', name: integration.name, script, err }); throw new Meteor.Error('error-evaluating-script'); } if (!sandbox.Script) { - logger.outgoing.error(`Class "Script" not in Trigger ${ integration.name }:`); + outgoingLogger.error(`Class "Script" not in Trigger ${ integration.name }:`); throw new Meteor.Error('class-script-not-found'); } } @@ -295,7 +292,7 @@ export class RocketChatIntegrationHandler { } if (!script[method]) { - logger.outgoing.error(`Method "${ method }" no found in the Integration "${ integration.name }"`); + outgoingLogger.error(`Method "${ method }" no found in the Integration "${ integration.name }"`); this.updateHistory({ historyId, step: `execute-script-no-method-${ method }` }); return; } @@ -323,16 +320,13 @@ export class RocketChatIntegrationHandler { timeout: 3000, })).wait(); - logger.outgoing.debug(`Script method "${ method }" result of the Integration "${ integration.name }" is:`); - logger.outgoing.debug(result); + outgoingLogger.debug({ msg: `Script method "${ method }" result of the Integration "${ integration.name }" is:`, result }); return result; - } catch (e) { - this.updateHistory({ historyId, step: `execute-script-error-running-${ method }`, error: true, errorStack: e.stack.replace(/^/gm, ' ') }); - logger.outgoing.error(`Error running Script in the Integration ${ integration.name }:`); - logger.outgoing.debug(integration.scriptCompiled.replace(/^/gm, ' ')); // Only output the compiled script if debugging is enabled, so the logs don't get spammed. - logger.outgoing.error('Stack:'); - logger.outgoing.error(e.stack.replace(/^/gm, ' ')); + } catch (err) { + this.updateHistory({ historyId, step: `execute-script-error-running-${ method }`, error: true, errorStack: err.stack.replace(/^/gm, ' ') }); + outgoingLogger.error({ msg: 'Error running Script in the Integration', name: integration.name, err }); + outgoingLogger.debug({ msg: 'Error running Script in the Integration', name: integration.name, script: integration.scriptCompiled }); // Only output the compiled script if debugging is enabled, so the logs don't get spammed. } } @@ -381,12 +375,12 @@ export class RocketChatIntegrationHandler { } break; default: - logger.outgoing.warn(`An Unhandled Trigger Event was called: ${ argObject.event }`); + outgoingLogger.warn(`An Unhandled Trigger Event was called: ${ argObject.event }`); argObject.event = undefined; break; } - logger.outgoing.debug(`Got the event arguments for the event: ${ argObject.event }`, argObject); + outgoingLogger.debug({ msg: `Got the event arguments for the event: ${ argObject.event }`, argObject }); return argObject; } @@ -546,7 +540,7 @@ export class RocketChatIntegrationHandler { } executeTriggers(...args) { - logger.outgoing.debug('Execute Trigger:', args[0]); + outgoingLogger.debug({ msg: 'Execute Trigger:', arg: args[0] }); const argObject = this.eventNameArgumentsToObject(...args); const { event, message, room } = argObject; @@ -558,7 +552,7 @@ export class RocketChatIntegrationHandler { return; } - logger.outgoing.debug('Starting search for triggers for the room:', room ? room._id : '__any'); + outgoingLogger.debug(`Starting search for triggers for the room: ${ room ? room._id : '__any' }`); const triggersToExecute = this.getTriggersToExecute(room, message); @@ -569,10 +563,10 @@ export class RocketChatIntegrationHandler { } } - logger.outgoing.debug(`Found ${ triggersToExecute.length } to iterate over and see if the match the event.`); + outgoingLogger.debug(`Found ${ triggersToExecute.length } to iterate over and see if the match the event.`); for (const triggerToExecute of triggersToExecute) { - logger.outgoing.debug(`Is "${ triggerToExecute.name }" enabled, ${ triggerToExecute.enabled }, and what is the event? ${ triggerToExecute.event }`); + outgoingLogger.debug(`Is "${ triggerToExecute.name }" enabled, ${ triggerToExecute.enabled }, and what is the event? ${ triggerToExecute.event }`); if (triggerToExecute.enabled === true && triggerToExecute.event === event) { this.executeTrigger(triggerToExecute, argObject); } @@ -587,11 +581,11 @@ export class RocketChatIntegrationHandler { executeTriggerUrl(url, trigger, { event, message, room, owner, user }, theHistoryId, tries = 0) { if (!this.isTriggerEnabled(trigger)) { - logger.outgoing.warn(`The trigger "${ trigger.name }" is no longer enabled, stopping execution of it at try: ${ tries }`); + outgoingLogger.warn(`The trigger "${ trigger.name }" is no longer enabled, stopping execution of it at try: ${ tries }`); return; } - logger.outgoing.debug(`Starting to execute trigger: ${ trigger.name } (${ trigger._id })`); + outgoingLogger.debug(`Starting to execute trigger: ${ trigger.name } (${ trigger._id })`); let word; // Not all triggers/events support triggerWords @@ -609,14 +603,14 @@ export class RocketChatIntegrationHandler { // Stop if there are triggerWords but none match if (!word) { - logger.outgoing.debug(`The trigger word which "${ trigger.name }" was expecting could not be found, not executing.`); + outgoingLogger.debug(`The trigger word which "${ trigger.name }" was expecting could not be found, not executing.`); return; } } } if (message && message.editedAt && !trigger.runOnEdits) { - logger.outgoing.debug(`The trigger "${ trigger.name }"'s run on edits is disabled and the message was edited.`); + outgoingLogger.debug(`The trigger "${ trigger.name }"'s run on edits is disabled and the message was edited.`); return; } @@ -634,8 +628,8 @@ export class RocketChatIntegrationHandler { this.mapEventArgsToData(data, { trigger, event, message, room, owner, user }); this.updateHistory({ historyId, step: 'mapped-args-to-data', data, triggerWord: word }); - logger.outgoing.info(`Will be executing the Integration "${ trigger.name }" to the url: ${ url }`); - logger.outgoing.debug(data); + outgoingLogger.info(`Will be executing the Integration "${ trigger.name }" to the url: ${ url }`); + outgoingLogger.debug(data); let opts = { params: {}, @@ -676,9 +670,9 @@ export class RocketChatIntegrationHandler { this.updateHistory({ historyId, step: 'pre-http-call', url: opts.url, httpCallData: opts.data }); HTTP.call(opts.method, opts.url, opts, (error, result) => { if (!result) { - logger.outgoing.warn(`Result for the Integration ${ trigger.name } to ${ url } is empty`); + outgoingLogger.warn(`Result for the Integration ${ trigger.name } to ${ url } is empty`); } else { - logger.outgoing.info(`Status code for the Integration ${ trigger.name } to ${ url } is ${ result.statusCode }`); + outgoingLogger.info(`Status code for the Integration ${ trigger.name } to ${ url } is ${ result.statusCode }`); } this.updateHistory({ historyId, step: 'after-http-call', httpError: error, httpResult: result }); @@ -712,25 +706,22 @@ export class RocketChatIntegrationHandler { // if the result contained nothing or wasn't a successful statusCode if (!result || !this.successResults.includes(result.statusCode)) { if (error) { - logger.outgoing.error(`Error for the Integration "${ trigger.name }" to ${ url } is:`); - logger.outgoing.error(error); + outgoingLogger.error({ msg: `Error for the Integration "${ trigger.name }" to ${ url }`, err: error }); } if (result) { - logger.outgoing.error(`Error for the Integration "${ trigger.name }" to ${ url } is:`); - logger.outgoing.error(result); + outgoingLogger.error({ msg: `Error for the Integration "${ trigger.name }" to ${ url }`, result }); if (result.statusCode === 410) { this.updateHistory({ historyId, step: 'after-process-http-status-410', error: true }); - logger.outgoing.error(`Disabling the Integration "${ trigger.name }" because the status code was 401 (Gone).`); + outgoingLogger.error(`Disabling the Integration "${ trigger.name }" because the status code was 401 (Gone).`); Models.Integrations.update({ _id: trigger._id }, { $set: { enabled: false } }); return; } if (result.statusCode === 500) { this.updateHistory({ historyId, step: 'after-process-http-status-500', error: true }); - logger.outgoing.error(`Error "500" for the Integration "${ trigger.name }" to ${ url }.`); - logger.outgoing.error(result.content); + outgoingLogger.error({ msg: `Error "500" for the Integration "${ trigger.name }" to ${ url }.`, content: result.content }); return; } } @@ -760,7 +751,7 @@ export class RocketChatIntegrationHandler { return; } - logger.outgoing.info(`Trying the Integration ${ trigger.name } to ${ url } again in ${ waitTime } milliseconds.`); + outgoingLogger.info(`Trying the Integration ${ trigger.name } to ${ url } again in ${ waitTime } milliseconds.`); Meteor.setTimeout(() => { this.executeTriggerUrl(url, trigger, { event, message, room, owner, user }, historyId, tries + 1); }, waitTime); diff --git a/app/integrations/server/logger.js b/app/integrations/server/logger.js index 4a293574b984..dd0076279883 100644 --- a/app/integrations/server/logger.js +++ b/app/integrations/server/logger.js @@ -1,8 +1,6 @@ import { Logger } from '../../logger'; -export const logger = new Logger('Integrations', { - sections: { - incoming: 'Incoming WebHook', - outgoing: 'Outgoing WebHook', - }, -}); +const logger = new Logger('Integrations'); + +export const incomingLogger = logger.section('Incoming WebHook'); +export const outgoingLogger = logger.section('Outgoing WebHook'); diff --git a/app/irc/server/irc-bridge/index.js b/app/irc/server/irc-bridge/index.js index c796720c471d..8f296f847e95 100644 --- a/app/irc/server/irc-bridge/index.js +++ b/app/irc/server/irc-bridge/index.js @@ -5,9 +5,13 @@ import _ from 'underscore'; import * as peerCommandHandlers from './peerHandlers'; import * as localCommandHandlers from './localHandlers'; -import { callbacks } from '../../../callbacks'; +import { callbacks } from '../../../callbacks/server'; import * as servers from '../servers'; import { Settings } from '../../../models/server'; +import { Logger } from '../../../logger/server'; + +const logger = new Logger('IRC Bridge'); +const queueLogger = logger.section('Queue'); let removed = false; const updateLastPing = _.throttle(Meteor.bindEnvironment(() => { @@ -82,11 +86,13 @@ class Bridge { * Log helper */ log(message) { - console.log(`[irc][bridge] ${ message }`); + // TODO logger: debug? + logger.info(message); } logQueue(message) { - console.log(`[irc][bridge][queue] ${ message }`); + // TODO logger: debug? + queueLogger.info(message); } /** diff --git a/app/irc/server/irc-bridge/localHandlers/onSaveMessage.js b/app/irc/server/irc-bridge/localHandlers/onSaveMessage.js index a5ebf1ddfb82..aed761ff127b 100644 --- a/app/irc/server/irc-bridge/localHandlers/onSaveMessage.js +++ b/app/irc/server/irc-bridge/localHandlers/onSaveMessage.js @@ -1,3 +1,4 @@ +import { SystemLogger } from '../../../../../server/lib/logger/system'; import { Subscriptions, Users } from '../../../../models'; export default function handleOnSaveMessage(message, to) { @@ -21,7 +22,7 @@ export default function handleOnSaveMessage(message, to) { }); if (!toIdentification) { - console.error('[irc][server] Target user not found'); + SystemLogger.error('[irc][server] Target user not found'); return; } } else { diff --git a/app/irc/server/servers/RFC2813/index.js b/app/irc/server/servers/RFC2813/index.js index 6d6335c4017b..77750b9d1059 100644 --- a/app/irc/server/servers/RFC2813/index.js +++ b/app/irc/server/servers/RFC2813/index.js @@ -5,6 +5,9 @@ import { EventEmitter } from 'events'; import parseMessage from './parseMessage'; import peerCommandHandlers from './peerCommandHandlers'; import localCommandHandlers from './localCommandHandlers'; +import { Logger } from '../../../../logger/server'; + +const logger = new Logger('IRC Server'); class RFC2813 { constructor(config) { @@ -35,7 +38,7 @@ class RFC2813 { this.socket.on('data', this.onReceiveFromPeer.bind(this)); this.socket.on('connect', this.onConnect.bind(this)); - this.socket.on('error', (err) => console.log('[irc][server][err]', err)); + this.socket.on('error', (err) => logger.error(err)); this.socket.on('timeout', () => this.log('Timeout')); this.socket.on('close', () => this.log('Connection Closed')); // Setup local @@ -46,7 +49,8 @@ class RFC2813 { * Log helper */ log(message) { - console.log(`[irc][server] ${ message }`); + // TODO logger: debug? + logger.info(message); } /** @@ -148,11 +152,11 @@ class RFC2813 { const command = peerCommandHandlers[parsedMessage.command].call(this, parsedMessage); if (command) { - this.log(`Emitting peer command to local: ${ JSON.stringify(command) }`); + this.log({ msg: 'Emitting peer command to local', command }); this.emit('peerCommand', command); } } else { - this.log(`Unhandled peer message: ${ JSON.stringify(parsedMessage) }`); + this.log({ msg: 'Unhandled peer message', parsedMessage }); } } }); @@ -171,7 +175,7 @@ class RFC2813 { localCommandHandlers[command].call(this, parameters, this); } else { - this.log(`Unhandled local command: ${ JSON.stringify(command) }`); + this.log({ msg: 'Unhandled local command', command }); } } } diff --git a/app/ldap/server/ldap.js b/app/ldap/server/ldap.js index eafdd3161796..a3bae173b835 100644 --- a/app/ldap/server/ldap.js +++ b/app/ldap/server/ldap.js @@ -6,14 +6,12 @@ import { callbacks } from '../../callbacks/server'; import { settings } from '../../settings'; import { Logger } from '../../logger'; -const logger = new Logger('LDAP', { - sections: { - connection: 'Connection', - bind: 'Bind', - search: 'Search', - auth: 'Auth', - }, -}); +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() { @@ -66,7 +64,7 @@ export default class LDAP { } connectAsync(callback) { - logger.connection.info('Init setup'); + connLogger.info('Init setup'); let replied = false; @@ -113,15 +111,15 @@ export default class LDAP { connectionOptions.url = `ldap://${ connectionOptions.url }`; } - logger.connection.info('Connecting', connectionOptions.url); - logger.connection.debug('connectionOptions', connectionOptions); + 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) => { - logger.connection.error('connection', error); + connLogger.error({ msg: 'connection', err: error }); if (replied === false) { replied = true; callback(error, null); @@ -129,12 +127,12 @@ export default class LDAP { }); this.client.on('idle', () => { - logger.search.info('Idle'); + searchLogger.info('Idle'); this.disconnect(); }); this.client.on('close', () => { - logger.search.info('Closed'); + searchLogger.info('Closed'); }); if (this.options.encryption === 'tls') { @@ -143,12 +141,12 @@ export default class LDAP { // https://github.com/mcavage/node-ldapjs/issues/349 tlsOptions.host = this.options.host; - logger.connection.info('Starting TLS'); - logger.connection.debug('tlsOptions', tlsOptions); + connLogger.info('Starting TLS'); + connLogger.debug({ tlsOptions }); this.client.starttls(tlsOptions, null, (error, response) => { if (error) { - logger.connection.error('TLS connection', error); + connLogger.error({ msg: 'TLS connection', err: error }); if (replied === false) { replied = true; callback(error, null); @@ -156,7 +154,7 @@ export default class LDAP { return; } - logger.connection.info('TLS connected'); + connLogger.info('TLS connected'); this.connected = true; if (replied === false) { replied = true; @@ -165,7 +163,7 @@ export default class LDAP { }); } else { this.client.on('connect', (response) => { - logger.connection.info('LDAP connected'); + connLogger.info('LDAP connected'); this.connected = true; if (replied === false) { replied = true; @@ -176,7 +174,7 @@ export default class LDAP { setTimeout(() => { if (replied === false) { - logger.connection.error('connection time out', connectionOptions.connectTimeout); + connLogger.error({ msg: 'connection time out', connectTimeout: connectionOptions.connectTimeout }); replied = true; callback(new Error('Timeout')); } @@ -216,7 +214,7 @@ export default class LDAP { return; } - logger.bind.info('Binding UserDN', this.options.Authentication_UserDN); + bindLogger.info({ msg: 'Binding UserDN', userDN: this.options.Authentication_UserDN }); this.bindSync(this.options.Authentication_UserDN, this.options.Authentication_Password); this.domainBinded = true; } @@ -237,9 +235,8 @@ export default class LDAP { }; } - logger.search.info('Searching user', username); - logger.search.debug('searchOptions', searchOptions); - logger.search.debug('BaseDN', this.options.BaseDN); + searchLogger.info({ msg: 'Searching user', username }); + searchLogger.debug({ searchOptions, BaseDN: this.options.BaseDN }); if (page) { return this.searchAllPaged(this.options.BaseDN, searchOptions, page); @@ -278,9 +275,8 @@ export default class LDAP { attributes: ['*', '+'], }; - logger.search.info('Searching by id', id); - logger.search.debug('search filter', searchOptions.filter.toString()); - logger.search.debug('BaseDN', this.options.BaseDN); + 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); @@ -289,7 +285,7 @@ export default class LDAP { } if (result.length > 1) { - logger.search.error('Search by id', id, 'returned', result.length, 'records'); + searchLogger.error(`Search by id ${ id } returned ${ result.length } records`); } return result[0]; @@ -303,9 +299,8 @@ export default class LDAP { scope: this.options.User_Search_Scope || 'sub', }; - logger.search.info('Searching user', username); - logger.search.debug('searchOptions', searchOptions); - logger.search.debug('BaseDN', this.options.BaseDN); + searchLogger.info({ msg: 'Searching user', username }); + searchLogger.debug({ searchOptions, BaseDN: this.options.BaseDN }); const result = this.searchAllSync(this.options.BaseDN, searchOptions); @@ -314,7 +309,7 @@ export default class LDAP { } if (result.length > 1) { - logger.search.error('Search by username', username, 'returned', result.length, 'records'); + searchLogger.error(`Search by username ${ username } returned ${ result.length } records`); } return result[0]; @@ -345,7 +340,7 @@ export default class LDAP { scope: 'sub', }; - logger.search.debug('Group filter LDAP:', searchOptions.filter); + searchLogger.debug({ msg: 'Group filter LDAP:', filter: searchOptions.filter }); const result = this.searchAllSync(this.options.BaseDN, searchOptions); @@ -389,7 +384,7 @@ export default class LDAP { ({ BaseDN, options } = callbacks.run('ldap.beforeSearchAll', { BaseDN, options })); const processPage = ({ entries, title, end, next }) => { - logger.search.info(title); + searchLogger.info(title); // Force LDAP idle to wait the record processing this.client._updateIdle(true); page(null, entries, { end, @@ -402,13 +397,13 @@ export default class LDAP { this.client.search(BaseDN, options, (error, res) => { if (error) { - logger.search.error(error); + searchLogger.error(error); page(error); return; } res.on('error', (error) => { - logger.search.error(error); + searchLogger.error(error); page(error); }); @@ -469,13 +464,13 @@ export default class LDAP { this.client.search(BaseDN, options, (error, res) => { if (error) { - logger.search.error(error); + searchLogger.error(error); callback(error); return; } res.on('error', (error) => { - logger.search.error(error); + searchLogger.error(error); callback(error); }); @@ -486,14 +481,14 @@ export default class LDAP { }); res.on('end', () => { - logger.search.info('Search result count', entries.length); + searchLogger.info(`Search result count ${ entries.length }`); callback(null, entries); }); }); } authSync(dn, password) { - logger.auth.info('Authenticating', dn); + authLogger.info({ msg: 'Authenticating', dn }); try { this.bindSync(dn, password); @@ -503,15 +498,15 @@ export default class LDAP { }; const result = this.searchAllSync(dn, searchOptions); if (result.length === 0) { - logger.auth.info('Bind successful but user was not found via search', dn, searchOptions); + authLogger.info({ msg: 'Bind successful but user was not found via search', dn, searchOptions }); return false; } } - logger.auth.info('Authenticated', dn); + authLogger.info({ msg: 'Authenticated', dn }); return true; } catch (error) { - logger.auth.info('Not authenticated', dn); - logger.auth.debug('error', error); + authLogger.info({ msg: 'Not authenticated', dn }); + authLogger.debug(error); return false; } } @@ -519,7 +514,7 @@ export default class LDAP { disconnect() { this.connected = false; this.domainBinded = false; - logger.connection.info('Disconecting'); + connLogger.info('Disconecting'); this.client.unbind(); } } diff --git a/app/ldap/server/loginHandler.js b/app/ldap/server/loginHandler.js index 79425c9dfe74..4f271b49ee6c 100644 --- a/app/ldap/server/loginHandler.js +++ b/app/ldap/server/loginHandler.js @@ -10,7 +10,7 @@ import { callbacks } from '../../callbacks'; import { Logger } from '../../logger'; -const logger = new Logger('LDAPHandler', {}); +const logger = new Logger('LDAPHandler'); function fallbackDefaultAccountSystem(bind, username, password) { if (typeof username === 'string') { diff --git a/app/ldap/server/sync.js b/app/ldap/server/sync.js index f4f0c65f993b..23cbe47c8304 100644 --- a/app/ldap/server/sync.js +++ b/app/ldap/server/sync.js @@ -16,7 +16,7 @@ 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 const logger = new Logger('LDAPSync'); export function isUserInLDAPGroup(ldap, ldapUser, user, ldapGroup) { const syncUserRolesFilter = settings.get('LDAP_Sync_User_Data_Groups_Filter').trim(); @@ -392,7 +392,7 @@ export function syncUserData(user, ldapUser, ldap) { const userChannels = mapLDAPGroupsToChannels(ldap, ldapUser, user); if (user && user._id && userData) { - logger.debug('setting', JSON.stringify(userData, null, 2)); + logger.debug({ msg: 'setting', userData }); if (userData.name) { _setRealName(user._id, userData.name); delete userData.name; diff --git a/app/ldap/server/testConnection.js b/app/ldap/server/testConnection.js index 1511a944e238..98be62dcb991 100644 --- a/app/ldap/server/testConnection.js +++ b/app/ldap/server/testConnection.js @@ -1,8 +1,9 @@ import { Meteor } from 'meteor/meteor'; import LDAP from './ldap'; -import { hasRole } from '../../authorization'; -import { settings } from '../../settings'; +import { hasRole } from '../../authorization/server'; +import { settings } from '../../settings/server'; +import { SystemLogger } from '../../../server/lib/logger/system'; Meteor.methods({ ldap_test_connection() { @@ -24,7 +25,7 @@ Meteor.methods({ ldap = new LDAP(); ldap.connectSync(); } catch (error) { - console.log(error); + SystemLogger.error(error); throw new Meteor.Error(error.message); } diff --git a/app/lib/server/functions/notifications/mobile.js b/app/lib/server/functions/notifications/mobile.js index 4dca10c46561..7211f9e0dfcf 100644 --- a/app/lib/server/functions/notifications/mobile.js +++ b/app/lib/server/functions/notifications/mobile.js @@ -96,10 +96,10 @@ export function shouldNotifyMobile({ } if (!mobilePushNotifications) { - if (settings.get('Accounts_Default_User_Preferences_mobileNotifications') === 'all' && (!isThread || hasReplyToThread)) { + if (settings.get('Accounts_Default_User_Preferences_pushNotifications') === 'all' && (!isThread || hasReplyToThread)) { return true; } - if (settings.get('Accounts_Default_User_Preferences_mobileNotifications') === 'nothing') { + if (settings.get('Accounts_Default_User_Preferences_pushNotifications') === 'nothing') { return false; } } diff --git a/app/lib/server/functions/processWebhookMessage.js b/app/lib/server/functions/processWebhookMessage.js index 63eeeb16252b..c487bd84a89b 100644 --- a/app/lib/server/functions/processWebhookMessage.js +++ b/app/lib/server/functions/processWebhookMessage.js @@ -6,13 +6,14 @@ import mem from 'mem'; import { getRoomByNameOrIdWithOptionToJoin } from './getRoomByNameOrIdWithOptionToJoin'; import { sendMessage } from './sendMessage'; import { validateRoomMessagePermissions } from '../../../authorization/server/functions/canSendMessage'; +import { SystemLogger } from '../../../../server/lib/logger/system'; import { getDirectMessageByIdWithOptionToJoin, getDirectMessageByNameOrIdWithOptionToJoin } from './getDirectMessageByNameOrIdWithOptionToJoin'; // show deprecation warning only once per hour for each integration const showDeprecation = mem(({ integration, channels, username }, error) => { console.warn(`Warning: The integration "${ integration }" failed to send a message to "${ [].concat(channels).join(',') }" because user "${ username }" doesn't have permission or is not a member of the channel.`); console.warn('This behavior is deprecated and starting from version v4.0.0 the following error will be thrown and the message will not be sent.'); - console.error(error); + SystemLogger.error(error); }, { maxAge: 360000, cacheKey: (integration) => JSON.stringify(integration) }); export const processWebhookMessage = function(messageObj, user, defaultValues = { channel: '', alias: '', avatar: '', emoji: '' }, integration = null) { @@ -52,7 +53,7 @@ export const processWebhookMessage = function(messageObj, user, defaultValues = } if (messageObj.attachments && !Array.isArray(messageObj.attachments)) { - console.log('Attachments should be Array, ignoring value'.red, messageObj.attachments); + SystemLogger.warn({ msg: 'Attachments should be Array, ignoring value', attachments: messageObj.attachments }); messageObj.attachments = undefined; } diff --git a/app/lib/server/functions/sendMessage.js b/app/lib/server/functions/sendMessage.js index a8b38a0b6f8f..c8c2420e928e 100644 --- a/app/lib/server/functions/sendMessage.js +++ b/app/lib/server/functions/sendMessage.js @@ -8,6 +8,7 @@ import { Apps } from '../../../apps/server'; import { isURL, isRelativeURL } from '../../../utils/lib/isURL'; import { FileUpload } from '../../../file-upload/server'; import { hasPermission } from '../../../authorization/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; import { parseUrlsInMessage } from './parseUrlsInMessage'; const { DISABLE_MESSAGE_PARSER = 'false' } = process.env; @@ -197,7 +198,7 @@ export const sendMessage = function(user, message, room, upsert = false) { const prevent = Promise.await(Apps.getBridges().getListenerBridge().messageEvent('IPreMessageSentPrevent', message)); if (prevent) { if (settings.get('Apps_Framework_Development_Mode')) { - console.log('A Rocket.Chat App prevented the message sending.', message); + SystemLogger.info({ msg: 'A Rocket.Chat App prevented the message sending.', message }); } return; @@ -223,7 +224,7 @@ export const sendMessage = function(user, message, room, upsert = false) { message.md = parser(message.msg); } } catch (e) { - console.log(e); // errors logged while the parser is at experimental stage + SystemLogger.error(e); // errors logged while the parser is at experimental stage } if (message) { if (message._id && upsert) { diff --git a/app/lib/server/functions/setUserAvatar.js b/app/lib/server/functions/setUserAvatar.js index ecc6e88e895f..5bcd36224583 100644 --- a/app/lib/server/functions/setUserAvatar.js +++ b/app/lib/server/functions/setUserAvatar.js @@ -1,9 +1,10 @@ import { Meteor } from 'meteor/meteor'; import { HTTP } from 'meteor/http'; -import { RocketChatFile } from '../../../file'; -import { FileUpload } from '../../../file-upload'; -import { Users } from '../../../models'; +import { RocketChatFile } from '../../../file/server'; +import { FileUpload } from '../../../file-upload/server'; +import { Users } from '../../../models/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; import { api } from '../../../../server/sdk/api'; export const setUserAvatar = function(user, dataURI, contentType, service) { @@ -18,23 +19,23 @@ export const setUserAvatar = function(user, dataURI, contentType, service) { try { result = HTTP.get(dataURI, { npmRequestOptions: { encoding: 'binary', rejectUnauthorized: false } }); if (!result) { - console.log(`Not a valid response, from the avatar url: ${ encodeURI(dataURI) }`); + SystemLogger.info(`Not a valid response, from the avatar url: ${ encodeURI(dataURI) }`); throw new Meteor.Error('error-avatar-invalid-url', `Invalid avatar URL: ${ encodeURI(dataURI) }`, { function: 'setUserAvatar', url: dataURI }); } } catch (error) { if (!error.response || error.response.statusCode !== 404) { - console.log(`Error while handling the setting of the avatar from a url (${ encodeURI(dataURI) }) for ${ user.username }:`, error); + SystemLogger.info(`Error while handling the setting of the avatar from a url (${ encodeURI(dataURI) }) for ${ user.username }:`, error); throw new Meteor.Error('error-avatar-url-handling', `Error while handling avatar setting from a URL (${ encodeURI(dataURI) }) for ${ user.username }`, { function: 'RocketChat.setUserAvatar', url: dataURI, username: user.username }); } } if (result.statusCode !== 200) { - console.log(`Not a valid response, ${ result.statusCode }, from the avatar url: ${ dataURI }`); + SystemLogger.info(`Not a valid response, ${ result.statusCode }, from the avatar url: ${ dataURI }`); throw new Meteor.Error('error-avatar-invalid-url', `Invalid avatar URL: ${ dataURI }`, { function: 'setUserAvatar', url: dataURI }); } if (!/image\/.+/.test(result.headers['content-type'])) { - console.log(`Not a valid content-type from the provided url, ${ result.headers['content-type'] }, from the avatar url: ${ dataURI }`); + SystemLogger.info(`Not a valid content-type from the provided url, ${ result.headers['content-type'] }, from the avatar url: ${ dataURI }`); throw new Meteor.Error('error-avatar-invalid-url', `Invalid avatar URL: ${ dataURI }`, { function: 'setUserAvatar', url: dataURI }); } diff --git a/app/lib/server/functions/setUsername.js b/app/lib/server/functions/setUsername.js index 832db3defcf8..8795fb6b01fc 100644 --- a/app/lib/server/functions/setUsername.js +++ b/app/lib/server/functions/setUsername.js @@ -9,6 +9,7 @@ import { RateLimiter } from '../lib'; import { addUserToRoom } from './addUserToRoom'; import { api } from '../../../../server/sdk/api'; import { checkUsernameAvailability, setUserAvatar, getAvatarSuggestionForUser } from '.'; +import { SystemLogger } from '../../../../server/lib/logger/system'; export const _setUsername = function(userId, u, fullUser) { const username = s.trim(u); @@ -44,7 +45,7 @@ export const _setUsername = function(userId, u, fullUser) { }); } } catch (e) { - console.error(e); + SystemLogger.error(e); } // Set new username* Users.setUsername(user._id, username); diff --git a/app/lib/server/functions/updateMessage.js b/app/lib/server/functions/updateMessage.js index eaa60b0318b5..bf68daf712d6 100644 --- a/app/lib/server/functions/updateMessage.js +++ b/app/lib/server/functions/updateMessage.js @@ -1,9 +1,10 @@ import { Meteor } from 'meteor/meteor'; import { parser } from '@rocket.chat/message-parser'; -import { Messages, Rooms } from '../../../models'; -import { settings } from '../../../settings'; -import { callbacks } from '../../../callbacks'; +import { Messages, Rooms } from '../../../models/server'; +import { settings } from '../../../settings/server'; +import { callbacks } from '../../../callbacks/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; import { Apps } from '../../../apps/server'; import { parseUrlsInMessage } from './parseUrlsInMessage'; @@ -52,7 +53,7 @@ export const updateMessage = function(message, user, originalMessage) { message.md = parser(message.msg); } } catch (e) { - console.log(e); // errors logged while the parser is at experimental stage + SystemLogger.error(e); // errors logged while the parser is at experimental stage } const tempid = message._id; diff --git a/app/lib/server/index.js b/app/lib/server/index.js index 5a89c8e44a35..78040f70c273 100644 --- a/app/lib/server/index.js +++ b/app/lib/server/index.js @@ -10,7 +10,6 @@ import '../lib/MessageTypes'; import '../startup'; import '../startup/defaultRoomTypes'; import './lib/bugsnag'; -import './lib/configLogger'; import './lib/debug'; import './lib/loginErrorMessageOverride'; import './oauth/oauth'; diff --git a/app/lib/server/lib/configLogger.js b/app/lib/server/lib/configLogger.js deleted file mode 100644 index 3039cc628598..000000000000 --- a/app/lib/server/lib/configLogger.js +++ /dev/null @@ -1,19 +0,0 @@ -import { Meteor } from 'meteor/meteor'; - -import { LoggerManager } from '../../../logger'; -import { settings } from '../../../settings'; - -settings.get('Log_Package', function(key, value) { - LoggerManager.showPackage = value; -}); - -settings.get('Log_File', function(key, value) { - LoggerManager.showFileAndLine = value; -}); - -settings.get('Log_Level', function(key, value) { - if (value != null) { - LoggerManager.logLevel = parseInt(value); - Meteor.setTimeout(() => LoggerManager.enable(true), 200); - } -}); diff --git a/app/lib/server/lib/debug.js b/app/lib/server/lib/debug.js index 0fb22935c534..2d37b333468e 100644 --- a/app/lib/server/lib/debug.js +++ b/app/lib/server/lib/debug.js @@ -3,27 +3,12 @@ import { WebApp } from 'meteor/webapp'; import { InstanceStatus } from 'meteor/konecty:multiple-instances-status'; import _ from 'underscore'; -import { settings } from '../../../settings'; -import { metrics } from '../../../metrics'; -import { Logger } from '../../../logger'; - -const logger = new Logger('Meteor', { - methods: { - method: { - type: 'info', - }, - publish: { - type: 'debug', - }, - }, -}); - -const { - LOG_METHOD_PAYLOAD = 'false', - LOG_REST_METHOD_PAYLOADS = 'false', -} = process.env; +import { settings } from '../../../settings/server'; +import { metrics } from '../../../metrics/server'; +import { Logger } from '../../../../server/lib/logger/Logger'; +import { getMethodArgs } from '../../../../server/lib/logger/logPayloads'; -const addPayloadToLog = LOG_METHOD_PAYLOAD !== 'false' || LOG_REST_METHOD_PAYLOADS !== 'false'; +const logger = new Logger('Meteor'); let Log_Trace_Methods; let Log_Trace_Subscriptions; @@ -56,20 +41,6 @@ const traceConnection = (enable, filter, prefix, name, connection, userId) => { } }; -const omitKeyArgs = (args, name) => { - if (name === 'saveSettings') { - return [args[0].map((arg) => _.omit(arg, 'value'))]; - } - - if (name === 'saveSetting') { - return [args[0], args[2]]; - } - - return args.map((arg) => (typeof arg !== 'object' - ? arg - : _.omit(arg, 'password', 'msg', 'pass', 'username', 'message'))); -}; - const wrapMethods = function(name, originalHandler, methodsMap) { methodsMap[name] = function(...originalArgs) { traceConnection(Log_Trace_Methods, Log_Trace_Methods_Filter, 'method', name, this.connection, this.userId); @@ -81,11 +52,16 @@ const wrapMethods = function(name, originalHandler, methodsMap) { has_connection: this.connection != null, has_user: this.userId != null, }); - const args = name === 'ufsWrite' ? Array.prototype.slice.call(originalArgs, 1) : originalArgs; - const dateTime = new Date().toISOString(); - const userId = Meteor.userId(); - logger.method(() => `${ this.connection?.clientAddress } - ${ userId } [${ dateTime }] "METHOD ${ method }" - "${ this.connection?.httpHeaders.referer }" "${ this.connection?.httpHeaders['user-agent'] }" | ${ addPayloadToLog ? JSON.stringify(omitKeyArgs(args, name)) : '' }`); + logger.method({ + method, + userId: Meteor.userId(), + userAgent: this.connection?.httpHeaders['user-agent'], + referer: this.connection?.httpHeaders.referer, + remoteIP: this.connection?.clientAddress, + instanceId: InstanceStatus.id(), + ...getMethodArgs(name, originalArgs), + }); const result = originalHandler.apply(this, originalArgs); end(); @@ -107,7 +83,16 @@ const originalMeteorPublish = Meteor.publish; Meteor.publish = function(name, func) { return originalMeteorPublish(name, function(...args) { traceConnection(Log_Trace_Subscriptions, Log_Trace_Subscriptions_Filter, 'subscription', name, this.connection, this.userId); - logger.publish(() => `${ name } -> userId: ${ this.userId }, arguments: ${ JSON.stringify(omitKeyArgs(args)) }`); + + logger.subscription({ + publication: name, + userId: this.userId, + userAgent: this.connection?.httpHeaders['user-agent'], + referer: this.connection?.httpHeaders.referer, + remoteIP: this.connection?.clientAddress, + instanceId: InstanceStatus.id(), + }); + const end = metrics.meteorSubscriptions.startTimer({ subscription: name }); const originalReady = this.ready; diff --git a/app/lib/server/lib/interceptDirectReplyEmails.js b/app/lib/server/lib/interceptDirectReplyEmails.js index ed7f022b5313..5447f80f679a 100644 --- a/app/lib/server/lib/interceptDirectReplyEmails.js +++ b/app/lib/server/lib/interceptDirectReplyEmails.js @@ -2,7 +2,8 @@ import { Meteor } from 'meteor/meteor'; import POP3Lib from 'poplib'; import { simpleParser } from 'mailparser'; -import { settings } from '../../../settings'; +import { settings } from '../../../settings/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; import { IMAPInterceptor } from '../../../../server/email/IMAPInterceptor'; import { processDirectEmail } from '.'; @@ -45,7 +46,7 @@ export class POP3Intercepter { // run on start this.pop3.list(); } else { - console.log('Unable to Log-in ....'); + SystemLogger.info('Unable to Log-in ....'); } })); @@ -61,7 +62,7 @@ export class POP3Intercepter { this.pop3.quit(); } } else { - console.log('Cannot Get Emails ....'); + SystemLogger.info('Cannot Get Emails ....'); } })); @@ -78,7 +79,7 @@ export class POP3Intercepter { // delete email this.pop3.dele(msgnumber); } else { - console.log('Cannot Retrieve Message ....'); + SystemLogger.info('Cannot Retrieve Message ....'); } })); @@ -93,18 +94,18 @@ export class POP3Intercepter { this.pop3.quit(); } } else { - console.log('Cannot Delete Message....'); + SystemLogger.info('Cannot Delete Message....'); } })); // invalid server state this.pop3.on('invalid-state', function(cmd) { - console.log(`Invalid state. You tried calling ${ cmd }`); + SystemLogger.info(`Invalid state. You tried calling ${ cmd }`); }); // locked => command already running, not finished yet this.pop3.on('locked', function(cmd) { - console.log(`Current command has not finished yet. You tried calling ${ cmd }`); + SystemLogger.info(`Current command has not finished yet. You tried calling ${ cmd }`); }); } diff --git a/app/lib/server/lib/processDirectEmail.js b/app/lib/server/lib/processDirectEmail.js index b00a042d476d..3b97938d4694 100644 --- a/app/lib/server/lib/processDirectEmail.js +++ b/app/lib/server/lib/processDirectEmail.js @@ -2,10 +2,11 @@ import { Meteor } from 'meteor/meteor'; import { EmailReplyParser as reply } from 'emailreplyparser'; import moment from 'moment'; -import { settings } from '../../../settings'; -import { Rooms, Messages, Users, Subscriptions } from '../../../models'; -import { metrics } from '../../../metrics'; -import { hasPermission } from '../../../authorization'; +import { settings } from '../../../settings/server'; +import { Rooms, Messages, Users, Subscriptions } from '../../../models/server'; +import { metrics } from '../../../metrics/server'; +import { hasPermission } from '../../../authorization/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; import { sendMessage as _sendMessage } from '../functions'; export const processDirectEmail = function(email) { @@ -126,6 +127,6 @@ export const processDirectEmail = function(email) { email.headers.mid = email.headers.to.split('@')[0].split('+')[1]; sendMessage(email); } else { - console.log('Invalid Email....If not. Please report it.'); + SystemLogger.error('Invalid Email....If not. Please report it.'); } }; diff --git a/app/lib/server/methods/sendMessage.js b/app/lib/server/methods/sendMessage.js index 3d91d72022d0..871bd69a431f 100644 --- a/app/lib/server/methods/sendMessage.js +++ b/app/lib/server/methods/sendMessage.js @@ -11,7 +11,7 @@ import { Users, Messages } from '../../../models'; import { sendMessage } from '../functions'; import { RateLimiter } from '../lib'; import { canSendMessage } from '../../../authorization/server'; -import { SystemLogger } from '../../../logger/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; import { api } from '../../../../server/sdk/api'; export function executeSendMessage(uid, message) { diff --git a/app/lib/server/startup/oAuthServicesUpdate.js b/app/lib/server/startup/oAuthServicesUpdate.js index 2e35236f05c5..b414abdab315 100644 --- a/app/lib/server/startup/oAuthServicesUpdate.js +++ b/app/lib/server/startup/oAuthServicesUpdate.js @@ -7,18 +7,12 @@ import { Logger } from '../../../logger'; import { settings } from '../../../settings'; import { addOAuthService } from '../functions/addOAuthService'; -const logger = new Logger('rocketchat:lib', { - methods: { - oauth_updated: { - type: 'info', - }, - }, -}); +const logger = new Logger('rocketchat:lib'); function _OAuthServicesUpdate() { const services = settings.get(/^(Accounts_OAuth_|Accounts_OAuth_Custom-)[a-z0-9_]+$/i); services.forEach((service) => { - logger.oauth_updated(service.key); + logger.info({ oauth_updated: service.key }); let serviceName = service.key.replace('Accounts_OAuth_', ''); if (serviceName === 'Meteor') { serviceName = 'meteor-developer'; diff --git a/app/lib/server/startup/rateLimiter.js b/app/lib/server/startup/rateLimiter.js index f12f23caa8c8..f7339c19958d 100644 --- a/app/lib/server/startup/rateLimiter.js +++ b/app/lib/server/startup/rateLimiter.js @@ -7,7 +7,7 @@ import { settings } from '../../../settings'; import { metrics } from '../../../metrics'; import { Logger } from '../../../logger'; -const logger = new Logger('RateLimiter', {}); +const logger = new Logger('RateLimiter'); // Get initial set of names already registered for rules const names = new Set(Object.values(DDPRateLimiter.printRules()) @@ -111,7 +111,7 @@ const ruleIds = {}; const callback = (message, name) => (reply, input) => { if (reply.allowed === false) { logger.info('DDP RATE LIMIT:', message); - logger.info(JSON.stringify({ ...reply, ...input }, null, 2)); + logger.info({ ...reply, ...input }); metrics.ddpRateLimitExceeded.inc({ limit_name: name, user_id: input.userId, diff --git a/app/lib/server/startup/settings.js b/app/lib/server/startup/settings.js index 1e3e5613e19a..4a851e9adcac 100644 --- a/app/lib/server/startup/settings.js +++ b/app/lib/server/startup/settings.js @@ -295,7 +295,7 @@ settings.addGroup('Accounts', function() { ], public: true, }); - this.add('Accounts_Default_User_Preferences_mobileNotifications', 'all', { + this.add('Accounts_Default_User_Preferences_pushNotifications', 'all', { type: 'select', values: [ { @@ -1605,14 +1605,6 @@ settings.addGroup('Logs', function() { ], public: true, }); - this.add('Log_Package', false, { - type: 'boolean', - public: true, - }); - this.add('Log_File', false, { - type: 'boolean', - public: true, - }); this.add('Log_View_Limit', 1000, { type: 'int', }); diff --git a/app/lib/server/startup/settingsOnLoadDirectReply.js b/app/lib/server/startup/settingsOnLoadDirectReply.js index 73675065cb5b..f38565b79981 100644 --- a/app/lib/server/startup/settingsOnLoadDirectReply.js +++ b/app/lib/server/startup/settingsOnLoadDirectReply.js @@ -1,37 +1,40 @@ import { Meteor } from 'meteor/meteor'; import _ from 'underscore'; +import { Logger } from '../../../logger/server'; import { settings } from '../../../settings'; import { IMAPIntercepter, POP3Helper, POP3 } from '../lib/interceptDirectReplyEmails.js'; +const logger = new Logger('Email Intercepter'); + let IMAP; let _POP3Helper; const startEmailIntercepter = _.debounce(Meteor.bindEnvironment(function() { - console.log('Starting Email Intercepter...'); + logger.debug('Starting Email Intercepter...'); if (settings.get('Direct_Reply_Enable') && settings.get('Direct_Reply_Protocol') && settings.get('Direct_Reply_Host') && settings.get('Direct_Reply_Port') && settings.get('Direct_Reply_Username') && settings.get('Direct_Reply_Password')) { if (settings.get('Direct_Reply_Protocol') === 'IMAP') { // stop already running IMAP instance if (IMAP && IMAP.isActive()) { - console.log('Disconnecting already running IMAP instance...'); + logger.debug('Disconnecting already running IMAP instance...'); IMAP.stop(Meteor.bindEnvironment(function() { - console.log('Starting new IMAP instance......'); + logger.debug('Starting new IMAP instance......'); IMAP = new IMAPIntercepter(); IMAP.start(); return true; })); } else if (POP3 && _POP3Helper && _POP3Helper.isActive()) { - console.log('Disconnecting already running POP instance...'); + logger.debug('Disconnecting already running POP instance...'); _POP3Helper.stop(Meteor.bindEnvironment(function() { - console.log('Starting new IMAP instance......'); + logger.debug('Starting new IMAP instance......'); IMAP = new IMAPIntercepter(); IMAP.start(); return true; })); } else { - console.log('Starting new IMAP instance......'); + logger.debug('Starting new IMAP instance......'); IMAP = new IMAPIntercepter(); IMAP.start(); return true; @@ -39,23 +42,23 @@ const startEmailIntercepter = _.debounce(Meteor.bindEnvironment(function() { } else if (settings.get('Direct_Reply_Protocol') === 'POP') { // stop already running POP instance if (POP3 && _POP3Helper && _POP3Helper.isActive()) { - console.log('Disconnecting already running POP instance...'); + logger.debug('Disconnecting already running POP instance...'); _POP3Helper.stop(Meteor.bindEnvironment(function() { - console.log('Starting new POP instance......'); + logger.debug('Starting new POP instance......'); _POP3Helper = new POP3Helper(); _POP3Helper.start(); return true; })); } else if (IMAP && IMAP.isActive()) { - console.log('Disconnecting already running IMAP instance...'); + logger.debug('Disconnecting already running IMAP instance...'); IMAP.stop(Meteor.bindEnvironment(function() { - console.log('Starting new POP instance......'); + logger.debug('Starting new POP instance......'); _POP3Helper = new POP3Helper(); _POP3Helper.start(); return true; })); } else { - console.log('Starting new POP instance......'); + logger.debug('Starting new POP instance......'); _POP3Helper = new POP3Helper(); _POP3Helper.start(); return true; diff --git a/app/lib/server/startup/settingsOnLoadSMTP.js b/app/lib/server/startup/settingsOnLoadSMTP.js index 4ad9b806933d..cb31e03e7541 100644 --- a/app/lib/server/startup/settingsOnLoadSMTP.js +++ b/app/lib/server/startup/settingsOnLoadSMTP.js @@ -1,10 +1,11 @@ import { Meteor } from 'meteor/meteor'; import _ from 'underscore'; -import { settings } from '../../../settings'; +import { settings } from '../../../settings/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; const buildMailURL = _.debounce(function() { - console.log('Updating process.env.MAIL_URL'); + SystemLogger.info('Updating process.env.MAIL_URL'); if (settings.get('SMTP_Host')) { process.env.MAIL_URL = `${ settings.get('SMTP_Protocol') }://`; diff --git a/app/livechat/imports/server/rest/facebook.js b/app/livechat/imports/server/rest/facebook.js index b4b8efa55034..cb9f19afc86c 100644 --- a/app/livechat/imports/server/rest/facebook.js +++ b/app/livechat/imports/server/rest/facebook.js @@ -90,7 +90,7 @@ API.v1.addRoute('livechat/facebook', { message: Livechat.sendMessage(sendMessage), }; } catch (e) { - console.error('Error using Facebook ->', e); + Livechat.logger.error('Error using Facebook ->', e); } }, }); diff --git a/app/livechat/imports/server/rest/sms.js b/app/livechat/imports/server/rest/sms.js index 51d22458c228..4f29e7e997e0 100644 --- a/app/livechat/imports/server/rest/sms.js +++ b/app/livechat/imports/server/rest/sms.js @@ -137,7 +137,7 @@ API.v1.addRoute('livechat/sms-incoming/:service', { attachment.video_size = file.size; } } catch (e) { - console.error(`Attachment upload failed: ${ e.message }`); + Livechat.logger.error(`Attachment upload failed: ${ e.message }`); attachment = { fields: [{ title: 'User upload failed', diff --git a/app/livechat/server/hooks/RDStation.js b/app/livechat/server/hooks/RDStation.js index bc60b1c1c9ef..b15453995eda 100644 --- a/app/livechat/server/hooks/RDStation.js +++ b/app/livechat/server/hooks/RDStation.js @@ -3,6 +3,7 @@ import { HTTP } from 'meteor/http'; import { settings } from '../../../settings'; import { callbacks } from '../../../callbacks'; import { Livechat } from '../lib/Livechat'; +import { SystemLogger } from '../../../../server/lib/logger/system'; function sendToRDStation(room) { if (!settings.get('Livechat_RDStation_Token')) { @@ -50,7 +51,7 @@ function sendToRDStation(room) { try { HTTP.call('POST', 'https://www.rdstation.com.br/api/1.3/conversions', options); } catch (e) { - console.error('Error sending lead to RD Station ->', e); + SystemLogger.error('Error sending lead to RD Station ->', e); } return room; diff --git a/app/livechat/server/lib/Helper.js b/app/livechat/server/lib/Helper.js index bf8db26e63b3..b7a0d2dd92de 100644 --- a/app/livechat/server/lib/Helper.js +++ b/app/livechat/server/lib/Helper.js @@ -203,7 +203,7 @@ export const parseAgentCustomFields = (customFields) => { return Object.keys(parseCustomFields) .filter((customFieldKey) => parseCustomFields[customFieldKey].sendToIntegrations === true); } catch (error) { - console.error(error); + Livechat.logger.error(error); return []; } }; diff --git a/app/livechat/server/lib/Livechat.js b/app/livechat/server/lib/Livechat.js index 108542221e4b..e6a9022421c3 100644 --- a/app/livechat/server/lib/Livechat.js +++ b/app/livechat/server/lib/Livechat.js @@ -41,18 +41,16 @@ import { Apps, AppEvents } from '../../../apps/server'; import { businessHourManager } from '../business-hour'; import notifications from '../../../notifications/server/lib/Notifications'; +const logger = new Logger('Livechat'); + const dnsResolveMx = Meteor.wrapAsync(dns.resolveMx); export const Livechat = { Analytics, historyMonitorType: 'url', - logger: new Logger('Livechat', { - sections: { - webhook: 'Webhook', - }, - }), - + logger, + webhookLogger: logger.section('Webhook'), findGuest(token) { return LivechatVisitors.getVisitorByToken(token, { @@ -713,7 +711,7 @@ export const Livechat = { this.saveTransferHistory(room, transferData); RoutingManager.unassignAgent(inquiry, departmentId); } catch (e) { - console.error(e); + this.logger.error(e); throw new Meteor.Error('error-returning-inquiry', 'Error returning inquiry to the queue', { method: 'livechat:returnRoomAsInquiry' }); } @@ -732,9 +730,9 @@ export const Livechat = { try { return HTTP.post(settings.get('Livechat_webhookUrl'), options); } catch (e) { - Livechat.logger.webhook.error(`Response error on ${ 11 - attempts } try ->`, e); + Livechat.webhookLogger.error(`Response error on ${ 11 - attempts } try ->`, e); // try 10 times after 10 seconds each - Livechat.logger.webhook.warn('Will try again in 10 seconds ...'); + Livechat.webhookLogger.warn('Will try again in 10 seconds ...'); setTimeout(Meteor.bindEnvironment(function() { Livechat.sendRequest(postData, callback, attempts--); }), 10000); diff --git a/app/livechat/server/lib/routing/External.js b/app/livechat/server/lib/routing/External.js index 4b104a9d2df0..5a72c1ef273f 100644 --- a/app/livechat/server/lib/routing/External.js +++ b/app/livechat/server/lib/routing/External.js @@ -4,6 +4,7 @@ import { HTTP } from 'meteor/http'; import { settings } from '../../../../settings/server'; import { RoutingManager } from '../RoutingManager'; import { Users } from '../../../../models/server'; +import { SystemLogger } from '../../../../../server/lib/logger/system'; class ExternalQueue { constructor() { @@ -45,7 +46,7 @@ class ExternalQueue { } } } catch (e) { - console.error('Error requesting agent from external queue.', e); + SystemLogger.error('Error requesting agent from external queue.', e); break; } } diff --git a/app/livechat/server/methods/facebook.js b/app/livechat/server/methods/facebook.js index 7d17161fe938..a6ef3b9aac94 100644 --- a/app/livechat/server/methods/facebook.js +++ b/app/livechat/server/methods/facebook.js @@ -1,6 +1,7 @@ import { Meteor } from 'meteor/meteor'; import { hasPermission } from '../../../authorization'; +import { SystemLogger } from '../../../../server/lib/logger/system'; import { settings } from '../../../settings'; import OmniChannel from '../lib/OmniChannel'; @@ -59,7 +60,7 @@ Meteor.methods({ throw new Meteor.Error('integration-error', e.response.data.error.message); } } - console.error('Error contacting omni.rocket.chat:', e); + SystemLogger.error('Error contacting omni.rocket.chat:', e); throw new Meteor.Error('integration-error', e.error); } }, diff --git a/app/livechat/server/methods/getAgentOverviewData.js b/app/livechat/server/methods/getAgentOverviewData.js index f6cc509f1441..d60d36957530 100644 --- a/app/livechat/server/methods/getAgentOverviewData.js +++ b/app/livechat/server/methods/getAgentOverviewData.js @@ -14,7 +14,7 @@ Meteor.methods({ } if (!(options.chartOptions && options.chartOptions.name)) { - console.log('Incorrect analytics options'); + Livechat.logger.warn('Incorrect analytics options'); return; } diff --git a/app/livechat/server/methods/getAnalyticsChartData.js b/app/livechat/server/methods/getAnalyticsChartData.js index 42b92ac31a4b..caa86c650899 100644 --- a/app/livechat/server/methods/getAnalyticsChartData.js +++ b/app/livechat/server/methods/getAnalyticsChartData.js @@ -14,7 +14,7 @@ Meteor.methods({ } if (!(options.chartOptions && options.chartOptions.name)) { - console.log('Incorrect chart options'); + Livechat.logger.warn('Incorrect chart options'); return; } diff --git a/app/livechat/server/methods/getAnalyticsOverviewData.js b/app/livechat/server/methods/getAnalyticsOverviewData.js index 741e26ccee53..30fdec7835d8 100644 --- a/app/livechat/server/methods/getAnalyticsOverviewData.js +++ b/app/livechat/server/methods/getAnalyticsOverviewData.js @@ -15,7 +15,7 @@ Meteor.methods({ } if (!(options.analyticsOptions && options.analyticsOptions.name)) { - console.error('Incorrect analytics options'); + Livechat.logger.error('Incorrect analytics options'); return; } diff --git a/app/livechat/server/methods/webhookTest.js b/app/livechat/server/methods/webhookTest.js index b834ec246b40..bc5b32fd75a0 100644 --- a/app/livechat/server/methods/webhookTest.js +++ b/app/livechat/server/methods/webhookTest.js @@ -2,6 +2,7 @@ import { Meteor } from 'meteor/meteor'; import { HTTP } from 'meteor/http'; import { settings } from '../../../settings/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; const postCatchError = function(url, options) { try { @@ -71,7 +72,7 @@ Meteor.methods({ const response = postCatchError(settings.get('Livechat_webhookUrl'), options); - console.log('response ->', response); + SystemLogger.debug({ response }); if (response && response.statusCode && response.statusCode === 200) { return true; diff --git a/app/logger/server/index.js b/app/logger/server/index.js index 06fa09708dbe..f535468e5d9f 100644 --- a/app/logger/server/index.js +++ b/app/logger/server/index.js @@ -1,8 +1,7 @@ -import './streamer.js'; -import { LoggerManager, Logger, SystemLogger } from './server'; +import { Logger } from '../../../server/lib/logger/Logger'; +import './streamer'; +// TODO there are imports pointing to this file still, ideally we should point everything to "/server/lib/logger/Logger" and remove this file export { - LoggerManager, Logger, - SystemLogger, }; diff --git a/app/logger/server/server.js b/app/logger/server/server.js deleted file mode 100644 index bce22758c551..000000000000 --- a/app/logger/server/server.js +++ /dev/null @@ -1,321 +0,0 @@ -import { EventEmitter } from 'events'; - -import _ from 'underscore'; -import s from 'underscore.string'; - -export const LoggerManager = new class extends EventEmitter { - constructor() { - super(); - this.enabled = false; - this.loggers = {}; - this.queue = []; - this.showPackage = false; - this.showFileAndLine = false; - this.logLevel = 0; - } - - register(logger) { - // eslint-disable-next-line no-use-before-define - if (!(logger instanceof Logger)) { - return; - } - this.loggers[logger.name] = logger; - this.emit('register', logger); - } - - addToQueue(logger, args) { - this.queue.push({ - logger, args, - }); - } - - dispatchQueue() { - _.each(this.queue, (item) => item.logger._log.apply(item.logger, item.args)); - this.clearQueue(); - } - - clearQueue() { - this.queue = []; - } - - disable() { - this.enabled = false; - } - - enable(dispatchQueue = false) { - this.enabled = true; - return dispatchQueue === true ? this.dispatchQueue() : this.clearQueue(); - } -}(); - -const defaultTypes = { - debug: { - name: 'debug', - color: 'blue', - level: 2, - }, - log: { - name: 'info', - color: 'blue', - level: 1, - }, - info: { - name: 'info', - color: 'blue', - level: 1, - }, - success: { - name: 'info', - color: 'green', - level: 1, - }, - warn: { - name: 'warn', - color: 'magenta', - level: 1, - }, - error: { - name: 'error', - color: 'red', - level: 0, - }, - deprecation: { - name: 'warn', - color: 'magenta', - level: 0, - }, -}; - -export class Logger { - constructor(name, config = {}) { - const self = this; - this.name = name; - - this.config = Object.assign({}, config); - if (LoggerManager.loggers && LoggerManager.loggers[this.name] != null) { - LoggerManager.loggers[this.name].warn('Duplicated instance'); - return LoggerManager.loggers[this.name]; - } - _.each(defaultTypes, (typeConfig, type) => { - this[type] = function(...args) { - return self._log.call(self, { - section: this.__section, - type, - level: typeConfig.level, - method: typeConfig.name, - arguments: args, - }); - }; - - self[`${ type }_box`] = function(...args) { - return self._log.call(self, { - section: this.__section, - type, - box: true, - level: typeConfig.level, - method: typeConfig.name, - arguments: args, - }); - }; - }); - if (this.config.methods) { - _.each(this.config.methods, (typeConfig, method) => { - if (this[method] != null) { - self.warn(`Method ${ method } already exists`); - } - if (defaultTypes[typeConfig.type] == null) { - self.warn(`Method type ${ typeConfig.type } does not exist`); - } - this[method] = function(...args) { - return self._log.call(self, { - section: this.__section, - type: typeConfig.type, - level: typeConfig.level != null ? typeConfig.level : defaultTypes[typeConfig.type] && defaultTypes[typeConfig.type].level, - method, - arguments: args, - }); - }; - this[`${ method }_box`] = function(...args) { - return self._log.call(self, { - section: this.__section, - type: typeConfig.type, - box: true, - level: typeConfig.level != null ? typeConfig.level : defaultTypes[typeConfig.type] && defaultTypes[typeConfig.type].level, - method, - arguments: args, - }); - }; - }); - } - if (this.config.sections) { - _.each(this.config.sections, (name, section) => { - this[section] = {}; - _.each(defaultTypes, (typeConfig, type) => { - self[section][type] = (...args) => this[type].apply({ __section: name }, args); - self[section][`${ type }_box`] = (...args) => this[`${ type }_box`].apply({ __section: name }, args); - }); - _.each(this.config.methods, (typeConfig, method) => { - self[section][method] = (...args) => self[method].apply({ __section: name }, args); - self[section][`${ method }_box`] = (...args) => self[`${ method }_box`].apply({ __section: name }, args); - }); - }); - } - - LoggerManager.register(this); - } - - getPrefix(options) { - let prefix = `${ this.name } ➔ ${ options.method }`; - if (options.section) { - prefix = `${ this.name } ➔ ${ options.section }.${ options.method }`; - } - const details = this._getCallerDetails(); - const detailParts = []; - if (details.package && (LoggerManager.showPackage === true || options.type === 'error')) { - detailParts.push(details.package); - } - if (LoggerManager.showFileAndLine === true || options.type === 'error') { - if ((details.file != null) && (details.line != null)) { - detailParts.push(`${ details.file }:${ details.line }`); - } else { - if (details.file != null) { - detailParts.push(details.file); - } - if (details.line != null) { - detailParts.push(details.line); - } - } - } - if (defaultTypes[options.type]) { - // format the message to a colored message - prefix = prefix[defaultTypes[options.type].color]; - } - if (detailParts.length > 0) { - prefix = `${ detailParts.join(' ') } ${ prefix }`; - } - return prefix; - } - - _getCallerDetails() { - const getStack = () => { - // We do NOT use Error.prepareStackTrace here (a V8 extension that gets us a - // core-parsed stack) since it's impossible to compose it with the use of - // Error.prepareStackTrace used on the server for source maps. - const { stack } = new Error(); - return stack; - }; - const stack = getStack(); - if (!stack) { - return {}; - } - const lines = stack.split('\n').splice(1); - // looking for the first line outside the logging package (or an - // eval if we find that first) - let line = lines[0]; - for (let index = 0, len = lines.length; index < len; index++, line = lines[index]) { - if (line.match(/^\s*at eval \(eval/)) { - return { file: 'eval' }; - } - - if (!line.match(/packages\/rocketchat_logger(?:\/|\.js)/)) { - break; - } - } - - const details = {}; - // The format for FF is 'functionName@filePath:lineNumber' - // The format for V8 is 'functionName (packages/logging/logging.js:81)' or - // 'packages/logging/logging.js:81' - const match = /(?:[@(]| at )([^(]+?):([0-9:]+)(?:\)|$)/.exec(line); - if (!match) { - return details; - } - details.line = match[2].split(':')[0]; - // Possible format: https://foo.bar.com/scripts/file.js?random=foobar - // XXX: if you can write the following in better way, please do it - // XXX: what about evals? - details.file = match[1].split('/').slice(-1)[0].split('?')[0]; - const packageMatch = match[1].match(/packages\/([^\.\/]+)(?:\/|\.)/); - if (packageMatch) { - details.package = packageMatch[1]; - } - return details; - } - - makeABox(message, title) { - if (!_.isArray(message)) { - message = message.split('\n'); - } - let len = 0; - - len = Math.max.apply(null, message.map((line) => line.length)); - - const topLine = `+--${ s.pad('', len, '-') }--+`; - const separator = `| ${ s.pad('', len, '') } |`; - let lines = []; - - lines.push(topLine); - if (title) { - lines.push(`| ${ s.lrpad(title, len) } |`); - lines.push(topLine); - } - lines.push(separator); - - lines = [...lines, ...message.map((line) => `| ${ s.rpad(line, len) } |`)]; - - lines.push(separator); - lines.push(topLine); - return lines; - } - - _log(options, ...args) { - if (LoggerManager.enabled === false) { - LoggerManager.addToQueue(this, [options, ...args]); - return; - } - if (options.level == null) { - options.level = 1; - } - - if (LoggerManager.logLevel < options.level) { - return; - } - - // Deferred logging - if (typeof options.arguments[0] === 'function') { - options.arguments[0] = options.arguments[0](); - } - - const prefix = this.getPrefix(options); - - if (options.box === true && _.isString(options.arguments[0])) { - let color = undefined; - if (defaultTypes[options.type]) { - color = defaultTypes[options.type].color; - } - - const box = this.makeABox(options.arguments[0], options.arguments[1]); - let subPrefix = '➔'; - if (color) { - subPrefix = subPrefix[color]; - } - - console.log(subPrefix, prefix); - box.forEach((line) => { - console.log(subPrefix, color ? line[color] : line); - }); - } else { - options.arguments.unshift(prefix); - console.log.apply(console, options.arguments); - } - } -} - -export const SystemLogger = new Logger('System', { - methods: { - startup: { - type: 'success', - level: 0, - }, - }, -}); diff --git a/app/logger/server/streamer.js b/app/logger/server/streamer.js index 3bff9032aafb..7e7294439310 100644 --- a/app/logger/server/streamer.js +++ b/app/logger/server/streamer.js @@ -1,14 +1,13 @@ import { EventEmitter } from 'events'; import { Meteor } from 'meteor/meteor'; -import { Random } from 'meteor/random'; import { EJSON } from 'meteor/ejson'; import { Log } from 'meteor/logging'; -import { settings } from '../../settings'; +import { settings } from '../../settings/server'; import notifications from '../../notifications/server/lib/Notifications'; -export const processString = function(string, date) { +const processString = function(string, date) { let obj; try { if (string[0] === '{') { @@ -26,31 +25,35 @@ export const processString = function(string, date) { } }; -export const StdOut = new class extends EventEmitter { - constructor() { - super(); - const { write } = process.stdout; - this.queue = []; - process.stdout.write = (...args) => { - write.apply(process.stdout, args); - const date = new Date(); - const string = processString(args[0], date); - const item = { - id: Random.id(), - string, - ts: date, - }; - this.queue.push(item); +export const StdOut = new EventEmitter(); + +const { write } = process.stdout; + +const queue = []; + +const maxInt = 2147483647; +let queueSize = 0; - const limit = settings.get('Log_View_Limit') || 1000; - if (limit && this.queue.length > limit) { - this.queue.shift(); - } +process.stdout.write = (...args) => { + write.apply(process.stdout, args); + const date = new Date(); + const string = processString(args[0], date); + const item = { + id: `logid-${ queueSize }`, + string, + ts: date, + }; + queue.push(item); + + queueSize = (queueSize + 1) & maxInt; - this.emit('write', string, item); - }; + const limit = settings.get('Log_View_Limit') || 1000; + if (queueSize > limit) { + queue.shift(); } -}(); + + StdOut.emit('write', string, item); +}; Meteor.startup(() => { const handler = (string, item) => { diff --git a/app/mail-messages/server/functions/sendMail.js b/app/mail-messages/server/functions/sendMail.js index 65dc7687331b..6b33a1dc2b0f 100644 --- a/app/mail-messages/server/functions/sendMail.js +++ b/app/mail-messages/server/functions/sendMail.js @@ -3,7 +3,8 @@ import { EJSON } from 'meteor/ejson'; import { FlowRouter } from 'meteor/kadira:flow-router'; import { escapeHTML } from '@rocket.chat/string-helpers'; -import { placeholders } from '../../../utils'; +import { placeholders } from '../../../utils/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; import * as Mailer from '../../../mailer'; export const sendMail = function(from, subject, body, dryrun, query) { @@ -33,7 +34,7 @@ export const sendMail = function(from, subject, body, dryrun, query) { email, }); - console.log(`Sending email to ${ email }`); + SystemLogger.debug(`Sending email to ${ email }`); return Mailer.send({ to: email, from, @@ -54,7 +55,7 @@ export const sendMail = function(from, subject, body, dryrun, query) { name: escapeHTML(user.name), email: escapeHTML(email), }); - console.log(`Sending email to ${ email }`); + SystemLogger.debug(`Sending email to ${ email }`); return Mailer.send({ to: email, from, diff --git a/app/mail-messages/server/functions/unsubscribe.js b/app/mail-messages/server/functions/unsubscribe.js index 9d892acb0c50..c06c568ff822 100644 --- a/app/mail-messages/server/functions/unsubscribe.js +++ b/app/mail-messages/server/functions/unsubscribe.js @@ -1,8 +1,13 @@ -import { Users } from '../../../models'; +import { Users } from '../../../models/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; export const unsubscribe = function(_id, createdAt) { if (_id && createdAt) { - return Users.rocketMailUnsubscribe(_id, createdAt) === 1; + const affectedRows = Users.rocketMailUnsubscribe(_id, createdAt) === 1; + + SystemLogger.debug('[Mailer:Unsubscribe]', _id, createdAt, new Date(parseInt(createdAt)), affectedRows); + + return affectedRows; } return false; }; diff --git a/app/message-mark-as-unread/server/logger.js b/app/message-mark-as-unread/server/logger.js index 1327ecda6e8c..4752c07a23dc 100644 --- a/app/message-mark-as-unread/server/logger.js +++ b/app/message-mark-as-unread/server/logger.js @@ -1,9 +1,4 @@ import { Logger } from '../../logger'; -const logger = new Logger('MessageMarkAsUnread', { - sections: { - connection: 'Connection', - events: 'Events', - }, -}); +const logger = new Logger('MessageMarkAsUnread'); export default logger; diff --git a/app/message-mark-as-unread/server/unreadMessages.js b/app/message-mark-as-unread/server/unreadMessages.js index da31e72a35af..c10a3fc1ae5c 100644 --- a/app/message-mark-as-unread/server/unreadMessages.js +++ b/app/message-mark-as-unread/server/unreadMessages.js @@ -48,9 +48,9 @@ Meteor.methods({ } const lastSeen = Subscriptions.findOneByRoomIdAndUserId(originalMessage.rid, userId).ls; if (firstUnreadMessage.ts >= lastSeen) { - return logger.connection.debug('Provided message is already marked as unread'); + return logger.debug('Provided message is already marked as unread'); } - logger.connection.debug(`Updating unread message of ${ originalMessage.ts } as the first unread`); + logger.debug(`Updating unread message of ${ originalMessage.ts } as the first unread`); return Subscriptions.setAsUnreadByRoomIdAndUserId(originalMessage.rid, userId, originalMessage.ts); }, }); diff --git a/app/meteor-accounts-saml/server/lib/SAML.ts b/app/meteor-accounts-saml/server/lib/SAML.ts index ca876193ac37..9327aa44ac7f 100644 --- a/app/meteor-accounts-saml/server/lib/SAML.ts +++ b/app/meteor-accounts-saml/server/lib/SAML.ts @@ -17,6 +17,7 @@ import { IServiceProviderOptions } from '../definition/IServiceProviderOptions'; import { ISAMLAction } from '../definition/ISAMLAction'; import { ISAMLUser } from '../definition/ISAMLUser'; import { SAMLUtils } from './Utils'; +import { SystemLogger } from '../../../../server/lib/logger/system'; const showErrorMessage = function(res: ServerResponse, err: string): void { res.writeHead(200, { @@ -240,7 +241,7 @@ export class SAML { const serviceProvider = new SAMLServiceProvider(service); serviceProvider.validateLogoutRequest(req.query.SAMLRequest, (err, result) => { if (err) { - console.error(err); + SystemLogger.error({ err }); throw new Meteor.Error('Unable to Validate Logout Request'); } @@ -293,14 +294,14 @@ export class SAML { serviceProvider.logoutResponseToUrl(response, (err, url) => { if (err) { - console.error(err); + SystemLogger.error({ err }); return redirect(); } redirect(url); }); } catch (e) { - console.error(e); + SystemLogger.error(e); redirect(); } }).run(); @@ -472,7 +473,7 @@ export class SAML { } } } catch (err) { - console.error(err); + SystemLogger.error(err); } } } diff --git a/app/meteor-accounts-saml/server/lib/Utils.ts b/app/meteor-accounts-saml/server/lib/Utils.ts index 20671c07a415..aa4156c8c567 100644 --- a/app/meteor-accounts-saml/server/lib/Utils.ts +++ b/app/meteor-accounts-saml/server/lib/Utils.ts @@ -141,7 +141,7 @@ export class SAMLUtils { public static log(...args: Array): void { if (debug && logger) { - logger.info(...args); + logger.debug(...args); } } diff --git a/app/meteor-accounts-saml/server/lib/parsers/LogoutRequest.ts b/app/meteor-accounts-saml/server/lib/parsers/LogoutRequest.ts index 7f6d85181ef0..67da8570c493 100644 --- a/app/meteor-accounts-saml/server/lib/parsers/LogoutRequest.ts +++ b/app/meteor-accounts-saml/server/lib/parsers/LogoutRequest.ts @@ -38,7 +38,7 @@ export class LogoutRequestParser { return callback(null, { idpSession, nameID, id }); } catch (e) { - console.error(e); + SAMLUtils.error(e); SAMLUtils.log(`Caught error: ${ e }`); const msg = doc.getElementsByTagNameNS('urn:oasis:names:tc:SAML:2.0:protocol', 'StatusMessage'); diff --git a/app/meteor-accounts-saml/server/lib/parsers/Response.ts b/app/meteor-accounts-saml/server/lib/parsers/Response.ts index 1a813b3f0a75..4a21f29cf88f 100644 --- a/app/meteor-accounts-saml/server/lib/parsers/Response.ts +++ b/app/meteor-accounts-saml/server/lib/parsers/Response.ts @@ -140,7 +140,7 @@ export class ResponseParser { } } - SAMLUtils.log(`NameID: ${ JSON.stringify(profile) }`); + SAMLUtils.log({ msg: 'NameID', profile }); return callback(null, profile, false); } @@ -178,7 +178,7 @@ export class ResponseParser { const encData = encAssertion.getElementsByTagNameNS('*', 'EncryptedData')[0]; xmlenc.decrypt(encData, options, function(err: Error, result: string) { if (err) { - console.error(err); + SAMLUtils.error(err); } const document = new xmldom.DOMParser().parseFromString(result, 'text/xml'); @@ -320,7 +320,7 @@ export class ResponseParser { const options = { key: this.serviceProviderOptions.privateKey }; xmlenc.decrypt(encSubject.getElementsByTagNameNS('*', 'EncryptedData')[0], options, function(err: Error, result: string) { if (err) { - console.error(err); + SAMLUtils.error(err); } subject = new xmldom.DOMParser().parseFromString(result, 'text/xml'); }); diff --git a/app/meteor-accounts-saml/server/lib/settings.ts b/app/meteor-accounts-saml/server/lib/settings.ts index b18b509c772d..b71cc6551af8 100644 --- a/app/meteor-accounts-saml/server/lib/settings.ts +++ b/app/meteor-accounts-saml/server/lib/settings.ts @@ -2,6 +2,7 @@ import { Meteor } from 'meteor/meteor'; import { ServiceConfiguration } from 'meteor/service-configuration'; import { settings } from '../../../settings/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; import { SettingComposedValue } from '../../../settings/lib/settings'; import { IServiceProviderOptions } from '../definition/IServiceProviderOptions'; import { SAMLUtils } from './Utils'; @@ -131,7 +132,7 @@ export const loadSamlServiceProviders = function(): void { }; export const addSamlService = function(name: string): void { - console.log(`Adding ${ name } is deprecated`); + SystemLogger.warn(`Adding ${ name } is deprecated`); }; export const addSettings = function(name: string): void { diff --git a/app/meteor-accounts-saml/server/listener.ts b/app/meteor-accounts-saml/server/listener.ts index 4edae1cb301a..d4352315459b 100644 --- a/app/meteor-accounts-saml/server/listener.ts +++ b/app/meteor-accounts-saml/server/listener.ts @@ -6,6 +6,7 @@ import { RoutePolicy } from 'meteor/routepolicy'; import bodyParser from 'body-parser'; import fiber from 'fibers'; +import { SystemLogger } from '../../../server/lib/logger/system'; import { SAML } from './lib/SAML'; import { SAMLUtils } from './lib/Utils'; import { ISAMLAction } from './definition/ISAMLAction'; @@ -54,14 +55,14 @@ const middleware = function(req: IIncomingMessage, res: ServerResponse, next: (e const service = SAMLUtils.getServiceProviderOptions(samlObject.serviceName); if (!service) { - console.error(`${ samlObject.serviceName } service provider not found`); + SystemLogger.error(`${ samlObject.serviceName } service provider not found`); throw new Error('SAML Service Provider not found.'); } SAML.processRequest(req, res, service, samlObject); } catch (err) { // @ToDo: Ideally we should send some error message to the client, but there's no way to do it on a redirect right now. - console.log(err); + SystemLogger.error(err); const url = Meteor.absoluteUrl('home'); res.writeHead(302, { diff --git a/app/meteor-accounts-saml/server/loginHandler.ts b/app/meteor-accounts-saml/server/loginHandler.ts index 84beec3091aa..64680efbfb64 100644 --- a/app/meteor-accounts-saml/server/loginHandler.ts +++ b/app/meteor-accounts-saml/server/loginHandler.ts @@ -3,6 +3,7 @@ import { Accounts } from 'meteor/accounts-base'; import { SAMLUtils } from './lib/Utils'; import { SAML } from './lib/SAML'; +import { SystemLogger } from '../../../server/lib/logger/system'; const makeError = (message: string): Record => ({ type: 'saml', @@ -16,7 +17,7 @@ Accounts.registerLoginHandler('saml', function(loginRequest) { } const loginResult = SAML.retrieveCredential(loginRequest.credentialToken); - SAMLUtils.log(`RESULT :${ JSON.stringify(loginResult) }`); + SAMLUtils.log({ msg: 'RESULT', loginResult }); if (!loginResult) { return makeError('No matching login attempt found'); @@ -31,7 +32,7 @@ Accounts.registerLoginHandler('saml', function(loginRequest) { return SAML.insertOrUpdateSAMLUser(userObject); } catch (error) { - console.error(error); + SystemLogger.error(error); return makeError(error.toString()); } }); diff --git a/app/meteor-accounts-saml/server/methods/samlLogout.ts b/app/meteor-accounts-saml/server/methods/samlLogout.ts index ceedc2de0cb1..9ee693123a9a 100644 --- a/app/meteor-accounts-saml/server/methods/samlLogout.ts +++ b/app/meteor-accounts-saml/server/methods/samlLogout.ts @@ -32,7 +32,7 @@ Meteor.methods({ } const providerConfig = getSamlServiceProviderOptions(provider); - SAMLUtils.log(`Logout request from ${ JSON.stringify(providerConfig) }`); + SAMLUtils.log({ msg: 'Logout request', providerConfig }); // This query should respect upcoming array of SAML logins const user = Users.getSAMLByIdAndSAMLProvider(Meteor.userId(), provider); if (!user || !user.services || !user.services.saml) { @@ -40,7 +40,7 @@ Meteor.methods({ } const { nameID, idpSession } = user.services.saml; - SAMLUtils.log(`NameID for user ${ Meteor.userId() } found: ${ JSON.stringify(nameID) }`); + SAMLUtils.log({ msg: `NameID for user ${ Meteor.userId() } found`, nameID }); const _saml = new SAMLServiceProvider(providerConfig); diff --git a/app/meteor-accounts-saml/server/startup.ts b/app/meteor-accounts-saml/server/startup.ts index d76cf007d418..a3067c26dfd3 100644 --- a/app/meteor-accounts-saml/server/startup.ts +++ b/app/meteor-accounts-saml/server/startup.ts @@ -8,7 +8,7 @@ import { SAMLUtils } from './lib/Utils'; settings.addGroup('SAML'); -export const logger = new Logger('steffo:meteor-accounts-saml', {}); +export const logger = new Logger('steffo:meteor-accounts-saml'); SAMLUtils.setLoggerInstance(logger); const updateServices = _.debounce(Meteor.bindEnvironment(() => { diff --git a/app/metrics/server/lib/collectMetrics.js b/app/metrics/server/lib/collectMetrics.js index 66a24da4df91..be97d5b98e87 100644 --- a/app/metrics/server/lib/collectMetrics.js +++ b/app/metrics/server/lib/collectMetrics.js @@ -8,9 +8,10 @@ import { Meteor } from 'meteor/meteor'; import { Facts } from 'meteor/facts-base'; import { Info, getOplogInfo } from '../../../utils/server'; -import { Migrations } from '../../../migrations'; -import { settings } from '../../../settings'; -import { Statistics } from '../../../models'; +import { Migrations } from '../../../migrations/server'; +import { settings } from '../../../settings/server'; +import { Statistics } from '../../../models/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; import { metrics } from './metrics'; import { getAppsStatistics } from '../../../statistics/server/lib/getAppsStatistics'; @@ -136,7 +137,7 @@ const updatePrometheusConfig = async () => { if (!is.enabled) { if (was.enabled) { - console.log('Disabling Prometheus'); + SystemLogger.info('Disabling Prometheus'); server.close(); Meteor.clearInterval(timer); } @@ -144,7 +145,7 @@ const updatePrometheusConfig = async () => { return; } - console.log('Configuring Prometheus', is); + SystemLogger.debug({ msg: 'Configuring Prometheus', is }); if (!was.enabled) { server.listen({ @@ -174,7 +175,7 @@ const updatePrometheusConfig = async () => { gcStats()(); } } catch (error) { - console.error(error); + SystemLogger.error(error); } Object.assign(was, is); diff --git a/app/migrations/server/migrations.js b/app/migrations/server/migrations.js index c7d25a94dad6..dbfebfeaa531 100644 --- a/app/migrations/server/migrations.js +++ b/app/migrations/server/migrations.js @@ -1,13 +1,13 @@ /* eslint no-use-before-define:0 */ import { Meteor } from 'meteor/meteor'; -import { Match, check } from 'meteor/check'; +import { check } from 'meteor/check'; import { Mongo } from 'meteor/mongo'; -import { Log } from 'meteor/logging'; import _ from 'underscore'; import s from 'underscore.string'; import moment from 'moment'; -import { Info } from '../../utils'; +import { Info } from '../../utils/server'; +import { Logger } from '../../logger/server'; /* Adds migration capabilities. Migrations are defined like: @@ -87,50 +87,7 @@ function makeABox(message, color = 'red') { return `\n${ topLine }\n${ separator }\n${ text }\n${ separator }\n${ bottomLine }\n`; } -/* - Logger factory function. Takes a prefix string and options object - and uses an injected `logger` if provided, else falls back to - Meteor's `Log` package. - Will send a log object to the injected logger, on the following form: - message: String - level: String (info, warn, error, debug) - tag: 'Migrations' -*/ -function createLogger(prefix) { - check(prefix, String); - - // Return noop if logging is disabled. - if (Migrations.options.log === false) { - return function() {}; - } - - return function(level, message) { - check(level, Match.OneOf('info', 'error', 'warn', 'debug')); - check(message, Match.OneOf(String, [String])); - - const logger = Migrations.options && Migrations.options.logger; - - if (logger && _.isFunction(logger)) { - logger({ - level, - message, - tag: prefix, - }); - } else { - Log[level]({ - message: `${ prefix }: ${ message }`, - }); - } - }; -} - -// collection holding the control record - -const log = createLogger('Migrations'); - -['info', 'warn', 'error', 'debug'].forEach(function(level) { - log[level] = _.partial(log, level); -}); +const log = new Logger('Migrations'); // if (process.env.MIGRATE) // Migrations.migrateTo(process.env.MIGRATE); @@ -190,7 +147,7 @@ Migrations.migrateTo = function(command) { } else { willRetry = ''; } - console.log(`Not migrating, control is locked. Attempt ${ attempts }/${ maxAttempts }.${ willRetry }`.yellow); + log.warn(`Not migrating, control is locked. Attempt ${ attempts }/${ maxAttempts }.${ willRetry }`.yellow); } } if (!migrated) { @@ -275,7 +232,7 @@ Migrations._migrateTo = function(version, rerun) { try { migration[direction](migration); } catch (e) { - console.log(makeABox([ + console.error(makeABox([ 'ERROR! SERVER STOPPED', '', 'Your database migration failed:', diff --git a/app/models/server/models/Messages.js b/app/models/server/models/Messages.js index bc5a4b22cdb3..d7abb18a12b1 100644 --- a/app/models/server/models/Messages.js +++ b/app/models/server/models/Messages.js @@ -91,17 +91,6 @@ export class Messages extends Base { return this.update(query, update); } - setGoogleVisionData(messageId, visionData) { - const updateObj = {}; - for (const index in visionData) { - if (visionData.hasOwnProperty(index)) { - updateObj[`attachments.0.${ index }`] = visionData[index]; - } - } - - return this.update({ _id: messageId }, { $set: updateObj }); - } - createRoomSettingsChangedWithTypeRoomIdMessageAndUser(type, roomId, message, user, extraData) { return this.createWithTypeRoomIdMessageAndUser(type, roomId, message, user, extraData); } diff --git a/app/models/server/models/Rooms.js b/app/models/server/models/Rooms.js index 05751f59cae5..d884208317fc 100644 --- a/app/models/server/models/Rooms.js +++ b/app/models/server/models/Rooms.js @@ -334,6 +334,7 @@ export class Rooms extends Base { let channelName = s.trim(name); try { + // TODO evaluate if this function call should be here channelName = getValidRoomName(channelName, null, { allowDuplicates: true }); } catch (e) { console.error(e); diff --git a/app/models/server/models/Users.js b/app/models/server/models/Users.js index 63b2c4278e97..c760c4d7172a 100644 --- a/app/models/server/models/Users.js +++ b/app/models/server/models/Users.js @@ -354,7 +354,6 @@ export class Users extends Base { }, }; const affectedRows = this.update(query, update); - console.log('[Mailer:Unsubscribe]', _id, createdAt, new Date(parseInt(createdAt)), affectedRows); return affectedRows; } diff --git a/app/models/server/models/_BaseDb.js b/app/models/server/models/_BaseDb.js index 46a285b53560..6c9473c81fb8 100644 --- a/app/models/server/models/_BaseDb.js +++ b/app/models/server/models/_BaseDb.js @@ -7,6 +7,7 @@ import _ from 'underscore'; import { setUpdatedAt } from '../lib/setUpdatedAt'; import { metrics } from '../../../metrics/server/lib/metrics'; import { getOplogHandle } from './_oplogHandle'; +import { SystemLogger } from '../../../../server/lib/logger/system'; const baseName = 'rocketchat_'; @@ -20,7 +21,7 @@ try { trash._ensureIndex({ rid: 1, __collection__: 1, _deletedAt: 1 }); } catch (e) { - console.log(e); + SystemLogger.error(e); } const actions = { diff --git a/app/nextcloud/server/addWebdavServer.js b/app/nextcloud/server/addWebdavServer.js index fa331312705f..89622e54fd79 100644 --- a/app/nextcloud/server/addWebdavServer.js +++ b/app/nextcloud/server/addWebdavServer.js @@ -1,7 +1,8 @@ import { Meteor } from 'meteor/meteor'; -import { callbacks } from '../../callbacks'; -import { settings } from '../../settings'; +import { callbacks } from '../../callbacks/server'; +import { settings } from '../../settings/server'; +import { SystemLogger } from '../../../server/lib/logger/system'; Meteor.startup(() => { settings.get('Webdav_Integration_Enabled', (key, value) => { @@ -25,7 +26,7 @@ Meteor.startup(() => { try { Meteor.runAsUser(user._id, () => Meteor.call('addWebdavAccountByToken', data)); } catch (error) { - console.log(error); + SystemLogger.error(error); } }, callbacks.priority.MEDIUM, 'add-webdav-server'); } diff --git a/app/notification-queue/server/NotificationQueue.ts b/app/notification-queue/server/NotificationQueue.ts index 42f05827b919..d16da1cc71ee 100644 --- a/app/notification-queue/server/NotificationQueue.ts +++ b/app/notification-queue/server/NotificationQueue.ts @@ -5,6 +5,7 @@ import { NotificationQueue, Users } from '../../models/server/raw'; import { sendEmailFromData } from '../../lib/server/functions/notifications/email'; import { PushNotification } from '../../push-notifications/server'; import { IUser } from '../../../definition/IUser'; +import { SystemLogger } from '../../../server/lib/logger/system'; const { NOTIFICATIONS_WORKER_TIMEOUT = 2000, @@ -45,7 +46,7 @@ class NotificationClass { try { this.worker(); } catch (e) { - console.error('Error sending notification', e); + SystemLogger.error('Error sending notification', e); this.executeWorkerLater(); } }, this.cyclePause); @@ -81,7 +82,7 @@ class NotificationClass { NotificationQueue.removeById(notification._id); } catch (e) { - console.error(e); + SystemLogger.error(e); await NotificationQueue.setErrorById(notification._id, e.message); } diff --git a/app/oembed/server/providers.js b/app/oembed/server/providers.js index f6ba54a3d3ba..09415153a64b 100644 --- a/app/oembed/server/providers.js +++ b/app/oembed/server/providers.js @@ -4,7 +4,8 @@ import QueryString from 'querystring'; import { camelCase } from 'change-case'; import _ from 'underscore'; -import { callbacks } from '../../callbacks'; +import { callbacks } from '../../callbacks/server'; +import { SystemLogger } from '../../../server/lib/logger/system'; class Providers { constructor() { @@ -146,7 +147,7 @@ callbacks.add('oembed:afterParseContent', function(data) { } }); } catch (error) { - console.log(error); + SystemLogger.error(error); } return data; }, callbacks.priority.MEDIUM, 'oembed-providers-after'); diff --git a/app/oembed/server/server.js b/app/oembed/server/server.js index 34aa1a8eee1a..b859b4ed80de 100644 --- a/app/oembed/server/server.js +++ b/app/oembed/server/server.js @@ -14,6 +14,7 @@ import { OEmbedCache, Messages } from '../../models'; import { callbacks } from '../../callbacks'; import { settings } from '../../settings'; import { isURL } from '../../utils/lib/isURL'; +import { SystemLogger } from '../../../server/lib/logger/system'; const request = HTTPInternals.NpmModules.request.module; const OEmbed = {}; @@ -224,7 +225,7 @@ OEmbed.getUrlMetaWithCache = function(url, withFragment) { try { OEmbedCache.createWithIdAndData(url, data); } catch (_error) { - console.error('OEmbed duplicated record', url); + SystemLogger.error('OEmbed duplicated record', url); } return data; } diff --git a/app/push/server/apn.js b/app/push/server/apn.js index 693f8dcc0529..d84846fd592e 100644 --- a/app/push/server/apn.js +++ b/app/push/server/apn.js @@ -70,7 +70,7 @@ export const initAPN = ({ options, absoluteUrl }) => { // Give the user warnings about development settings if (options.apn.development) { // This flag is normally set by the configuration file - console.warn('WARNING: Push APN is using development key and certificate'); + logger.warn('WARNING: Push APN is using development key and certificate'); } else if (options.apn.gateway) { // We check the apn gateway i the options, we could risk shipping // server into production while using the production configuration. @@ -83,39 +83,39 @@ export const initAPN = ({ options, absoluteUrl }) => { if (options.apn.gateway === 'gateway.sandbox.push.apple.com') { // Using the development sandbox - console.warn('WARNING: Push APN is in development mode'); + logger.warn('WARNING: Push APN is in development mode'); } else if (options.apn.gateway === 'gateway.push.apple.com') { // In production - but warn if we are running on localhost if (/http:\/\/localhost/.test(absoluteUrl)) { - console.warn('WARNING: Push APN is configured to production mode - but server is running from localhost'); + logger.warn('WARNING: Push APN is configured to production mode - but server is running from localhost'); } } else { // Warn about gateways we dont know about - console.warn(`WARNING: Push APN unknown gateway "${ options.apn.gateway }"`); + logger.warn(`WARNING: Push APN unknown gateway "${ options.apn.gateway }"`); } } else if (options.apn.production) { if (/http:\/\/localhost/.test(absoluteUrl)) { - console.warn('WARNING: Push APN is configured to production mode - but server is running from localhost'); + logger.warn('WARNING: Push APN is configured to production mode - but server is running from localhost'); } } else { - console.warn('WARNING: Push APN is in development mode'); + logger.warn('WARNING: Push APN is in development mode'); } // Check certificate data if (!options.apn.cert || !options.apn.cert.length) { - console.error('ERROR: Push server could not find cert'); + logger.error('ERROR: Push server could not find cert'); } // Check key data if (!options.apn.key || !options.apn.key.length) { - console.error('ERROR: Push server could not find key'); + logger.error('ERROR: Push server could not find key'); } // Rig apn connection try { apnConnection = new apn.Provider(options.apn); } catch (e) { - console.error('Error trying to initialize APN'); - console.error(e); + logger.error('Error trying to initialize APN'); + logger.error(e); } }; diff --git a/app/push/server/gcm.js b/app/push/server/gcm.js index a677e630b196..dc3890825593 100644 --- a/app/push/server/gcm.js +++ b/app/push/server/gcm.js @@ -92,7 +92,7 @@ export const sendGCM = function({ userTokens, notification, _replaceToken, _remo sender.send(message, userTokens, 5, function(err, result) { if (err) { - logger.debug(`ANDROID ERROR: result of sender: ${ result }`); + logger.debug({ msg: 'ANDROID ERROR: result of sender', result }); return; } @@ -101,14 +101,14 @@ export const sendGCM = function({ userTokens, notification, _replaceToken, _remo return; } - logger.debug(`ANDROID: Result of sender: ${ JSON.stringify(result) }`); + logger.debug({ msg: 'ANDROID: Result of sender', result }); if (result.canonical_ids === 1 && userToken) { // This is an old device, token is replaced try { _replaceToken({ gcm: userToken }, { gcm: result.results[0].registration_id }); } catch (err) { - logger.error('Error replacing token', err); + logger.error({ msg: 'Error replacing token', err }); } } // We cant send to that token - might not be registered @@ -118,7 +118,7 @@ export const sendGCM = function({ userTokens, notification, _replaceToken, _remo try { _removeToken({ gcm: userToken }); } catch (err) { - logger.error('Error removing token', err); + logger.error({ msg: 'Error removing token', err }); } } }); diff --git a/app/push/server/logger.js b/app/push/server/logger.js index 553e253eee47..f770aef378f6 100644 --- a/app/push/server/logger.js +++ b/app/push/server/logger.js @@ -1,4 +1,3 @@ -import { Logger, LoggerManager } from '../../logger/server'; +import { Logger } from '../../../server/lib/logger/Logger'; export const logger = new Logger('Push'); -export { LoggerManager }; diff --git a/app/push/server/push.js b/app/push/server/push.js index e95ca8f88716..2d576fe3ea34 100644 --- a/app/push/server/push.js +++ b/app/push/server/push.js @@ -6,7 +6,7 @@ import _ from 'underscore'; import { initAPN, sendAPN } from './apn'; import { sendGCM } from './gcm'; -import { logger, LoggerManager } from './logger'; +import { logger } from './logger'; import { settings } from '../../settings/server'; export const _matchToken = Match.OneOf({ apn: String }, { gcm: String }); @@ -208,7 +208,7 @@ export class PushClass { return this.sendNotificationNative(app, notification, countApn, countGcm); }); - if (LoggerManager.logLevel === 2) { + if (settings.get('Log_Level') === '2') { logger.debug(`Sent message "${ notification.title }" to ${ countApn.length } ios apps ${ countGcm.length } android apps`); // Add some verbosity about the send result, making sure the developer diff --git a/app/reactions/client/stylesheets/reaction.css b/app/reactions/client/stylesheets/reaction.css index b8d6e3897130..7bb7a232b0fc 100644 --- a/app/reactions/client/stylesheets/reaction.css +++ b/app/reactions/client/stylesheets/reaction.css @@ -1,6 +1,6 @@ .message { & .reactions { - margin-top: 4px; + margin-top: 8px; padding: 0; & > li { diff --git a/app/search/server/logger/logger.js b/app/search/server/logger/logger.js index 86464e1c6acd..bd0ddbf10f4d 100644 --- a/app/search/server/logger/logger.js +++ b/app/search/server/logger/logger.js @@ -1,4 +1,4 @@ import { Logger } from '../../../logger'; -const SearchLogger = new Logger('Search Logger', {}); +const SearchLogger = new Logger('Search Logger'); export default SearchLogger; diff --git a/app/search/server/service/providerService.js b/app/search/server/service/providerService.js index ac913f8cfb46..2288a06e390b 100644 --- a/app/search/server/service/providerService.js +++ b/app/search/server/service/providerService.js @@ -142,7 +142,7 @@ Meteor.methods({ throw new Error('Provider currently not active'); } - SearchLogger.debug('search: ', `\n\tText:${ text }\n\tContext:${ JSON.stringify(context) }\n\tPayload:${ JSON.stringify(payload) }`); + SearchLogger.debug({ msg: 'search', text, context, payload }); searchProviderService.activeProvider.search(text, context, payload, (error, data) => { if (error) { @@ -163,7 +163,7 @@ Meteor.methods({ try { if (!searchProviderService.activeProvider) { throw new Error('Provider currently not active'); } - SearchLogger.debug('suggest: ', `\n\tText:${ text }\n\tContext:${ JSON.stringify(context) }\n\tPayload:${ JSON.stringify(payload) }`); + SearchLogger.debug({ msg: 'suggest', text, context, payload }); searchProviderService.activeProvider.suggest(text, context, payload, (error, data) => { if (error) { diff --git a/app/settings/server/functions/settings.ts b/app/settings/server/functions/settings.ts index 72ad2a970f73..7341393bc60a 100644 --- a/app/settings/server/functions/settings.ts +++ b/app/settings/server/functions/settings.ts @@ -7,6 +7,7 @@ import { SettingsBase } from '../../lib/settings'; import SettingsModel from '../../../models/server/models/Settings'; import { updateValue } from '../raw'; import { ISetting, SettingValue } from '../../../../definition/ISetting'; +import { SystemLogger } from '../../../../server/lib/logger/system'; const blockedSettings = new Set(); const hiddenSettings = new Set(); @@ -131,7 +132,7 @@ class Settings extends SettingsBase { options.enterprise = options.enterprise || false; if (options.enterprise && !('invalidValue' in options)) { - console.error(`Enterprise setting ${ _id } is missing the invalidValue option`); + SystemLogger.error(`Enterprise setting ${ _id } is missing the invalidValue option`); throw new Error(`Enterprise setting ${ _id } is missing the invalidValue option`); } diff --git a/app/slackbridge/server/RocketAdapter.js b/app/slackbridge/server/RocketAdapter.js index e84efba8d201..db674910be44 100644 --- a/app/slackbridge/server/RocketAdapter.js +++ b/app/slackbridge/server/RocketAdapter.js @@ -5,7 +5,7 @@ import { Meteor } from 'meteor/meteor'; import { Accounts } from 'meteor/accounts-base'; import { Random } from 'meteor/random'; -import { logger } from './logger'; +import { rocketLogger } from './logger'; import { callbacks } from '../../callbacks'; import { settings } from '../../settings'; import { Messages, Rooms, Users } from '../../models'; @@ -13,7 +13,7 @@ import { createRoom, sendMessage, setUserAvatar } from '../../lib'; export default class RocketAdapter { constructor(slackBridge) { - logger.rocket.debug('constructor'); + rocketLogger.debug('constructor'); this.slackBridge = slackBridge; this.util = util; this.userTags = {}; @@ -39,7 +39,7 @@ export default class RocketAdapter { } registerForEvents() { - logger.rocket.debug('Register for events'); + rocketLogger.debug('Register for events'); callbacks.add('afterSaveMessage', this.onMessage.bind(this), callbacks.priority.LOW, 'SlackBridge_Out'); callbacks.add('afterDeleteMessage', this.onMessageDelete.bind(this), callbacks.priority.LOW, 'SlackBridge_Delete'); callbacks.add('setReaction', this.onSetReaction.bind(this), callbacks.priority.LOW, 'SlackBridge_SetReaction'); @@ -47,7 +47,7 @@ export default class RocketAdapter { } unregisterForEvents() { - logger.rocket.debug('Unregister for events'); + rocketLogger.debug('Unregister for events'); callbacks.remove('afterSaveMessage', 'SlackBridge_Out'); callbacks.remove('afterDeleteMessage', 'SlackBridge_Delete'); callbacks.remove('setReaction', 'SlackBridge_SetReaction'); @@ -61,10 +61,10 @@ export default class RocketAdapter { // This is on a channel that the rocket bot is not subscribed on this slack server return; } - logger.rocket.debug('onRocketMessageDelete', rocketMessageDeleted); + rocketLogger.debug('onRocketMessageDelete', rocketMessageDeleted); slack.postDeleteMessage(rocketMessageDeleted); } catch (err) { - logger.rocket.error('Unhandled error onMessageDelete', err); + rocketLogger.error('Unhandled error onMessageDelete', err); } }); } @@ -75,7 +75,7 @@ export default class RocketAdapter { return; } - logger.rocket.debug('onRocketSetReaction'); + rocketLogger.debug('onRocketSetReaction'); if (rocketMsgID && reaction) { if (this.slackBridge.reactionsMap.delete(`set${ rocketMsgID }${ reaction }`)) { @@ -94,7 +94,7 @@ export default class RocketAdapter { } } } catch (err) { - logger.rocket.error('Unhandled error onSetReaction', err); + rocketLogger.error('Unhandled error onSetReaction', err); } } @@ -104,7 +104,7 @@ export default class RocketAdapter { return; } - logger.rocket.debug('onRocketUnSetReaction'); + rocketLogger.debug('onRocketUnSetReaction'); if (rocketMsgID && reaction) { if (this.slackBridge.reactionsMap.delete(`unset${ rocketMsgID }${ reaction }`)) { @@ -124,7 +124,7 @@ export default class RocketAdapter { } } } catch (err) { - logger.rocket.error('Unhandled error onUnSetReaction', err); + rocketLogger.error('Unhandled error onUnSetReaction', err); } } @@ -135,7 +135,7 @@ export default class RocketAdapter { // This is on a channel that the rocket bot is not subscribed return; } - logger.rocket.debug('onRocketMessage', rocketMessage); + rocketLogger.debug('onRocketMessage', rocketMessage); if (rocketMessage.editedAt) { // This is an Edit Event @@ -154,7 +154,7 @@ export default class RocketAdapter { // A new message from Rocket.Chat this.processSendMessage(rocketMessage, slack); } catch (err) { - logger.rocket.error('Unhandled error onMessage', err); + rocketLogger.error('Unhandled error onMessage', err); } }); @@ -168,7 +168,7 @@ export default class RocketAdapter { } else { // They want to limit to certain groups const outSlackChannels = _.pluck(settings.get('SlackBridge_Out_Channels'), '_id') || []; - // logger.rocket.debug('Out SlackChannels: ', outSlackChannels); + // rocketLogger.debug('Out SlackChannels: ', outSlackChannels); if (outSlackChannels.indexOf(rocketMessage.rid) !== -1) { slack.postMessage(slack.getSlackChannel(rocketMessage.rid), rocketMessage); } @@ -260,7 +260,7 @@ export default class RocketAdapter { } addChannel(slackChannelID, hasRetried = false) { - logger.rocket.debug('Adding Rocket.Chat channel from Slack', slackChannelID); + rocketLogger.debug('Adding Rocket.Chat channel from Slack', slackChannelID); let addedRoom; this.slackAdapters.forEach((slack) => { @@ -272,7 +272,7 @@ export default class RocketAdapter { if (slackChannel) { const members = slack.slackAPI.getMembers(slackChannelID); if (!members) { - logger.rocket.error('Could not fetch room members'); + rocketLogger.error('Could not fetch room members'); return; } @@ -286,7 +286,7 @@ export default class RocketAdapter { const rocketUserCreator = this.getRocketUserCreator(slackChannel); if (!rocketUserCreator) { - logger.rocket.error('Could not fetch room creator information', slackChannel.creator); + rocketLogger.error('Could not fetch room creator information', slackChannel.creator); return; } @@ -296,12 +296,12 @@ export default class RocketAdapter { rocketChannel.rocketId = rocketChannel.rid; } catch (e) { if (!hasRetried) { - logger.rocket.debug('Error adding channel from Slack. Will retry in 1s.', e.message); + rocketLogger.debug('Error adding channel from Slack. Will retry in 1s.', e.message); // If first time trying to create channel fails, could be because of multiple messages received at the same time. Try again once after 1s. Meteor._sleepForMs(1000); return this.findChannel(slackChannelID) || this.addChannel(slackChannelID, true); } - console.log(e.message); + rocketLogger.error(e.message); } const roomUpdate = { @@ -327,7 +327,7 @@ export default class RocketAdapter { }); if (!addedRoom) { - logger.rocket.debug('Channel not added'); + rocketLogger.debug('Channel not added'); } return addedRoom; } @@ -341,7 +341,7 @@ export default class RocketAdapter { } addUser(slackUserID) { - logger.rocket.debug('Adding Rocket.Chat user from Slack', slackUserID); + rocketLogger.debug('Adding Rocket.Chat user from Slack', slackUserID); let addedUser; this.slackAdapters.forEach((slack) => { if (addedUser) { @@ -408,7 +408,7 @@ export default class RocketAdapter { try { setUserAvatar(user, url, null, 'url'); } catch (error) { - logger.rocket.debug('Error setting user avatar', error.message); + rocketLogger.debug('Error setting user avatar', error.message); } } } @@ -426,7 +426,7 @@ export default class RocketAdapter { }); if (!addedUser) { - logger.rocket.debug('User not added'); + rocketLogger.debug('User not added'); } return addedUser; @@ -495,7 +495,7 @@ export default class RocketAdapter { } }, 500); } else { - logger.rocket.debug('Send message to Rocket.Chat'); + rocketLogger.debug('Send message to Rocket.Chat'); sendMessage(rocketUser, rocketMsgObj, rocketChannel, true); } } diff --git a/app/slackbridge/server/SlackAdapter.js b/app/slackbridge/server/SlackAdapter.js index c61092f7cde5..1cb12c2bdacc 100644 --- a/app/slackbridge/server/SlackAdapter.js +++ b/app/slackbridge/server/SlackAdapter.js @@ -5,7 +5,7 @@ import https from 'https'; import { RTMClient } from '@slack/client'; import { Meteor } from 'meteor/meteor'; -import { logger } from './logger'; +import { slackLogger } from './logger'; import { SlackAPI } from './SlackAPI'; import { getUserAvatarURL } from '../../utils/lib/getUserAvatarURL'; import { Messages, Rooms, Users } from '../../models'; @@ -24,7 +24,7 @@ import { FileUpload } from '../../file-upload'; export default class SlackAdapter { constructor(slackBridge) { - logger.slack.debug('constructor'); + slackLogger.debug('constructor'); this.slackBridge = slackBridge; this.rtm = {}; // slack-client Real Time Messaging API this.apiToken = {}; // Slack API Token passed in via Connect @@ -56,7 +56,7 @@ export default class SlackAdapter { try { this.populateMembershipChannelMap(); // If run outside of Meteor.startup, HTTP is not defined } catch (err) { - logger.slack.error('Error attempting to connect to Slack', err); + slackLogger.error('Error attempting to connect to Slack', err); this.slackBridge.disconnect(); } }); @@ -74,9 +74,9 @@ export default class SlackAdapter { } registerForEvents() { - logger.slack.debug('Register for events'); + slackLogger.debug('Register for events'); this.rtm.on('authenticated', () => { - logger.slack.info('Connected to Slack'); + slackLogger.info('Connected to Slack'); }); this.rtm.on('unable_to_rtm_start', () => { @@ -84,7 +84,7 @@ export default class SlackAdapter { }); this.rtm.on('disconnected', () => { - logger.slack.info('Disconnected from Slack'); + slackLogger.info('Disconnected from Slack'); this.slackBridge.disconnect(); }); @@ -102,34 +102,34 @@ export default class SlackAdapter { * } **/ this.rtm.on('message', Meteor.bindEnvironment((slackMessage) => { - logger.slack.debug('OnSlackEvent-MESSAGE: ', slackMessage); + slackLogger.debug('OnSlackEvent-MESSAGE: ', slackMessage); if (slackMessage) { try { this.onMessage(slackMessage); } catch (err) { - logger.slack.error('Unhandled error onMessage', err); + slackLogger.error('Unhandled error onMessage', err); } } })); this.rtm.on('reaction_added', Meteor.bindEnvironment((reactionMsg) => { - logger.slack.debug('OnSlackEvent-REACTION_ADDED: ', reactionMsg); + slackLogger.debug('OnSlackEvent-REACTION_ADDED: ', reactionMsg); if (reactionMsg) { try { this.onReactionAdded(reactionMsg); } catch (err) { - logger.slack.error('Unhandled error onReactionAdded', err); + slackLogger.error('Unhandled error onReactionAdded', err); } } })); this.rtm.on('reaction_removed', Meteor.bindEnvironment((reactionMsg) => { - logger.slack.debug('OnSlackEvent-REACTION_REMOVED: ', reactionMsg); + slackLogger.debug('OnSlackEvent-REACTION_REMOVED: ', reactionMsg); if (reactionMsg) { try { this.onReactionRemoved(reactionMsg); } catch (err) { - logger.slack.error('Unhandled error onReactionRemoved', err); + slackLogger.error('Unhandled error onReactionRemoved', err); } } })); @@ -193,12 +193,12 @@ export default class SlackAdapter { * } **/ this.rtm.on('channel_left', Meteor.bindEnvironment((channelLeftMsg) => { - logger.slack.debug('OnSlackEvent-CHANNEL_LEFT: ', channelLeftMsg); + slackLogger.debug('OnSlackEvent-CHANNEL_LEFT: ', channelLeftMsg); if (channelLeftMsg) { try { this.onChannelLeft(channelLeftMsg); } catch (err) { - logger.slack.error('Unhandled error onChannelLeft', err); + slackLogger.error('Unhandled error onChannelLeft', err); } } })); @@ -365,7 +365,7 @@ export default class SlackAdapter { // Stash this away to key off it later so we don't send it back to Slack this.slackBridge.reactionsMap.set(`unset${ rocketMsg._id }${ rocketReaction }`, rocketUser); - logger.slack.debug('Removing reaction from Slack'); + slackLogger.debug('Removing reaction from Slack'); Meteor.runAsUser(rocketUser._id, () => { Meteor.call('setReaction', rocketReaction, rocketMsg._id); }); @@ -411,7 +411,7 @@ export default class SlackAdapter { // Stash this away to key off it later so we don't send it back to Slack this.slackBridge.reactionsMap.set(`set${ rocketMsg._id }${ rocketReaction }`, rocketUser); - logger.slack.debug('Adding reaction from Slack'); + slackLogger.debug('Adding reaction from Slack'); Meteor.runAsUser(rocketUser._id, () => { Meteor.call('setReaction', rocketReaction, rocketMsg._id); }); @@ -455,7 +455,7 @@ export default class SlackAdapter { } postFindChannel(rocketChannelName) { - logger.slack.debug('Searching for Slack channel or group', rocketChannelName); + slackLogger.debug('Searching for Slack channel or group', rocketChannelName); const channels = this.slackAPI.getChannels(); if (channels && channels.length > 0) { for (const channel of channels) { @@ -506,7 +506,7 @@ export default class SlackAdapter { addSlackChannel(rocketChID, slackChID) { const ch = this.getSlackChannel(rocketChID); if (ch == null) { - logger.slack.debug('Added channel', { rocketChID, slackChID }); + slackLogger.debug('Added channel', { rocketChID, slackChID }); this.slackChannelRocketBotMembershipMap.set(rocketChID, { id: slackChID, family: slackChID.charAt(0) === 'C' ? 'channels' : 'groups' }); } } @@ -558,7 +558,7 @@ export default class SlackAdapter { } populateMembershipChannelMap() { - logger.slack.debug('Populating channel map'); + slackLogger.debug('Populating channel map'); this.populateMembershipChannelMapByChannels(); this.populateMembershipChannelMapByGroups(); } @@ -575,10 +575,10 @@ export default class SlackAdapter { timestamp: slackTS, }; - logger.slack.debug('Posting Add Reaction to Slack'); + slackLogger.debug('Posting Add Reaction to Slack'); const postResult = this.slackAPI.react(data); if (postResult) { - logger.slack.debug('Reaction added to Slack'); + slackLogger.debug('Reaction added to Slack'); } } } @@ -595,10 +595,10 @@ export default class SlackAdapter { timestamp: slackTS, }; - logger.slack.debug('Posting Remove Reaction to Slack'); + slackLogger.debug('Posting Remove Reaction to Slack'); const postResult = this.slackAPI.removeReaction(data); if (postResult) { - logger.slack.debug('Reaction removed from Slack'); + slackLogger.debug('Reaction removed from Slack'); } } } @@ -615,10 +615,10 @@ export default class SlackAdapter { as_user: true, }; - logger.slack.debug('Post Delete Message to Slack', data); + slackLogger.debug('Post Delete Message to Slack', data); const postResult = this.slackAPI.removeMessage(data); if (postResult) { - logger.slack.debug('Message deleted on Slack'); + slackLogger.debug('Message deleted on Slack'); } } } @@ -674,7 +674,7 @@ export default class SlackAdapter { data.thread_ts = tmessage.slackTs; } } - logger.slack.debug('Post Message To Slack', data); + slackLogger.debug('Post Message To Slack', data); // If we don't have the bot id yet and we have multiple slack bridges, we need to keep track of the messages that are being sent if (!this.slackBotId && this.rocket.slackAdapters && this.rocket.slackAdapters.length >= 2) { @@ -690,7 +690,7 @@ export default class SlackAdapter { if (postResult.statusCode === 200 && postResult.data && postResult.data.message && postResult.data.message.bot_id && postResult.data.message.ts) { this.slackBotId = postResult.data.message.bot_id; Messages.setSlackBotIdAndSlackTs(rocketMessage._id, postResult.data.message.bot_id, postResult.data.message.ts); - logger.slack.debug(`RocketMsgID=${ rocketMessage._id } SlackMsgID=${ postResult.data.message.ts } SlackBotID=${ postResult.data.message.bot_id }`); + slackLogger.debug(`RocketMsgID=${ rocketMessage._id } SlackMsgID=${ postResult.data.message.ts } SlackBotID=${ postResult.data.message.bot_id }`); } } } @@ -707,16 +707,16 @@ export default class SlackAdapter { text: rocketMessage.msg, as_user: true, }; - logger.slack.debug('Post UpdateMessage To Slack', data); + slackLogger.debug('Post UpdateMessage To Slack', data); const postResult = this.slackAPI.updateMessage(data); if (postResult) { - logger.slack.debug('Message updated on Slack'); + slackLogger.debug('Message updated on Slack'); } } } processChannelJoin(slackMessage) { - logger.slack.debug('Channel join', slackMessage.channel.id); + slackLogger.debug('Channel join', slackMessage.channel.id); const rocketCh = this.rocket.addChannel(slackMessage.channel); if (rocketCh != null) { this.addSlackChannel(rocketCh._id, slackMessage.channel); @@ -775,7 +775,7 @@ export default class SlackAdapter { if (rocketMsgObj) { deleteMessage(rocketMsgObj, rocketUser); - logger.slack.debug('Rocket message deleted by Slack'); + slackLogger.debug('Rocket message deleted by Slack'); } } } @@ -802,7 +802,7 @@ export default class SlackAdapter { }; updateMessage(rocketMsgObj, rocketUser); - logger.slack.debug('Rocket message updated by Slack'); + slackLogger.debug('Rocket message updated by Slack'); } } } @@ -975,7 +975,7 @@ export default class SlackAdapter { return rocketMsgObj; } - logger.slack.error('Pinned item with no attachment'); + slackLogger.error('Pinned item with no attachment'); } processSubtypedMessage(rocketChannel, rocketUser, slackMessage, isImporting) { @@ -1015,15 +1015,15 @@ export default class SlackAdapter { case 'file_share': return this.processShareMessage(rocketChannel, rocketUser, slackMessage, isImporting); case 'file_comment': - logger.slack.error('File comment not implemented'); + slackLogger.error('File comment not implemented'); return; case 'file_mention': - logger.slack.error('File mentioned not implemented'); + slackLogger.error('File mentioned not implemented'); return; case 'pinned_item': return this.processPinnedItemMessage(rocketChannel, rocketUser, slackMessage, isImporting); case 'unpinned_item': - logger.slack.error('Unpinned item not implemented'); + slackLogger.error('Unpinned item not implemented'); } } @@ -1096,12 +1096,12 @@ export default class SlackAdapter { } importFromHistory(family, options) { - logger.slack.debug('Importing messages history'); + slackLogger.debug('Importing messages history'); const data = this.slackAPI.getHistory(family, options); if (Array.isArray(data.messages) && data.messages.length) { let latest = 0; for (const message of data.messages.reverse()) { - logger.slack.debug('MESSAGE: ', message); + slackLogger.debug('MESSAGE: ', message); if (!latest || message.ts > latest) { latest = message.ts; } @@ -1113,7 +1113,7 @@ export default class SlackAdapter { } copyChannelInfo(rid, channelMap) { - logger.slack.debug('Copying users from Slack channel to Rocket.Chat', channelMap.id, rid); + slackLogger.debug('Copying users from Slack channel to Rocket.Chat', channelMap.id, rid); const channel = this.slackAPI.getRoomInfo(channelMap.id); if (channel) { const members = this.slackAPI.getMembers(channelMap.id); @@ -1121,7 +1121,7 @@ export default class SlackAdapter { for (const member of members) { const user = this.rocket.findUser(member) || this.rocket.addUser(member); if (user) { - logger.slack.debug('Adding user to room', user.username, rid); + slackLogger.debug('Adding user to room', user.username, rid); addUserToRoom(rid, user, null, true); } } @@ -1150,7 +1150,7 @@ export default class SlackAdapter { if (topic) { const creator = this.rocket.findUser(topic_creator) || this.rocket.addUser(topic_creator); - logger.slack.debug('Setting room topic', rid, topic, creator.username); + slackLogger.debug('Setting room topic', rid, topic, creator.username); saveRoomTopic(rid, topic, creator, false); } } @@ -1185,19 +1185,19 @@ export default class SlackAdapter { } importMessages(rid, callback) { - logger.slack.info('importMessages: ', rid); + slackLogger.info('importMessages: ', rid); const rocketchat_room = Rooms.findOneById(rid); if (rocketchat_room) { if (this.getSlackChannel(rid)) { this.copyChannelInfo(rid, this.getSlackChannel(rid)); - logger.slack.debug('Importing messages from Slack to Rocket.Chat', this.getSlackChannel(rid), rid); + slackLogger.debug('Importing messages from Slack to Rocket.Chat', this.getSlackChannel(rid), rid); let results = this.importFromHistory(this.getSlackChannel(rid).family, { channel: this.getSlackChannel(rid).id, oldest: 1 }); while (results && results.has_more) { results = this.importFromHistory(this.getSlackChannel(rid).family, { channel: this.getSlackChannel(rid).id, oldest: results.ts }); } - logger.slack.debug('Pinning Slack channel messages to Rocket.Chat', this.getSlackChannel(rid), rid); + slackLogger.debug('Pinning Slack channel messages to Rocket.Chat', this.getSlackChannel(rid), rid); this.copyPins(rid, this.getSlackChannel(rid)); return callback(); @@ -1207,10 +1207,10 @@ export default class SlackAdapter { this.addSlackChannel(rid, slack_room.id); return this.importMessages(rid, callback); } - logger.slack.error('Could not find Slack room with specified name', rocketchat_room.name); + slackLogger.error('Could not find Slack room with specified name', rocketchat_room.name); return callback(new Meteor.Error('error-slack-room-not-found', 'Could not find Slack room with specified name')); } - logger.slack.error('Could not find Rocket.Chat room with specified id', rid); + slackLogger.error('Could not find Rocket.Chat room with specified id', rid); return callback(new Meteor.Error('error-invalid-room', 'Invalid room')); } } diff --git a/app/slackbridge/server/logger.js b/app/slackbridge/server/logger.js index f8cf66078391..6f25e8015ff3 100644 --- a/app/slackbridge/server/logger.js +++ b/app/slackbridge/server/logger.js @@ -1,11 +1,8 @@ import { Logger } from '../../logger'; -export const logger = new Logger('SlackBridge', { - sections: { - connection: 'Connection', - events: 'Events', - class: 'Class', - slack: 'Slack', - rocket: 'Rocket', - }, -}); +export const logger = new Logger('SlackBridge'); + +export const connLogger = logger.section('Connection'); +export const classLogger = logger.section('Class'); +export const slackLogger = logger.section('Slack'); +export const rocketLogger = logger.section('Rocket'); diff --git a/app/slackbridge/server/slackbridge.js b/app/slackbridge/server/slackbridge.js index 0c3e7b9e6d42..addb0c1a2e9a 100644 --- a/app/slackbridge/server/slackbridge.js +++ b/app/slackbridge/server/slackbridge.js @@ -1,6 +1,6 @@ import SlackAdapter from './SlackAdapter.js'; import RocketAdapter from './RocketAdapter.js'; -import { logger } from './logger'; +import { classLogger, connLogger } from './logger'; import { settings } from '../../settings'; /** @@ -44,7 +44,7 @@ class SlackBridgeClass { } this.connected = true; - logger.connection.info('Enabled'); + connLogger.info('Enabled'); } } @@ -56,7 +56,7 @@ class SlackBridgeClass { }); this.slackAdapters = []; this.connected = false; - logger.connection.info('Disabled'); + connLogger.info('Disabled'); } } @@ -71,25 +71,25 @@ class SlackBridgeClass { } } - logger.class.debug(`Setting: ${ key }`, value); + classLogger.debug(`Setting: ${ key }`, value); }); // Import messages from Slack with an alias; %s is replaced by the username of the user. If empty, no alias will be used. settings.get('SlackBridge_AliasFormat', (key, value) => { this.aliasFormat = value; - logger.class.debug(`Setting: ${ key }`, value); + classLogger.debug(`Setting: ${ key }`, value); }); // Do not propagate messages from bots whose name matches the regular expression above. If left empty, all messages from bots will be propagated. settings.get('SlackBridge_ExcludeBotnames', (key, value) => { this.excludeBotnames = value; - logger.class.debug(`Setting: ${ key }`, value); + classLogger.debug(`Setting: ${ key }`, value); }); // Reactions settings.get('SlackBridge_Reactions_Enabled', (key, value) => { this.isReactionsEnabled = value; - logger.class.debug(`Setting: ${ key }`, value); + classLogger.debug(`Setting: ${ key }`, value); }); // Is this entire SlackBridge enabled @@ -99,7 +99,7 @@ class SlackBridgeClass { } else { this.disconnect(); } - logger.class.debug(`Setting: ${ key }`, value); + classLogger.debug(`Setting: ${ key }`, value); }); } } diff --git a/app/sms/server/services/mobex.js b/app/sms/server/services/mobex.js index 1f41dece2210..a85f1650e65d 100644 --- a/app/sms/server/services/mobex.js +++ b/app/sms/server/services/mobex.js @@ -3,6 +3,7 @@ import { Base64 } from 'meteor/base64'; import { settings } from '../../../settings'; import { SMS } from '../SMS'; +import { SystemLogger } from '../../../../server/lib/logger/system'; class Mobex { constructor() { @@ -27,7 +28,7 @@ class Mobex { } if (isNaN(numMedia)) { - console.error(`Error parsing NumMedia ${ data.NumMedia }`); + SystemLogger.error(`Error parsing NumMedia ${ data.NumMedia }`); return returnData; } @@ -84,7 +85,7 @@ class Mobex { } } catch (e) { result.resultMsg = `Error while sending SMS with Mobex. Detail: ${ e }`; - console.error('Error while sending SMS with Mobex', e); + SystemLogger.error('Error while sending SMS with Mobex', e); } return result; @@ -129,7 +130,7 @@ class Mobex { result.response = response; } catch (e) { result.resultMsg = `Error while sending SMS with Mobex. Detail: ${ e }`; - console.error('Error while sending SMS with Mobex', e); + SystemLogger.error('Error while sending SMS with Mobex', e); } return result; diff --git a/app/sms/server/services/twilio.js b/app/sms/server/services/twilio.js index bf52dcd5491f..eeae457ff694 100644 --- a/app/sms/server/services/twilio.js +++ b/app/sms/server/services/twilio.js @@ -7,6 +7,7 @@ import { settings } from '../../../settings'; import { SMS } from '../SMS'; import { fileUploadIsValidContentType } from '../../../utils/lib/fileUploadRestrictions'; import { api } from '../../../../server/sdk/api'; +import { SystemLogger } from '../../../../server/lib/logger/system'; const MAX_FILE_SIZE = 5242880; @@ -49,7 +50,7 @@ class Twilio { } if (isNaN(numMedia)) { - console.error(`Error parsing NumMedia ${ data.NumMedia }`); + SystemLogger.error(`Error parsing NumMedia ${ data.NumMedia }`); return returnData; } @@ -98,7 +99,7 @@ class Twilio { if (reason) { rid && userId && notifyAgent(userId, rid, reason); - return console.error(`(Twilio) -> ${ reason }`); + return SystemLogger.error(`(Twilio) -> ${ reason }`); } mediaUrl = [publicFilePath]; diff --git a/app/sms/server/services/voxtelesys.js b/app/sms/server/services/voxtelesys.js index 3b0c7dd0ae92..c2b00e59d2e3 100644 --- a/app/sms/server/services/voxtelesys.js +++ b/app/sms/server/services/voxtelesys.js @@ -8,6 +8,7 @@ import { SMS } from '../SMS'; import { fileUploadIsValidContentType } from '../../../utils/lib/fileUploadRestrictions'; import { mime } from '../../../utils/lib/mimeTypes'; import { api } from '../../../../server/sdk/api'; +import { SystemLogger } from '../../../../server/lib/logger/system'; const MAX_FILE_SIZE = 5242880; @@ -79,7 +80,7 @@ class Voxtelesys { if (reason) { rid && userId && notifyAgent(userId, rid, reason); - return console.error(`(Voxtelesys) -> ${ reason }`); + return SystemLogger.error(`(Voxtelesys) -> ${ reason }`); } media = [publicFilePath]; @@ -100,7 +101,7 @@ class Voxtelesys { try { HTTP.call('POST', this.URL || 'https://smsapi.voxtelesys.net/api/v1/sms', options); } catch (error) { - console.error(`Error connecting to Voxtelesys SMS API: ${ error }`); + SystemLogger.error(`Error connecting to Voxtelesys SMS API: ${ error }`); } } diff --git a/app/theme/client/imports/general/base_old.css b/app/theme/client/imports/general/base_old.css index 0139ed9abd3e..fdedb50d4faa 100644 --- a/app/theme/client/imports/general/base_old.css +++ b/app/theme/client/imports/general/base_old.css @@ -62,14 +62,6 @@ content: ""; } - &:first-child { - margin-top: 4px; - } - - &:last-child { - margin-bottom: 4px; - } - &:first-child::before { border-radius: 2px 2px 0 0; } diff --git a/app/theme/server/server.js b/app/theme/server/server.js index b1a55d40ac20..fbdc4fcee936 100644 --- a/app/theme/server/server.js +++ b/app/theme/server/server.js @@ -10,13 +10,7 @@ import { settings } from '../../settings'; import { Logger } from '../../logger'; import { addStyle } from '../../ui-master/server/inject'; -const logger = new Logger('rocketchat:theme', { - methods: { - stop_rendering: { - type: 'info', - }, - }, -}); +const logger = new Logger('rocketchat:theme'); let currentHash = ''; let currentSize = 0; @@ -69,9 +63,9 @@ export const theme = new class { }; const start = Date.now(); return less.render(content, options, function(err, data) { - logger.stop_rendering(Date.now() - start); + logger.info({ stop_rendering: Date.now() - start }); if (err != null) { - return console.log(err); + return logger.error(err); } settings.updateById('css', data.css); diff --git a/app/threads/client/components/ThreadComponent.tsx b/app/threads/client/components/ThreadComponent.tsx index 5af90e6c875b..6e30d2d57cdf 100644 --- a/app/threads/client/components/ThreadComponent.tsx +++ b/app/threads/client/components/ThreadComponent.tsx @@ -16,18 +16,16 @@ import ThreadView from './ThreadView'; import { IMessage } from '../../../../definition/IMessage'; import { IRoom } from '../../../../definition/IRoom'; import { useTabBarOpenUserInfo } from '../../../../client/views/room/providers/ToolboxProvider'; +import { mapMessageFromApi } from '../../../../client/lib/fromApi'; const subscriptionFields = {}; const useThreadMessage = (tmid: string): IMessage => { const [message, setMessage] = useState(() => Tracker.nonreactive(() => ChatMessage.findOne({ _id: tmid }))); const getMessage = useEndpoint('GET', 'chat.getMessage'); - const getMessageParsed = useCallback<(params: Parameters[0]) => Promise>(async (params) => { + const getMessageParsed = useCallback<(params: { msgId: IMessage['_id'] }) => Promise>(async (params) => { const { message } = await getMessage(params); - return { - ...message, - _updatedAt: new Date(message._updatedAt), - }; + return mapMessageFromApi(message); }, [getMessage]); useEffect(() => { diff --git a/app/utils/lib/getUserNotificationPreference.js b/app/utils/lib/getUserNotificationPreference.js index ce80cd5befbb..bab787117d6f 100644 --- a/app/utils/lib/getUserNotificationPreference.js +++ b/app/utils/lib/getUserNotificationPreference.js @@ -10,7 +10,7 @@ export const getUserNotificationPreference = (user, pref) => { switch (pref) { case 'audio': preferenceKey = 'audioNotifications'; break; case 'desktop': preferenceKey = 'desktopNotifications'; break; - case 'mobile': preferenceKey = 'mobileNotifications'; break; + case 'mobile': preferenceKey = 'pushNotifications'; break; case 'email': preferenceKey = 'emailNotificationMode'; break; } diff --git a/app/utils/lib/templateVarHandler.js b/app/utils/lib/templateVarHandler.js index 463a48ed34e3..dba5cdef43bf 100644 --- a/app/utils/lib/templateVarHandler.js +++ b/app/utils/lib/templateVarHandler.js @@ -3,8 +3,8 @@ import { Meteor } from 'meteor/meteor'; let logger; if (Meteor.isServer) { - const { Logger } = require('../../logger/server/server'); - logger = new Logger('TemplateVarHandler', {}); + const { Logger } = require('../../../server/lib/logger/Logger'); + logger = new Logger('TemplateVarHandler'); } export const templateVarHandler = function(variable, object) { diff --git a/app/videobridge/server/methods/bbb.js b/app/videobridge/server/methods/bbb.js index 3695cc389cd3..4721dc9842ce 100644 --- a/app/videobridge/server/methods/bbb.js +++ b/app/videobridge/server/methods/bbb.js @@ -3,9 +3,10 @@ import { HTTP } from 'meteor/http'; import xml2js from 'xml2js'; import BigBlueButtonApi from '../../../bigbluebutton/server'; -import { settings } from '../../../settings'; -import { Rooms, Users } from '../../../models'; -import { saveStreamingOptions } from '../../../channel-settings'; +import { SystemLogger } from '../../../../server/lib/logger/system'; +import { settings } from '../../../settings/server'; +import { Rooms, Users } from '../../../models/server'; +import { saveStreamingOptions } from '../../../channel-settings/server'; import { API } from '../../../api/server'; const parser = new xml2js.Parser({ @@ -66,7 +67,7 @@ Meteor.methods({ if (hookResult.statusCode !== 200) { // TODO improve error logging - console.log({ hookResult }); + SystemLogger.error(hookResult); return; } @@ -130,7 +131,7 @@ API.v1.addRoute('videoconference.bbb.update/:id', { authRequired: false }, { const meetingID = event.data.attributes.meeting['external-meeting-id']; const rid = meetingID.replace(settings.get('uniqueID'), ''); - console.log(eventType, rid); + SystemLogger.debug(eventType, rid); if (eventType === 'meeting-ended') { saveStreamingOptions(rid, {}); @@ -147,14 +148,14 @@ API.v1.addRoute('videoconference.bbb.update/:id', { authRequired: false }, { // if (getMeetingInfoResult.statusCode !== 200) { // // TODO improve error logging - // console.log({ getMeetingInfoResult }); + // SystemLogger.error({ getMeetingInfoResult }); // } // const doc = parseString(getMeetingInfoResult.content); // if (doc.response.returncode[0]) { // const participantCount = parseInt(doc.response.participantCount[0]); - // console.log(participantCount); + // SystemLogger.debug(participantCount); // } // } }, diff --git a/app/videobridge/server/methods/jitsiSetTimeout.js b/app/videobridge/server/methods/jitsiSetTimeout.js index 3f630067d222..bfb109efd322 100644 --- a/app/videobridge/server/methods/jitsiSetTimeout.js +++ b/app/videobridge/server/methods/jitsiSetTimeout.js @@ -6,7 +6,7 @@ import { callbacks } from '../../../callbacks/server'; import { metrics } from '../../../metrics/server'; import * as CONSTANTS from '../../constants'; import { canSendMessage } from '../../../authorization/server'; -import { SystemLogger } from '../../../logger/server'; +import { SystemLogger } from '../../../../server/lib/logger/system'; Meteor.methods({ 'jitsi:updateTimeout': (rid, joiningNow = true) => { diff --git a/app/webdav/server/methods/uploadFileToWebdav.ts b/app/webdav/server/methods/uploadFileToWebdav.ts index b818579dcf1d..345550285e7f 100644 --- a/app/webdav/server/methods/uploadFileToWebdav.ts +++ b/app/webdav/server/methods/uploadFileToWebdav.ts @@ -6,7 +6,7 @@ import { getWebdavCredentials } from './getWebdavCredentials'; import { WebdavAccounts } from '../../../models/server'; import { WebdavClientAdapter } from '../lib/webdavClientAdapter'; -const logger = new Logger('WebDAV_Upload', {}); +const logger = new Logger('WebDAV_Upload'); Meteor.methods({ async uploadFileToWebdav(accountId, fileData, name) { diff --git a/client/components/CreateDiscussion/CreateDiscussion.tsx b/client/components/CreateDiscussion/CreateDiscussion.tsx index c936e0d3ba70..c792e2348fa8 100644 --- a/client/components/CreateDiscussion/CreateDiscussion.tsx +++ b/client/components/CreateDiscussion/CreateDiscussion.tsx @@ -17,7 +17,7 @@ import { IMessage } from '../../../definition/IMessage'; import { IRoom } from '../../../definition/IRoom'; import { IUser } from '../../../definition/IUser'; import { useTranslation } from '../../contexts/TranslationContext'; -import { useEndpointActionExperimental } from '../../hooks/useEndpointAction'; +import { useEndpointActionExperimental } from '../../hooks/useEndpointActionExperimental'; import { useForm } from '../../hooks/useForm'; import { goToRoomById } from '../../lib/goToRoomById'; import RoomAutoComplete from '../RoomAutoComplete'; @@ -76,7 +76,7 @@ const CreateDiscussion = ({ ...(parentMessageId && { pmid: parentMessageId }), }); - goToRoomById(result?.discussion?.rid); + goToRoomById(result.discussion._id); onClose(); } catch (error) { console.warn(error); diff --git a/client/components/Message/Attachments/QuoteAttachment.tsx b/client/components/Message/Attachments/QuoteAttachment.tsx index acbabe4f9b65..f8413028553c 100644 --- a/client/components/Message/Attachments/QuoteAttachment.tsx +++ b/client/components/Message/Attachments/QuoteAttachment.tsx @@ -57,7 +57,7 @@ export const QuoteAttachment: FC = ({ {attachments && ( - + )} diff --git a/client/contexts/ServerContext/ServerContext.ts b/client/contexts/ServerContext/ServerContext.ts index 8467dccad400..6e38e849f332 100644 --- a/client/contexts/ServerContext/ServerContext.ts +++ b/client/contexts/ServerContext/ServerContext.ts @@ -1,13 +1,7 @@ import { createContext, useCallback, useContext, useMemo } from 'react'; -import { - ServerEndpointMethodOf, - ServerEndpointPath, - ServerEndpointFunction, - ServerEndpointRequestPayload, - ServerEndpointFormData, - ServerEndpointResponsePayload, -} from './endpoints'; +import type { Serialized } from '../../../definition/Serialized'; +import type { PathFor, Params, Return, Method } from './endpoints'; import { ServerMethodFunction, ServerMethodName, @@ -23,12 +17,11 @@ type ServerContextValue = { methodName: MethodName, ...args: ServerMethodParameters ) => Promise>; - callEndpoint?: , Path extends ServerEndpointPath>( - httpMethod: Method, - endpoint: Path, - params: ServerEndpointRequestPayload, - formData?: ServerEndpointFormData, - ) => Promise>; + callEndpoint: >( + method: M, + path: P, + params: Params[0], + ) => Promise>>; uploadToEndpoint: (endpoint: string, params: any, formData: any) => Promise; getStream: ( streamName: string, @@ -39,6 +32,9 @@ type ServerContextValue = { export const ServerContext = createContext({ info: {}, absoluteUrl: (path) => path, + callEndpoint: () => { + throw new Error('not implemented'); + }, uploadToEndpoint: async () => undefined, getStream: () => () => (): void => undefined, }); @@ -67,30 +63,13 @@ export const useMethod = ( ); }; -export const useEndpoint = < - Method extends ServerEndpointMethodOf, - Path extends ServerEndpointPath, ->( - httpMethod: Method, - endpoint: Path, -): ServerEndpointFunction => { +export const useEndpoint = >( + method: M, + path: P, +): ((params: Params[0]) => Promise>>) => { const { callEndpoint } = useContext(ServerContext); - return useCallback( - ( - params: ServerEndpointRequestPayload, - formData?: ServerEndpointFormData, - ) => { - if (!callEndpoint) { - throw new Error( - `cannot use useEndpoint(${httpMethod}, ${endpoint}) hook without a wrapping ServerContext`, - ); - } - - return callEndpoint(httpMethod, endpoint, params, formData); - }, - [callEndpoint, endpoint, httpMethod], - ); + return useCallback((params) => callEndpoint(method, path, params), [callEndpoint, path, method]); }; export const useUpload = (endpoint: string): ((params: any, formData: any) => Promise) => { diff --git a/client/contexts/ServerContext/endpoints.ts b/client/contexts/ServerContext/endpoints.ts index 774c37f4d121..7b0bc1bc24c1 100644 --- a/client/contexts/ServerContext/endpoints.ts +++ b/client/contexts/ServerContext/endpoints.ts @@ -1,122 +1,79 @@ -import { EngagementDashboardActiveUsersEndpoint } from '../../../ee/app/engagement-dashboard/client/contexts/ServerContext/endpoints/EngagementDashboardActiveUsers'; -import { ExternalComponentsEndpoint as AppsExternalComponentsEndpoint } from './endpoints/apps/externalComponents'; -import { FilesEndpoint as ChannelsFilesEndpoint } from './endpoints/v1/channels/files'; -import { ChannelsMembersEndpoint } from './endpoints/v1/channels/members'; -import { FollowMessageEndpoint as ChatFollowMessageEndpoint } from './endpoints/v1/chat/followMessage'; -import { GetDiscussionsEndpoint as ChatGetDiscussionsEndpoint } from './endpoints/v1/chat/getDiscussions'; -import { GetMessageEndpoint as ChatGetMessageEndpoint } from './endpoints/v1/chat/getMessage'; -import { GetThreadsListEndpoint as ChatGetThreadsListEndpoint } from './endpoints/v1/chat/getThreadsList'; -import { UnfollowMessageEndpoint as ChatUnfollowMessageEndpoint } from './endpoints/v1/chat/unfollowMessage'; -import { ManualRegisterEndpoint as CloudManualRegisterEndpoint } from './endpoints/v1/cloud/manualRegister'; -import { ListEndpoint as CustomUserStatusListEndpoint } from './endpoints/v1/custom-user-status/list'; -import { ResolveSrvEndpoint } from './endpoints/v1/dns/resolve.srv'; -import { ResolveTxtEndpoint } from './endpoints/v1/dns/resolve.txt'; -import { ListEndpoint as EmojiCustomListEndpoint } from './endpoints/v1/emoji-custom/list'; -import { FilesEndpoint as GroupsFilesEndpoint } from './endpoints/v1/groups/files'; -import { GroupsMembersEndpoint } from './endpoints/v1/groups/members'; -import { FilesEndpoint as ImFilesEndpoint } from './endpoints/v1/im/files'; -import { ImMembersEndpoint } from './endpoints/v1/im/members'; -import { AppearanceEndpoint as LivechatAppearanceEndpoint } from './endpoints/v1/livechat/appearance'; -import { LivechatCustomFieldsEndpoint } from './endpoints/v1/livechat/customFields'; -import { LivechatDepartment } from './endpoints/v1/livechat/department'; -import { LivechatDepartmentSingle } from './endpoints/v1/livechat/departmentSingle'; -import { LivechatDepartmentsByUnit } from './endpoints/v1/livechat/departmentsByUnit'; -import { LivechatMonitorsList } from './endpoints/v1/livechat/monitorsList'; -import { LivechatRoomOnHoldEndpoint } from './endpoints/v1/livechat/onHold'; -import { LivechatRoomsEndpoint } from './endpoints/v1/livechat/rooms'; -import { LivechatTagsList } from './endpoints/v1/livechat/tagsList'; -import { LivechatUsersAgentEndpoint } from './endpoints/v1/livechat/usersAgent'; -import { LivechatVisitorInfoEndpoint } from './endpoints/v1/livechat/visitorInfo'; -import { CannedResponseEndpoint } from './endpoints/v1/omnichannel/cannedResponse'; -import { CannedResponsesEndpoint } from './endpoints/v1/omnichannel/cannedResponses'; -import { AutocompleteAvailableForTeamsEndpoint as RoomsAutocompleteTeamsEndpoint } from './endpoints/v1/rooms/autocompleteAvailableForTeams'; -import { AutocompleteChannelAndPrivateEndpoint as RoomsAutocompleteEndpoint } from './endpoints/v1/rooms/autocompleteChannelAndPrivate'; -import { AutocompleteChannelAndPrivateEndpointWithPagination as RoomsAutocompleteEndpointWithPagination } from './endpoints/v1/rooms/autocompleteChannelAndPrivateWithPagination'; -import { RoomsInfo as RoomsInfoEndpoint } from './endpoints/v1/rooms/roomsInfo'; -import { AddRoomsEndpoint as TeamsAddRoomsEndpoint } from './endpoints/v1/teams/addRooms'; -import { ListRoomsEndpoint } from './endpoints/v1/teams/listRooms'; -import { ListRoomsOfUserEndpoint } from './endpoints/v1/teams/listRoomsOfUser'; -import { AutocompleteEndpoint as UsersAutocompleteEndpoint } from './endpoints/v1/users/autocomplete'; -import { SendEmailCodeEndpoint } from './endpoints/v1/users/twoFactorAuth/sendEmailCode'; +import type { ExtractKeys, ValueOf } from '../../../definition/utils'; +import type { EngagementDashboardEndpoints } from '../../../ee/client/contexts/ServerContext/endpoints/v1/engagementDashboard'; +import type { AppsEndpoints } from './endpoints/apps'; +import type { ChannelsEndpoints } from './endpoints/v1/channels'; +import type { ChatEndpoints } from './endpoints/v1/chat'; +import type { CloudEndpoints } from './endpoints/v1/cloud'; +import type { CustomUserStatusEndpoints } from './endpoints/v1/customUserStatus'; +import type { DmEndpoints } from './endpoints/v1/dm'; +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 { OmnichannelEndpoints } from './endpoints/v1/omnichannel'; +import type { RoomsEndpoints } from './endpoints/v1/rooms'; +import type { TeamsEndpoints } from './endpoints/v1/teams'; +import type { UsersEndpoints } from './endpoints/v1/users'; -export type ServerEndpoints = { - 'chat.getMessage': ChatGetMessageEndpoint; - 'chat.followMessage': ChatFollowMessageEndpoint; - 'chat.unfollowMessage': ChatUnfollowMessageEndpoint; - 'cloud.manualRegister': CloudManualRegisterEndpoint; - 'chat.getDiscussions': ChatGetDiscussionsEndpoint; - 'chat.getThreadsList': ChatGetThreadsListEndpoint; - 'dns.resolve.srv': ResolveSrvEndpoint; - 'dns.resolve.txt': ResolveTxtEndpoint; - 'emoji-custom.list': EmojiCustomListEndpoint; - 'channels.files': ChannelsFilesEndpoint; - 'im.files': ImFilesEndpoint; - 'im.members': ImMembersEndpoint; - 'groups.files': GroupsFilesEndpoint; - 'groups.members': GroupsMembersEndpoint; - 'channels.members': ChannelsMembersEndpoint; - 'users.autocomplete': UsersAutocompleteEndpoint; - 'livechat/appearance': LivechatAppearanceEndpoint; - 'custom-user-status.list': CustomUserStatusListEndpoint; - '/apps/externalComponents': AppsExternalComponentsEndpoint; - 'rooms.autocomplete.channelAndPrivate': RoomsAutocompleteEndpoint; - 'rooms.autocomplete.channelAndPrivate.withPagination': RoomsAutocompleteEndpointWithPagination; - 'rooms.autocomplete.availableForTeams': RoomsAutocompleteTeamsEndpoint; - 'teams.listRooms': ListRoomsEndpoint; - 'teams.listRoomsOfUser': ListRoomsOfUserEndpoint; - 'teams.addRooms': TeamsAddRoomsEndpoint; - 'livechat/visitors.info': LivechatVisitorInfoEndpoint; - 'livechat/room.onHold': LivechatRoomOnHoldEndpoint; - 'livechat/monitors.list': LivechatMonitorsList; - 'livechat/tags.list': LivechatTagsList; - 'livechat/department': LivechatDepartment; - 'livechat/department/${string}': LivechatDepartmentSingle; - 'livechat/departments.by-unit/': LivechatDepartmentsByUnit; - 'engagement-dashboard/users/active-users': EngagementDashboardActiveUsersEndpoint; - 'rooms.info': RoomsInfoEndpoint; - 'users.2fa.sendEmailCode': SendEmailCodeEndpoint; - 'livechat/custom-fields': LivechatCustomFieldsEndpoint; - 'livechat/rooms': LivechatRoomsEndpoint; - 'livechat/users/agent': LivechatUsersAgentEndpoint; - 'canned-responses': CannedResponsesEndpoint; - 'canned-responses/${string}': CannedResponseEndpoint; -}; +type Endpoints = ChatEndpoints & + ChannelsEndpoints & + CloudEndpoints & + CustomUserStatusEndpoints & + DmEndpoints & + DnsEndpoints & + EmojiCustomEndpoints & + GroupsEndpoints & + ImEndpoints & + RoomsEndpoints & + TeamsEndpoints & + UsersEndpoints & + EngagementDashboardEndpoints & + AppsEndpoints & + OmnichannelEndpoints; -export type ServerEndpointPath = keyof ServerEndpoints; -export type ServerEndpointMethodOf = keyof ServerEndpoints[Path] & - ('GET' | 'POST' | 'DELETE'); +type Endpoint = UnionizeEndpoints; -type ServerEndpoint< - Method extends ServerEndpointMethodOf, - Path extends ServerEndpointPath, -> = ServerEndpoints[Path][Method] extends (...args: any[]) => any - ? ServerEndpoints[Path][Method] - : (...args: any[]) => any; +type UnionizeEndpoints = ValueOf< + { + [P in keyof EE]: UnionizeMethods; + } +>; -export type ServerEndpointRequestPayload< - Method extends ServerEndpointMethodOf, - Path extends ServerEndpointPath, -> = Parameters>[0]; +type ExtractOperations = ExtractKeys any>; -export type ServerEndpointFormData< - Method extends ServerEndpointMethodOf, - Path extends ServerEndpointPath, -> = Parameters>[1]; +type UnionizeMethods = ValueOf< + { + [M in keyof OO as ExtractOperations]: ( + method: M, + path: OO extends { path: string } ? OO['path'] : P, + ...params: Parameters any>> + ) => ReturnType any>>; + } +>; -export type ServerEndpointResponsePayload< - Method extends ServerEndpointMethodOf, - Path extends ServerEndpointPath, -> = ReturnType>; +export type Method = Parameters[0]; +export type Path = Parameters[1]; -export type ServerEndpointFunction< - Method extends ServerEndpointMethodOf, - Path extends ServerEndpointPath, -> = { - (params: ServerEndpointRequestPayload): Promise< - ServerEndpointResponsePayload - >; - ( - params: ServerEndpointRequestPayload, - formData: ServerEndpointFormData, - ): Promise>; -}; +export type MethodFor

= P extends any + ? Parameters any>>[0] + : never; +export type PathFor = M extends any + ? Parameters any>>[1] + : never; + +type Operation> = M extends any + ? P extends any + ? Extract any> + : never + : never; + +type ExtractParams = Q extends [any, any] + ? [undefined?] + : Q extends [any, any, any, ...any[]] + ? [Q[2]] + : never; + +export type Params> = ExtractParams< + Parameters> +>; +export type Return> = ReturnType>; diff --git a/client/contexts/ServerContext/endpoints/apps.ts b/client/contexts/ServerContext/endpoints/apps.ts new file mode 100644 index 000000000000..58410ae1012c --- /dev/null +++ b/client/contexts/ServerContext/endpoints/apps.ts @@ -0,0 +1,7 @@ +import type { IExternalComponent } from '@rocket.chat/apps-engine/definition/externalComponent'; + +export type AppsEndpoints = { + '/apps/externalComponents': { + GET: () => { externalComponents: IExternalComponent[] }; + }; +}; diff --git a/client/contexts/ServerContext/endpoints/apps/externalComponents.ts b/client/contexts/ServerContext/endpoints/apps/externalComponents.ts deleted file mode 100644 index 8367ebdd6a19..000000000000 --- a/client/contexts/ServerContext/endpoints/apps/externalComponents.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { IExternalComponent } from '@rocket.chat/apps-engine/definition/externalComponent'; - -export type ExternalComponentsEndpoint = { - GET: (params: Record) => { externalComponents: IExternalComponent[] }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/channels.ts b/client/contexts/ServerContext/endpoints/v1/channels.ts new file mode 100644 index 000000000000..0e2abbf7751c --- /dev/null +++ b/client/contexts/ServerContext/endpoints/v1/channels.ts @@ -0,0 +1,32 @@ +import type { IMessage } from '../../../../../definition/IMessage/IMessage'; +import type { IRoom } from '../../../../../definition/IRoom'; +import type { IUser } from '../../../../../definition/IUser'; + +export type ChannelsEndpoints = { + 'channels.files': { + GET: (params: { + roomId: IRoom['_id']; + offset: number; + count: number; + sort: string; + query: string; + }) => { + files: IMessage[]; + total: number; + }; + }; + 'channels.members': { + GET: (params: { + roomId: IRoom['_id']; + offset?: number; + count?: number; + filter?: string; + status?: string[]; + }) => { + count: number; + offset: number; + members: IUser[]; + total: number; + }; + }; +}; diff --git a/client/contexts/ServerContext/endpoints/v1/channels/files.ts b/client/contexts/ServerContext/endpoints/v1/channels/files.ts deleted file mode 100644 index 31e49187ea75..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/channels/files.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { IMessage } from '../../../../../../definition/IMessage/IMessage'; -import { IRoom } from '../../../../../../definition/IRoom'; -import { ObjectFromApi } from '../../../../../../definition/ObjectFromApi'; - -export type FilesEndpoint = { - GET: (params: { - roomId: IRoom['_id']; - offset: number; - count: number; - sort: string; - query: string; - }) => { - files: ObjectFromApi[]; - total: number; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/channels/members.ts b/client/contexts/ServerContext/endpoints/v1/channels/members.ts deleted file mode 100644 index 4bea17737b48..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/channels/members.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { IUser } from '../../../../../../definition/IUser'; - -export type ChannelsMembersEndpoint = { - GET: (params: { - roomId: string; - offset?: number; - count?: number; - filter?: string; - status?: Array; - }) => { - count: number; - offset: number; - members: Array; - total: number; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/chat.ts b/client/contexts/ServerContext/endpoints/v1/chat.ts new file mode 100644 index 000000000000..0ed5c1e02980 --- /dev/null +++ b/client/contexts/ServerContext/endpoints/v1/chat.ts @@ -0,0 +1,34 @@ +import type { IMessage } from '../../../../../definition/IMessage'; +import type { IRoom } from '../../../../../definition/IRoom'; + +export type ChatEndpoints = { + 'chat.getMessage': { + GET: (params: { msgId: IMessage['_id'] }) => { + message: IMessage; + }; + }; + 'chat.followMessage': { + POST: (params: { mid: IMessage['_id'] }) => void; + }; + 'chat.unfollowMessage': { + POST: (params: { mid: IMessage['_id'] }) => void; + }; + 'chat.getDiscussions': { + GET: (params: { roomId: IRoom['_id']; text?: string; offset: number; count: number }) => { + messages: IMessage[]; + total: number; + }; + }; + 'chat.getThreadsList': { + GET: (params: { + rid: IRoom['_id']; + type: 'unread' | 'following' | 'all'; + text?: string; + offset: number; + count: number; + }) => { + threads: IMessage[]; + total: number; + }; + }; +}; diff --git a/client/contexts/ServerContext/endpoints/v1/chat/followMessage.ts b/client/contexts/ServerContext/endpoints/v1/chat/followMessage.ts deleted file mode 100644 index 8a31f7bbd5c4..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/chat/followMessage.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { IMessage } from '../../../../../../definition/IMessage'; - -export type FollowMessageEndpoint = { - POST: (params: { mid: IMessage['_id'] }) => { - success: true; - statusCode: 200; - body: {}; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/chat/getDiscussions.ts b/client/contexts/ServerContext/endpoints/v1/chat/getDiscussions.ts deleted file mode 100644 index b12b141cb954..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/chat/getDiscussions.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { IMessage } from '../../../../../../definition/IMessage'; -import { IRoom } from '../../../../../../definition/IRoom'; -import { ObjectFromApi } from '../../../../../../definition/ObjectFromApi'; - -export type GetDiscussionsEndpoint = { - GET: (params: { roomId: IRoom['_id']; text?: string; offset: number; count: number }) => { - messages: ObjectFromApi[]; - total: number; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/chat/getMessage.ts b/client/contexts/ServerContext/endpoints/v1/chat/getMessage.ts deleted file mode 100644 index ac868502ef5e..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/chat/getMessage.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { IMessage } from '../../../../../../definition/IMessage'; - -export type GetMessageEndpoint = { - GET: (params: { msgId: IMessage['_id'] }) => { - message: IMessage; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/chat/getThreadsList.ts b/client/contexts/ServerContext/endpoints/v1/chat/getThreadsList.ts deleted file mode 100644 index 6e9b9b0d46a7..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/chat/getThreadsList.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { IMessage } from '../../../../../../definition/IMessage'; -import { IRoom } from '../../../../../../definition/IRoom'; -import { ObjectFromApi } from '../../../../../../definition/ObjectFromApi'; - -export type GetThreadsListEndpoint = { - GET: (params: { - rid: IRoom['_id']; - type: 'unread' | 'following' | 'all'; - text?: string; - offset: number; - count: number; - }) => { - threads: ObjectFromApi[]; - total: number; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/chat/unfollowMessage.ts b/client/contexts/ServerContext/endpoints/v1/chat/unfollowMessage.ts deleted file mode 100644 index 0814dcc2be28..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/chat/unfollowMessage.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { IMessage } from '../../../../../../definition/IMessage'; - -export type UnfollowMessageEndpoint = { - POST: (params: { mid: IMessage['_id'] }) => { - success: true; - statusCode: 200; - body: {}; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/cloud.ts b/client/contexts/ServerContext/endpoints/v1/cloud.ts new file mode 100644 index 000000000000..31bfee7f03f0 --- /dev/null +++ b/client/contexts/ServerContext/endpoints/v1/cloud.ts @@ -0,0 +1,5 @@ +export type CloudEndpoints = { + 'cloud.manualRegister': { + POST: (params: { cloudBlob: string }) => void; + }; +}; diff --git a/client/contexts/ServerContext/endpoints/v1/cloud/manualRegister.ts b/client/contexts/ServerContext/endpoints/v1/cloud/manualRegister.ts deleted file mode 100644 index 77db549901a7..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/cloud/manualRegister.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type ManualRegisterEndpoint = { - POST: (params: Record, formData: { cloudBlob: string }) => void; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/custom-user-status/list.ts b/client/contexts/ServerContext/endpoints/v1/custom-user-status/list.ts deleted file mode 100644 index aa81cfe70469..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/custom-user-status/list.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type ListEndpoint = { - GET: (params: { query: string }) => { - statuses: unknown[]; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/customUserStatus.ts b/client/contexts/ServerContext/endpoints/v1/customUserStatus.ts new file mode 100644 index 000000000000..db5e76ee4f7a --- /dev/null +++ b/client/contexts/ServerContext/endpoints/v1/customUserStatus.ts @@ -0,0 +1,7 @@ +export type CustomUserStatusEndpoints = { + 'custom-user-status.list': { + GET: (params: { query: string }) => { + statuses: unknown[]; + }; + }; +}; diff --git a/client/contexts/ServerContext/endpoints/v1/dm.ts b/client/contexts/ServerContext/endpoints/v1/dm.ts new file mode 100644 index 000000000000..0b20aad1819c --- /dev/null +++ b/client/contexts/ServerContext/endpoints/v1/dm.ts @@ -0,0 +1,21 @@ +import type { IRoom } from '../../../../../definition/IRoom'; +import type { IUser } from '../../../../../definition/IUser'; + +export type DmEndpoints = { + 'dm.create': { + POST: ( + params: ( + | { + username: Exclude; + } + | { + usernames: string; + } + ) & { + excludeSelf?: boolean; + }, + ) => { + room: IRoom & { rid: IRoom['_id'] }; + }; + }; +}; diff --git a/client/contexts/ServerContext/endpoints/v1/dns.ts b/client/contexts/ServerContext/endpoints/v1/dns.ts new file mode 100644 index 000000000000..136e8d698a98 --- /dev/null +++ b/client/contexts/ServerContext/endpoints/v1/dns.ts @@ -0,0 +1,12 @@ +export type DnsEndpoints = { + 'dns.resolve.srv': { + GET: (params: { url: string }) => { + resolved: Record; + }; + }; + 'dns.resolve.txt': { + GET: (params: { url: string }) => { + resolved: Record; + }; + }; +}; diff --git a/client/contexts/ServerContext/endpoints/v1/dns/resolve.srv.ts b/client/contexts/ServerContext/endpoints/v1/dns/resolve.srv.ts deleted file mode 100644 index e773864064e9..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/dns/resolve.srv.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type ResolveSrvEndpoint = { - GET: (params: { url: string }) => { - resolved: Record; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/dns/resolve.txt.ts b/client/contexts/ServerContext/endpoints/v1/dns/resolve.txt.ts deleted file mode 100644 index 56cea2196f8b..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/dns/resolve.txt.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type ResolveTxtEndpoint = { - GET: (params: { url: string }) => { - resolved: Record; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/emoji-custom/list.ts b/client/contexts/ServerContext/endpoints/v1/emoji-custom/list.ts deleted file mode 100644 index ca83af01bc83..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/emoji-custom/list.ts +++ /dev/null @@ -1,14 +0,0 @@ -type EmojiDescriptor = { - _id: string; - name: string; - aliases: string[]; - extension: string; -}; - -export type ListEndpoint = { - GET: (params: { query: string }) => { - emojis?: { - update: EmojiDescriptor[]; - }; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/emojiCustom.ts b/client/contexts/ServerContext/endpoints/v1/emojiCustom.ts new file mode 100644 index 000000000000..63648e6f3e26 --- /dev/null +++ b/client/contexts/ServerContext/endpoints/v1/emojiCustom.ts @@ -0,0 +1,14 @@ +import type { ICustomEmojiDescriptor } from '../../../../../definition/ICustomEmojiDescriptor'; + +export type EmojiCustomEndpoints = { + 'emoji-custom.list': { + GET: (params: { query: string }) => { + emojis?: { + update: ICustomEmojiDescriptor[]; + }; + }; + }; + 'emoji-custom.delete': { + POST: (params: { emojiId: ICustomEmojiDescriptor['_id'] }) => void; + }; +}; diff --git a/client/contexts/ServerContext/endpoints/v1/groups.ts b/client/contexts/ServerContext/endpoints/v1/groups.ts new file mode 100644 index 000000000000..5b01d443d451 --- /dev/null +++ b/client/contexts/ServerContext/endpoints/v1/groups.ts @@ -0,0 +1,26 @@ +import type { IMessage } from '../../../../../definition/IMessage'; +import type { IRoom } from '../../../../../definition/IRoom'; +import type { IUser } from '../../../../../definition/IUser'; + +export type GroupsEndpoints = { + 'groups.files': { + GET: (params: { roomId: IRoom['_id']; count: number; sort: string; query: string }) => { + files: IMessage[]; + total: number; + }; + }; + 'groups.members': { + GET: (params: { + roomId: IRoom['_id']; + offset?: number; + count?: number; + filter?: string; + status?: string[]; + }) => { + count: number; + offset: number; + members: IUser[]; + total: number; + }; + }; +}; diff --git a/client/contexts/ServerContext/endpoints/v1/groups/files.ts b/client/contexts/ServerContext/endpoints/v1/groups/files.ts deleted file mode 100644 index 9f3f7c66f2c5..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/groups/files.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { IMessage } from '../../../../../../definition/IMessage'; -import { IRoom } from '../../../../../../definition/IRoom'; -import { ObjectFromApi } from '../../../../../../definition/ObjectFromApi'; - -export type FilesEndpoint = { - GET: (params: { roomId: IRoom['_id']; count: number; sort: string; query: string }) => { - files: ObjectFromApi[]; - total: number; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/groups/members.ts b/client/contexts/ServerContext/endpoints/v1/groups/members.ts deleted file mode 100644 index 83ee648f2535..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/groups/members.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { ChannelsMembersEndpoint } from '../channels/members'; - -export type GroupsMembersEndpoint = ChannelsMembersEndpoint; diff --git a/client/contexts/ServerContext/endpoints/v1/im.ts b/client/contexts/ServerContext/endpoints/v1/im.ts new file mode 100644 index 000000000000..700cdecfda44 --- /dev/null +++ b/client/contexts/ServerContext/endpoints/v1/im.ts @@ -0,0 +1,42 @@ +import type { IMessage } from '../../../../../definition/IMessage'; +import type { IRoom } from '../../../../../definition/IRoom'; +import type { IUser } from '../../../../../definition/IUser'; + +export type ImEndpoints = { + 'im.create': { + POST: ( + params: ( + | { + username: Exclude; + } + | { + usernames: string; + } + ) & { + excludeSelf?: boolean; + }, + ) => { + room: IRoom; + }; + }; + 'im.files': { + GET: (params: { roomId: IRoom['_id']; count: number; sort: string; query: string }) => { + files: IMessage[]; + total: number; + }; + }; + 'im.members': { + GET: (params: { + roomId: IRoom['_id']; + offset?: number; + count?: number; + filter?: string; + status?: string[]; + }) => { + count: number; + offset: number; + members: IUser[]; + total: number; + }; + }; +}; diff --git a/client/contexts/ServerContext/endpoints/v1/im/files.ts b/client/contexts/ServerContext/endpoints/v1/im/files.ts deleted file mode 100644 index 9f3f7c66f2c5..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/im/files.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { IMessage } from '../../../../../../definition/IMessage'; -import { IRoom } from '../../../../../../definition/IRoom'; -import { ObjectFromApi } from '../../../../../../definition/ObjectFromApi'; - -export type FilesEndpoint = { - GET: (params: { roomId: IRoom['_id']; count: number; sort: string; query: string }) => { - files: ObjectFromApi[]; - total: number; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/im/members.ts b/client/contexts/ServerContext/endpoints/v1/im/members.ts deleted file mode 100644 index eeb6c42802d4..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/im/members.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { ChannelsMembersEndpoint } from '../channels/members'; - -export type ImMembersEndpoint = ChannelsMembersEndpoint; diff --git a/client/contexts/ServerContext/endpoints/v1/livechat/appearance.ts b/client/contexts/ServerContext/endpoints/v1/livechat/appearance.ts deleted file mode 100644 index e27fc9e1d20f..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/livechat/appearance.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ISetting } from '../../../../../../definition/ISetting'; - -export type AppearanceEndpoint = { - GET: (params: Record) => { - success: boolean; - appearance: ISetting[]; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/livechat/canned-responses.ts b/client/contexts/ServerContext/endpoints/v1/livechat/canned-responses.ts deleted file mode 100644 index a00dd3af22e7..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/livechat/canned-responses.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ObjectFromApi } from '../../../../../../definition/ObjectFromApi'; -import { IOmnichannelCannedResponse } from '../../../../../../ee/client/omnichannel/cannedResponses/IOmnichannelCannedResponse'; - -export type CannedResponses = { - GET: (params: { text: string; offset?: number | undefined; count?: number | undefined }) => { - cannedResponses: ObjectFromApi[]; - total: number; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/livechat/customFields.ts b/client/contexts/ServerContext/endpoints/v1/livechat/customFields.ts deleted file mode 100644 index 5968bd12c025..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/livechat/customFields.ts +++ /dev/null @@ -1,10 +0,0 @@ -export type LivechatCustomFieldsEndpoint = { - GET: (params: {}) => { - customFields: [ - { - _id: string; - label: string; - }, - ]; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/livechat/department.ts b/client/contexts/ServerContext/endpoints/v1/livechat/department.ts deleted file mode 100644 index 04c1a7c9499f..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/livechat/department.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { ILivechatDepartment } from '../../../../../../definition/ILivechatDepartment'; -import { ObjectFromApi } from '../../../../../../definition/ObjectFromApi'; - -export type LivechatDepartment = { - GET: (params: { - text: string; - offset?: number; - count?: number; - sort?: string; - onlyMyDepartments?: boolean; - }) => { - departments: ObjectFromApi[]; - total: number; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/livechat/departmentSingle.ts b/client/contexts/ServerContext/endpoints/v1/livechat/departmentSingle.ts deleted file mode 100644 index 6bfbe5768e2e..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/livechat/departmentSingle.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ILivechatDepartment } from '../../../../../../definition/ILivechatDepartment'; - -export type LivechatDepartmentSingleGetReturn = { - department: ILivechatDepartment; - success: boolean; -}; - -export type LivechatDepartmentSingle = { - GET: () => LivechatDepartmentSingleGetReturn; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/livechat/departmentsByUnit.ts b/client/contexts/ServerContext/endpoints/v1/livechat/departmentsByUnit.ts deleted file mode 100644 index aeb706af7598..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/livechat/departmentsByUnit.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ILivechatDepartment } from '../../../../../../definition/ILivechatDepartment'; -import { ObjectFromApi } from '../../../../../../definition/ObjectFromApi'; - -export type LivechatDepartmentsByUnit = { - GET: (params: { text: string; offset: number; count: number }) => { - departments: ObjectFromApi[]; - total: number; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/livechat/monitorsList.ts b/client/contexts/ServerContext/endpoints/v1/livechat/monitorsList.ts deleted file mode 100644 index c521255cd0fa..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/livechat/monitorsList.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ILivechatMonitor } from '../../../../../../definition/ILivechatMonitor'; -import { ObjectFromApi } from '../../../../../../definition/ObjectFromApi'; - -export type LivechatMonitorsList = { - GET: (params: { text: string; offset: number; count: number }) => { - monitors: ObjectFromApi[]; - total: number; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/livechat/onHold.ts b/client/contexts/ServerContext/endpoints/v1/livechat/onHold.ts deleted file mode 100644 index 9757fa92b9b2..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/livechat/onHold.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type LivechatRoomOnHoldEndpoint = { - POST: (roomId: string) => { - success: boolean; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/livechat/rooms.ts b/client/contexts/ServerContext/endpoints/v1/livechat/rooms.ts deleted file mode 100644 index 4d2d0b318f83..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/livechat/rooms.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { IOmnichannelRoom } from '../../../../../../definition/IRoom'; - -export type LivechatRoomsEndpoint = { - GET: (params: { - guest: string; - fname: string; - servedBy: string[]; - status: string; - department: string; - from: string; - to: string; - customFields: any; - current: number; - itemsPerPage: number; - tags: string[]; - }) => { - rooms: IOmnichannelRoom[]; - count: number; - offset: number; - total: number; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/livechat/tagsList.ts b/client/contexts/ServerContext/endpoints/v1/livechat/tagsList.ts deleted file mode 100644 index 8bbec65cc0c8..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/livechat/tagsList.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ILivechatTag } from '../../../../../../definition/ILivechatTag'; -import { ObjectFromApi } from '../../../../../../definition/ObjectFromApi'; - -export type LivechatTagsList = { - GET: (params: { text: string; offset: number; count: number }) => { - tags: ObjectFromApi[]; - total: number; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/livechat/user/agent.ts b/client/contexts/ServerContext/endpoints/v1/livechat/user/agent.ts deleted file mode 100644 index eddae7f3ca09..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/livechat/user/agent.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ILivechatAgent } from '../../../../../../../definition/ILivechatAgent'; -import { ObjectFromApi } from '../../../../../../../definition/ObjectFromApi'; - -export type LivechatAgents = { - GET: (params: { text: string; offset?: number | undefined; count?: number | undefined }) => { - tags: ObjectFromApi[]; - total: number; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/livechat/usersAgent.ts b/client/contexts/ServerContext/endpoints/v1/livechat/usersAgent.ts deleted file mode 100644 index c435f8b0bc3c..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/livechat/usersAgent.ts +++ /dev/null @@ -1,22 +0,0 @@ -export type LivechatUsersAgentEndpoint = { - GET: (params?: { text?: string; offset?: number; count?: number; sort?: string }) => { - users: { - _id: string; - emails: { - address: string; - verified: boolean; - }[]; - status: string; - name: string; - username: string; - statusLivechat: string; - livechat: { - maxNumberSimultaneousChat: number; - }; - }[]; - count: number; - offset: number; - total: number; - success: boolean; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/livechat/visitorInfo.ts b/client/contexts/ServerContext/endpoints/v1/livechat/visitorInfo.ts deleted file mode 100644 index 4926a0401e10..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/livechat/visitorInfo.ts +++ /dev/null @@ -1,10 +0,0 @@ -export type LivechatVisitorInfoEndpoint = { - GET: (params: { visitorId: string }) => { - success: boolean; - visitor: { - visitorEmails: Array<{ - address: string; - }>; - }; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/omnichannel.ts b/client/contexts/ServerContext/endpoints/v1/omnichannel.ts new file mode 100644 index 000000000000..4254db71253a --- /dev/null +++ b/client/contexts/ServerContext/endpoints/v1/omnichannel.ts @@ -0,0 +1,146 @@ +import { ILivechatDepartment } from '../../../../../definition/ILivechatDepartment'; +import { ILivechatMonitor } from '../../../../../definition/ILivechatMonitor'; +import { ILivechatTag } from '../../../../../definition/ILivechatTag'; +import { IOmnichannelCannedResponse } from '../../../../../definition/IOmnichannelCannedResponse'; +import { IOmnichannelRoom, IRoom } from '../../../../../definition/IRoom'; +import { ISetting } from '../../../../../definition/ISetting'; +import { IUser } from '../../../../../definition/IUser'; + +export type OmnichannelEndpoints = { + 'livechat/appearance': { + GET: () => { + appearance: ISetting[]; + }; + }; + 'livechat/visitors.info': { + GET: (params: { visitorId: string }) => { + visitor: { + visitorEmails: Array<{ + address: string; + }>; + }; + }; + }; + 'livechat/room.onHold': { + POST: (params: { roomId: IRoom['_id'] }) => void; + }; + 'livechat/monitors.list': { + GET: (params: { text: string; offset: number; count: number }) => { + monitors: ILivechatMonitor[]; + total: number; + }; + }; + 'livechat/tags.list': { + GET: (params: { text: string; offset: number; count: number }) => { + tags: ILivechatTag[]; + total: number; + }; + }; + 'livechat/department': { + GET: (params: { + text: string; + offset?: number; + count?: number; + sort?: string; + onlyMyDepartments?: boolean; + }) => { + departments: ILivechatDepartment[]; + total: number; + }; + }; + 'livechat/department/:_id': { + path: `livechat/department/${string}`; + GET: () => { + department: ILivechatDepartment; + }; + }; + 'livechat/departments.by-unit/': { + GET: (params: { text: string; offset: number; count: number }) => { + departments: ILivechatDepartment[]; + total: number; + }; + }; + 'livechat/custom-fields': { + GET: () => { + customFields: [ + { + _id: string; + label: string; + }, + ]; + }; + }; + 'livechat/rooms': { + GET: (params: { + guest: string; + fname: string; + servedBy: string[]; + status: string; + department: string; + from: string; + to: string; + customFields: any; + current: number; + itemsPerPage: number; + tags: string[]; + }) => { + rooms: IOmnichannelRoom[]; + count: number; + offset: number; + total: number; + }; + }; + 'livechat/users/agent': { + GET: (params: { text?: string; offset?: number; count?: number; sort?: string }) => { + users: { + _id: string; + emails: { + address: string; + verified: boolean; + }[]; + status: string; + name: string; + username: string; + statusLivechat: string; + livechat: { + maxNumberSimultaneousChat: number; + }; + }[]; + count: number; + offset: number; + total: number; + }; + }; + 'canned-responses': { + GET: (params: { + shortcut?: string; + text?: string; + scope?: string; + createdBy?: IUser['username']; + tags?: any; + departmentId?: ILivechatDepartment['_id']; + offset?: number; + count?: number; + }) => { + cannedResponses: IOmnichannelCannedResponse[]; + count?: number; + offset?: number; + total: number; + }; + POST: (params: { + _id?: IOmnichannelCannedResponse['_id']; + shortcut: string; + text: string; + scope: string; + tags?: any; + departmentId?: ILivechatDepartment['_id']; + }) => void; + DELETE: (params: { _id: IOmnichannelCannedResponse['_id'] }) => void; + }; + 'canned-responses/:_id': { + path: `canned-responses/${string}`; + GET: () => { + cannedResponse: IOmnichannelCannedResponse; + }; + }; +}; diff --git a/client/contexts/ServerContext/endpoints/v1/omnichannel/cannedResponse.tsx b/client/contexts/ServerContext/endpoints/v1/omnichannel/cannedResponse.tsx deleted file mode 100644 index 57b84d74dfb3..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/omnichannel/cannedResponse.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { IOmnichannelCannedResponse } from '../../../../../../definition/IOmnichannelCannedResponse'; - -export type CannedResponseEndpointGetReturn = { - cannedResponse: IOmnichannelCannedResponse; - success: boolean; -}; - -export type CannedResponseEndpoint = { - GET: () => CannedResponseEndpointGetReturn; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/omnichannel/cannedResponses.tsx b/client/contexts/ServerContext/endpoints/v1/omnichannel/cannedResponses.tsx deleted file mode 100644 index d9e6819f789a..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/omnichannel/cannedResponses.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { ILivechatDepartment } from '../../../../../../definition/ILivechatDepartment'; -import { IOmnichannelCannedResponse } from '../../../../../../definition/IOmnichannelCannedResponse'; -import { IUser } from '../../../../../../definition/IUser'; - -export type CannedResponsesEndpoint = { - GET: (params: { - shortcut?: string; - text?: string; - scope?: string; - createdBy?: IUser['username']; - tags?: any; - departmentId?: ILivechatDepartment['_id']; - offset?: number; - count?: number; - }) => { - cannedResponses: IOmnichannelCannedResponse[]; - count?: number; - offset?: number; - total: number; - }; - POST: (params: { - _id?: IOmnichannelCannedResponse['_id']; - shortcut: string; - text: string; - scope: string; - tags?: any; - departmentId?: ILivechatDepartment['_id']; - }) => { - success: true; - statusCode: 200; - }; - DELETE: (params: { _id: IOmnichannelCannedResponse['_id'] }) => { - success: true; - statusCode: 200; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/rooms.ts b/client/contexts/ServerContext/endpoints/v1/rooms.ts new file mode 100644 index 000000000000..960610ec558a --- /dev/null +++ b/client/contexts/ServerContext/endpoints/v1/rooms.ts @@ -0,0 +1,41 @@ +import type { IMessage } from '../../../../../definition/IMessage'; +import type { IRoom } from '../../../../../definition/IRoom'; +import type { IUser } from '../../../../../definition/IUser'; + +export type RoomsEndpoints = { + 'rooms.autocomplete.channelAndPrivate': { + GET: (params: { selector: string }) => { + items: IRoom[]; + }; + }; + 'rooms.autocomplete.channelAndPrivate.withPagination': { + GET: (params: { selector: string; offset?: number; count?: number; sort?: string }) => { + items: IRoom[]; + count: number; + offset: number; + total: number; + }; + }; + 'rooms.autocomplete.availableForTeams': { + GET: (params: { name: string }) => { + items: IRoom[]; + }; + }; + 'rooms.info': { + GET: (params: { roomId: string } | { roomName: string }) => { + room: IRoom; + }; + }; + 'rooms.createDiscussion': { + POST: (params: { + prid: IRoom['_id']; + pmid?: IMessage['_id']; + t_name: IRoom['fname']; + users?: IUser['username'][]; + encrypted?: boolean; + reply?: string; + }) => { + discussion: IRoom; + }; + }; +}; diff --git a/client/contexts/ServerContext/endpoints/v1/rooms/autocompleteAvailableForTeams.ts b/client/contexts/ServerContext/endpoints/v1/rooms/autocompleteAvailableForTeams.ts deleted file mode 100644 index bcec28cfcae4..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/rooms/autocompleteAvailableForTeams.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { IRoom } from '../../../../../../definition/IRoom'; - -export type AutocompleteAvailableForTeamsEndpoint = { - GET: (params: { name: string }) => { items: IRoom[] }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/rooms/autocompleteChannelAndPrivate.ts b/client/contexts/ServerContext/endpoints/v1/rooms/autocompleteChannelAndPrivate.ts deleted file mode 100644 index 0b84607ca8d9..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/rooms/autocompleteChannelAndPrivate.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { IRoom } from '../../../../../../definition/IRoom'; - -export type AutocompleteChannelAndPrivateEndpoint = { - GET: (params: { selector: string }) => { items: IRoom[] }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/rooms/autocompleteChannelAndPrivateWithPagination.ts b/client/contexts/ServerContext/endpoints/v1/rooms/autocompleteChannelAndPrivateWithPagination.ts deleted file mode 100644 index ee0ce416b494..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/rooms/autocompleteChannelAndPrivateWithPagination.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { IRoom } from '../../../../../../definition/IRoom'; - -export type AutocompleteChannelAndPrivateEndpointWithPagination = { - GET: (params: { selector: string; offset?: number; count?: number; sort?: string }) => { - items: IRoom[]; - count: number; - offset: number; - total: number; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/rooms/roomsInfo.ts b/client/contexts/ServerContext/endpoints/v1/rooms/roomsInfo.ts deleted file mode 100644 index 06cbfbea68e2..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/rooms/roomsInfo.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { IRoom } from '../../../../../../definition/IRoom'; - -export type RoomsInfo = { - GET: (params: { roomId: string } | { roomName: string }) => { room: IRoom; success: boolean }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/teams.ts b/client/contexts/ServerContext/endpoints/v1/teams.ts new file mode 100644 index 000000000000..2fae8fbac8a5 --- /dev/null +++ b/client/contexts/ServerContext/endpoints/v1/teams.ts @@ -0,0 +1,73 @@ +import type { IRoom } from '../../../../../definition/IRoom'; +import type { IRecordsWithTotal, ITeam } from '../../../../../definition/ITeam'; +import type { IUser } from '../../../../../definition/IUser'; + +export type TeamsEndpoints = { + 'teams.addRooms': { + POST: (params: { rooms: IRoom['_id'][]; teamId: string }) => void; + }; + 'teams.listRooms': { + GET: (params: { + teamId: ITeam['_id']; + offset?: number; + count?: number; + filter: string; + type: string; + }) => Omit, 'records'> & { + count: number; + offset: number; + rooms: IRecordsWithTotal['records']; + }; + }; + 'teams.listRoomsOfUser': { + GET: (params: { + teamId: ITeam['_id']; + teamName?: string; + userId?: string; + canUserDelete?: boolean; + offset?: number; + count?: number; + }) => Omit, 'records'> & { + count: number; + offset: number; + rooms: IRecordsWithTotal['records']; + }; + }; + 'teams.create': { + POST: (params: { + name: ITeam['name']; + type?: ITeam['type']; + members?: IUser['_id'][]; + room: { + id?: string; + name?: IRoom['name']; + members?: IUser['_id'][]; + readOnly?: boolean; + extraData?: { + teamId?: string; + teamMain?: boolean; + } & { [key: string]: string | boolean }; + options?: { + nameValidationRegex?: string; + creator: string; + subscriptionExtra?: { + open: boolean; + ls: Date; + prid: IRoom['_id']; + }; + } & { + [key: string]: + | string + | { + open: boolean; + ls: Date; + prid: IRoom['_id']; + }; + }; + }; + owner?: IUser['_id']; + }) => { + team: ITeam; + }; + }; +}; diff --git a/client/contexts/ServerContext/endpoints/v1/teams/addRooms.ts b/client/contexts/ServerContext/endpoints/v1/teams/addRooms.ts deleted file mode 100644 index cc1a8fc9ef47..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/teams/addRooms.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { IRoom } from '../../../../../../definition/IRoom'; - -export type AddRoomsEndpoint = { - POST: (params: { rooms: IRoom['_id'][]; teamId: string }) => { - success: true; - statusCode: 200; - body: IRoom[]; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/teams/listRooms.ts b/client/contexts/ServerContext/endpoints/v1/teams/listRooms.ts deleted file mode 100644 index 96d9ebedc61d..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/teams/listRooms.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { IRoom } from '../../../../../../definition/IRoom'; -import { IRecordsWithTotal } from '../../../../../../definition/ITeam'; - -export type ListRoomsEndpoint = { - GET: (params: { - teamId: string; - offset?: number; - count?: number; - filter: string; - type: string; - }) => Omit, 'records'> & { - count: number; - offset: number; - rooms: IRecordsWithTotal['records']; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/teams/listRoomsOfUser.ts b/client/contexts/ServerContext/endpoints/v1/teams/listRoomsOfUser.ts deleted file mode 100644 index 32e113b57ab9..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/teams/listRoomsOfUser.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { IRoom } from '../../../../../../definition/IRoom'; -import { IRecordsWithTotal } from '../../../../../../definition/ITeam'; - -export type ListRoomsOfUserEndpoint = { - GET: (params: { - teamId: string; - teamName?: string; - userId?: string; - canUserDelete?: boolean; - offset?: number; - count?: number; - }) => Omit, 'records'> & { - count: number; - offset: number; - rooms: IRecordsWithTotal['records']; - }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/users.ts b/client/contexts/ServerContext/endpoints/v1/users.ts new file mode 100644 index 000000000000..27cc45a04c63 --- /dev/null +++ b/client/contexts/ServerContext/endpoints/v1/users.ts @@ -0,0 +1,10 @@ +import type { IUser } from '../../../../../definition/IUser'; + +export type UsersEndpoints = { + 'users.2fa.sendEmailCode': { + POST: (params: { emailOrUsername: string }) => void; + }; + 'users.autocomplete': { + GET: (params: { selector: string }) => { items: IUser[] }; + }; +}; diff --git a/client/contexts/ServerContext/endpoints/v1/users/autocomplete.ts b/client/contexts/ServerContext/endpoints/v1/users/autocomplete.ts deleted file mode 100644 index 4b3d41eeb0be..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/users/autocomplete.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { IUser } from '../../../../../../definition/IUser'; - -export type AutocompleteEndpoint = { - GET: (params: { selector: string }) => { items: IUser[] }; -}; diff --git a/client/contexts/ServerContext/endpoints/v1/users/twoFactorAuth/sendEmailCode.ts b/client/contexts/ServerContext/endpoints/v1/users/twoFactorAuth/sendEmailCode.ts deleted file mode 100644 index a321871b75ee..000000000000 --- a/client/contexts/ServerContext/endpoints/v1/users/twoFactorAuth/sendEmailCode.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type SendEmailCodeEndpoint = { - POST: (params: { emailOrUsername: string }) => { success: boolean }; -}; diff --git a/client/hooks/lists/useScrollableMessageList.ts b/client/hooks/lists/useScrollableMessageList.ts index e9d11dc3442a..e6f9d43c4dde 100644 --- a/client/hooks/lists/useScrollableMessageList.ts +++ b/client/hooks/lists/useScrollableMessageList.ts @@ -1,31 +1,25 @@ import { useCallback } from 'react'; import { IMessage } from '../../../definition/IMessage'; -import { ObjectFromApi } from '../../../definition/ObjectFromApi'; +import { Serialized } from '../../../definition/Serialized'; +import { mapMessageFromApi } from '../../lib/fromApi'; import { MessageList } from '../../lib/lists/MessageList'; import { RecordListBatchChanges } from '../../lib/lists/RecordList'; import { useScrollableRecordList } from './useScrollableRecordList'; -const convertMessageFromApi = (apiMessage: ObjectFromApi): IMessage => ({ - ...apiMessage, - _updatedAt: new Date(apiMessage._updatedAt), - ts: new Date(apiMessage.ts), - ...(apiMessage.tlm && { tlm: new Date(apiMessage.tlm) }), -}); - export const useScrollableMessageList = ( messageList: MessageList, fetchMessages: ( start: number, end: number, - ) => Promise>>, + ) => Promise>>, initialItemCount?: number, ): ReturnType => { const fetchItems = useCallback( async (start: number, end: number): Promise> => { const batchChanges = await fetchMessages(start, end); return { - ...(batchChanges.items && { items: batchChanges.items.map(convertMessageFromApi) }), + ...(batchChanges.items && { items: batchChanges.items.map(mapMessageFromApi) }), ...(batchChanges.itemCount && { itemCount: batchChanges.itemCount }), }; }, diff --git a/client/hooks/useEndpointAction.js b/client/hooks/useEndpointAction.js deleted file mode 100644 index b600bfaac93d..000000000000 --- a/client/hooks/useEndpointAction.js +++ /dev/null @@ -1,54 +0,0 @@ -import { useCallback } from 'react'; - -import { useEndpoint } from '../contexts/ServerContext'; -import { useToastMessageDispatch } from '../contexts/ToastMessagesContext'; - -export const useEndpointAction = (httpMethod, endpoint, params = {}, successMessage) => { - const sendData = useEndpoint(httpMethod, endpoint); - const dispatchToastMessage = useToastMessageDispatch(); - - return useCallback( - async (...args) => { - try { - const data = await sendData(params, ...args); - - if (!data.success) { - throw new Error(data.status); - } - - successMessage && dispatchToastMessage({ type: 'success', message: successMessage }); - - return data; - } catch (error) { - dispatchToastMessage({ type: 'error', message: error }); - return { success: false }; - } - }, - [dispatchToastMessage, params, sendData, successMessage], - ); -}; - -export const useEndpointActionExperimental = (httpMethod, endpoint, successMessage) => { - const sendData = useEndpoint(httpMethod, endpoint); - const dispatchToastMessage = useToastMessageDispatch(); - - return useCallback( - async (params, ...args) => { - try { - const data = await sendData(params, ...args); - - if (!data.success) { - throw new Error(data.status); - } - - successMessage && dispatchToastMessage({ type: 'success', message: successMessage }); - - return data; - } catch (error) { - dispatchToastMessage({ type: 'error', message: error }); - return { success: false }; - } - }, - [dispatchToastMessage, sendData, successMessage], - ); -}; diff --git a/client/hooks/useEndpointAction.ts b/client/hooks/useEndpointAction.ts new file mode 100644 index 000000000000..65a7f2ccaed3 --- /dev/null +++ b/client/hooks/useEndpointAction.ts @@ -0,0 +1,31 @@ +import { useCallback } from 'react'; + +import { Serialized } from '../../definition/Serialized'; +import { useEndpoint } from '../contexts/ServerContext'; +import { Method, Params, PathFor, Return } from '../contexts/ServerContext/endpoints'; +import { useToastMessageDispatch } from '../contexts/ToastMessagesContext'; + +export const useEndpointAction = >( + method: M, + path: P, + params: Params[0] = {}, + successMessage?: string, +): ((extraParams?: Params[1]) => Promise>>) => { + const sendData = useEndpoint(method, path); + const dispatchToastMessage = useToastMessageDispatch(); + + return useCallback(async () => { + try { + const data = await sendData(params); + + if (successMessage) { + dispatchToastMessage({ type: 'success', message: successMessage }); + } + + return data; + } catch (error) { + dispatchToastMessage({ type: 'error', message: error }); + throw error; + } + }, [dispatchToastMessage, params, sendData, successMessage]); +}; diff --git a/client/hooks/useEndpointActionExperimental.ts b/client/hooks/useEndpointActionExperimental.ts new file mode 100644 index 000000000000..b6cb286f46ae --- /dev/null +++ b/client/hooks/useEndpointActionExperimental.ts @@ -0,0 +1,34 @@ +import { useCallback } from 'react'; + +import { Serialized } from '../../definition/Serialized'; +import { useEndpoint } from '../contexts/ServerContext'; +import { Method, Params, PathFor, Return } from '../contexts/ServerContext/endpoints'; +import { useToastMessageDispatch } from '../contexts/ToastMessagesContext'; + +export const useEndpointActionExperimental = >( + method: M, + path: P, + successMessage?: string, +): ((params: Params[0]) => Promise>>) => { + const sendData = useEndpoint(method, path); + const dispatchToastMessage = useToastMessageDispatch(); + + return useCallback( + async (params) => { + try { + const data = await sendData(params); + + if (successMessage) { + dispatchToastMessage({ type: 'success', message: successMessage }); + } + + return data; + } catch (error) { + dispatchToastMessage({ type: 'error', message: error }); + // return { success: false }; + throw error; + } + }, + [dispatchToastMessage, sendData, successMessage], + ); +}; diff --git a/client/hooks/useEndpointData.ts b/client/hooks/useEndpointData.ts index 7593ecb46eca..6412cd9d7f3b 100644 --- a/client/hooks/useEndpointData.ts +++ b/client/hooks/useEndpointData.ts @@ -1,33 +1,19 @@ import { useCallback, useEffect } from 'react'; -import { - ServerEndpointPath, - ServerEndpointRequestPayload, - ServerEndpointResponsePayload, - ServerEndpoints, - useEndpoint, -} from '../contexts/ServerContext'; +import { Serialized } from '../../definition/Serialized'; +import { useEndpoint } from '../contexts/ServerContext'; +import { Params, PathFor, Return } from '../contexts/ServerContext/endpoints'; import { useToastMessageDispatch } from '../contexts/ToastMessagesContext'; import { AsyncState, useAsyncState } from './useAsyncState'; const defaultParams = {}; -type ServerGetEndpointPaths = { - [K in ServerEndpointPath]: ServerEndpoints[K] extends { GET: any } ? K : never; -}; - -export const useEndpointData = < - _T, - Path extends ServerGetEndpointPaths[keyof ServerGetEndpointPaths], ->( - endpoint: Path, - params: ServerEndpointRequestPayload<'GET', Path> = defaultParams, - initialValue?: - | ServerEndpointResponsePayload<'GET', Path> - | (() => ServerEndpointResponsePayload<'GET', Path>), -): AsyncState> & { reload: () => void } => { - const { resolve, reject, reset, ...state } = - useAsyncState>(initialValue); +export const useEndpointData =

>( + endpoint: P, + params: Params<'GET', P>[0] = defaultParams as Params<'GET', P>[0], + initialValue?: Serialized> | (() => Serialized>), +): AsyncState>> & { reload: () => void } => { + const { resolve, reject, reset, ...state } = useAsyncState(initialValue); const dispatchToastMessage = useToastMessageDispatch(); const getData = useEndpoint('GET', endpoint); diff --git a/client/importPackages.ts b/client/importPackages.ts index a6c7c487b987..6d7330c66d65 100644 --- a/client/importPackages.ts +++ b/client/importPackages.ts @@ -17,7 +17,6 @@ import '../app/favico'; import '../app/file-upload'; import '../app/github-enterprise/client'; import '../app/gitlab/client'; -import '../app/google-vision/client'; import '../app/iframe-login/client'; import '../app/importer/client'; import '../app/importer-csv/client'; diff --git a/client/lib/fromApi.ts b/client/lib/fromApi.ts new file mode 100644 index 000000000000..06f1224067dc --- /dev/null +++ b/client/lib/fromApi.ts @@ -0,0 +1,19 @@ +import { IMessage } from '../../definition/IMessage'; +import { Serialized } from '../../definition/Serialized'; + +export const mapMessageFromApi = ({ + attachments = [], + tlm, + ts, + _updatedAt, + ...message +}: Serialized): IMessage => ({ + ...message, + ts: new Date(ts), + ...(tlm && { tlm: new Date(tlm) }), + _updatedAt: new Date(_updatedAt), + attachments: attachments.map(({ ts, ...attachment }) => ({ + ...(ts && { ts: new Date(ts) }), + ...attachment, + })), +}); diff --git a/client/providers/ServerProvider.js b/client/providers/ServerProvider.js deleted file mode 100644 index 81abde0d261e..000000000000 --- a/client/providers/ServerProvider.js +++ /dev/null @@ -1,70 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import React from 'react'; - -import { Info as info, APIClient } from '../../app/utils/client'; -import { ServerContext } from '../contexts/ServerContext'; - -const absoluteUrl = (path) => Meteor.absoluteUrl(path); - -const callMethod = (methodName, ...args) => - new Promise((resolve, reject) => { - Meteor.call(methodName, ...args, (error, result) => { - if (error) { - reject(error); - return; - } - - resolve(result); - }); - }); - -const callEndpoint = (httpMethod, endpoint, ...args) => { - const allowedHttpMethods = ['get', 'post', 'delete']; - if (!httpMethod || !allowedHttpMethods.includes(httpMethod.toLowerCase())) { - throw new Error('Invalid http method provided to "useEndpoint"'); - } - if (!endpoint) { - throw new Error('Invalid endpoint provided to "useEndpoint"'); - } - - if (endpoint[0] === '/') { - return APIClient[httpMethod.toLowerCase()](endpoint.slice(1), ...args); - } - - return APIClient.v1[httpMethod.toLowerCase()](endpoint, ...args); -}; - -const uploadToEndpoint = (endpoint, params, formData) => { - if (endpoint[0] === '/') { - return APIClient.upload(endpoint.slice(1), params, formData).promise; - } - - return APIClient.v1.upload(endpoint, params, formData).promise; -}; - -const getStream = (streamName, options = {}) => { - const streamer = Meteor.StreamerCentral.instances[streamName] - ? Meteor.StreamerCentral.instances[streamName] - : new Meteor.Streamer(streamName, options); - return (eventName, callback) => { - streamer.on(eventName, callback); - return () => { - streamer.removeListener(eventName, callback); - }; - }; -}; - -const contextValue = { - info, - absoluteUrl, - callMethod, - callEndpoint, - uploadToEndpoint, - getStream, -}; - -const ServerProvider = ({ children }) => ( - -); - -export default ServerProvider; diff --git a/client/providers/ServerProvider.tsx b/client/providers/ServerProvider.tsx new file mode 100644 index 000000000000..9fd145054714 --- /dev/null +++ b/client/providers/ServerProvider.tsx @@ -0,0 +1,106 @@ +import { Meteor } from 'meteor/meteor'; +import React, { FC } from 'react'; + +import { Info as info, APIClient } from '../../app/utils/client'; +import { Serialized } from '../../definition/Serialized'; +import { + Method, + Params, + PathFor, + Return, + ServerContext, + ServerMethodName, + ServerMethodParameters, + ServerMethodReturn, +} from '../contexts/ServerContext'; + +const absoluteUrl = (path: string): string => Meteor.absoluteUrl(path); + +const callMethod = ( + methodName: MethodName, + ...args: ServerMethodParameters +): Promise> => + new Promise((resolve, reject) => { + Meteor.call(methodName, ...args, (error: Error, result: ServerMethodReturn) => { + if (error) { + reject(error); + return; + } + + resolve(result); + }); + }); + +const callEndpoint = >( + method: M, + path: P, + params: Params[0], +): Promise>> => { + const api = path[0] === '/' ? APIClient : APIClient.v1; + const endpointPath = path[0] === '/' ? path.slice(1) : path; + + switch (method) { + case 'GET': + return api.get(endpointPath, params); + + case 'POST': + return api.post(endpointPath, {}, params); + + case 'DELETE': + return api.delete(endpointPath, params); + + default: + throw new Error('Invalid HTTP method'); + } +}; + +const uploadToEndpoint = (endpoint: string, params: any, formData: any): Promise => { + if (endpoint[0] === '/') { + return APIClient.upload(endpoint.slice(1), params, formData).promise; + } + + return APIClient.v1.upload(endpoint, params, formData).promise; +}; + +declare module 'meteor/meteor' { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace Meteor { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace StreamerCentral { + const instances: { + [name: string]: typeof Meteor.Streamer; + }; + } + } +} + +const getStream = ( + streamName: string, + options: {} = {}, +): ((eventName: string, callback: (data: T) => void) => () => void) => { + const streamer = Meteor.StreamerCentral.instances[streamName] + ? Meteor.StreamerCentral.instances[streamName] + : new Meteor.Streamer(streamName, options); + + return (eventName, callback): (() => void) => { + streamer.on(eventName, callback); + return (): void => { + streamer.removeListener(eventName, callback); + }; + }; +}; + +const contextValue = { + info, + absoluteUrl, + callMethod, + callEndpoint, + uploadToEndpoint, + getStream, +}; + +const ServerProvider: FC = ({ children }) => ( + +); + +export default ServerProvider; diff --git a/client/sidebar/header/CreateChannelWithData.js b/client/sidebar/header/CreateChannelWithData.js index 75b37c574e4d..40cf5c2ceb85 100644 --- a/client/sidebar/header/CreateChannelWithData.js +++ b/client/sidebar/header/CreateChannelWithData.js @@ -3,7 +3,7 @@ import React, { memo, useCallback, useMemo } from 'react'; import { usePermission } from '../../contexts/AuthorizationContext'; import { useSetting } from '../../contexts/SettingsContext'; -import { useEndpointActionExperimental } from '../../hooks/useEndpointAction'; +import { useEndpointActionExperimental } from '../../hooks/useEndpointActionExperimental'; import { useForm } from '../../hooks/useForm'; import { goToRoomById } from '../../lib/goToRoomById'; import CreateChannel from './CreateChannel'; diff --git a/client/sidebar/header/CreateDirectMessage.tsx b/client/sidebar/header/CreateDirectMessage.tsx index f09dde805425..3835399ac3eb 100644 --- a/client/sidebar/header/CreateDirectMessage.tsx +++ b/client/sidebar/header/CreateDirectMessage.tsx @@ -5,7 +5,7 @@ import React, { FC, useState, memo } from 'react'; import { IUser } from '../../../definition/IUser'; import UserAutoCompleteMultiple from '../../components/UserAutoCompleteMultiple'; import { useTranslation } from '../../contexts/TranslationContext'; -import { useEndpointActionExperimental } from '../../hooks/useEndpointAction'; +import { useEndpointActionExperimental } from '../../hooks/useEndpointActionExperimental'; import { goToRoomById } from '../../lib/goToRoomById'; type Username = IUser['username']; diff --git a/client/startup/renderMessage/googlevision.ts b/client/startup/renderMessage/googlevision.ts deleted file mode 100644 index 73abc30ea08b..000000000000 --- a/client/startup/renderMessage/googlevision.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import { Tracker } from 'meteor/tracker'; - -import { callbacks } from '../../../app/callbacks/client'; -import { settings } from '../../../app/settings/client'; - -Meteor.startup(() => { - Tracker.autorun(() => { - const isEnabled = settings.get('GoogleVision_Enable'); - - if (!isEnabled) { - callbacks.remove('renderMessage', 'googlevision'); - return; - } - - import('../../../app/google-vision/client').then(({ createGoogleVisionMessageRenderer }) => { - const renderMessage = createGoogleVisionMessageRenderer(); - callbacks.remove('renderMessage', 'googlevision'); - callbacks.add('renderMessage', renderMessage, callbacks.priority.HIGH - 3, 'googlevision'); - }); - }); -}); diff --git a/client/startup/renderMessage/index.ts b/client/startup/renderMessage/index.ts index c4ac327c8cdf..09eeca80dd1e 100644 --- a/client/startup/renderMessage/index.ts +++ b/client/startup/renderMessage/index.ts @@ -1,7 +1,6 @@ import './autolinker'; import './autotranslate'; import './emoji'; -import './googlevision'; import './hexcolor'; import './highlightWords'; import './issuelink'; diff --git a/client/startup/streamMessage/googlevision.ts b/client/startup/streamMessage/googlevision.ts deleted file mode 100644 index 4d2347952d6d..000000000000 --- a/client/startup/streamMessage/googlevision.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import { Tracker } from 'meteor/tracker'; - -import { callbacks } from '../../../app/callbacks/client'; -import { settings } from '../../../app/settings/client'; - -Meteor.startup(() => { - Tracker.autorun(() => { - const isEnabled = settings.get('GoogleVision_Enable'); - - if (!isEnabled) { - callbacks.remove('streamMessage', 'googlevision'); - return; - } - - import('../../../app/google-vision/client').then( - ({ createGoogleVisionMessageStreamHandler }) => { - const streamMessage = createGoogleVisionMessageStreamHandler(); - callbacks.remove('streamMessage', 'googlevision'); - callbacks.add('streamMessage', streamMessage, callbacks.priority.HIGH - 3, 'googlevision'); - }, - ); - }); -}); diff --git a/client/startup/streamMessage/index.ts b/client/startup/streamMessage/index.ts index 04adf712942f..d6815e9f0050 100644 --- a/client/startup/streamMessage/index.ts +++ b/client/startup/streamMessage/index.ts @@ -1,2 +1 @@ import './autotranslate'; -import './googlevision'; diff --git a/client/views/account/preferences/PreferencesNotificationsSection.js b/client/views/account/preferences/PreferencesNotificationsSection.js index 5d1aabb326fd..b2c9dbf40ac8 100644 --- a/client/views/account/preferences/PreferencesNotificationsSection.js +++ b/client/views/account/preferences/PreferencesNotificationsSection.js @@ -35,7 +35,7 @@ const PreferencesNotificationsSection = ({ onChange, commitRef, ...props }) => { 'desktopNotificationRequireInteraction', ); const userDesktopNotifications = useUserPreference('desktopNotifications'); - const userMobileNotifications = useUserPreference('mobileNotifications'); + const userMobileNotifications = useUserPreference('pushNotifications'); const userEmailNotificationMode = useUserPreference('emailNotificationMode'); const userDesktopAudioNotifications = useUserPreference('audioNotifications'); @@ -46,7 +46,7 @@ const PreferencesNotificationsSection = ({ onChange, commitRef, ...props }) => { 'Accounts_Default_User_Preferences_audioNotifications', ); const defaultMobileNotifications = useSetting( - 'Accounts_Default_User_Preferences_mobileNotifications', + 'Accounts_Default_User_Preferences_pushNotifications', ); const canChangeEmailNotification = useSetting('Accounts_AllowEmailNotifications'); @@ -194,7 +194,7 @@ const PreferencesNotificationsSection = ({ onChange, commitRef, ...props }) => { - {t('Notification_Mobile_Default_For')} + {t('Notification_Push_Default_For')}