feat(*): allow to select auth providers + add multiworkspace with subdomain management (#8656)
## Summary Add support for multi-workspace feature and adjust configurations and states accordingly. - Introduced new state isMultiWorkspaceEnabledState. - Updated ClientConfigProviderEffect component to handle multi-workspace. - Modified GraphQL schema and queries to include multi-workspace related configurations. - Adjusted server environment variables and their respective documentation to support multi-workspace toggle. - Updated server-side logic to handle new multi-workspace configurations and conditions.
This commit is contained in:
@ -18,6 +18,11 @@ import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/worksp
|
||||
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { userValidator } from 'src/engine/core-modules/user/user.validate';
|
||||
import {
|
||||
AuthException,
|
||||
AuthExceptionCode,
|
||||
} from 'src/engine/core-modules/auth/auth.exception';
|
||||
|
||||
// eslint-disable-next-line @nx/workspace-inject-workspace-repository
|
||||
export class UserService extends TypeOrmQueryService<User> {
|
||||
@ -64,9 +69,7 @@ export class UserService extends TypeOrmQueryService<User> {
|
||||
'workspaceMember',
|
||||
);
|
||||
|
||||
const workspaceMembers = workspaceMemberRepository.find();
|
||||
|
||||
return workspaceMembers;
|
||||
return workspaceMemberRepository.find();
|
||||
}
|
||||
|
||||
async deleteUser(userId: string): Promise<User> {
|
||||
@ -131,4 +134,29 @@ export class UserService extends TypeOrmQueryService<User> {
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
async saveDefaultWorkspace(userId: string, workspaceId: string) {
|
||||
const user = await this.userRepository.findOne({
|
||||
where: {
|
||||
id: userId,
|
||||
workspaces: {
|
||||
workspaceId,
|
||||
},
|
||||
},
|
||||
relations: ['workspaces'],
|
||||
});
|
||||
|
||||
userValidator.assertIsExist(
|
||||
user,
|
||||
new AuthException(
|
||||
'User does not have access to this workspace',
|
||||
AuthExceptionCode.FORBIDDEN_EXCEPTION,
|
||||
),
|
||||
);
|
||||
|
||||
return await this.userRepository.save({
|
||||
id: userId,
|
||||
defaultWorkspaceId: workspaceId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@ import {
|
||||
} from '@nestjs/graphql';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import assert from 'assert';
|
||||
import crypto from 'crypto';
|
||||
|
||||
import { GraphQLJSONObject } from 'graphql-type-json';
|
||||
@ -40,6 +39,11 @@ import { DemoEnvGuard } from 'src/engine/guards/demo.env.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { streamToBuffer } from 'src/utils/stream-to-buffer';
|
||||
import { AccountsToReconnectKeys } from 'src/modules/connected-account/types/accounts-to-reconnect-key-value.type';
|
||||
import {
|
||||
AuthException,
|
||||
AuthExceptionCode,
|
||||
} from 'src/engine/core-modules/auth/auth.exception';
|
||||
import { userValidator } from 'src/engine/core-modules/user/user.validate';
|
||||
|
||||
const getHMACKey = (email?: string, key?: string | null) => {
|
||||
if (!email || !key) return null;
|
||||
@ -65,7 +69,17 @@ export class UserResolver {
|
||||
) {}
|
||||
|
||||
@Query(() => User)
|
||||
async currentUser(@AuthUser() { id: userId }: User): Promise<User> {
|
||||
async currentUser(
|
||||
@AuthUser() { id: userId }: User,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
): Promise<User> {
|
||||
if (
|
||||
this.environmentService.get('IS_MULTIWORKSPACE_ENABLED') &&
|
||||
workspaceId
|
||||
) {
|
||||
await this.userService.saveDefaultWorkspace(userId, workspaceId);
|
||||
}
|
||||
|
||||
const user = await this.userRepository.findOne({
|
||||
where: {
|
||||
id: userId,
|
||||
@ -73,7 +87,10 @@ export class UserResolver {
|
||||
relations: ['defaultWorkspace', 'workspaces', 'workspaces.workspace'],
|
||||
});
|
||||
|
||||
assert(user, 'User not found');
|
||||
userValidator.assertIsExist(
|
||||
user,
|
||||
new AuthException('User not found', AuthExceptionCode.USER_NOT_FOUND),
|
||||
);
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
import { User } from 'src/engine/core-modules/user/user.entity';
|
||||
import { CustomException } from 'src/utils/custom-exception';
|
||||
|
||||
const assertIsExist = (
|
||||
user: User | undefined | null,
|
||||
exceptionToThrow: CustomException,
|
||||
): asserts user is User => {
|
||||
if (!user) {
|
||||
throw exceptionToThrow;
|
||||
}
|
||||
};
|
||||
|
||||
const isExist = (user: User | undefined | null): user is User => {
|
||||
return !!user;
|
||||
};
|
||||
|
||||
const assertHasDefaultWorkspace = (
|
||||
user: User,
|
||||
exceptionToThrow?: CustomException,
|
||||
): asserts user is User & { defaultWorkspaceId: string } => {
|
||||
if (!user.defaultWorkspaceId) {
|
||||
throw exceptionToThrow;
|
||||
}
|
||||
};
|
||||
|
||||
export const userValidator: {
|
||||
assertIsExist: typeof assertIsExist;
|
||||
assertHasDefaultWorkspace: typeof assertHasDefaultWorkspace;
|
||||
isExist: typeof isExist;
|
||||
} = {
|
||||
assertIsExist,
|
||||
assertHasDefaultWorkspace,
|
||||
isExist,
|
||||
};
|
||||
Reference in New Issue
Block a user