0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-31 22:51:25 -05:00

fix(core): align jsonb replace mode (#1138)

This commit is contained in:
Wang Sijie 2022-06-17 14:45:39 +08:00 committed by GitHub
parent ae0caa8f8b
commit 3cf34b5911
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 15 additions and 85 deletions

View file

@ -43,9 +43,8 @@ const updateApplication = buildUpdateWhere<CreateApplication, Application>(Appli
export const updateApplicationById = async (
id: string,
set: Partial<OmitAutoSetFields<CreateApplication>>,
jsonbMode: 'replace' | 'merge' = 'merge'
) => updateApplication({ set, where: { id }, jsonbMode });
set: Partial<OmitAutoSetFields<CreateApplication>>
) => updateApplication({ set, where: { id }, jsonbMode: 'replace' });
export const deleteApplicationById = async (id: string) => {
const { rowCount } = await envSet.pool.query(sql`

View file

@ -16,12 +16,9 @@ export const getSetting = async () =>
where ${fields.id}=${defaultSettingId}
`);
export const updateSetting = async (
setting: Partial<OmitAutoSetFields<CreateSetting>>,
jsonbMode: 'replace' | 'merge' = 'merge'
) => {
export const updateSetting = async (setting: Partial<OmitAutoSetFields<CreateSetting>>) => {
return buildUpdateWhere<CreateSetting, Setting>(
Settings,
true
)({ set: setting, where: { id: defaultSettingId }, jsonbMode });
)({ set: setting, where: { id: defaultSettingId }, jsonbMode: 'merge' });
};

View file

@ -55,9 +55,7 @@ describe('sign-in-experience query', () => {
/* eslint-disable sql/no-unsafe-query */
const expectSql = `
update "sign_in_experiences"
set
"terms_of_use"=
coalesce("terms_of_use",'{}'::jsonb)|| $1
set "terms_of_use"=$1
where "id"=$2
returning *
`;

View file

@ -14,10 +14,8 @@ const updateSignInExperience = buildUpdateWhere<CreateSignInExperience, SignInEx
const id = 'default';
export const updateDefaultSignInExperience = async (
set: Partial<CreateSignInExperience>,
jsonbMode: 'replace' | 'merge' = 'merge'
) => updateSignInExperience({ set, where: { id }, jsonbMode });
export const updateDefaultSignInExperience = async (set: Partial<CreateSignInExperience>) =>
updateSignInExperience({ set, where: { id }, jsonbMode: 'replace' });
export const findDefaultSignInExperience = async () =>
envSet.pool.one<SignInExperience>(sql`

View file

@ -23,7 +23,6 @@ import {
findUsers,
updateUserById,
deleteUserById,
clearUserCustomDataById,
deleteUserIdentity,
} from './user';
@ -366,42 +365,6 @@ describe('user query', () => {
await expect(deleteUserById(id)).rejects.toMatchError(new DeletionError(Users.table, id));
});
it('clearUserCustomDataById', async () => {
const id = 'foo';
const expectSql = sql`
update ${table}
set ${fields.customData}='{}'::jsonb
where ${fields.id}=$1
`;
mockQuery.mockImplementationOnce(async (sql, values) => {
expectSqlAssert(sql, expectSql.sql);
expect(values).toEqual([id]);
return createMockQueryResult([dbvalue]);
});
await clearUserCustomDataById(id);
});
it('clearUserCustomDataById should throw when user can not be found by id', async () => {
const id = 'foo';
const expectSql = sql`
update ${table}
set ${fields.customData}='{}'::jsonb
where ${fields.id}=$1
`;
mockQuery.mockImplementationOnce(async (sql, values) => {
expectSqlAssert(sql, expectSql.sql);
expect(values).toEqual([id]);
return createMockQueryResult([]);
});
await expect(clearUserCustomDataById(id)).rejects.toThrowError();
});
it('deleteUserIdentity', async () => {
const userId = 'foo';
const target = 'connector1';

View file

@ -5,7 +5,7 @@ import { buildInsertInto } from '@/database/insert-into';
import { buildUpdateWhere } from '@/database/update-where';
import { conditionalSql, convertToIdentifiers, OmitAutoSetFields } from '@/database/utils';
import envSet from '@/env-set';
import { DeletionError, UpdateError } from '@/errors/SlonikError';
import { DeletionError } from '@/errors/SlonikError';
const { table, fields } = convertToIdentifiers(Users);
@ -131,18 +131,6 @@ export const deleteUserById = async (id: string) => {
}
};
export const clearUserCustomDataById = async (id: string) => {
const { rowCount } = await envSet.pool.query<User>(sql`
update ${table}
set ${fields.customData}='{}'::jsonb
where ${fields.id}=${id}
`);
if (rowCount < 1) {
throw new UpdateError(Users, { set: { customData: {} }, where: { id }, jsonbMode: 'replace' });
}
};
export const deleteUserIdentity = async (userId: string, target: string) =>
envSet.pool.one<User>(sql`
update ${table}

View file

@ -11,7 +11,6 @@ import {
updateUserById,
deleteUserIdentity,
deleteUserById,
clearUserCustomDataById,
} from '@/queries/user';
import { createRequester } from '@/utils/test-utils';
@ -51,7 +50,6 @@ jest.mock('@/queries/user', () => ({
...user,
})
),
clearUserCustomDataById: jest.fn(),
deleteUserIdentity: jest.fn(),
}));
@ -169,15 +167,6 @@ describe('adminUserRoutes', () => {
});
});
it('PATCH /users/:userId should call clearUserCustomDataById if customData is present', async () => {
const updateNameResponse = await userRequest.patch('/users/foo').send({ customData: {} });
expect(updateNameResponse.status).toEqual(200);
expect(updateNameResponse.body).toEqual({
...mockUserResponse,
});
expect(clearUserCustomDataById).toHaveBeenCalledTimes(1);
});
it('PATCH /users/:userId should updated with one field if the other is undefined', async () => {
const name = 'Micheal';

View file

@ -12,7 +12,6 @@ import koaGuard from '@/middleware/koa-guard';
import koaPagination from '@/middleware/koa-pagination';
import { findRolesByRoleNames } from '@/queries/roles';
import {
clearUserCustomDataById,
deleteUserById,
deleteUserIdentity,
findUsers,
@ -124,11 +123,6 @@ export default function adminUserRoutes<T extends AuthedRouter>(router: T) {
await findUserById(userId);
// Clear customData to achieve full replacement
if (body.customData) {
await clearUserCustomDataById(userId);
}
// Temp solution to validate the existence of input roleNames
if (body.roleNames?.length) {
const { roleNames } = body;
@ -143,9 +137,13 @@ export default function adminUserRoutes<T extends AuthedRouter>(router: T) {
}
}
const user = await updateUserById(userId, {
...body,
});
const user = await updateUserById(
userId,
{
...body,
},
'replace'
);
ctx.body = pick(user, ...userInfoSelectFields);