Assign user to workspace on signin

This commit is contained in:
Charles Bochet
2023-04-24 14:50:48 +02:00
parent a5bfeef2d6
commit 6d2c8bbdf9
36 changed files with 547 additions and 34 deletions

View File

@ -13,10 +13,4 @@ describe('AppController', () => {
appController = app.get<AppController>(AppController);
});
describe('root', () => {
it('should return "Hello World!"', () => {
expect(appController.health()).toBe('Healthy!');
});
});
});

View File

@ -4,9 +4,4 @@ import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get('/health')
health(): string {
return this.appService.health();
}
}

View File

@ -3,10 +3,20 @@ import { AppController } from './app.controller';
import { AppService } from './app.service';
import { HealthController } from './health.controller';
import { TerminusModule } from '@nestjs/terminus';
import { HasuraModule } from '@golevelup/nestjs-hasura';
import { UserService } from './user/user.service';
import { UserModule } from './user/user.module';
const path = require('path');
@Module({
imports: [TerminusModule],
imports: [UserModule, TerminusModule, HasuraModule.forRoot(HasuraModule, {
webhookConfig: {
secretFactory: process.env.HASURA_EVENT_HANDLER_SECRET_HEADER,
secretHeader: 'secret-header',
},
})
],
controllers: [AppController, HealthController],
providers: [AppService],
providers: [AppService, UserService],
})
export class AppModule {}

View File

@ -0,0 +1,8 @@
import { Module } from '@nestjs/common';
import { PrismaService } from './prisma.service';
@Module({
providers: [PrismaService],
exports: [PrismaService],
})
export class PrismaModule {}

View File

@ -0,0 +1,15 @@
import { INestApplication, Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
async onModuleInit() {
await this.$connect();
}
async enableShutdownHooks(app: INestApplication) {
this.$on('beforeExit', async () => {
await app.close();
});
}
}

View File

@ -0,0 +1,30 @@
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("SERVER_DATABASE_URL")
}
model WorkspaceMember {
id Int @id @default(autoincrement())
created_at DateTime @default(now())
updated_at DateTime @updatedAt
deleted_at DateTime?
user_id String @unique
workspace_id Int
@@map("workspace_members")
}
model Workspace {
id Int @id @default(autoincrement())
created_at DateTime @default(now())
updated_at DateTime @updatedAt
deleted_at DateTime?
domain_name String @unique
display_name String
@@map("workspaces")
}

View File

@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { PrismaModule } from 'src/database/prisma.module';
import { UserRepository } from './user.repository';
import { UserService } from './user.service';
import { WorkspaceRepository } from './workspace.repository';
@Module({
imports: [PrismaModule],
providers: [UserRepository, UserService, WorkspaceRepository],
exports: [UserService, UserRepository, WorkspaceRepository],
})
export class UserModule {}

View File

@ -0,0 +1,23 @@
import { Injectable } from '@nestjs/common';
import { Prisma, WorkspaceMember } from '@prisma/client';
import { PrismaService } from 'src/database/prisma.service';
@Injectable()
export class UserRepository {
constructor(private prisma: PrismaService) {}
async upsertWorkspaceMember(params: { data: Prisma.WorkspaceMemberCreateInput }): Promise<WorkspaceMember> {
const { data } = params;
return this.prisma.workspaceMember.upsert({
where: {
user_id: data.user_id,
},
create: {
user_id: data.user_id,
workspace_id: data.workspace_id,
},
update: {
}
});
}
}

View File

@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { UserService } from './user.service';
describe('UserService', () => {
let service: UserService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [UserService],
}).compile();
service = module.get<UserService>(UserService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View File

@ -0,0 +1,40 @@
import { HasuraInsertEvent, TrackedHasuraEventHandler } from '@golevelup/nestjs-hasura';
import { UserRepository} from "./user.repository"
import { Injectable, Response } from '@nestjs/common';
import { WorkspaceRepository } from './workspace.repository';
import { response } from 'express';
interface User {
id: number;
email: string;
}
@Injectable()
export class UserService {
constructor(private repository: UserRepository, private workspaceRepository: WorkspaceRepository) {}
@TrackedHasuraEventHandler({
triggerName: 'user-created',
tableName: 'users',
schema: 'auth',
definition: { type: 'insert' },
})
async handleUserCreated(evt: HasuraInsertEvent<User>) {
const workspace = await this.workspaceRepository.findWorkspaceByDomainName(
{ where: { domain_name:evt.event.data.new.email.split('@')[1] }
});
console.log(workspace)
if (!workspace) {
return;
}
const workspaceMember = await this.repository.upsertWorkspaceMember({
data: {
user_id: String(evt.event.data.new.id),
workspace_id: workspace.id,
},
});
}
}

View File

@ -0,0 +1,12 @@
import { Injectable } from '@nestjs/common';
import { Prisma, Workspace } from '@prisma/client';
import { PrismaService } from 'src/database/prisma.service';
@Injectable()
export class WorkspaceRepository {
constructor(private prisma: PrismaService) {}
async findWorkspaceByDomainName(data: Prisma.WorkspaceFindUniqueArgs): Promise<Workspace> {
return this.prisma.workspace.findUnique(data);
}
}