Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added logs to credentials, executions and workflows #2915

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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