refactor(workspace, users, billing): remove default workspace + rename (#9360)
Replaced user-based parameterization with workspace-focused logic across seed scripts, mocks, and billing services. Removed redundant `user` references and standardized to `workspace` to align with updated business rules. Adjusted mock data and tests to reflect these changes. Fix https://github.com/twentyhq/twenty/issues/9295
This commit is contained in:
@ -10,7 +10,7 @@ import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { getCompaniesMock } from '~/testing/mock-data/companies';
|
||||
import {
|
||||
mockDefaultWorkspace,
|
||||
mockCurrentWorkspace,
|
||||
mockedWorkspaceMemberData,
|
||||
} from '~/testing/mock-data/users';
|
||||
import { sleep } from '~/utils/sleep';
|
||||
@ -54,7 +54,7 @@ const meta: Meta<typeof CommandMenu> = {
|
||||
isCommandMenuOpenedState,
|
||||
);
|
||||
|
||||
setCurrentWorkspace(mockDefaultWorkspace);
|
||||
setCurrentWorkspace(mockCurrentWorkspace);
|
||||
setCurrentWorkspaceMember(mockedWorkspaceMemberData);
|
||||
setIsCommandMenuOpened(true);
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadat
|
||||
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import {
|
||||
mockDefaultWorkspace,
|
||||
mockCurrentWorkspace,
|
||||
mockedWorkspaceMemberData,
|
||||
} from '~/testing/mock-data/users';
|
||||
|
||||
@ -26,7 +26,7 @@ const RelationWorkspaceSetterEffect = () => {
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setCurrentWorkspace(mockDefaultWorkspace);
|
||||
setCurrentWorkspace(mockCurrentWorkspace);
|
||||
setCurrentWorkspaceMember(mockedWorkspaceMemberData);
|
||||
}, [setCurrentWorkspace, setCurrentWorkspaceMember]);
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadat
|
||||
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import {
|
||||
mockDefaultWorkspace,
|
||||
mockCurrentWorkspace,
|
||||
mockedWorkspaceMemberData,
|
||||
} from '~/testing/mock-data/users';
|
||||
|
||||
@ -32,7 +32,7 @@ const RelationWorkspaceSetterEffect = () => {
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setCurrentWorkspace(mockDefaultWorkspace);
|
||||
setCurrentWorkspace(mockCurrentWorkspace);
|
||||
setCurrentWorkspaceMember(mockedWorkspaceMemberData);
|
||||
}, [setCurrentWorkspace, setCurrentWorkspaceMember]);
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { useSetNextOnboardingStatus } from '@/onboarding/hooks/useSetNextOnboardingStatus';
|
||||
import { OnboardingStatus, SubscriptionStatus } from '~/generated/graphql';
|
||||
import {
|
||||
mockDefaultWorkspace,
|
||||
mockCurrentWorkspace,
|
||||
mockedUserData,
|
||||
} from '~/testing/mock-data/users';
|
||||
|
||||
@ -35,7 +35,7 @@ const renderHooks = (
|
||||
act(() => {
|
||||
result.current.setCurrentUser({ ...mockedUserData, onboardingStatus });
|
||||
result.current.setCurrentWorkspace({
|
||||
...mockDefaultWorkspace,
|
||||
...mockCurrentWorkspace,
|
||||
currentBillingSubscription: withCurrentBillingSubscription
|
||||
? { id: v4(), status: SubscriptionStatus.Active }
|
||||
: undefined,
|
||||
|
||||
@ -9,7 +9,7 @@ import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { supportChatState } from '@/client-config/states/supportChatState';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import {
|
||||
mockDefaultWorkspace,
|
||||
mockCurrentWorkspace,
|
||||
mockedUserData,
|
||||
mockedWorkspaceMemberData,
|
||||
} from '~/testing/mock-data/users';
|
||||
@ -29,7 +29,7 @@ const meta: Meta<typeof SupportDropdown> = {
|
||||
currentWorkspaceMemberState,
|
||||
);
|
||||
|
||||
setCurrentWorkspace(mockDefaultWorkspace);
|
||||
setCurrentWorkspace(mockCurrentWorkspace);
|
||||
setCurrentWorkspaceMember(mockedWorkspaceMemberData);
|
||||
setCurrentUser(mockedUserData);
|
||||
setSupportChat({ supportDriver: 'front', supportFrontChatId: '1234' });
|
||||
|
||||
@ -36,7 +36,7 @@ export const avatarUrl =
|
||||
export const workspaceLogoUrl =
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACb0lEQVR4nO2VO4taQRTHr3AblbjxEVlwCwVhg7BoqqCIjy/gAyyFWNlYBOxsfH0KuxgQGwXRUkGuL2S7i1barGAgiwbdW93SnGOc4BonPiKahf3DwXFmuP/fPM4ZlvmlTxAhCBdzHnEQWYiv7Mr4C3NeuVYhQYDPzOUUQgDLBQGcLHNhvQK8DACPx8PTxiqVyvISG43GbyaT6Qfpn06n0m63e/tPAPF4vJ1MJu8kEsnWTCkWi1yr1RKGw+GDRqPBOTfr44vFQvD7/Q/lcpmaaVQAr9fLp1IpO22c47hGOBz+MB6PH+Vy+VYDAL8qlUoGtVotzOfzq4MAgsHgE/6KojiQyWR/bKVSqbSszHFM8Pl8z1YK48JsNltCOBwOnrYLO+8AAIjb+nHbycoTiUQfDJ7tFq4YAHiVSmXBxcD41u8flQU8z7fhzO0r83atVns3Go3u9Xr9x0O/RQXo9/tsIBBg6vX606a52Wz+bZ7P5/WwG29gxSJzhKgA6XTaDoFNF+krFAocmC//4yWEcSf2wTm7mCO19xFgSsKOLI16vV7b7XY7mRNoLwA0JymJ5uQIzgIAuX5PzDElT2m+E8BqtQ4ymcx7Yq7T6a6ZE4sKgOadTucaCwkxp1UzlEKh0GDxIXOwDWHAdi6Xe3swQDQa/Q7mywoolUpvsaptymazDWKxmBHTlWXZm405BFZoNpuGgwEmk4mE2SGtVivii4f1AO7J3ZopkQCQj7Ar1FeRChCJRJzVapX6DKNIfSc1Ax+wtQWQ55h6bH8FWDfYV4fO3wlwDr0C/BcADYiTPCxHqIEA2QsCZAkAKnRGkMbKN/sTX5YHPQ1e7SkAAAAASUVORK5CYII=';
|
||||
|
||||
export const mockDefaultWorkspace: Workspace = {
|
||||
export const mockCurrentWorkspace: Workspace = {
|
||||
subdomain: 'acme.twenty.com',
|
||||
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6w',
|
||||
displayName: 'Twenty',
|
||||
@ -107,9 +107,9 @@ export const mockedUserData: MockedUser = {
|
||||
supportUserHash:
|
||||
'a95afad9ff6f0b364e2a3fd3e246a1a852c22b6e55a3ca33745a86c201f9c10d',
|
||||
workspaceMember: mockedWorkspaceMemberData,
|
||||
currentWorkspace: mockDefaultWorkspace,
|
||||
currentWorkspace: mockCurrentWorkspace,
|
||||
locale: 'en',
|
||||
workspaces: [{ workspace: mockDefaultWorkspace }],
|
||||
workspaces: [{ workspace: mockCurrentWorkspace }],
|
||||
workspaceMembers: [mockedWorkspaceMemberData],
|
||||
onboardingStatus: OnboardingStatus.Completed,
|
||||
userVars: {},
|
||||
@ -129,9 +129,9 @@ export const mockedOnboardingUserData = (
|
||||
supportUserHash:
|
||||
'4fb61d34ed3a4aeda2476d4b308b5162db9e1809b2b8277e6fdc6efc4a609254',
|
||||
workspaceMember: null,
|
||||
currentWorkspace: mockDefaultWorkspace,
|
||||
currentWorkspace: mockCurrentWorkspace,
|
||||
locale: 'en',
|
||||
workspaces: [{ workspace: mockDefaultWorkspace }],
|
||||
workspaces: [{ workspace: mockCurrentWorkspace }],
|
||||
onboardingStatus: onboardingStatus || null,
|
||||
};
|
||||
};
|
||||
|
||||
@ -21,7 +21,7 @@ export const seedCoreSchema = async (
|
||||
const schemaName = 'core';
|
||||
|
||||
await seedWorkspaces(workspaceDataSource, schemaName, workspaceId);
|
||||
await seedUsers(workspaceDataSource, schemaName, workspaceId);
|
||||
await seedUsers(workspaceDataSource, schemaName);
|
||||
await seedUserWorkspaces(workspaceDataSource, schemaName, workspaceId);
|
||||
};
|
||||
|
||||
|
||||
@ -13,7 +13,6 @@ export const DEMO_SEED_USER_IDS = {
|
||||
export const seedUsers = async (
|
||||
workspaceDataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await workspaceDataSource
|
||||
.createQueryBuilder()
|
||||
@ -56,16 +55,22 @@ export const seedUsers = async (
|
||||
};
|
||||
|
||||
export const deleteUsersByWorkspace = async (
|
||||
workspaceDataSource: DataSource,
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await workspaceDataSource
|
||||
const user = await dataSource
|
||||
.createQueryBuilder(`${schemaName}.${tableName}`, 'user')
|
||||
.leftJoinAndSelect('user.workspaces', 'userWorkspace')
|
||||
.where(`userWorkspace."workspaceId" = :workspaceId`, {
|
||||
workspaceId,
|
||||
})
|
||||
.getMany();
|
||||
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(`${schemaName}.${tableName}`)
|
||||
.where(`"${tableName}"."defaultWorkspaceId" = :workspaceId`, {
|
||||
workspaceId,
|
||||
})
|
||||
.where(`"${tableName}"."id" IN (:...ids)`, { ids: user.map((u) => u.id) })
|
||||
.execute();
|
||||
};
|
||||
|
||||
@ -12,7 +12,7 @@ export const seedCoreSchema = async (
|
||||
const schemaName = 'core';
|
||||
|
||||
await seedWorkspaces(workspaceDataSource, schemaName, workspaceId);
|
||||
await seedUsers(workspaceDataSource, schemaName, workspaceId);
|
||||
await seedUsers(workspaceDataSource, schemaName);
|
||||
await seedUserWorkspaces(workspaceDataSource, schemaName, workspaceId);
|
||||
await seedFeatureFlags(workspaceDataSource, schemaName, workspaceId);
|
||||
};
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
// import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces';
|
||||
|
||||
const tableName = 'user';
|
||||
|
||||
export const DEV_SEED_USER_IDS = {
|
||||
@ -13,7 +11,6 @@ export const DEV_SEED_USER_IDS = {
|
||||
export const seedUsers = async (
|
||||
workspaceDataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await workspaceDataSource
|
||||
.createQueryBuilder()
|
||||
@ -54,18 +51,3 @@ export const seedUsers = async (
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
|
||||
export const deleteUsersByWorkspace = async (
|
||||
workspaceDataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await workspaceDataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(`${schemaName}.${tableName}`)
|
||||
.where(`"${tableName}"."defaultWorkspaceId" = :workspaceId`, {
|
||||
workspaceId,
|
||||
})
|
||||
.execute();
|
||||
};
|
||||
|
||||
@ -37,9 +37,8 @@ export class BillingResolver {
|
||||
}
|
||||
|
||||
@Query(() => SessionEntity)
|
||||
@UseGuards(WorkspaceAuthGuard, UserAuthGuard)
|
||||
@UseGuards(WorkspaceAuthGuard)
|
||||
async billingPortalSession(
|
||||
@AuthUser() user: User,
|
||||
@AuthWorkspace() workspace: Workspace,
|
||||
@Args() { returnUrlPath }: BillingSessionInput,
|
||||
) {
|
||||
@ -89,8 +88,8 @@ export class BillingResolver {
|
||||
|
||||
@Mutation(() => UpdateBillingEntity)
|
||||
@UseGuards(WorkspaceAuthGuard)
|
||||
async updateBillingSubscription(@AuthUser() user: User) {
|
||||
await this.billingSubscriptionService.applyBillingSubscription(user);
|
||||
async updateBillingSubscription(@AuthWorkspace() workspace: Workspace) {
|
||||
await this.billingSubscriptionService.applyBillingSubscription(workspace);
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
@ -3,7 +3,6 @@ import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import assert from 'assert';
|
||||
|
||||
import { User } from '@sentry/node';
|
||||
import Stripe from 'stripe';
|
||||
import { Not, Repository } from 'typeorm';
|
||||
|
||||
@ -15,6 +14,7 @@ import { SubscriptionInterval } from 'src/engine/core-modules/billing/enums/bill
|
||||
import { SubscriptionStatus } from 'src/engine/core-modules/billing/enums/billing-subscription-status.enum';
|
||||
import { StripeService } from 'src/engine/core-modules/billing/stripe/stripe.service';
|
||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
|
||||
@Injectable()
|
||||
export class BillingSubscriptionService {
|
||||
@ -114,9 +114,9 @@ export class BillingSubscriptionService {
|
||||
return entitlement.value;
|
||||
}
|
||||
|
||||
async applyBillingSubscription(user: User) {
|
||||
async applyBillingSubscription(workspace: Workspace) {
|
||||
const billingSubscription = await this.getCurrentBillingSubscriptionOrThrow(
|
||||
{ workspaceId: user.defaultWorkspaceId },
|
||||
{ workspaceId: workspace.id },
|
||||
);
|
||||
|
||||
const newInterval =
|
||||
@ -125,9 +125,7 @@ export class BillingSubscriptionService {
|
||||
: SubscriptionInterval.Year;
|
||||
|
||||
const billingSubscriptionItem =
|
||||
await this.getCurrentBillingSubscriptionItemOrThrow(
|
||||
user.defaultWorkspaceId,
|
||||
);
|
||||
await this.getCurrentBillingSubscriptionItemOrThrow(workspace.id);
|
||||
|
||||
const productPrice = await this.stripeService.getStripePrice(
|
||||
AvailableProduct.BasePlan,
|
||||
|
||||
Reference in New Issue
Block a user