feat: user update and subscribers added
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
|
import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
|
||||||
import { PrismaClient } from '@prisma/client/scripts/default-index';
|
import { PrismaClient } from '@prisma/client';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PrismaService
|
export class PrismaService
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { Field, InputType } from '@nestjs/graphql';
|
||||||
|
|
||||||
|
@InputType()
|
||||||
|
export class UpdateUserInput {
|
||||||
|
@Field({
|
||||||
|
nullable: true,
|
||||||
|
name: 'currentRESTSession',
|
||||||
|
description: 'JSON string of the session',
|
||||||
|
})
|
||||||
|
currentRESTSession?: string;
|
||||||
|
|
||||||
|
@Field({
|
||||||
|
nullable: true,
|
||||||
|
name: 'currentGQLSession',
|
||||||
|
description: 'JSON string of the session',
|
||||||
|
})
|
||||||
|
currentGQLSession?: string;
|
||||||
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { UserResolver } from './user.resolver';
|
import { UserResolver } from './user.resolver';
|
||||||
import { PubSubModule } from 'src/pubsub/pubsub.module';
|
import { PubSubModule } from 'src/pubsub/pubsub.module';
|
||||||
|
import { PrismaModule } from 'src/prisma/prisma.module';
|
||||||
|
import { UserService } from './user.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [PubSubModule],
|
imports: [PubSubModule, PrismaModule],
|
||||||
providers: [UserResolver],
|
providers: [UserResolver, UserService],
|
||||||
exports: [],
|
exports: [],
|
||||||
})
|
})
|
||||||
export class UserModule {}
|
export class UserModule {}
|
||||||
|
|||||||
@@ -1,14 +1,22 @@
|
|||||||
import { Resolver, Query } from '@nestjs/graphql';
|
import { Resolver, Query, Mutation, Args, Subscription } from '@nestjs/graphql';
|
||||||
import { User } from './user.model';
|
import { User } from './user.model';
|
||||||
import { UseGuards } from '@nestjs/common';
|
import { UseGuards } from '@nestjs/common';
|
||||||
import { GqlAuthGuard } from '../guards/gql-auth.guard';
|
import { GqlAuthGuard } from '../guards/gql-auth.guard';
|
||||||
import { GqlUser } from '../decorators/gql-user.decorator';
|
import { GqlUser } from '../decorators/gql-user.decorator';
|
||||||
|
import { UserService } from './user.service';
|
||||||
|
import { throwErr } from 'src/utils';
|
||||||
|
import * as E from 'fp-ts/lib/Either';
|
||||||
|
import { UpdateUserInput } from './dtos/update-user-input.dto';
|
||||||
|
import { PubSubService } from 'src/pubsub/pubsub.service';
|
||||||
|
|
||||||
@Resolver(() => User)
|
@Resolver(() => User)
|
||||||
export class UserResolver {
|
export class UserResolver {
|
||||||
// TODO: remove the eslint-disable line below once dependencies are added to user.service file
|
// TODO: remove the eslint-disable line below once dependencies are added to user.service file
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
constructor() {}
|
constructor(
|
||||||
|
private readonly userService: UserService,
|
||||||
|
private readonly pubsub: PubSubService,
|
||||||
|
) {}
|
||||||
|
|
||||||
@Query(() => User, {
|
@Query(() => User, {
|
||||||
description:
|
description:
|
||||||
@@ -27,4 +35,30 @@ export class UserResolver {
|
|||||||
me2(@GqlUser() user: User): User {
|
me2(@GqlUser() user: User): User {
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mutations */
|
||||||
|
|
||||||
|
@Mutation(() => User, {
|
||||||
|
description: 'Update user information',
|
||||||
|
})
|
||||||
|
@UseGuards(GqlAuthGuard)
|
||||||
|
async updateUser(
|
||||||
|
@GqlUser() user: User,
|
||||||
|
@Args('userInput') userInput: UpdateUserInput,
|
||||||
|
): Promise<User> {
|
||||||
|
const updatedUser = await this.userService.updateUser(user, userInput);
|
||||||
|
if (E.isLeft(updatedUser)) throwErr(updatedUser.left);
|
||||||
|
return updatedUser.right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Subscriptions */
|
||||||
|
|
||||||
|
@Subscription(() => User, {
|
||||||
|
description: 'Listen for user updates',
|
||||||
|
resolve: (value) => value,
|
||||||
|
})
|
||||||
|
@UseGuards(GqlAuthGuard)
|
||||||
|
userSettingsUpdated(@GqlUser() user: User) {
|
||||||
|
return this.pubsub.asyncIterator(`user/${user.uid}/updated`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
34
packages/hoppscotch-backend/src/user/user.service.ts
Normal file
34
packages/hoppscotch-backend/src/user/user.service.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { PrismaService } from '../prisma/prisma.service';
|
||||||
|
import { User } from './user.model';
|
||||||
|
import * as E from 'fp-ts/lib/Either';
|
||||||
|
import { USER_NOT_FOUND } from 'src/errors';
|
||||||
|
import { UpdateUserInput } from './dtos/update-user-input.dto';
|
||||||
|
import { PubSubService } from 'src/pubsub/pubsub.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UserService {
|
||||||
|
constructor(
|
||||||
|
private readonly prisma: PrismaService,
|
||||||
|
private readonly pubsub: PubSubService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async updateUser(user: User, updateUserDto: UpdateUserInput) {
|
||||||
|
try {
|
||||||
|
const updatedUser = await this.prisma.user.update({
|
||||||
|
where: { uid: user.uid },
|
||||||
|
data: updateUserDto,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Publish subscription for user updates
|
||||||
|
await this.pubsub.publish(
|
||||||
|
`user_settings/${user.uid}/updated`,
|
||||||
|
updatedUser,
|
||||||
|
);
|
||||||
|
|
||||||
|
return E.right(updatedUser);
|
||||||
|
} catch (e) {
|
||||||
|
return E.left(USER_NOT_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user