feat(server): removed role and roleid field dropping from project membership table for rolling forward migration

This commit is contained in:
Akhil Mohan
2024-03-12 21:50:39 +05:30
parent fc57884035
commit 47906c4dd4
13 changed files with 99 additions and 103 deletions
@@ -48,30 +48,14 @@ export async function up(knex: Knex): Promise<void> {
} }
} }
if (rows.length) await knex(TableName.ProjectUserMembershipRole).insert(rows); if (rows.length) await knex(TableName.ProjectUserMembershipRole).insert(rows);
await knex.schema.alterTable(TableName.ProjectMembership, (t) => { // will be dropped later
t.dropColumn("roleId"); // await knex.schema.alterTable(TableName.ProjectMembership, (t) => {
t.dropColumn("role"); // t.dropColumn("roleId");
}); // t.dropColumn("role");
// });
} }
export async function down(knex: Knex): Promise<void> { export async function down(knex: Knex): Promise<void> {
const projectUserMembershipRoleStream = knex.select("*").from(TableName.ProjectUserMembershipRole).stream();
await knex.schema.alterTable(TableName.ProjectMembership, (t) => {
t.string("role");
t.uuid("roleId");
t.foreign("roleId").references("id").inTable(TableName.ProjectRoles);
});
for await (const row of projectUserMembershipRoleStream) {
await knex(TableName.ProjectMembership).where({ id: row.projectMembershipId }).update({
// @ts-ignore - since the latest one doesn't have roleId anymore there will be type error here
roleId: row.customRoleId,
role: row.role
});
}
await knex.schema.alterTable(TableName.ProjectMembership, (t) => {
t.string("role").notNullable().alter({ alterNullable: true });
});
await knex.schema.dropTableIfExists(TableName.ProjectUserMembershipRole); await knex.schema.dropTableIfExists(TableName.ProjectUserMembershipRole);
await dropOnUpdateTrigger(knex, TableName.ProjectUserMembershipRole); await dropOnUpdateTrigger(knex, TableName.ProjectUserMembershipRole);
} }
@@ -51,30 +51,13 @@ export async function up(knex: Knex): Promise<void> {
} }
} }
if(rows.length) await knex(TableName.IdentityProjectMembershipRole).insert(rows); if(rows.length) await knex(TableName.IdentityProjectMembershipRole).insert(rows);
await knex.schema.alterTable(TableName.IdentityProjectMembership, (t) => { // await knex.schema.alterTable(TableName.IdentityProjectMembership, (t) => {
t.dropColumn("roleId"); // t.dropColumn("roleId");
t.dropColumn("role"); // t.dropColumn("role");
}); // });
} }
export async function down(knex: Knex): Promise<void> { export async function down(knex: Knex): Promise<void> {
const projectIdentityMembershipRoleStream = knex.select("*").from(TableName.IdentityProjectMembershipRole).stream();
await knex.schema.alterTable(TableName.IdentityProjectMembership, (t) => {
t.string("role");
t.uuid("roleId");
t.foreign("roleId").references("id").inTable(TableName.ProjectRoles);
});
for await (const row of projectIdentityMembershipRoleStream) {
await knex(TableName.IdentityProjectMembership).where({ id: row.projectMembershipId }).update({
// @ts-ignore - since the latest one doesn't have roleId anymore there will be type error here
roleId: row.customRoleId,
role: row.role
});
}
await knex.schema.alterTable(TableName.IdentityProjectMembership, (t) => {
t.string("role").notNullable().alter({ alterNullable: true });
});
await knex.schema.dropTableIfExists(TableName.IdentityProjectMembershipRole); await knex.schema.dropTableIfExists(TableName.IdentityProjectMembershipRole);
await dropOnUpdateTrigger(knex, TableName.IdentityProjectMembershipRole); await dropOnUpdateTrigger(knex, TableName.IdentityProjectMembershipRole);
} }
@@ -9,6 +9,8 @@ import { TImmutableDBKeys } from "./models";
export const IdentityProjectMembershipsSchema = z.object({ export const IdentityProjectMembershipsSchema = z.object({
id: z.string().uuid(), id: z.string().uuid(),
role: z.string(),
roleId: z.string().uuid().nullable().optional(),
projectId: z.string(), projectId: z.string(),
identityId: z.string().uuid(), identityId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
@@ -9,10 +9,12 @@ import { TImmutableDBKeys } from "./models";
export const ProjectMembershipsSchema = z.object({ export const ProjectMembershipsSchema = z.object({
id: z.string().uuid(), id: z.string().uuid(),
role: z.string(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
userId: z.string().uuid(), userId: z.string().uuid(),
projectId: z.string() projectId: z.string(),
roleId: z.string().uuid().nullable().optional()
}); });
export type TProjectMemberships = z.infer<typeof ProjectMembershipsSchema>; export type TProjectMemberships = z.infer<typeof ProjectMembershipsSchema>;
+2 -1
View File
@@ -33,7 +33,8 @@ export async function seed(knex: Knex): Promise<void> {
const projectMembership = await knex(TableName.ProjectMembership) const projectMembership = await knex(TableName.ProjectMembership)
.insert({ .insert({
projectId: project.id, projectId: project.id,
userId: seedData1.id userId: seedData1.id,
role: ProjectMembershipRole.Admin
}) })
.returning("*"); .returning("*");
await knex(TableName.ProjectUserMembershipRole).insert({ await knex(TableName.ProjectUserMembershipRole).insert({
+2 -1
View File
@@ -78,7 +78,8 @@ export async function seed(knex: Knex): Promise<void> {
const identityProjectMembership = await knex(TableName.IdentityProjectMembership) const identityProjectMembership = await knex(TableName.IdentityProjectMembership)
.insert({ .insert({
identityId: seedData1.machineIdentity.id, identityId: seedData1.machineIdentity.id,
projectId: seedData1.project.id projectId: seedData1.project.id,
role: ProjectMembershipRole.Admin
}) })
.returning("*"); .returning("*");
@@ -63,6 +63,8 @@ export const permissionDALFactory = (db: TDbClient) => {
.select(selectAllTableCols(TableName.ProjectUserMembershipRole)) .select(selectAllTableCols(TableName.ProjectUserMembershipRole))
.select( .select(
db.ref("id").withSchema(TableName.ProjectMembership).as("membershipId"), db.ref("id").withSchema(TableName.ProjectMembership).as("membershipId"),
// TODO(roll-forward-migration): remove this field when we drop this in next migration after a week
db.ref("role").withSchema(TableName.ProjectMembership).as("oldRoleField"),
db.ref("createdAt").withSchema(TableName.ProjectMembership).as("membershipCreatedAt"), db.ref("createdAt").withSchema(TableName.ProjectMembership).as("membershipCreatedAt"),
db.ref("updatedAt").withSchema(TableName.ProjectMembership).as("membershipUpdatedAt"), db.ref("updatedAt").withSchema(TableName.ProjectMembership).as("membershipUpdatedAt"),
db.ref("authEnforced").withSchema(TableName.Organization).as("orgAuthEnforced"), db.ref("authEnforced").withSchema(TableName.Organization).as("orgAuthEnforced"),
@@ -74,10 +76,18 @@ export const permissionDALFactory = (db: TDbClient) => {
const permission = sqlNestRelationships({ const permission = sqlNestRelationships({
data: docs, data: docs,
key: "membershipId", key: "membershipId",
parentMapper: ({ orgId, orgAuthEnforced, membershipId, membershipCreatedAt, membershipUpdatedAt }) => ({ parentMapper: ({
orgId,
orgAuthEnforced,
membershipId,
membershipCreatedAt,
membershipUpdatedAt,
oldRoleField
}) => ({
orgId, orgId,
orgAuthEnforced, orgAuthEnforced,
userId, userId,
role: oldRoleField,
id: membershipId, id: membershipId,
projectId, projectId,
createdAt: membershipCreatedAt, createdAt: membershipCreatedAt,
@@ -124,6 +134,7 @@ export const permissionDALFactory = (db: TDbClient) => {
.select(selectAllTableCols(TableName.IdentityProjectMembershipRole)) .select(selectAllTableCols(TableName.IdentityProjectMembershipRole))
.select( .select(
db.ref("id").withSchema(TableName.IdentityProjectMembership).as("membershipId"), db.ref("id").withSchema(TableName.IdentityProjectMembership).as("membershipId"),
db.ref("role").withSchema(TableName.IdentityProjectMembership).as("oldRoleField"),
db.ref("createdAt").withSchema(TableName.IdentityProjectMembership).as("membershipCreatedAt"), db.ref("createdAt").withSchema(TableName.IdentityProjectMembership).as("membershipCreatedAt"),
db.ref("updatedAt").withSchema(TableName.IdentityProjectMembership).as("membershipUpdatedAt"), db.ref("updatedAt").withSchema(TableName.IdentityProjectMembership).as("membershipUpdatedAt"),
db.ref("slug").withSchema(TableName.ProjectRoles).as("customRoleSlug") db.ref("slug").withSchema(TableName.ProjectRoles).as("customRoleSlug")
@@ -133,10 +144,11 @@ export const permissionDALFactory = (db: TDbClient) => {
const permission = sqlNestRelationships({ const permission = sqlNestRelationships({
data: docs, data: docs,
key: "membershipId", key: "membershipId",
parentMapper: ({ membershipId, membershipCreatedAt, membershipUpdatedAt }) => ({ parentMapper: ({ membershipId, membershipCreatedAt, membershipUpdatedAt, oldRoleField }) => ({
id: membershipId, id: membershipId,
identityId, identityId,
projectId, projectId,
role: oldRoleField,
createdAt: membershipCreatedAt, createdAt: membershipCreatedAt,
updatedAt: membershipUpdatedAt, updatedAt: membershipUpdatedAt,
// just a prefilled value // just a prefilled value
@@ -30,30 +30,31 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
}), }),
response: { response: {
200: z.object({ 200: z.object({
memberships: ProjectMembershipsSchema.merge( memberships: ProjectMembershipsSchema.omit({ role: true })
z.object({ .merge(
user: UsersSchema.pick({ z.object({
email: true, user: UsersSchema.pick({
firstName: true, email: true,
lastName: true, firstName: true,
id: true lastName: true,
}).merge(UserEncryptionKeysSchema.pick({ publicKey: true })), id: true
roles: z.array( }).merge(UserEncryptionKeysSchema.pick({ publicKey: true })),
z.object({ roles: z.array(
id: z.string(), z.object({
role: z.string(), id: z.string(),
customRoleId: z.string().optional().nullable(), role: z.string(),
customRoleName: z.string().optional().nullable(), customRoleId: z.string().optional().nullable(),
customRoleSlug: z.string().optional().nullable(), customRoleName: z.string().optional().nullable(),
isTemporary: z.boolean(), customRoleSlug: z.string().optional().nullable(),
temporaryMode: z.string().optional().nullable(), isTemporary: z.boolean(),
temporaryRange: z.string().nullable().optional(), temporaryMode: z.string().optional().nullable(),
temporaryAccessStartTime: z.date().nullable().optional(), temporaryRange: z.string().nullable().optional(),
temporaryAccessEndTime: z.date().nullable().optional() temporaryAccessStartTime: z.date().nullable().optional(),
}) temporaryAccessEndTime: z.date().nullable().optional()
) })
}) )
) })
)
.omit({ createdAt: true, updatedAt: true }) .omit({ createdAt: true, updatedAt: true })
.array() .array()
}) })
+26 -25
View File
@@ -60,31 +60,32 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
}), }),
response: { response: {
200: z.object({ 200: z.object({
users: ProjectMembershipsSchema.merge( users: ProjectMembershipsSchema.omit({ role: true })
z.object({ .merge(
user: UsersSchema.pick({ z.object({
username: true, user: UsersSchema.pick({
email: true, username: true,
firstName: true, email: true,
lastName: true, firstName: true,
id: true lastName: true,
}).merge(UserEncryptionKeysSchema.pick({ publicKey: true })), id: true
roles: z.array( }).merge(UserEncryptionKeysSchema.pick({ publicKey: true })),
z.object({ roles: z.array(
id: z.string(), z.object({
role: z.string(), id: z.string(),
customRoleId: z.string().optional().nullable(), role: z.string(),
customRoleName: z.string().optional().nullable(), customRoleId: z.string().optional().nullable(),
customRoleSlug: z.string().optional().nullable(), customRoleName: z.string().optional().nullable(),
isTemporary: z.boolean(), customRoleSlug: z.string().optional().nullable(),
temporaryMode: z.string().optional().nullable(), isTemporary: z.boolean(),
temporaryRange: z.string().nullable().optional(), temporaryMode: z.string().optional().nullable(),
temporaryAccessStartTime: z.date().nullable().optional(), temporaryRange: z.string().nullable().optional(),
temporaryAccessEndTime: z.date().nullable().optional() temporaryAccessStartTime: z.date().nullable().optional(),
}) temporaryAccessEndTime: z.date().nullable().optional()
) })
}) )
) })
)
.omit({ createdAt: true, updatedAt: true }) .omit({ createdAt: true, updatedAt: true })
.array() .array()
}) })
@@ -86,7 +86,9 @@ export const identityProjectServiceFactory = ({
const identityProjectMembership = await identityProjectDAL.create( const identityProjectMembership = await identityProjectDAL.create(
{ {
identityId, identityId,
projectId: project.id projectId: project.id,
role: isCustomRole ? ProjectMembershipRole.Custom : role,
roleId: customRole?.id
}, },
tx tx
); );
@@ -105,7 +105,8 @@ export const projectMembershipServiceFactory = ({
const projectMemberships = await projectMembershipDAL.insertMany( const projectMemberships = await projectMembershipDAL.insertMany(
orgMembers.map(({ userId }) => ({ orgMembers.map(({ userId }) => ({
projectId, projectId,
userId: userId as string userId: userId as string,
role: ProjectMembershipRole.Member
})), })),
tx tx
); );
@@ -223,7 +224,8 @@ export const projectMembershipServiceFactory = ({
const projectMemberships = await projectMembershipDAL.insertMany( const projectMemberships = await projectMembershipDAL.insertMany(
orgMembers.map(({ user }) => ({ orgMembers.map(({ user }) => ({
projectId, projectId,
userId: user.id userId: user.id,
role: ProjectMembershipRole.Member
})), })),
tx tx
); );
@@ -232,7 +232,8 @@ export const projectQueueFactory = ({
const projectMembership = await projectMembershipDAL.create( const projectMembership = await projectMembershipDAL.create(
{ {
projectId: project.id, projectId: project.id,
userId: ghostUser.user.id userId: ghostUser.user.id,
role: ProjectMembershipRole.Admin
}, },
tx tx
); );
@@ -123,7 +123,8 @@ export const projectServiceFactory = ({
const projectMembership = await projectMembershipDAL.create( const projectMembership = await projectMembershipDAL.create(
{ {
userId: ghostUser.user.id, userId: ghostUser.user.id,
projectId: project.id projectId: project.id,
role: ProjectMembershipRole.Admin
}, },
tx tx
); );
@@ -225,7 +226,8 @@ export const projectServiceFactory = ({
const userProjectMembership = await projectMembershipDAL.create( const userProjectMembership = await projectMembershipDAL.create(
{ {
projectId: project.id, projectId: project.id,
userId: user.id userId: user.id,
role: projectAdmin.projectRole
}, },
tx tx
); );
@@ -281,7 +283,9 @@ export const projectServiceFactory = ({
const identityProjectMembership = await identityProjectDAL.create( const identityProjectMembership = await identityProjectDAL.create(
{ {
identityId: actorId, identityId: actorId,
projectId: project.id projectId: project.id,
role: isCustomRole ? ProjectMembershipRole.Custom : ProjectMembershipRole.Admin,
roleId: customRole?.id
}, },
tx tx
); );