0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00
logto/packages/schemas/alterations/1.0.0_rc.0-1672815959-user-roles.ts
2023-02-02 22:21:34 +08:00

77 lines
2.1 KiB
TypeScript

import { sql } from 'slonik';
import type { AlterationScript } from '../lib/types/alteration.js';
const alteration: AlterationScript = {
up: async (pool) => {
await pool.query(sql`
create table users_roles (
user_id varchar(21) not null references users (id) on update cascade on delete cascade,
role_id varchar(21) not null references roles (id) on update cascade on delete cascade,
primary key (user_id, role_id)
);
`);
const users = await pool.any<{ id: string; roleNames: string[] }>(sql`
select * from users where jsonb_array_length(role_names) > 0
`);
const roles = await pool.any<{ id: string; name: string }>(sql`
select * from roles
`);
for (const user of users) {
for (const roleName of user.roleNames) {
if (!roleName) {
continue;
}
const role = roles.find(({ name }) => name === roleName);
if (!role) {
throw new Error(`Unable to find role: ${roleName}`);
}
// eslint-disable-next-line no-await-in-loop
await pool.query(sql`
insert into users_roles (user_id, role_id) values (${user.id}, ${role.id})
`);
}
}
await pool.query(sql`
alter table users drop column role_names
`);
},
down: async (pool) => {
await pool.query(sql`
alter table users add column role_names jsonb not null default '[]'::jsonb
`);
const relations = await pool.any<{ userId: string; roleId: string }>(sql`
select * from users_roles
`);
const roles = await pool.any<{ id: string; name: string }>(sql`
select * from roles
`);
for (const relation of relations) {
const role = roles.find(({ id }) => id === relation.roleId);
if (!role) {
continue;
}
// eslint-disable-next-line no-await-in-loop
await pool.query(sql`
update users
set role_names = role_names || ${sql.jsonb([role.name])}
where id = ${relation.userId}
`);
}
await pool.query(sql`
drop table users_roles;
`);
},
};
export default alteration;