Skip to content

Commit

Permalink
πŸ”Š Added logs to credentials, executions and workflows (#2915)
Browse files Browse the repository at this point in the history
* Added logs to credentials, executions and workflows

* Some updates according to ivov's feedback

* ⚑ update log levels

* βœ… fix tests

Co-authored-by: Ben Hesseldieck <b.hesseldieck@gmail.com>
  • Loading branch information
krynble and BHesseldieck committed Mar 7, 2022
1 parent 1f2a39b commit 8c84df8
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 27 deletions.
3 changes: 2 additions & 1 deletion packages/cli/src/CredentialsHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
Workflow,
WorkflowExecuteMode,
ITaskDataConnections,
LoggerProxy as Logger,
} from 'n8n-workflow';

// eslint-disable-next-line import/no-cycle
Expand Down Expand Up @@ -668,7 +669,7 @@ export class CredentialsHelper extends ICredentialsHelper {
};
}
}

Logger.debug('Credential test failed', error);
return {
status: 'Error',
message: error.message.toString(),
Expand Down
106 changes: 104 additions & 2 deletions packages/cli/src/Server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,7 @@ class App {
});

if (!savedWorkflow) {
LoggerProxy.error('Failed to create workflow', { userId: req.user.id });
throw new ResponseHelper.ResponseError('Failed to save workflow');
}

Expand Down Expand Up @@ -938,6 +939,10 @@ class App {
});

