Add support chat (#1066)

* Add support chat

Co-authored-by: v1b3m <vibenjamin6@gmail.com>

* Refactor the chat logic

Co-authored-by: v1b3m <vibenjamin6@gmail.com>

* Add HMAC signing

Co-authored-by: v1b3m <vibenjamin6@gmail.com>

* Update the button styles

Co-authored-by: v1b3m <vibenjamin6@gmail.com>

* Update the button styles

Co-authored-by: v1b3m <vibenjamin6@gmail.com>

* Refactor the chat logic

Co-authored-by: v1b3m <vibenjamin6@gmail.com>

* Fix the chat not loading

Co-authored-by: v1b3m <vibenjamin6@gmail.com>

* Fix the chat not loading

Co-authored-by: v1b3m <vibenjamin6@gmail.com>

* Add requested changes

Co-authored-by: v1b3m <vibenjamin6@gmail.com>

* Add requested changes

Co-authored-by: v1b3m <vibenjamin6@gmail.com>

* Add requested changes

Co-authored-by: v1b3m <vibenjamin6@gmail.com>

* Add requested changes

Co-authored-by: v1b3m <vibenjamin6@gmail.com>

* Add requested changes

Co-authored-by: v1b3m <vibenjamin6@gmail.com>

---------

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
This commit is contained in:
gitstart-twenty
2023-08-05 07:52:59 +08:00
committed by GitHub
parent 5e6351e099
commit 57c465176a
17 changed files with 239 additions and 11 deletions

View File

@ -17,4 +17,7 @@ SIGN_IN_PREFILLED=true
# FRONT_AUTH_CALLBACK_URL=http://localhost:3001/verify
# AUTH_GOOGLE_ENABLED=false
# STORAGE_TYPE=local
# STORAGE_LOCAL_PATH=.local-storage
# STORAGE_LOCAL_PATH=.local-storage
# SUPPORT_DRIVER=front
# SUPPORT_HMAC_KEY=replace_me_with_a_random_string
# SUPPORT_FRONTEND_KEY=replace_me_with_a_random_string

View File

@ -21,6 +21,15 @@ class Telemetry {
anonymizationEnabled: boolean;
}
@ObjectType()
class SupportChat {
@Field(() => String)
supportDriver: string;
@Field(() => String, { nullable: true })
supportFrontendKey: string | null;
}
@ObjectType()
export class ClientConfig {
@Field(() => AuthProviders, { nullable: false })
@ -34,4 +43,7 @@ export class ClientConfig {
@Field(() => Boolean)
debugMode: boolean;
@Field(() => SupportChat)
supportChat: SupportChat;
}

View File

@ -23,6 +23,10 @@ export class ClientConfigResolver {
},
signInPrefilled: this.environmentService.isSignInPrefilled(),
debugMode: this.environmentService.isDebugMode(),
supportChat: {
supportDriver: this.environmentService.getSupportDriver(),
supportFrontendKey: this.environmentService.getSupportFrontendKey(),
},
};
return Promise.resolve(clientConfig);

View File

@ -0,0 +1,9 @@
import { Field, ObjectType } from '@nestjs/graphql';
import { User } from 'src/core/@generated/user/user.model';
@ObjectType()
export class UserWithHMACKey extends User {
@Field(() => String, { nullable: true })
supportHMACKey: string | null;
}

View File

@ -2,12 +2,13 @@ import { Module } from '@nestjs/common';
import { FileModule } from 'src/core/file/file.module';
import { WorkspaceModule } from 'src/core/workspace/workspace.module';
import { EnvironmentModule } from 'src/integrations/environment/environment.module';
import { UserService } from './user.service';
import { UserResolver } from './user.resolver';
@Module({
imports: [FileModule, WorkspaceModule],
imports: [FileModule, WorkspaceModule, EnvironmentModule],
providers: [UserService, UserResolver],
exports: [UserService],
})

View File

@ -2,6 +2,7 @@ import { Test, TestingModule } from '@nestjs/testing';
import { AbilityFactory } from 'src/ability/ability.factory';
import { FileUploadService } from 'src/core/file/services/file-upload.service';
import { EnvironmentService } from 'src/integrations/environment/environment.service';
import { UserResolver } from './user.resolver';
import { UserService } from './user.service';
@ -25,6 +26,10 @@ describe('UserResolver', () => {
provide: FileUploadService,
useValue: {},
},
{
provide: EnvironmentService,
useValue: {},
},
],
}).compile();

View File

@ -8,6 +8,8 @@ import {
} from '@nestjs/graphql';
import { UseFilters, UseGuards } from '@nestjs/common';
import crypto from 'crypto';
import { accessibleBy } from '@casl/prisma';
import { Prisma, Workspace } from '@prisma/client';
import { FileUpload, GraphQLUpload } from 'graphql-upload';
@ -37,32 +39,48 @@ import { UpdateOneUserArgs } from 'src/core/@generated/user/update-one-user.args
import { streamToBuffer } from 'src/utils/stream-to-buffer';
import { FileUploadService } from 'src/core/file/services/file-upload.service';
import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator';
import { EnvironmentService } from 'src/integrations/environment/environment.service';
import { UserService } from './user.service';
import { UserWithHMACKey } from './dto/user-with-HMAC';
function getHMACKey(email?: string, key?: string | null) {
if (!email || !key) return null;
const hmac = crypto.createHmac('sha256', key);
return hmac.update(email).digest('hex');
}
@UseGuards(JwtAuthGuard)
@Resolver(() => User)
export class UserResolver {
constructor(
private readonly userService: UserService,
private readonly fileUploadService: FileUploadService,
private environmentService: EnvironmentService,
) {}
@Query(() => User)
@Query(() => UserWithHMACKey)
async currentUser(
@AuthUser() { id }: User,
@AuthUser() { id, email }: User,
@PrismaSelector({ modelName: 'User' })
prismaSelect: PrismaSelect<'User'>,
) {
const key = this.environmentService.getSupportHMACKey();
const select = prismaSelect.value;
delete select['supportHMACKey'];
const user = await this.userService.findUnique({
where: {
id,
},
select: prismaSelect.value,
select,
});
assert(user, 'User not found');
return user;
return { ...user, supportHMACKey: getHMACKey(email, key) };
}
@UseFilters(ExceptionFilter)

View File

@ -101,4 +101,16 @@ export class EnvironmentService {
this.configService.get<string>('STORAGE_LOCAL_PATH') ?? '.local-storage'
);
}
getSupportDriver(): string {
return this.configService.get<string>('SUPPORT_DRIVER') ?? 'front';
}
getSupportFrontendKey(): string | null {
return this.configService.get<string>('SUPPORT_FRONTEND_KEY') ?? null;
}
getSupportHMACKey(): string | null {
return this.configService.get<string>('SUPPORT_HMAC_KEY') ?? null;
}
}