Files
hoppscotch/packages/hoppscotch-backend/src/user-collection/user-collection.resolver.ts
Balu Babu 18864bfecf feat: addition of data field into User and Team Collections (#3614)
* feat: added new columns into the TeamCollections and UserCollections models

* feat: completed addition of new data field in TeamCollection

* feat: completed addition of new data field in UserCollections

* chore: updated all tests in team-collection module

* chore: added tests for updateTeamCollection method in team-collection module

* chore: refactored all existing testcases in user-collection to reflect new changes

* chore: added new testcases for updateUserCollection method in user-collection module

* chore: made data field optional in team and user collections

* chore: fixed edgecases for data being null

* chore: resolved issue with team-request testcases

* chore: completed changes requested in PR review

* chore: changed target to prod in hoppscotch-old-backend service
2023-12-05 20:12:37 +05:30

444 lines
12 KiB
TypeScript

import { UseGuards } from '@nestjs/common';
import {
Resolver,
Mutation,
Args,
ID,
Query,
ResolveField,
Parent,
Subscription,
} from '@nestjs/graphql';
import { GqlUser } from 'src/decorators/gql-user.decorator';
import { GqlAuthGuard } from 'src/guards/gql-auth.guard';
import { PubSubService } from 'src/pubsub/pubsub.service';
import { AuthUser } from 'src/types/AuthUser';
import { UserCollectionService } from './user-collection.service';
import {
UserCollection,
UserCollectionExportJSONData,
UserCollectionRemovedData,
UserCollectionReorderData,
} from './user-collections.model';
import { throwErr } from 'src/utils';
import { User } from 'src/user/user.model';
import { PaginationArgs } from 'src/types/input-types.args';
import {
CreateChildUserCollectionArgs,
CreateRootUserCollectionArgs,
ImportUserCollectionsFromJSONArgs,
MoveUserCollectionArgs,
RenameUserCollectionsArgs,
UpdateUserCollectionArgs,
UpdateUserCollectionsArgs,
} from './input-type.args';
import { ReqType } from 'src/types/RequestTypes';
import * as E from 'fp-ts/Either';
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
import { SkipThrottle } from '@nestjs/throttler';
@UseGuards(GqlThrottlerGuard)
@Resolver(() => UserCollection)
export class UserCollectionResolver {
constructor(
private readonly userCollectionService: UserCollectionService,
private readonly pubSub: PubSubService,
) {}
// Field Resolvers
@ResolveField(() => User, {
description: 'User the collection belongs to',
})
async user(@GqlUser() user: AuthUser) {
return user;
}
@ResolveField(() => UserCollection, {
description: 'Parent user collection (null if root)',
nullable: true,
})
async parent(@Parent() collection: UserCollection) {
return this.userCollectionService.getParentOfUserCollection(collection.id);
}
@ResolveField(() => [UserCollection], {
description: 'List of children REST user collection',
complexity: 3,
})
childrenREST(
@Parent() collection: UserCollection,
@Args() args: PaginationArgs,
) {
return this.userCollectionService.getChildrenOfUserCollection(
collection.id,
args.cursor,
args.take,
ReqType.REST,
);
}
@ResolveField(() => [UserCollection], {
description: 'List of children GraphQL user collection',
complexity: 3,
})
childrenGQL(
@Parent() collection: UserCollection,
@Args() args: PaginationArgs,
) {
return this.userCollectionService.getChildrenOfUserCollection(
collection.id,
args.cursor,
args.take,
ReqType.GQL,
);
}
// Queries
@Query(() => [UserCollection], {
description: 'Get the root REST user collections for a user',
})
@UseGuards(GqlAuthGuard)
rootRESTUserCollections(
@GqlUser() user: AuthUser,
@Args() args: PaginationArgs,
) {
return this.userCollectionService.getUserRootCollections(
user,
args.cursor,
args.take,
ReqType.REST,
);
}
@Query(() => [UserCollection], {
description: 'Get the root GraphQL user collections for a user',
})
@UseGuards(GqlAuthGuard)
rootGQLUserCollections(
@GqlUser() user: AuthUser,
@Args() args: PaginationArgs,
) {
return this.userCollectionService.getUserRootCollections(
user,
args.cursor,
args.take,
ReqType.GQL,
);
}
@Query(() => UserCollection, {
description: 'Get user collection with ID',
})
@UseGuards(GqlAuthGuard)
async userCollection(
@Args({
type: () => ID,
name: 'userCollectionID',
description: 'ID of the user collection',
})
userCollectionID: string,
) {
const userCollection = await this.userCollectionService.getUserCollection(
userCollectionID,
);
if (E.isLeft(userCollection)) throwErr(userCollection.left);
return <UserCollection>{
...userCollection.right,
userID: userCollection.right.userUid,
data: !userCollection.right.data
? null
: JSON.stringify(userCollection.right.data),
};
}
@Query(() => UserCollectionExportJSONData, {
description:
'Returns the JSON string giving the collections and their contents of a user',
})
@UseGuards(GqlAuthGuard)
async exportUserCollectionsToJSON(
@GqlUser() user: AuthUser,
@Args({
type: () => ID,
name: 'collectionID',
description: 'ID of the user collection',
nullable: true,
defaultValue: null,
})
collectionID: string,
@Args({
type: () => ReqType,
name: 'collectionType',
description: 'Type of the user collection',
})
collectionType: ReqType,
) {
const jsonString =
await this.userCollectionService.exportUserCollectionsToJSON(
user.uid,
collectionID,
collectionType,
);
if (E.isLeft(jsonString)) throwErr(jsonString.left as string);
return jsonString.right;
}
// Mutations
@Mutation(() => UserCollection, {
description: 'Creates root REST user collection(no parent user collection)',
})
@UseGuards(GqlAuthGuard)
async createRESTRootUserCollection(
@GqlUser() user: AuthUser,
@Args() args: CreateRootUserCollectionArgs,
) {
const userCollection =
await this.userCollectionService.createUserCollection(
user,
args.title,
args.data,
null,
ReqType.REST,
);
if (E.isLeft(userCollection)) throwErr(userCollection.left);
return userCollection.right;
}
@Mutation(() => UserCollection, {
description:
'Creates root GraphQL user collection(no parent user collection)',
})
@UseGuards(GqlAuthGuard)
async createGQLRootUserCollection(
@GqlUser() user: AuthUser,
@Args() args: CreateRootUserCollectionArgs,
) {
const userCollection =
await this.userCollectionService.createUserCollection(
user,
args.title,
args.data,
null,
ReqType.GQL,
);
if (E.isLeft(userCollection)) throwErr(userCollection.left);
return userCollection.right;
}
@Mutation(() => UserCollection, {
description: 'Creates a new child GraphQL user collection',
})
@UseGuards(GqlAuthGuard)
async createGQLChildUserCollection(
@GqlUser() user: AuthUser,
@Args() args: CreateChildUserCollectionArgs,
) {
const userCollection =
await this.userCollectionService.createUserCollection(
user,
args.title,
args.data,
args.parentUserCollectionID,
ReqType.GQL,
);
if (E.isLeft(userCollection)) throwErr(userCollection.left);
return userCollection.right;
}
@Mutation(() => UserCollection, {
description: 'Creates a new child REST user collection',
})
@UseGuards(GqlAuthGuard)
async createRESTChildUserCollection(
@GqlUser() user: AuthUser,
@Args() args: CreateChildUserCollectionArgs,
) {
const userCollection =
await this.userCollectionService.createUserCollection(
user,
args.title,
args.data,
args.parentUserCollectionID,
ReqType.REST,
);
if (E.isLeft(userCollection)) throwErr(userCollection.left);
return userCollection.right;
}
@Mutation(() => UserCollection, {
description: 'Rename a user collection',
})
@UseGuards(GqlAuthGuard)
async renameUserCollection(
@GqlUser() user: AuthUser,
@Args() args: RenameUserCollectionsArgs,
) {
const updatedUserCollection =
await this.userCollectionService.renameUserCollection(
args.newTitle,
args.userCollectionID,
user.uid,
);
if (E.isLeft(updatedUserCollection)) throwErr(updatedUserCollection.left);
return updatedUserCollection.right;
}
@Mutation(() => Boolean, {
description: 'Delete a user collection',
})
@UseGuards(GqlAuthGuard)
async deleteUserCollection(
@Args({
name: 'userCollectionID',
description: 'ID of the user collection',
type: () => ID,
})
userCollectionID: string,
@GqlUser() user: AuthUser,
) {
const result = await this.userCollectionService.deleteUserCollection(
userCollectionID,
user.uid,
);
if (E.isLeft(result)) throwErr(result.left);
return result.right;
}
@Mutation(() => UserCollection, {
description: 'Move user collection into new parent or root',
})
@UseGuards(GqlAuthGuard)
async moveUserCollection(
@Args() args: MoveUserCollectionArgs,
@GqlUser() user: AuthUser,
) {
const res = await this.userCollectionService.moveUserCollection(
args.userCollectionID,
args.destCollectionID,
user.uid,
);
if (E.isLeft(res)) {
throwErr(res.left);
}
return res.right;
}
@Mutation(() => Boolean, {
description:
'Update the order of UserCollections inside parent collection or in root',
})
@UseGuards(GqlAuthGuard)
async updateUserCollectionOrder(
@Args() args: UpdateUserCollectionArgs,
@GqlUser() user: AuthUser,
) {
const res = await this.userCollectionService.updateUserCollectionOrder(
args.collectionID,
args.nextCollectionID,
user.uid,
);
if (E.isLeft(res)) {
throwErr(res.left);
}
return res.right;
}
@Mutation(() => Boolean, {
description: 'Import collections from JSON string to the specified Team',
})
@UseGuards(GqlAuthGuard)
async importUserCollectionsFromJSON(
@Args() args: ImportUserCollectionsFromJSONArgs,
@GqlUser() user: AuthUser,
) {
const importedCollection =
await this.userCollectionService.importCollectionsFromJSON(
args.jsonString,
user.uid,
args.parentCollectionID,
args.reqType,
);
if (E.isLeft(importedCollection)) throwErr(importedCollection.left);
return importedCollection.right;
}
@Mutation(() => UserCollection, {
description: 'Update a UserCollection',
})
@UseGuards(GqlAuthGuard)
async updateUserCollection(
@GqlUser() user: AuthUser,
@Args() args: UpdateUserCollectionsArgs,
) {
const updatedUserCollection =
await this.userCollectionService.updateUserCollection(
args.newTitle,
args.data,
args.userCollectionID,
user.uid,
);
if (E.isLeft(updatedUserCollection)) throwErr(updatedUserCollection.left);
return updatedUserCollection.right;
}
// Subscriptions
@Subscription(() => UserCollection, {
description: 'Listen for User Collection Creation',
resolve: (value) => value,
})
@SkipThrottle()
@UseGuards(GqlAuthGuard)
userCollectionCreated(@GqlUser() user: AuthUser) {
return this.pubSub.asyncIterator(`user_coll/${user.uid}/created`);
}
@Subscription(() => UserCollection, {
description: 'Listen to when a User Collection has been updated.',
resolve: (value) => value,
})
@SkipThrottle()
@UseGuards(GqlAuthGuard)
userCollectionUpdated(@GqlUser() user: AuthUser) {
return this.pubSub.asyncIterator(`user_coll/${user.uid}/updated`);
}
@Subscription(() => UserCollectionRemovedData, {
description: 'Listen to when a User Collection has been deleted',
resolve: (value) => value,
})
@SkipThrottle()
@UseGuards(GqlAuthGuard)
userCollectionRemoved(@GqlUser() user: AuthUser) {
return this.pubSub.asyncIterator(`user_coll/${user.uid}/deleted`);
}
@Subscription(() => UserCollection, {
description: 'Listen to when a User Collection has been moved',
resolve: (value) => value,
})
@SkipThrottle()
@UseGuards(GqlAuthGuard)
userCollectionMoved(@GqlUser() user: AuthUser) {
return this.pubSub.asyncIterator(`user_coll/${user.uid}/moved`);
}
@Subscription(() => UserCollectionReorderData, {
description: 'Listen to when a User Collections position has changed',
resolve: (value) => value,
})
@SkipThrottle()
@UseGuards(GqlAuthGuard)
userCollectionOrderUpdated(@GqlUser() user: AuthUser) {
return this.pubSub.asyncIterator(`user_coll/${user.uid}/order_updated`);
}
}