chore: rolling migration removed role and roleId field from project membership and identity project membership

This commit is contained in:
Akhil Mohan
2024-04-15 02:16:11 +05:30
parent fbc7b34786
commit c47a91715f
12 changed files with 99 additions and 84 deletions
+3 -2
View File
@@ -23,16 +23,17 @@ module.exports = {
root: true, root: true,
overrides: [ overrides: [
{ {
files: ["./e2e-test/**/*"], files: ["./e2e-test/**/*", "./src/db/migrations/**/*"],
rules: { rules: {
"@typescript-eslint/no-unsafe-member-access": "off", "@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-assignment": "off", "@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-argument": "off", "@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/no-unsafe-return": "off", "@typescript-eslint/no-unsafe-return": "off",
"@typescript-eslint/no-unsafe-call": "off", "@typescript-eslint/no-unsafe-call": "off"
} }
} }
], ],
rules: { rules: {
"@typescript-eslint/no-empty-function": "off", "@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-unsafe-enum-comparison": "off", "@typescript-eslint/no-unsafe-enum-comparison": "off",
@@ -0,0 +1,47 @@
import { Knex } from "knex";
import { ProjectMembershipRole, TableName } from "../schemas";
export async function up(knex: Knex): Promise<void> {
const doesProjectRoleFieldExist = await knex.schema.hasColumn(TableName.ProjectMembership, "role");
const doesProjectRoleIdFieldExist = await knex.schema.hasColumn(TableName.ProjectMembership, "roleId");
await knex.schema.alterTable(TableName.ProjectMembership, (t) => {
if (doesProjectRoleFieldExist) t.dropColumn("roleId");
if (doesProjectRoleIdFieldExist) t.dropColumn("role");
});
const doesIdentityProjectRoleFieldExist = await knex.schema.hasColumn(TableName.IdentityProjectMembership, "role");
const doesIdentityProjectRoleIdFieldExist = await knex.schema.hasColumn(
TableName.IdentityProjectMembership,
"roleId"
);
await knex.schema.alterTable(TableName.IdentityProjectMembership, (t) => {
if (doesIdentityProjectRoleFieldExist) t.dropColumn("roleId");
if (doesIdentityProjectRoleIdFieldExist) t.dropColumn("role");
});
}
export async function down(knex: Knex): Promise<void> {
const doesProjectRoleFieldExist = await knex.schema.hasColumn(TableName.ProjectMembership, "role");
const doesProjectRoleIdFieldExist = await knex.schema.hasColumn(TableName.ProjectMembership, "roleId");
await knex.schema.alterTable(TableName.ProjectMembership, (t) => {
if (!doesProjectRoleFieldExist) t.string("role").defaultTo(ProjectMembershipRole.Member);
if (!doesProjectRoleIdFieldExist) {
t.uuid("roleId");
t.foreign("roleId").references("id").inTable(TableName.ProjectRoles);
}
});
const doesIdentityProjectRoleFieldExist = await knex.schema.hasColumn(TableName.IdentityProjectMembership, "role");
const doesIdentityProjectRoleIdFieldExist = await knex.schema.hasColumn(
TableName.IdentityProjectMembership,
"roleId"
);
await knex.schema.alterTable(TableName.IdentityProjectMembership, (t) => {
if (!doesIdentityProjectRoleFieldExist) t.string("role").defaultTo(ProjectMembershipRole.Member);
if (!doesIdentityProjectRoleIdFieldExist) {
t.uuid("roleId");
t.foreign("roleId").references("id").inTable(TableName.ProjectRoles);
}
});
}
@@ -9,8 +9,6 @@ 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,12 +9,10 @@ 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>;
+1 -2
View File
@@ -33,8 +33,7 @@ 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({
+1 -2
View File
@@ -78,8 +78,7 @@ 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("*");
@@ -72,7 +72,6 @@ export const permissionDALFactory = (db: TDbClient) => {
.select(selectAllTableCols(TableName.GroupProjectMembershipRole)) .select(selectAllTableCols(TableName.GroupProjectMembershipRole))
.select( .select(
db.ref("id").withSchema(TableName.GroupProjectMembership).as("membershipId"), db.ref("id").withSchema(TableName.GroupProjectMembership).as("membershipId"),
// TODO(roll-forward-migration): remove this field when we drop this in next migration after a week
db.ref("createdAt").withSchema(TableName.GroupProjectMembership).as("membershipCreatedAt"), db.ref("createdAt").withSchema(TableName.GroupProjectMembership).as("membershipCreatedAt"),
db.ref("updatedAt").withSchema(TableName.GroupProjectMembership).as("membershipUpdatedAt"), db.ref("updatedAt").withSchema(TableName.GroupProjectMembership).as("membershipUpdatedAt"),
db.ref("projectId").withSchema(TableName.GroupProjectMembership), db.ref("projectId").withSchema(TableName.GroupProjectMembership),
@@ -105,7 +104,6 @@ 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("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("projectId").withSchema(TableName.ProjectMembership), db.ref("projectId").withSchema(TableName.ProjectMembership),
@@ -131,11 +129,10 @@ export const permissionDALFactory = (db: TDbClient) => {
const permission = sqlNestRelationships({ const permission = sqlNestRelationships({
data: docs, data: docs,
key: "projectId", key: "projectId",
parentMapper: ({ orgId, orgAuthEnforced, membershipId, membershipCreatedAt, membershipUpdatedAt, role }) => ({ parentMapper: ({ orgId, orgAuthEnforced, membershipId, membershipCreatedAt, membershipUpdatedAt }) => ({
orgId, orgId,
orgAuthEnforced, orgAuthEnforced,
userId, userId,
role,
id: membershipId, id: membershipId,
projectId, projectId,
createdAt: membershipCreatedAt, createdAt: membershipCreatedAt,
@@ -179,18 +176,10 @@ export const permissionDALFactory = (db: TDbClient) => {
? sqlNestRelationships({ ? sqlNestRelationships({
data: groupDocs, data: groupDocs,
key: "projectId", key: "projectId",
parentMapper: ({ parentMapper: ({ orgId, orgAuthEnforced, membershipId, membershipCreatedAt, membershipUpdatedAt }) => ({
orgId,
orgAuthEnforced,
membershipId,
membershipCreatedAt,
membershipUpdatedAt,
role
}) => ({
orgId, orgId,
orgAuthEnforced, orgAuthEnforced,
userId, userId,
role,
id: membershipId, id: membershipId,
projectId, projectId,
createdAt: membershipCreatedAt, createdAt: membershipCreatedAt,
@@ -270,7 +259,6 @@ export const permissionDALFactory = (db: TDbClient) => {
.select( .select(
db.ref("id").withSchema(TableName.IdentityProjectMembership).as("membershipId"), db.ref("id").withSchema(TableName.IdentityProjectMembership).as("membershipId"),
db.ref("orgId").withSchema(TableName.Project).as("orgId"), // Now you can select orgId from Project db.ref("orgId").withSchema(TableName.Project).as("orgId"), // Now you can select orgId from Project
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"),
@@ -299,11 +287,10 @@ export const permissionDALFactory = (db: TDbClient) => {
const permission = sqlNestRelationships({ const permission = sqlNestRelationships({
data: docs, data: docs,
key: "membershipId", key: "membershipId",
parentMapper: ({ membershipId, membershipCreatedAt, membershipUpdatedAt, oldRoleField, orgId }) => ({ parentMapper: ({ membershipId, membershipCreatedAt, membershipUpdatedAt, orgId }) => ({
id: membershipId, id: membershipId,
identityId, identityId,
projectId, projectId,
role: oldRoleField,
createdAt: membershipCreatedAt, createdAt: membershipCreatedAt,
updatedAt: membershipUpdatedAt, updatedAt: membershipUpdatedAt,
orgId, orgId,
@@ -35,31 +35,28 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
}), }),
response: { response: {
200: z.object({ 200: z.object({
memberships: ProjectMembershipsSchema.omit({ role: true }) memberships: ProjectMembershipsSchema.extend({
.merge( user: UsersSchema.pick({
email: true,
firstName: true,
lastName: true,
id: true
}).merge(UserEncryptionKeysSchema.pick({ publicKey: true })),
roles: z.array(
z.object({ z.object({
user: UsersSchema.pick({ id: z.string(),
email: true, role: z.string(),
firstName: true, customRoleId: z.string().optional().nullable(),
lastName: true, customRoleName: z.string().optional().nullable(),
id: true customRoleSlug: z.string().optional().nullable(),
}).merge(UserEncryptionKeysSchema.pick({ publicKey: true })), isTemporary: z.boolean(),
roles: z.array( temporaryMode: z.string().optional().nullable(),
z.object({ temporaryRange: z.string().nullable().optional(),
id: z.string(), temporaryAccessStartTime: z.date().nullable().optional(),
role: z.string(), temporaryAccessEndTime: z.date().nullable().optional()
customRoleId: z.string().optional().nullable(),
customRoleName: z.string().optional().nullable(),
customRoleSlug: z.string().optional().nullable(),
isTemporary: z.boolean(),
temporaryMode: z.string().optional().nullable(),
temporaryRange: z.string().nullable().optional(),
temporaryAccessStartTime: z.date().nullable().optional(),
temporaryAccessEndTime: z.date().nullable().optional()
})
)
}) })
) )
})
.omit({ createdAt: true, updatedAt: true }) .omit({ createdAt: true, updatedAt: true })
.array() .array()
}) })
+19 -23
View File
@@ -70,32 +70,28 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
}), }),
response: { response: {
200: z.object({ 200: z.object({
users: ProjectMembershipsSchema.omit({ role: true }) users: ProjectMembershipsSchema.extend({
.merge( user: UsersSchema.pick({
email: true,
firstName: true,
lastName: true,
id: true
}).merge(UserEncryptionKeysSchema.pick({ publicKey: true })),
roles: z.array(
z.object({ z.object({
user: UsersSchema.pick({ id: z.string(),
username: true, role: z.string(),
email: true, customRoleId: z.string().optional().nullable(),
firstName: true, customRoleName: z.string().optional().nullable(),
lastName: true, customRoleSlug: z.string().optional().nullable(),
id: true isTemporary: z.boolean(),
}).merge(UserEncryptionKeysSchema.pick({ publicKey: true })), temporaryMode: z.string().optional().nullable(),
roles: z.array( temporaryRange: z.string().nullable().optional(),
z.object({ temporaryAccessStartTime: z.date().nullable().optional(),
id: z.string(), temporaryAccessEndTime: z.date().nullable().optional()
role: z.string(),
customRoleId: z.string().optional().nullable(),
customRoleName: z.string().optional().nullable(),
customRoleSlug: z.string().optional().nullable(),
isTemporary: z.boolean(),
temporaryMode: z.string().optional().nullable(),
temporaryRange: z.string().nullable().optional(),
temporaryAccessStartTime: z.date().nullable().optional(),
temporaryAccessEndTime: z.date().nullable().optional()
})
)
}) })
) )
})
.omit({ createdAt: true, updatedAt: true }) .omit({ createdAt: true, updatedAt: true })
.array() .array()
}) })
@@ -93,9 +93,7 @@ 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
); );
@@ -232,8 +232,7 @@ 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
); );
@@ -141,8 +141,7 @@ 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
); );
@@ -244,8 +243,7 @@ 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
); );
@@ -302,9 +300,7 @@ 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
); );