ci: Remove unnecessary async/await, enable await-thenable linting rule (no-changelog) (#8076)

## Summary
We accidentally made some functions `async` in
https://github.com/n8n-io/n8n/pull/7846
This PR reverts that change. 

## Review / Merge checklist
- [x] PR title and summary are descriptive.
This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2023-12-19 13:52:42 +01:00 committed by GitHub
parent a7ffed245a
commit 464b565283
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 47 additions and 57 deletions

View file

@ -153,6 +153,9 @@ const config = (module.exports = {
*/ */
'@typescript-eslint/array-type': ['error', { default: 'array-simple' }], '@typescript-eslint/array-type': ['error', { default: 'array-simple' }],
/** https://typescript-eslint.io/rules/await-thenable/ */
'@typescript-eslint/await-thenable': 'error',
/** /**
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-ts-comment.md * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-ts-comment.md
*/ */
@ -477,7 +480,6 @@ const config = (module.exports = {
process.env.NODE_ENV === 'development' ? 'warn' : 'error', process.env.NODE_ENV === 'development' ? 'warn' : 'error',
// TODO: Remove these // TODO: Remove these
'@typescript-eslint/await-thenable': 'off',
'@typescript-eslint/ban-ts-comment': 'off', '@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/naming-convention': 'off', '@typescript-eslint/naming-convention': 'off',
'import/no-duplicates': 'off', 'import/no-duplicates': 'off',

View file

@ -76,7 +76,7 @@
"@types/formidable": "^3.4.0", "@types/formidable": "^3.4.0",
"@types/json-diff": "^1.0.0", "@types/json-diff": "^1.0.0",
"@types/jsonwebtoken": "^9.0.1", "@types/jsonwebtoken": "^9.0.1",
"@types/localtunnel": "^1.9.0", "@types/localtunnel": "^2.0.4",
"@types/lodash": "^4.14.195", "@types/lodash": "^4.14.195",
"@types/passport-jwt": "^3.0.6", "@types/passport-jwt": "^3.0.6",
"@types/psl": "^1.1.0", "@types/psl": "^1.1.0",

View file

@ -276,7 +276,7 @@ export class ActiveWorkflowRunner implements IWebhookManager {
* Get the IDs of active workflows from storage. * Get the IDs of active workflows from storage.
*/ */
async allActiveInStorage(options?: { user: User; scope: Scope | Scope[] }) { async allActiveInStorage(options?: { user: User; scope: Scope | Scope[] }) {
const isFullAccess = !options?.user || (await options.user.hasGlobalScope(options.scope)); const isFullAccess = !options?.user || options.user.hasGlobalScope(options.scope);
const activationErrors = await this.activationErrorsService.getAll(); const activationErrors = await this.activationErrorsService.getAll();
@ -291,7 +291,7 @@ export class ActiveWorkflowRunner implements IWebhookManager {
.filter((workflowId) => !activationErrors[workflowId]); .filter((workflowId) => !activationErrors[workflowId]);
} }
const where = await whereClause({ const where = whereClause({
user: options.user, user: options.user,
globalScope: 'workflow:list', globalScope: 'workflow:list',
entityType: 'workflow', entityType: 'workflow',

View file

@ -579,7 +579,7 @@ export class CredentialsHelper extends ICredentialsHelper {
credentialType, credentialType,
'internal' as WorkflowExecuteMode, 'internal' as WorkflowExecuteMode,
undefined, undefined,
await user.hasGlobalScope('externalSecret:use'), user.hasGlobalScope('externalSecret:use'),
); );
} catch (error) { } catch (error) {
this.logger.debug('Credential test failed', error); this.logger.debug('Credential test failed', error);

View file

@ -466,7 +466,7 @@ export class Server extends AbstractServer {
const shared = await Container.get(SharedWorkflowRepository).findOne({ const shared = await Container.get(SharedWorkflowRepository).findOne({
relations: ['workflow'], relations: ['workflow'],
where: await whereClause({ where: whereClause({
user: req.user, user: req.user,
globalScope: 'workflow:read', globalScope: 'workflow:read',
entityType: 'workflow', entityType: 'workflow',

View file

@ -32,7 +32,7 @@ export class PermissionChecker {
relations: ['globalRole'], relations: ['globalRole'],
}); });
if (await user.hasGlobalScope('workflow:execute')) return; if (user.hasGlobalScope('workflow:execute')) return;
// allow if all creds used in this workflow are a subset of // allow if all creds used in this workflow are a subset of
// all creds accessible to users who have access to this workflow // all creds accessible to users who have access to this workflow

View file

@ -58,7 +58,7 @@ export function rightDiff<T1, T2>(
* Build a `where` clause for a TypeORM entity search, * Build a `where` clause for a TypeORM entity search,
* checking for member access if the user is not an owner. * checking for member access if the user is not an owner.
*/ */
export async function whereClause({ export function whereClause({
user, user,
entityType, entityType,
globalScope, globalScope,
@ -70,10 +70,10 @@ export async function whereClause({
globalScope: Scope; globalScope: Scope;
entityId?: string; entityId?: string;
roles?: string[]; roles?: string[];
}): Promise<WhereClause> { }): WhereClause {
const where: WhereClause = entityId ? { [entityType]: { id: entityId } } : {}; const where: WhereClause = entityId ? { [entityType]: { id: entityId } } : {};
if (!(await user.hasGlobalScope(globalScope))) { if (!user.hasGlobalScope(globalScope)) {
where.user = { id: user.id }; where.user = { id: user.id };
if (roles?.length) { if (roles?.length) {
where.role = { name: In(roles) }; where.role = { name: In(roles) };

View file

@ -422,7 +422,7 @@ export async function replaceInvalidCredentials(workflow: WorkflowEntity): Promi
*/ */
export async function getSharedWorkflowIds(user: User, roles?: RoleNames[]): Promise<string[]> { export async function getSharedWorkflowIds(user: User, roles?: RoleNames[]): Promise<string[]> {
const where: FindOptionsWhere<SharedWorkflow> = {}; const where: FindOptionsWhere<SharedWorkflow> = {};
if (!(await user.hasGlobalScope('workflow:read'))) { if (!user.hasGlobalScope('workflow:read')) {
where.userId = user.id; where.userId = user.id;
} }
if (roles?.length) { if (roles?.length) {

View file

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/await-thenable */
/* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { Container } from 'typedi'; import { Container } from 'typedi';
@ -316,7 +315,6 @@ export class Start extends BaseCommand {
const port = config.getEnv('port'); const port = config.getEnv('port');
// @ts-ignore
const webhookTunnel = await localtunnel(port, tunnelSettings); const webhookTunnel = await localtunnel(port, tunnelSettings);
process.env.WEBHOOK_URL = `${webhookTunnel.url}/`; process.env.WEBHOOK_URL = `${webhookTunnel.url}/`;

View file

@ -96,7 +96,7 @@ export class PasswordResetController {
if ( if (
isSamlCurrentAuthenticationMethod() && isSamlCurrentAuthenticationMethod() &&
!( !(
(user && (await user.hasGlobalScope('user:resetPassword'))) === true || (user && user.hasGlobalScope('user:resetPassword')) === true ||
user?.settings?.allowSSOManualLogin === true user?.settings?.allowSSOManualLogin === true
) )
) { ) {

View file

@ -37,7 +37,7 @@ export class WorkflowStatisticsController {
const workflowId = req.params.id; const workflowId = req.params.id;
const allowed = await this.sharedWorkflowRepository.exist({ const allowed = await this.sharedWorkflowRepository.exist({
relations: ['workflow'], relations: ['workflow'],
where: await whereClause({ where: whereClause({
user, user,
globalScope: 'workflow:read', globalScope: 'workflow:read',
entityType: 'workflow', entityType: 'workflow',

View file

@ -50,7 +50,7 @@ EECredentialsController.get(
const userSharing = credential.shared?.find((shared) => shared.user.id === req.user.id); const userSharing = credential.shared?.find((shared) => shared.user.id === req.user.id);
if (!userSharing && !(await req.user.hasGlobalScope('credential:read'))) { if (!userSharing && !req.user.hasGlobalScope('credential:read')) {
throw new UnauthorizedError('Forbidden.'); throw new UnauthorizedError('Forbidden.');
} }
@ -130,7 +130,7 @@ EECredentialsController.put(
if (!ownsCredential || !credential) { if (!ownsCredential || !credential) {
credential = undefined; credential = undefined;
// Allow owners/admins to share // Allow owners/admins to share
if (await req.user.hasGlobalScope('credential:share')) { if (req.user.hasGlobalScope('credential:share')) {
const sharedRes = await EECredentials.getSharing(req.user, credentialId, { const sharedRes = await EECredentials.getSharing(req.user, credentialId, {
allowGlobalScope: true, allowGlobalScope: true,
globalScope: 'credential:share', globalScope: 'credential:share',

View file

@ -163,7 +163,7 @@ credentialsController.patch(
); );
} }
if (sharing.role.name !== 'owner' && !(await req.user.hasGlobalScope('credential:update'))) { if (sharing.role.name !== 'owner' && !req.user.hasGlobalScope('credential:update')) {
Container.get(Logger).info( Container.get(Logger).info(
'Attempt to update credential blocked due to lack of permissions', 'Attempt to update credential blocked due to lack of permissions',
{ {
@ -232,7 +232,7 @@ credentialsController.delete(
); );
} }
if (sharing.role.name !== 'owner' && !(await req.user.hasGlobalScope('credential:delete'))) { if (sharing.role.name !== 'owner' && !req.user.hasGlobalScope('credential:delete')) {
Container.get(Logger).info( Container.get(Logger).info(
'Attempt to delete credential blocked due to lack of permissions', 'Attempt to delete credential blocked due to lack of permissions',
{ {

View file

@ -40,7 +40,7 @@ export class EECredentialsService extends CredentialsService {
// Omit user from where if the requesting user has relevant // Omit user from where if the requesting user has relevant
// global credential permissions. This allows the user to // global credential permissions. This allows the user to
// access credentials they don't own. // access credentials they don't own.
if (!options.allowGlobalScope || !(await user.hasGlobalScope(options.globalScope))) { if (!options.allowGlobalScope || !user.hasGlobalScope(options.globalScope)) {
where.userId = user.id; where.userId = user.id;
} }

View file

@ -88,7 +88,7 @@ export class CredentialsService {
) { ) {
const findManyOptions = this.toFindManyOptions(options.listQueryOptions); const findManyOptions = this.toFindManyOptions(options.listQueryOptions);
const returnAll = (await user.hasGlobalScope('credential:list')) && !options.onlyOwn; const returnAll = user.hasGlobalScope('credential:list') && !options.onlyOwn;
const isDefaultSelect = !options.listQueryOptions?.select; const isDefaultSelect = !options.listQueryOptions?.select;
if (returnAll) { if (returnAll) {
@ -150,7 +150,7 @@ export class CredentialsService {
// Omit user from where if the requesting user has relevant // Omit user from where if the requesting user has relevant
// global credential permissions. This allows the user to // global credential permissions. This allows the user to
// access credentials they don't own. // access credentials they don't own.
if (!options.allowGlobalScope || !(await user.hasGlobalScope(options.globalScope))) { if (!options.allowGlobalScope || !user.hasGlobalScope(options.globalScope)) {
Object.assign(where, { Object.assign(where, {
userId: user.id, userId: user.id,
role: { name: 'owner' }, role: { name: 'owner' },

View file

@ -134,7 +134,7 @@ export class User extends WithTimestamps implements IUser {
return STATIC_SCOPE_MAP[this.globalRole?.name] ?? []; return STATIC_SCOPE_MAP[this.globalRole?.name] ?? [];
} }
async hasGlobalScope(scope: Scope | Scope[], scopeOptions?: ScopeOptions): Promise<boolean> { hasGlobalScope(scope: Scope | Scope[], scopeOptions?: ScopeOptions): boolean {
return hasScope( return hasScope(
scope, scope,
{ {

View file

@ -15,7 +15,7 @@ export class SharedCredentialsRepository extends Repository<SharedCredentials> {
relations: ['credentials'], relations: ['credentials'],
where: { where: {
credentialsId, credentialsId,
...(!(await user.hasGlobalScope('credential:read')) ? { userId: user.id } : {}), ...(!user.hasGlobalScope('credential:read') ? { userId: user.id } : {}),
}, },
}); });
if (!sharedCredential) return null; if (!sharedCredential) return null;

View file

@ -68,7 +68,7 @@ export const createGlobalScopeMiddleware =
if (!user) return res.status(401).json({ status: 'error', message: 'Unauthorized' }); if (!user) return res.status(401).json({ status: 'error', message: 'Unauthorized' });
const hasScopes = await user.hasGlobalScope(scopes); const hasScopes = user.hasGlobalScope(scopes);
if (!hasScopes) { if (!hasScopes) {
return res.status(403).json({ status: 'error', message: 'Unauthorized' }); return res.status(403).json({ status: 'error', message: 'Unauthorized' });
} }

View file

@ -155,7 +155,7 @@ export class ExecutionsService {
filter, filter,
sharedWorkflowIds, sharedWorkflowIds,
executingWorkflowIds, executingWorkflowIds,
await req.user.hasGlobalScope('workflow:list'), req.user.hasGlobalScope('workflow:list'),
); );
const formattedExecutions = await Container.get(ExecutionRepository).searchExecutions( const formattedExecutions = await Container.get(ExecutionRepository).searchExecutions(

View file

@ -71,7 +71,7 @@ export class WorkflowService {
// Omit user from where if the requesting user has relevant // Omit user from where if the requesting user has relevant
// global workflow permissions. This allows the user to // global workflow permissions. This allows the user to
// access workflows they don't own. // access workflows they don't own.
if (!options.allowGlobalScope || !(await user.hasGlobalScope(options.globalScope))) { if (!options.allowGlobalScope || !user.hasGlobalScope(options.globalScope)) {
where.userId = user.id; where.userId = user.id;
} }
@ -215,7 +215,7 @@ export class WorkflowService {
): Promise<WorkflowEntity> { ): Promise<WorkflowEntity> {
const shared = await this.sharedWorkflowRepository.findOne({ const shared = await this.sharedWorkflowRepository.findOne({
relations: ['workflow', 'role'], relations: ['workflow', 'role'],
where: await whereClause({ where: whereClause({
user, user,
globalScope: 'workflow:update', globalScope: 'workflow:update',
entityType: 'workflow', entityType: 'workflow',
@ -482,7 +482,7 @@ export class WorkflowService {
const sharedWorkflow = await this.sharedWorkflowRepository.findOne({ const sharedWorkflow = await this.sharedWorkflowRepository.findOne({
relations: ['workflow', 'role'], relations: ['workflow', 'role'],
where: await whereClause({ where: whereClause({
user, user,
globalScope: 'workflow:delete', globalScope: 'workflow:delete',
entityType: 'workflow', entityType: 'workflow',

View file

@ -21,7 +21,7 @@ export class WorkflowHistoryService {
private async getSharedWorkflow(user: User, workflowId: string): Promise<SharedWorkflow | null> { private async getSharedWorkflow(user: User, workflowId: string): Promise<SharedWorkflow | null> {
return this.sharedWorkflowRepository.findOne({ return this.sharedWorkflowRepository.findOne({
where: { where: {
...(!(await user.hasGlobalScope('workflow:read')) && { userId: user.id }), ...(!user.hasGlobalScope('workflow:read') && { userId: user.id }),
workflowId, workflowId,
}, },
}); });

View file

@ -67,7 +67,7 @@ EEWorkflowController.put(
if (!ownsWorkflow || !workflow) { if (!ownsWorkflow || !workflow) {
workflow = undefined; workflow = undefined;
// Allow owners/admins to share // Allow owners/admins to share
if (await req.user.hasGlobalScope('workflow:share')) { if (req.user.hasGlobalScope('workflow:share')) {
const sharedRes = await Container.get(WorkflowService).getSharing(req.user, workflowId, { const sharedRes = await Container.get(WorkflowService).getSharing(req.user, workflowId, {
allowGlobalScope: true, allowGlobalScope: true,
globalScope: 'workflow:share', globalScope: 'workflow:share',
@ -136,7 +136,7 @@ EEWorkflowController.get(
} }
const userSharing = workflow.shared?.find((shared) => shared.user.id === req.user.id); const userSharing = workflow.shared?.find((shared) => shared.user.id === req.user.id);
if (!userSharing && !(await req.user.hasGlobalScope('workflow:read'))) { if (!userSharing && !req.user.hasGlobalScope('workflow:read')) {
throw new UnauthorizedError( throw new UnauthorizedError(
'You do not have permission to access this workflow. Ask the owner to share it with you', 'You do not have permission to access this workflow. Ask the owner to share it with you',
); );

View file

@ -209,7 +209,7 @@ workflowsController.get(
const shared = await Container.get(SharedWorkflowRepository).findOne({ const shared = await Container.get(SharedWorkflowRepository).findOne({
relations, relations,
where: await whereClause({ where: whereClause({
user: req.user, user: req.user,
entityType: 'workflow', entityType: 'workflow',
globalScope: 'workflow:read', globalScope: 'workflow:read',

View file

@ -24,20 +24,18 @@ describe('SharedCredentialsRepository', () => {
sharedCredential.credentials = mock<CredentialsEntity>({ id: credentialsId }); sharedCredential.credentials = mock<CredentialsEntity>({ id: credentialsId });
const owner = mock<User>({ const owner = mock<User>({
isOwner: true, isOwner: true,
hasGlobalScope: async (scope) => { hasGlobalScope: (scope) =>
return hasScope(scope, { hasScope(scope, {
global: ownerPermissions, global: ownerPermissions,
}); }),
},
}); });
const member = mock<User>({ const member = mock<User>({
isOwner: false, isOwner: false,
id: 'test', id: 'test',
hasGlobalScope: async (scope) => { hasGlobalScope: (scope) =>
return hasScope(scope, { hasScope(scope, {
global: memberPermissions, global: memberPermissions,
}); }),
},
}); });
beforeEach(() => { beforeEach(() => {

View file

@ -1,7 +1,6 @@
import util from 'util'; import util from 'util';
import type { import type {
IExecuteFunctions, IExecuteFunctions,
GenericValue,
ICredentialDataDecryptedObject, ICredentialDataDecryptedObject,
ICredentialsDecrypted, ICredentialsDecrypted,
ICredentialTestFunctions, ICredentialTestFunctions,
@ -757,17 +756,8 @@ export class Redis implements INodeType {
continue; continue;
} }
const promises: {
[key: string]: GenericValue;
} = {};
for (const keyName of keys) { for (const keyName of keys) {
promises[keyName] = await getValue(client, keyName); item.json[keyName] = await getValue(client, keyName);
}
for (const keyName of keys) {
// eslint-disable-next-line @typescript-eslint/await-thenable
item.json[keyName] = await promises[keyName];
} }
returnItems.push(item); returnItems.push(item);
} else if (operation === 'set') { } else if (operation === 'set') {

View file

@ -706,7 +706,7 @@ describe('RoutingNode', () => {
mode, mode,
); );
const result = await routingNode.getRequestOptionsFromParameters( const result = routingNode.getRequestOptionsFromParameters(
executeSingleFunctions, executeSingleFunctions,
testData.input.nodeTypeProperties, testData.input.nodeTypeProperties,
itemIndex, itemIndex,

View file

@ -749,8 +749,8 @@ importers:
specifier: ^9.0.1 specifier: ^9.0.1
version: 9.0.1 version: 9.0.1
'@types/localtunnel': '@types/localtunnel':
specifier: ^1.9.0 specifier: ^2.0.4
version: 1.9.0 version: 2.0.4
'@types/lodash': '@types/lodash':
specifier: ^4.14.195 specifier: ^4.14.195
version: 4.14.195 version: 4.14.195
@ -9357,8 +9357,10 @@ packages:
/@types/linkify-it@3.0.2: /@types/linkify-it@3.0.2:
resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==} resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==}
/@types/localtunnel@1.9.0: /@types/localtunnel@2.0.4:
resolution: {integrity: sha512-3YxO7RHRrmtYNX6Rhkr97bnXHrF1Ckfo4axENWLcBXWi+8B1WsNbqPqe5Eg6TA5survjAWWvLTu1KQesuLHVgQ==} resolution: {integrity: sha512-7WM5nlEfEKp8MpwthPa2utdy+f/7ZBxMPzu8qw6EijFFTcpzh5CXgt2YoncxWAZNOPNieMofXCKFudtDEY4bag==}
dependencies:
'@types/node': 18.16.16
dev: true dev: true
/@types/lodash-es@4.17.6: /@types/lodash-es@4.17.6: