1
1
mirror of https://github.com/n8n-io/n8n.git synced 2024-09-11 13:15:28 +03:00

fix: Fix typeorm .save usage (no-changelog) (#8678)

This commit is contained in:
Tomi Turtiainen 2024-02-20 17:34:54 +02:00 committed by GitHub
parent afd2eb1f4a
commit 05e13a68ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 96 additions and 57 deletions

View File

@ -216,10 +216,13 @@ export const processUsers = async (
export const saveLdapSynchronization = async (
data: Omit<AuthProviderSyncHistory, 'id' | 'providerType'>,
): Promise<void> => {
await Container.get(AuthProviderSyncHistoryRepository).save({
...data,
providerType: 'ldap',
});
await Container.get(AuthProviderSyncHistoryRepository).save(
{
...data,
providerType: 'ldap',
},
{ transaction: false },
);
};
/**
@ -257,15 +260,20 @@ export const getMappingAttributes = (ldapConfig: LdapConfig): string[] => {
};
export const createLdapAuthIdentity = async (user: User, ldapId: string) => {
return await Container.get(AuthIdentityRepository).save(AuthIdentity.create(user, ldapId));
return await Container.get(AuthIdentityRepository).save(AuthIdentity.create(user, ldapId), {
transaction: false,
});
};
export const createLdapUserOnLocalDb = async (data: Partial<User>, ldapId: string) => {
const user = await Container.get(UserRepository).save({
password: randomPassword(),
role: 'global:member',
...data,
});
const user = await Container.get(UserRepository).save(
{
password: randomPassword(),
role: 'global:member',
...data,
},
{ transaction: false },
);
await createLdapAuthIdentity(user, ldapId);
return user;
};

View File

@ -163,7 +163,7 @@ export class InvitationController {
invitee.lastName = lastName;
invitee.password = await this.passwordUtility.hash(validPassword);
const updatedUser = await this.userRepository.save(invitee);
const updatedUser = await this.userRepository.save(invitee, { transaction: false });
await issueCookie(res, updatedUser);

View File

@ -104,12 +104,13 @@ export class MeController {
*/
@Patch('/password')
async updatePassword(req: MeRequest.Password, res: Response) {
const { user } = req;
const { currentPassword, newPassword } = req.body;
// If SAML is enabled, we don't allow the user to change their email address
if (isSamlLicensedAndEnabled()) {
this.logger.debug('Attempted to change password for user, while SAML is enabled', {
userId: req.user?.id,
userId: user.id,
});
throw new BadRequestError(
'With SAML enabled, users need to use their SAML provider to change passwords',
@ -120,33 +121,30 @@ export class MeController {
throw new BadRequestError('Invalid payload.');
}
if (!req.user.password) {
if (!user.password) {
throw new BadRequestError('Requesting user not set up.');
}
const isCurrentPwCorrect = await this.passwordUtility.compare(
currentPassword,
req.user.password,
);
const isCurrentPwCorrect = await this.passwordUtility.compare(currentPassword, user.password);
if (!isCurrentPwCorrect) {
throw new BadRequestError('Provided current password is incorrect.');
}
const validPassword = this.passwordUtility.validate(newPassword);
req.user.password = await this.passwordUtility.hash(validPassword);
user.password = await this.passwordUtility.hash(validPassword);
const user = await this.userRepository.save(req.user);
const updatedUser = await this.userRepository.save(user, { transaction: false });
this.logger.info('Password updated successfully', { userId: user.id });
await issueCookie(res, user);
await issueCookie(res, updatedUser);
void this.internalHooks.onUserUpdate({
user,
user: updatedUser,
fields_changed: ['password'],
});
await this.externalHooks.run('user.password.update', [user.email, req.user.password]);
await this.externalHooks.run('user.password.update', [updatedUser.email, updatedUser.password]);
return { success: true };
}
@ -168,11 +166,13 @@ export class MeController {
throw new BadRequestError('Personalization answers are mandatory');
}
await this.userRepository.save({
id: req.user.id,
// @ts-ignore
personalizationAnswers,
});
await this.userRepository.save(
{
id: req.user.id,
personalizationAnswers,
},
{ transaction: false },
);
this.logger.info('User survey updated successfully', { userId: req.user.id });

View File

@ -76,7 +76,7 @@ export class OwnerController {
await validateEntity(owner);
owner = await this.userRepository.save(owner);
owner = await this.userRepository.save(owner, { transaction: false });
this.logger.info('Owner was set up successfully', { userId });

View File

@ -12,7 +12,11 @@ export class SettingsRepository extends Repository<Settings> {
}
async getEncryptedSecretsProviderSettings(): Promise<string | null> {
return (await this.findOne({ where: { key: EXTERNAL_SECRETS_DB_KEY } }))?.value ?? null;
return (await this.findByKey(EXTERNAL_SECRETS_DB_KEY))?.value ?? null;
}
async findByKey(key: string): Promise<Settings | null> {
return await this.findOneBy({ key });
}
async saveEncryptedSecretsProviderSettings(data: string): Promise<void> {
@ -38,7 +42,7 @@ export class SettingsRepository extends Repository<Settings> {
await this.update({ key }, { value, loadOnStartup: true });
} else {
value = JSON.stringify([bannerName]);
await this.save({ key, value, loadOnStartup: true });
await this.save({ key, value, loadOnStartup: true }, { transaction: false });
}
config.set(key, value);
return { success: true };

View File

@ -492,7 +492,7 @@ export class SourceControlImportService {
key,
value: valueOverrides[key],
});
await Container.get(VariablesRepository).save(newVariable);
await Container.get(VariablesRepository).save(newVariable, { transaction: false });
}
}

View File

@ -173,11 +173,14 @@ export class SourceControlPreferencesService {
if (saveToDb) {
const settingsValue = JSON.stringify(this._sourceControlPreferences);
try {
await Container.get(SettingsRepository).save({
key: SOURCE_CONTROL_PREFERENCES_DB_KEY,
value: settingsValue,
loadOnStartup: true,
});
await Container.get(SettingsRepository).save(
{
key: SOURCE_CONTROL_PREFERENCES_DB_KEY,
value: settingsValue,
loadOnStartup: true,
},
{ transaction: false },
);
} catch (error) {
throw new ApplicationError('Failed to save source control preferences', { cause: error });
}

View File

@ -71,10 +71,13 @@ export class VariablesService {
this.validateVariable(variable);
void Container.get(InternalHooks).onVariableCreated({ variable_type: variable.type });
const saveResult = await this.variablesRepository.save({
...variable,
id: generateNanoId(),
});
const saveResult = await this.variablesRepository.save(
{
...variable,
id: generateNanoId(),
},
{ transaction: false },
);
await this.updateCache();
return saveResult;
}

View File

@ -27,7 +27,7 @@ export class TagService {
await this.externalHooks.run(`tag.before${action}`, [tag]);
const savedTag = this.tagRepository.save(tag);
const savedTag = this.tagRepository.save(tag, { transaction: false });
await this.externalHooks.run(`tag.after${action}`, [tag]);

View File

@ -287,13 +287,18 @@ export class SamlService {
let result: Settings;
if (samlPreferences) {
samlPreferences.value = settingsValue;
result = await Container.get(SettingsRepository).save(samlPreferences);
} else {
result = await Container.get(SettingsRepository).save({
key: SAML_PREFERENCES_DB_KEY,
value: settingsValue,
loadOnStartup: true,
result = await Container.get(SettingsRepository).save(samlPreferences, {
transaction: false,
});
} else {
result = await Container.get(SettingsRepository).save(
{
key: SAML_PREFERENCES_DB_KEY,
value: settingsValue,
loadOnStartup: true,
},
{ transaction: false },
);
}
if (result) return jsonParse<SamlPreferences>(result.value);
return;

View File

@ -109,10 +109,12 @@ export async function createUserFromSamlAttributes(attributes: SamlUserAttribute
authIdentity.providerId = attributes.userPrincipalName;
authIdentity.providerType = 'saml';
authIdentity.user = user;
const resultAuthIdentity = await Container.get(AuthIdentityRepository).save(authIdentity);
const resultAuthIdentity = await Container.get(AuthIdentityRepository).save(authIdentity, {
transaction: false,
});
if (!resultAuthIdentity) throw new AuthError('Could not create AuthIdentity');
user.authIdentities = [authIdentity];
const resultUser = await Container.get(UserRepository).save(user);
const resultUser = await Container.get(UserRepository).save(user, { transaction: false });
if (!resultUser) throw new AuthError('Could not create User');
return resultUser;
}
@ -133,10 +135,10 @@ export async function updateUserFromSamlAttributes(
} else {
samlAuthIdentity.providerId = attributes.userPrincipalName;
}
await Container.get(AuthIdentityRepository).save(samlAuthIdentity);
await Container.get(AuthIdentityRepository).save(samlAuthIdentity, { transaction: false });
user.firstName = attributes.firstName;
user.lastName = attributes.lastName;
const resultUser = await Container.get(UserRepository).save(user);
const resultUser = await Container.get(UserRepository).save(user, { transaction: false });
if (!resultUser) throw new AuthError('Could not create User');
return resultUser;
}

View File

@ -13,11 +13,14 @@ export async function setCurrentAuthenticationMethod(
authenticationMethod: AuthProviderType,
): Promise<void> {
config.set('userManagement.authenticationMethod', authenticationMethod);
await Container.get(SettingsRepository).save({
key: 'userManagement.authenticationMethod',
value: authenticationMethod,
loadOnStartup: true,
});
await Container.get(SettingsRepository).save(
{
key: 'userManagement.authenticationMethod',
value: authenticationMethod,
loadOnStartup: true,
},
{ transaction: false },
);
}
export function getCurrentAuthenticationMethod(): AuthProviderType {

View File

@ -192,6 +192,17 @@ describe('MeController', () => {
});
});
describe('storeSurveyAnswers', () => {
it('should throw BadRequestError if answers are missing in the payload', async () => {
const req = mock<MeRequest.SurveyAnswers>({
body: undefined,
});
await expect(controller.storeSurveyAnswers(req)).rejects.toThrowError(
new BadRequestError('Personalization answers are mandatory'),
);
});
});
describe('API Key methods', () => {
let req: AuthenticatedRequest;
beforeAll(() => {

View File

@ -95,7 +95,7 @@ describe('OwnerController', () => {
await controller.setupOwner(req, res);
expect(userRepository.save).toHaveBeenCalledWith(user);
expect(userRepository.save).toHaveBeenCalledWith(user, { transaction: false });
const cookieOptions = captor<CookieOptions>();
expect(res.cookie).toHaveBeenCalledWith(AUTH_COOKIE_NAME, 'signed-token', cookieOptions);