feat: db schema update from string to json column type
This commit is contained in:
@@ -83,8 +83,8 @@ model User {
|
|||||||
displayName String?
|
displayName String?
|
||||||
email String?
|
email String?
|
||||||
photoURL String?
|
photoURL String?
|
||||||
currentRESTSession String?
|
currentRESTSession Json?
|
||||||
currentGQLSession String?
|
currentGQLSession Json?
|
||||||
UserEnvironments UserEnvironment[]
|
UserEnvironments UserEnvironment[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ export const USER_FB_DOCUMENT_DELETION_FAILED =
|
|||||||
*/
|
*/
|
||||||
export const USER_NOT_FOUND = 'user/not_found' as const;
|
export const USER_NOT_FOUND = 'user/not_found' as const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User update failure
|
||||||
|
* (UserService)
|
||||||
|
*/
|
||||||
|
export const USER_UPDATE_FAILED = 'user/update_failed' as const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User deletion failure
|
* User deletion failure
|
||||||
* (UserService)
|
* (UserService)
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ export type TopicDef = {
|
|||||||
[
|
[
|
||||||
topic: `user_environment/${string}/${'created' | 'updated' | 'deleted'}`
|
topic: `user_environment/${string}/${'created' | 'updated' | 'deleted'}`
|
||||||
]: UserEnvironment;
|
]: UserEnvironment;
|
||||||
[
|
[topic: `user/${string}/${'updated'}`]: User;
|
||||||
topic: `user/${string}/${'created' | 'updated' | 'deleted'}`
|
|
||||||
]: User;
|
|
||||||
[topic: `user_environment/${string}/deleted_many`]: number;
|
[topic: `user_environment/${string}/deleted_many`]: number;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
import { Field, InputType } from '@nestjs/graphql';
|
|
||||||
|
|
||||||
@InputType()
|
|
||||||
export class UpdateUserInput {
|
|
||||||
@Field({
|
|
||||||
nullable: true,
|
|
||||||
name: 'displayName',
|
|
||||||
description: 'Displayed name of the user (if given)',
|
|
||||||
})
|
|
||||||
displayName?: string;
|
|
||||||
|
|
||||||
@Field({
|
|
||||||
nullable: true,
|
|
||||||
name: 'photoURL',
|
|
||||||
description: 'URL to the profile photo of the user (if given)',
|
|
||||||
})
|
|
||||||
photoURL?: string;
|
|
||||||
|
|
||||||
@Field({
|
|
||||||
nullable: true,
|
|
||||||
name: 'currentRESTSession',
|
|
||||||
description: 'JSON string of the saved REST session',
|
|
||||||
})
|
|
||||||
currentRESTSession?: string;
|
|
||||||
|
|
||||||
@Field({
|
|
||||||
nullable: true,
|
|
||||||
name: 'currentGQLSession',
|
|
||||||
description: 'JSON string of the saved GQL session',
|
|
||||||
})
|
|
||||||
currentGQLSession?: string;
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ObjectType, ID, Field } from '@nestjs/graphql';
|
import { ObjectType, ID, Field, InputType } from '@nestjs/graphql';
|
||||||
|
|
||||||
@ObjectType()
|
@ObjectType()
|
||||||
export class User {
|
export class User {
|
||||||
@@ -37,3 +37,34 @@ export class User {
|
|||||||
})
|
})
|
||||||
currentGQLSession?: string;
|
currentGQLSession?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@InputType()
|
||||||
|
export class UpdateUserInput {
|
||||||
|
@Field({
|
||||||
|
nullable: true,
|
||||||
|
name: 'displayName',
|
||||||
|
description: 'Displayed name of the user (if given)',
|
||||||
|
})
|
||||||
|
displayName?: string;
|
||||||
|
|
||||||
|
@Field({
|
||||||
|
nullable: true,
|
||||||
|
name: 'photoURL',
|
||||||
|
description: 'URL to the profile photo of the user (if given)',
|
||||||
|
})
|
||||||
|
photoURL?: string;
|
||||||
|
|
||||||
|
@Field({
|
||||||
|
nullable: true,
|
||||||
|
name: 'currentRESTSession',
|
||||||
|
description: 'JSON string of the saved REST session',
|
||||||
|
})
|
||||||
|
currentRESTSession?: string;
|
||||||
|
|
||||||
|
@Field({
|
||||||
|
nullable: true,
|
||||||
|
name: 'currentGQLSession',
|
||||||
|
description: 'JSON string of the saved GQL session',
|
||||||
|
})
|
||||||
|
currentGQLSession?: string;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import { Resolver, Query, Mutation, Args, Subscription } from '@nestjs/graphql';
|
import { Resolver, Query, Mutation, Args, Subscription } from '@nestjs/graphql';
|
||||||
import { User } from './user.model';
|
import { UpdateUserInput, 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 { UserService } from './user.service';
|
||||||
import { throwErr } from 'src/utils';
|
import { throwErr } from 'src/utils';
|
||||||
import * as E from 'fp-ts/lib/Either';
|
import * as E from 'fp-ts/lib/Either';
|
||||||
import { UpdateUserInput } from './dtos/update-user-input.dto';
|
|
||||||
import { PubSubService } from 'src/pubsub/pubsub.service';
|
import { PubSubService } from 'src/pubsub/pubsub.service';
|
||||||
|
|
||||||
@Resolver(() => User)
|
@Resolver(() => User)
|
||||||
@@ -58,7 +57,7 @@ export class UserResolver {
|
|||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userSettingsUpdated(@GqlUser() user: User) {
|
userUpdated(@GqlUser() user: User) {
|
||||||
return this.pubsub.asyncIterator(`user/${user.uid}/updated`);
|
return this.pubsub.asyncIterator(`user/${user.uid}/updated`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { PrismaService } from '../prisma/prisma.service';
|
import { PrismaService } from '../prisma/prisma.service';
|
||||||
import { User } from './user.model';
|
import { UpdateUserInput, User } from './user.model';
|
||||||
|
import { User as DbUser, Prisma } from '@prisma/client';
|
||||||
import * as E from 'fp-ts/lib/Either';
|
import * as E from 'fp-ts/lib/Either';
|
||||||
import { USER_NOT_FOUND } from 'src/errors';
|
import { USER_UPDATE_FAILED } from 'src/errors';
|
||||||
import { UpdateUserInput } from './dtos/update-user-input.dto';
|
|
||||||
import { PubSubService } from 'src/pubsub/pubsub.service';
|
import { PubSubService } from 'src/pubsub/pubsub.service';
|
||||||
|
import { stringToJson } from 'src/utils';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UserService {
|
export class UserService {
|
||||||
@@ -16,22 +17,53 @@ export class UserService {
|
|||||||
/**
|
/**
|
||||||
* Update a user's information
|
* Update a user's information
|
||||||
* @param user User object
|
* @param user User object
|
||||||
* @param updateUserData Properties to update
|
* @param updateData Properties to update
|
||||||
* @returns a Either of User or error
|
* @returns a Either of User or error
|
||||||
*/
|
*/
|
||||||
async updateUser(user: User, updateUserData: UpdateUserInput) {
|
async updateUser(
|
||||||
|
user: User,
|
||||||
|
updateData: UpdateUserInput,
|
||||||
|
): Promise<E.Either<string, User>> {
|
||||||
|
let { currentGQLSession, currentRESTSession, ...rest } = updateData;
|
||||||
|
let updateUserObj: Partial<DbUser> = rest;
|
||||||
|
|
||||||
|
// Convert stringified JSON to JSON
|
||||||
|
if (updateData?.currentGQLSession !== undefined) {
|
||||||
|
const jsonGql = stringToJson(updateData.currentGQLSession);
|
||||||
|
if (E.isLeft<string>(jsonGql)) return jsonGql;
|
||||||
|
|
||||||
|
updateUserObj.currentGQLSession = jsonGql?.right ?? Prisma.DbNull;
|
||||||
|
}
|
||||||
|
if (updateData?.currentRESTSession !== undefined) {
|
||||||
|
const jsonRest = stringToJson(updateData.currentRESTSession);
|
||||||
|
if (E.isLeft<string>(jsonRest)) return jsonRest;
|
||||||
|
|
||||||
|
updateUserObj.currentRESTSession = jsonRest?.right ?? Prisma.DbNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update user
|
||||||
try {
|
try {
|
||||||
const updatedUser = await this.prisma.user.update({
|
const dbUpdatedUser = await this.prisma.user.update({
|
||||||
where: { uid: user.uid },
|
where: { uid: user.uid },
|
||||||
data: updateUserData,
|
data: updateUserObj,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const updatedUser: User = {
|
||||||
|
...dbUpdatedUser,
|
||||||
|
currentGQLSession: dbUpdatedUser.currentGQLSession
|
||||||
|
? JSON.stringify(dbUpdatedUser.currentGQLSession)
|
||||||
|
: null,
|
||||||
|
currentRESTSession: dbUpdatedUser.currentRESTSession
|
||||||
|
? JSON.stringify(dbUpdatedUser.currentRESTSession)
|
||||||
|
: null,
|
||||||
|
};
|
||||||
|
|
||||||
// Publish subscription for user updates
|
// Publish subscription for user updates
|
||||||
await this.pubsub.publish(`user/${user.uid}/updated`, updatedUser);
|
await this.pubsub.publish(`user/${updatedUser.uid}/updated`, updatedUser);
|
||||||
|
|
||||||
return E.right(updatedUser);
|
return E.right(updatedUser);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return E.left(USER_NOT_FOUND);
|
return E.left(USER_UPDATE_FAILED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user