Skip to content

Commit

Permalink
[gh-NangoHQ#610] token refresh logging
Browse files Browse the repository at this point in the history
  • Loading branch information
khaliqgant committed May 3, 2023
1 parent 778b79f commit f6b5c9b
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 70 deletions.
37 changes: 16 additions & 21 deletions packages/server/lib/controllers/activity.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,34 +32,29 @@ class ActivityController {

/**
* Merge Sessions
* @desc identify if a property has a session id and there is a matching
* session id merge the two while maintaining ordering of the logs
* @desc append any messages of oauth continuation entries that have a merge property of true
* to an existing session id and update the end time while maintaing
* log ordering
*/
private mergeSessions(logs: LogData[]) {
const sessions: Record<string, LogData> = {};
const updatedLogs: LogData[] = [];
const sessions: Record<string, number> = {};

logs.forEach((item) => {
if (item.sessionId) {
if (!sessions[item.sessionId]) {
sessions[item.sessionId] = item;
updatedLogs.push(item);
} else {
sessions[item?.sessionId]!.messages = [...sessions[item?.sessionId]!.messages, ...item.messages];
sessions[item?.sessionId]!.merge = true;
}
} else {
updatedLogs.push(item);
}
});
for (let i = 0; i < logs.length; i++) {
const log = logs[i];

Object.values(sessions).forEach((item) => {
if (!item.merge) {
updatedLogs.push(item);
if (log?.sessionId && !log.merge) {
sessions[log.sessionId] = i;
}
delete item.merge;
});

if (log?.merge && sessions[log.sessionId as string]) {
const mergeIndex: number = sessions[log.sessionId as string] as number;
updatedLogs[mergeIndex]!.messages = [...updatedLogs[mergeIndex]!.messages, ...log.messages];
updatedLogs[mergeIndex]!.end = log.end as number;
} else {
updatedLogs.push(log as LogData);
}
}
return updatedLogs;
}
}
Expand Down
20 changes: 18 additions & 2 deletions packages/server/lib/controllers/connection.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import type { Request, Response } from 'express';
import connectionService from '../services/connection.service.js';
import type { NextFunction } from 'express';
import configService from '../services/config.service.js';
import { ProviderConfig, ProviderTemplate, Connection, ProviderAuthModes, ProviderTemplateOAuth2 } from '../models.js';
import { ProviderConfig, ProviderTemplate, Connection, ProviderAuthModes, ProviderTemplateOAuth2, HTTP_VERB } from '../models.js';
import analytics from '../utils/analytics.js';
import { getAccount, getUserAndAccountFromSession } from '../utils/utils.js';
import { getConnectionCredentials } from '../utils/connection.js';
import type { LogData, LogLevel, LogAction } from '../utils/file-logger.js';
import errorManager from '../utils/error.manager.js';

class ConnectionController {
Expand Down Expand Up @@ -151,7 +152,22 @@ class ConnectionController {
const providerConfigKey = req.query['provider_config_key'] as string;
const instantRefresh = req.query['force_refresh'] === 'true';

const connection = await getConnectionCredentials(res, connectionId, providerConfigKey, instantRefresh);
const log = {
level: 'debug' as LogLevel,
success: true,
action: 'token' as LogAction,
start: Date.now(),
end: Date.now(),
timestamp: Date.now(),
method: req.method as HTTP_VERB,
connectionId,
providerConfigKey,
messages: [] as LogData['messages'],
message: '',
endpoint: ''
};

const connection = await getConnectionCredentials(res, connectionId, providerConfigKey, log, instantRefresh);

res.status(200).send(connection);
} catch (err) {
Expand Down
29 changes: 14 additions & 15 deletions packages/server/lib/controllers/proxy.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,6 @@ class ProxyController {

logger.debug(configMessage);

const connection = await getConnectionCredentials(res, connectionId, providerConfigKey);

const credentialMessage = 'Connection credentials found successfully';

logger.debug(credentialMessage);

const log = {
level: 'debug' as LogLevel,
success: true,
Expand All @@ -67,19 +61,24 @@ class ProxyController {
method: req.method as HTTP_VERB,
connectionId,
providerConfigKey,
messages:
process.env['LOG_LEVEL'] === 'debug '
? [
{
timestamp: Date.now(),
content: `${Date.now()} ${configMessage}. ${credentialMessage}`
}
]
: [],
messages: [] as LogData['messages'],
message: '',
endpoint: ''
};

const connection = await getConnectionCredentials(res, connectionId, providerConfigKey, log);

const credentialMessage = 'Connection credentials found successfully';

logger.debug(credentialMessage);

if (process.env['LOG_LEVEL'] === 'debug') {
log.messages.push({
timestamp: Date.now(),
content: `${configMessage}. ${credentialMessage}`
});
}

const { method } = req;

const endpoint = req.params[0] as string;
Expand Down
22 changes: 22 additions & 0 deletions packages/server/lib/services/connection.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import db from '../db/database.js';
import type { ProviderConfig, Connection } from '../models.js';
import analytics from '../utils/analytics.js';
import providerClientManager from '../clients/provider.client.js';
import { fileLogger, LogData } from '../utils/file-logger.js';
import { parseTokenExpirationDate, isTokenExpired } from '../utils/utils.js';
import providerClient from '../clients/provider.client.js';
import { NangoError } from '../utils/error.js';
Expand Down Expand Up @@ -143,6 +144,7 @@ class ConnectionService {
connection: Connection,
providerConfig: ProviderConfig,
template: ProviderTemplateOAuth2,
log = {} as LogData,
instantRefresh = false
): Promise<OAuth2Credentials> {
let connectionId = connection.connection_id;
Expand Down Expand Up @@ -194,6 +196,19 @@ class ConnectionService {
return !(value.providerConfigKey === providerConfigKey && value.connectionId === connectionId);
});

log.action = 'token';
log.level = 'error';
log.end = Date.now();
log.success = false;
log.timestamp = Date.now();
log.messages = [
{
content: `Refresh oauth2 token call failed`,
timestamp: Date.now()
}
];
fileLogger.error('', log);

reject(e);
}
});
Expand All @@ -204,6 +219,13 @@ class ConnectionService {
promise: promise
} as CredentialsRefresh;

log.messages.push({
content: `Token refresh for ${providerConfigKey} and connection ${connectionId}`,
timestamp: Date.now(),
providerConfigKey,
connectionId
});

this.runningCredentialsRefreshes.push(refresh);

return promise;
Expand Down
57 changes: 25 additions & 32 deletions packages/server/lib/utils/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import connectionService from '../services/connection.service.js';
import configService from '../services/config.service.js';
import analytics from './analytics.js';
import { getAccount } from './utils.js';
import { fileLogger } from './file-logger.js';
import { fileLogger, LogData } from './file-logger.js';

export const getConnectionCredentials = async (res: Response, connectionId: string, providerConfigKey: string, instantRefresh = false) => {
export const getConnectionCredentials = async (res: Response, connectionId: string, providerConfigKey: string, log: LogData, instantRefresh = false) => {
const accountId = getAccount(res);

if (connectionId === null) {
Expand All @@ -24,21 +24,17 @@ export const getConnectionCredentials = async (res: Response, connectionId: stri
const connection: Connection | null = await connectionService.getConnection(connectionId, providerConfigKey, accountId);

if (connection === null) {
fileLogger.error('', {
level: 'error',
success: false,
action: 'token',
timestamp: Date.now(),
method: null,
connectionId,
providerConfigKey,
messages: [
{
content: `Connection not found using connectionId: ${connectionId} and providerConfigKey: ${providerConfigKey}`,
timestamp: Date.now()
}
]
});
log.level = 'error';
log.end = Date.now();
log.success = false;
log.timestamp = Date.now();
log.messages = [
{
content: `Connection not found using connectionId: ${connectionId} and providerConfigKey: ${providerConfigKey}`,
timestamp: Date.now()
}
];
fileLogger.error('', log);

errorManager.errRes(res, 'unkown_connection');
throw new Error(`Connection not found`);
Expand All @@ -47,21 +43,17 @@ export const getConnectionCredentials = async (res: Response, connectionId: stri
const config: ProviderConfig | null = await configService.getProviderConfig(connection.provider_config_key, accountId);

if (config === null) {
fileLogger.error('', {
level: 'error',
success: false,
action: 'token',
timestamp: Date.now(),
method: null,
connectionId,
providerConfigKey,
messages: [
{
content: `Configuration not found using the providerConfigKey: ${providerConfigKey} and the account id: ${accountId}}`,
timestamp: Date.now()
}
]
});
log.level = 'error';
log.end = Date.now();
log.success = false;
log.timestamp = Date.now();
log.messages = [
{
content: `Configuration not found using the providerConfigKey: ${providerConfigKey} and the account id: ${accountId}}`,
timestamp: Date.now()
}
];
fileLogger.error('', log);

errorManager.errRes(res, 'unknown_provider_config');
throw new Error(`Provider config not found`);
Expand All @@ -74,6 +66,7 @@ export const getConnectionCredentials = async (res: Response, connectionId: stri
connection,
config,
template as ProviderTemplateOAuth2,
log,
instantRefresh
);
}
Expand Down

0 comments on commit f6b5c9b

Please sign in to comment.