if (!shared) {
LoggerProxy.info('User attempted to access a workflow without permissions', {
workflowId,
userId: req.user.id,
});
throw new ResponseHelper.ResponseError(
`Workflow with ID "${workflowId}" could not be found.`,
undefined,
Expand Down Expand Up @@ -976,6 +981,10 @@ class App {
});

if (!shared) {
LoggerProxy.info('User attempted to update a workflow without permissions', {
workflowId,
userId: req.user.id,
});
throw new ResponseHelper.ResponseError(
`Workflow with ID "${workflowId}" could not be found to be updated.`,
undefined,
Expand Down Expand Up @@ -1114,6 +1123,10 @@ class App {
});

if (!shared) {
LoggerProxy.info('User attempted to delete a workflow without permissions', {
workflowId,
userId: req.user.id,
});
throw new ResponseHelper.ResponseError(
`Workflow with ID "${workflowId}" could not be found to be deleted.`,
undefined,
Expand Down Expand Up @@ -1573,6 +1586,11 @@ class App {
});

if (!shared) {
LoggerProxy.info('User attempted to access workflow errors without permissions', {
workflowId,
userId: req.user.id,
});

throw new ResponseHelper.ResponseError(
`Workflow with ID "${workflowId}" could not be found.`,
undefined,
Expand Down Expand Up @@ -1653,6 +1671,7 @@ class App {
const { id: credentialId } = req.query;

if (!credentialId) {
LoggerProxy.error('OAuth1 credential authorization failed due to missing credential ID');
throw new ResponseHelper.ResponseError(
'Required credential ID is missing',
undefined,
Expand All @@ -1663,6 +1682,10 @@ class App {
const credential = await getCredentialForUser(credentialId, req.user);

if (!credential) {
LoggerProxy.error(
'OAuth1 credential authorization failed because the current user does not have the correct permissions',
{ userId: req.user.id },
);
throw new ResponseHelper.ResponseError(
RESPONSE_ERROR_MESSAGES.NO_CREDENTIAL,
undefined,
Expand Down Expand Up @@ -1757,6 +1780,11 @@ class App {
// Update the credentials in DB
await Db.collections.Credentials!.update(credentialId, newCredentialsData);

LoggerProxy.verbose('OAuth1 authorization successful for new credential', {
userId: req.user.id,
credentialId,
});

return returnUri;
}),
);
Expand All @@ -1776,12 +1804,23 @@ class App {
undefined,
503,
);
LoggerProxy.error(
'OAuth1 callback failed because of insufficient parameters received',
{
userId: req.user.id,
credentialId,
},
);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}

const credential = await getCredentialForUser(credentialId, req.user);

if (!credential) {
LoggerProxy.error('OAuth1 callback failed because of insufficient user permissions', {
userId: req.user.id,
credentialId,
});
const errorResponse = new ResponseHelper.ResponseError(
RESPONSE_ERROR_MESSAGES.NO_CREDENTIAL,
undefined,
Expand Down Expand Up @@ -1829,6 +1868,10 @@ class App {
try {
oauthToken = await requestPromise(options);
} catch (error) {
LoggerProxy.error('Unable to fetch tokens for OAuth1 callback', {
userId: req.user.id,
credentialId,
});
const errorResponse = new ResponseHelper.ResponseError(
'Unable to get access tokens!',
undefined,
Expand All @@ -1855,8 +1898,16 @@ class App {
// Save the credentials in DB
await Db.collections.Credentials!.update(credentialId, newCredentialsData);

LoggerProxy.verbose('OAuth1 callback successful for new credential', {
userId: req.user.id,
credentialId,
});
res.sendFile(pathResolve(__dirname, '../../templates/oauth-callback.html'));
} catch (error) {
LoggerProxy.error('OAuth1 callback failed because of insufficient user permissions', {
userId: req.user.id,
credentialId: req.query.cid,
});
// Error response
return ResponseHelper.sendErrorResponse(res, error);
}
Expand Down Expand Up @@ -1884,6 +1935,10 @@ class App {
const credential = await getCredentialForUser(credentialId, req.user);

if (!credential) {
LoggerProxy.error('Failed to authorize OAuth2 due to lack of permissions', {
userId: req.user.id,
credentialId,
});
throw new ResponseHelper.ResponseError(
RESPONSE_ERROR_MESSAGES.NO_CREDENTIAL,
undefined,
Expand Down Expand Up @@ -1971,6 +2026,10 @@ class App {
returnUri += `&${authQueryParameters}`;
}

LoggerProxy.verbose('OAuth2 authentication successful for new credential', {
userId: req.user.id,
credentialId,
});
return returnUri;
}),
);
Expand Down Expand Up @@ -2013,6 +2072,10 @@ class App {
const credential = await getCredentialForUser(state.cid, req.user);

if (!credential) {
LoggerProxy.error('OAuth2 callback failed because of insufficient permissions', {
userId: req.user.id,
credentialId: state.cid,
});
const errorResponse = new ResponseHelper.ResponseError(
RESPONSE_ERROR_MESSAGES.NO_CREDENTIAL,
undefined,
Expand Down Expand Up @@ -2051,6 +2114,10 @@ class App {
decryptedDataOriginal.csrfSecret === undefined ||
!token.verify(decryptedDataOriginal.csrfSecret as string, state.token)
) {
LoggerProxy.debug('OAuth2 callback state is invalid', {
userId: req.user.id,
credentialId: state.cid,
});
const errorResponse = new ResponseHelper.ResponseError(
'The OAuth2 callback state is invalid!',
undefined,
Expand Down Expand Up @@ -2098,6 +2165,10 @@ class App {
}

if (oauthToken === undefined) {
LoggerProxy.error('OAuth2 callback failed: unable to get access tokens', {
userId: req.user.id,
credentialId: state.cid,
});
const errorResponse = new ResponseHelper.ResponseError(
'Unable to get access tokens!',
undefined,
Expand Down Expand Up @@ -2128,6 +2199,10 @@ class App {
newCredentialsData.updatedAt = this.getCurrentDate();
// Save the credentials in DB
await Db.collections.Credentials!.update(state.cid, newCredentialsData);
LoggerProxy.verbose('OAuth2 callback successful for new credential', {
userId: req.user.id,
credentialId: state.cid,
});

res.sendFile(pathResolve(__dirname, '../../templates/oauth-callback.html'));
} catch (error) {
Expand Down Expand Up @@ -2277,7 +2352,16 @@ class App {
},
});

if (!execution) return undefined;
if (!execution) {
LoggerProxy.info(
'Attempt to read execution was blocked due to insufficient permissions',
{
userId: req.user.id,
executionId,
},
);
return undefined;
}

if (req.query.unflattedResponse === 'true') {
return ResponseHelper.unflattenExecutionData(execution);
Expand Down Expand Up @@ -2312,6 +2396,13 @@ class App {
});

if (!execution) {
LoggerProxy.info(
'Attempt to retry an execution was blocked due to insufficient permissions',
{
userId: req.user.id,
executionId,
},
);
throw new ResponseHelper.ResponseError(
`The execution with the ID "${executionId}" does not exist.`,
404,
Expand Down Expand Up @@ -2387,6 +2478,11 @@ class App {
// Find the data of the last executed node in the new workflow
const node = workflowInstance.getNode(stack.node.name);
if (node === null) {
LoggerProxy.error('Failed to retry an execution because a node could not be found', {
userId: req.user.id,
executionId,
nodeName: stack.node.name,
});
throw new Error(
`Could not find the node "${stack.node.name}" in workflow. It probably got deleted or renamed. Without it the workflow can sadly not be retried.`,
);
Expand Down Expand Up @@ -2468,7 +2564,13 @@ class App {
},
});

if (!executions.length) return;
if (!executions.length) {
LoggerProxy.error('Failed to delete an execution due to insufficient permissions', {
userId: req.user.id,
executionIds: ids,
});
return;
}

const idsToDelete = executions.map(({ id }) => id.toString());

Expand Down
Loading

0 comments on commit 8c84df8

Please sign in to comment.