feat: multi-workspace followup (#4197)

* Seed UserWorkspace for existing demo/dev users

* add workspaces field to currentUser

* new token generation endpoint for switching workspace

* lint fix

* include dependency

* requested fixes

* resolver test pass

* changing defaultWorkspace and workspaceMember when switching workspaces

* tests fix

* requested changes

* delete user/workspace edge case handled

* after merge

* requested changes

* :wq!

* workspace manytoone relation

* lint fix / import fix

* gql codegen

* Fix migrations and generateJWT

* migration fix

* relations fix

---------

Co-authored-by: martmull <martmull@hotmail.fr>
This commit is contained in:
Aditya Pimpalkar
2024-03-04 15:14:04 +00:00
committed by GitHub
parent 4a0f2e8c24
commit 63d403454c
25 changed files with 363 additions and 22 deletions

View File

@ -9,6 +9,10 @@ import {
deleteWorkspaces,
} from 'src/database/typeorm-seeds/core/demo/workspaces';
import { deleteFeatureFlags } from 'src/database/typeorm-seeds/core/demo/feature-flags';
import {
deleteUserWorkspaces,
seedUserWorkspaces,
} from 'src/database/typeorm-seeds/core/demo/userWorkspaces';
export const seedCoreSchema = async (
workspaceDataSource: DataSource,
@ -18,6 +22,7 @@ export const seedCoreSchema = async (
await seedWorkspaces(workspaceDataSource, schemaName, workspaceId);
await seedUsers(workspaceDataSource, schemaName, workspaceId);
await seedUserWorkspaces(workspaceDataSource, schemaName, workspaceId);
};
export const deleteCoreSchema = async (
@ -26,6 +31,7 @@ export const deleteCoreSchema = async (
) => {
const schemaName = 'core';
await deleteUserWorkspaces(workspaceDataSource, schemaName, workspaceId);
await deleteUsersByWorkspace(workspaceDataSource, schemaName, workspaceId);
await deleteFeatureFlags(workspaceDataSource, schemaName, workspaceId);
// deleteWorkspaces should be last

View File

@ -0,0 +1,51 @@
import { DataSource } from 'typeorm';
const tableName = 'userWorkspace';
export enum DemoSeedUserIds {
Noah = '20202020-9e3b-46d4-a556-88b9ddc2b035',
Hugo = '20202020-3957-4908-9c36-2929a23f8358',
Julia = '20202020-7169-42cf-bc47-1cfef15264b9',
}
export const seedUserWorkspaces = async (
workspaceDataSource: DataSource,
schemaName: string,
workspaceId: string,
) => {
await workspaceDataSource
.createQueryBuilder()
.insert()
.into(`${schemaName}.${tableName}`, ['userId', 'workspaceId'])
.orIgnore()
.values([
{
userId: DemoSeedUserIds.Noah,
workspaceId: workspaceId,
},
{
userId: DemoSeedUserIds.Hugo,
workspaceId: workspaceId,
},
{
userId: DemoSeedUserIds.Julia,
workspaceId: workspaceId,
},
])
.execute();
};
export const deleteUserWorkspaces = async (
workspaceDataSource: DataSource,
schemaName: string,
workspaceId: string,
) => {
await workspaceDataSource
.createQueryBuilder()
.delete()
.from(`${schemaName}.${tableName}`)
.where(`"${tableName}"."workspaceId" = :workspaceId`, {
workspaceId,
})
.execute();
};

View File

@ -12,6 +12,10 @@ import {
seedFeatureFlags,
deleteFeatureFlags,
} from 'src/database/typeorm-seeds/core/feature-flags';
import {
deleteUserWorkspaces,
seedUserWorkspaces,
} from 'src/database/typeorm-seeds/core/userWorkspaces';
export const seedCoreSchema = async (
workspaceDataSource: DataSource,
@ -21,6 +25,7 @@ export const seedCoreSchema = async (
await seedWorkspaces(workspaceDataSource, schemaName, workspaceId);
await seedUsers(workspaceDataSource, schemaName, workspaceId);
await seedUserWorkspaces(workspaceDataSource, schemaName, workspaceId);
await seedFeatureFlags(workspaceDataSource, schemaName, workspaceId);
};
@ -30,6 +35,7 @@ export const deleteCoreSchema = async (
) => {
const schemaName = 'core';
await deleteUserWorkspaces(workspaceDataSource, schemaName, workspaceId);
await deleteUsersByWorkspace(workspaceDataSource, schemaName, workspaceId);
await deleteFeatureFlags(workspaceDataSource, schemaName, workspaceId);
// deleteWorkspaces should be last

View File

@ -0,0 +1,53 @@
import { DataSource } from 'typeorm';
// import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces';
const tableName = 'userWorkspace';
export enum SeedUserIds {
Tim = '20202020-9e3b-46d4-a556-88b9ddc2b034',
Jony = '20202020-3957-4908-9c36-2929a23f8357',
Phil = '20202020-7169-42cf-bc47-1cfef15264b8',
}
export const seedUserWorkspaces = async (
workspaceDataSource: DataSource,
schemaName: string,
workspaceId: string,
) => {
await workspaceDataSource
.createQueryBuilder()
.insert()
.into(`${schemaName}.${tableName}`, ['userId', 'workspaceId'])
.orIgnore()
.values([
{
userId: SeedUserIds.Tim,
workspaceId,
},
{
userId: SeedUserIds.Jony,
workspaceId,
},
{
userId: SeedUserIds.Phil,
workspaceId,
},
])
.execute();
};
export const deleteUserWorkspaces = async (
workspaceDataSource: DataSource,
schemaName: string,
workspaceId: string,
) => {
await workspaceDataSource
.createQueryBuilder()
.delete()
.from(`${schemaName}.${tableName}`)
.where(`"${tableName}"."workspaceId" = :workspaceId`, {
workspaceId,
})
.execute();
};

View File

@ -0,0 +1,28 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class UpdateUserWorkspace1709314035408 implements MigrationInterface {
name = 'UpdateUserWorkspace1709314035408';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE "core"."userWorkspace"
ADD CONSTRAINT "FK_37fdc7357af701e595c5c3a9bd6"
FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id")
ON DELETE CASCADE ON UPDATE NO ACTION
`);
await queryRunner.query(`
ALTER TABLE "core"."userWorkspace"
ADD CONSTRAINT "FK_cb488f32c6a0827b938edadf221"
FOREIGN KEY ("userId") REFERENCES "core"."user"("id")
ON DELETE CASCADE ON UPDATE NO ACTION
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "core"."userWorkspace" DROP CONSTRAINT "FK_cb488f32c6a0827b938edadf221"`,
);
await queryRunner.query(
`ALTER TABLE "core"."userWorkspace" DROP CONSTRAINT "FK_37fdc7357af701e595c5c3a9bd6"`,
);
}
}

View File

@ -10,6 +10,7 @@ import { RefreshToken } from 'src/core/refresh-token/refresh-token.entity';
import { FeatureFlagEntity } from 'src/core/feature-flag/feature-flag.entity';
import { BillingSubscription } from 'src/core/billing/entities/billing-subscription.entity';
import { BillingSubscriptionItem } from 'src/core/billing/entities/billing-subscription-item.entity';
import { UserWorkspace } from 'src/core/user-workspace/user-workspace.entity';
@Injectable()
export class TypeORMService implements OnModuleInit, OnModuleDestroy {
@ -26,6 +27,7 @@ export class TypeORMService implements OnModuleInit, OnModuleDestroy {
entities: [
User,
Workspace,
UserWorkspace,
RefreshToken,
FeatureFlagEntity,
BillingSubscription,