diff --git a/CHANGELOG.md b/CHANGELOG.md index 743896c..78bcd44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - user confirmation tokens - email verification - idx for fields and logic to have stable order +- ability to load submission by id if token is present ### Changed diff --git a/src/resolver/auth/auth.login.resolver.ts b/src/resolver/auth/auth.login.mutation.ts similarity index 95% rename from src/resolver/auth/auth.login.resolver.ts rename to src/resolver/auth/auth.login.mutation.ts index 39925eb..46108b4 100644 --- a/src/resolver/auth/auth.login.resolver.ts +++ b/src/resolver/auth/auth.login.mutation.ts @@ -4,7 +4,7 @@ import { AuthJwtModel } from '../../dto/auth/auth.jwt.model' import { AuthService } from '../../service/auth/auth.service' @Injectable() -export class AuthLoginResolver { +export class AuthLoginMutation { constructor( private readonly auth: AuthService ) { diff --git a/src/resolver/auth/auth.register.resolver.ts b/src/resolver/auth/auth.register.mutation.ts similarity index 97% rename from src/resolver/auth/auth.register.resolver.ts rename to src/resolver/auth/auth.register.mutation.ts index 2abdbd5..dcbf59d 100644 --- a/src/resolver/auth/auth.register.resolver.ts +++ b/src/resolver/auth/auth.register.mutation.ts @@ -8,7 +8,7 @@ import { SettingService } from '../../service/setting.service' import { UserCreateService } from '../../service/user/user.create.service' @Injectable() -export class AuthRegisterResolver { +export class AuthRegisterMutation { constructor( private readonly createUser: UserCreateService, private readonly settingService: SettingService, diff --git a/src/resolver/auth/index.ts b/src/resolver/auth/index.ts index a13e31b..0d83ae9 100644 --- a/src/resolver/auth/index.ts +++ b/src/resolver/auth/index.ts @@ -1,7 +1,7 @@ -import { AuthLoginResolver } from './auth.login.resolver' -import { AuthRegisterResolver } from './auth.register.resolver' +import { AuthLoginMutation } from './auth.login.mutation' +import { AuthRegisterMutation } from './auth.register.mutation' export const authServices = [ - AuthRegisterResolver, - AuthLoginResolver, + AuthRegisterMutation, + AuthLoginMutation, ] diff --git a/src/resolver/form/form.search.resolver.ts b/src/resolver/form/form.list.query.ts similarity index 74% rename from src/resolver/form/form.search.resolver.ts rename to src/resolver/form/form.list.query.ts index 25e7d74..14c154b 100644 --- a/src/resolver/form/form.search.resolver.ts +++ b/src/resolver/form/form.list.query.ts @@ -1,5 +1,5 @@ -import { Args, Context, Query, Resolver } from '@nestjs/graphql' -import { GraphQLInt } from 'graphql' +import { Injectable } from '@nestjs/common' +import { Args, Context, Int, Query } from '@nestjs/graphql' import { Roles } from '../../decorator/roles.decorator' import { User } from '../../decorator/user.decorator' import { FormModel } from '../../dto/form/form.model' @@ -9,8 +9,8 @@ import { UserEntity } from '../../entity/user.entity' import { FormService } from '../../service/form/form.service' import { ContextCache } from '../context.cache' -@Resolver(() => FormPagerModel) -export class FormSearchResolver { +@Injectable() +export class FormListQuery { constructor( private readonly formService: FormService, ) { @@ -20,8 +20,8 @@ export class FormSearchResolver { @Roles('user') async listForms( @User() user: UserEntity, - @Args('start', {type: () => GraphQLInt, defaultValue: 0, nullable: true}) start: number, - @Args('limit', {type: () => GraphQLInt, defaultValue: 50, nullable: true}) limit: number, + @Args('start', {type: () => Int, defaultValue: 0, nullable: true}) start: number, + @Args('limit', {type: () => Int, defaultValue: 50, nullable: true}) limit: number, @Context('cache') cache: ContextCache, ): Promise { const [forms, total] = await this.formService.find( diff --git a/src/resolver/form/form.query.ts b/src/resolver/form/form.query.ts index 78b00c4..b571320 100644 --- a/src/resolver/form/form.query.ts +++ b/src/resolver/form/form.query.ts @@ -1,4 +1,5 @@ -import { Args, Context, ID, Query, Resolver } from '@nestjs/graphql' +import { Injectable } from '@nestjs/common' +import { Args, Context, ID, Query } from '@nestjs/graphql' import { User } from '../../decorator/user.decorator' import { FormModel } from '../../dto/form/form.model' import { FormEntity } from '../../entity/form.entity' @@ -6,7 +7,7 @@ import { UserEntity } from '../../entity/user.entity' import { FormService } from '../../service/form/form.service' import { ContextCache } from '../context.cache' -@Resolver(() => FormModel) +@Injectable() export class FormQuery { constructor( private readonly formService: FormService, diff --git a/src/resolver/form/form.resolver.ts b/src/resolver/form/form.resolver.ts index 727ba8e..339268c 100644 --- a/src/resolver/form/form.resolver.ts +++ b/src/resolver/form/form.resolver.ts @@ -20,19 +20,19 @@ export class FormResolver { ) { } - @ResolveField('fields', () => [FormFieldModel]) - async getFields( + @ResolveField(() => [FormFieldModel]) + async fields( @User() user: UserEntity, @Parent() parent: FormModel, @Context('cache') cache: ContextCache, ): Promise { const form = await cache.get(cache.getCacheKey(FormEntity.name, parent.id)) - return form.fields?.map(field => new FormFieldModel(field)) || [] + return form.fields?.map(field => new FormFieldModel(field)).sort((a,b) => a.idx - b.idx) || [] } - @ResolveField('hooks', () => [FormHookModel]) - async getHooks( + @ResolveField(() => [FormHookModel]) + async hooks( @User() user: UserEntity, @Parent() parent: FormModel, @Context('cache') cache: ContextCache, @@ -42,9 +42,9 @@ export class FormResolver { return form.hooks?.map(hook => new FormHookModel(hook)) || [] } - @ResolveField('isLive', () => Boolean) + @ResolveField(() => Boolean) @Roles('admin') - async getRoles( + async isLive( @User() user: UserEntity, @Parent() parent: FormModel, @Context('cache') cache: ContextCache, @@ -58,9 +58,9 @@ export class FormResolver { return form.isLive } - @ResolveField('notifications', () => [FormNotificationModel]) + @ResolveField(() => [FormNotificationModel]) @Roles('admin') - async getNotifications( + async notifications( @User() user: UserEntity, @Parent() parent: FormModel, @Context('cache') cache: ContextCache, @@ -74,8 +74,8 @@ export class FormResolver { return form.notifications?.map(notification => new FormNotificationModel(notification)) || [] } - @ResolveField('design', () => DesignModel) - async getDesign( + @ResolveField(() => DesignModel) + async design( @User() user: UserEntity, @Parent() parent: FormModel, @Context('cache') cache: ContextCache, @@ -85,8 +85,8 @@ export class FormResolver { return new DesignModel(form.design) } - @ResolveField('startPage', () => PageModel) - async getStartPage( + @ResolveField(() => PageModel) + async startPage( @Parent() parent: FormModel, @Context('cache') cache: ContextCache, ): Promise { @@ -95,8 +95,8 @@ export class FormResolver { return new PageModel(form.startPage) } - @ResolveField('endPage', () => PageModel) - async getEndPage( + @ResolveField(() => PageModel) + async endPage( @Parent() parent: FormModel, @Context('cache') cache: ContextCache, ): Promise { @@ -105,9 +105,9 @@ export class FormResolver { return new PageModel(form.endPage) } - @ResolveField('admin', () => UserModel, { nullable: true }) + @ResolveField(() => UserModel, { nullable: true }) @Roles('admin') - async getAdmin( + async admin( @Parent() parent: FormModel, @Context('cache') cache: ContextCache, ): Promise { diff --git a/src/resolver/form/form.statistic.query.ts b/src/resolver/form/form.statistic.query.ts new file mode 100644 index 0000000..1cdc943 --- /dev/null +++ b/src/resolver/form/form.statistic.query.ts @@ -0,0 +1,11 @@ +import { Injectable } from '@nestjs/common' +import { Query } from '@nestjs/graphql' +import { FormStatisticModel } from '../../dto/form/form.statistic.model' + +@Injectable() +export class FormStatisticQuery { + @Query(() => FormStatisticModel) + getFormStatistic(): FormStatisticModel { + return new FormStatisticModel() + } +} diff --git a/src/resolver/form/form.statistic.resolver.ts b/src/resolver/form/form.statistic.resolver.ts index 2cbc102..021a947 100644 --- a/src/resolver/form/form.statistic.resolver.ts +++ b/src/resolver/form/form.statistic.resolver.ts @@ -1,5 +1,4 @@ -import { Query, ResolveField, Resolver } from '@nestjs/graphql' -import { GraphQLInt } from 'graphql' +import { Int, ResolveField, Resolver } from '@nestjs/graphql' import { Roles } from '../../decorator/roles.decorator' import { FormStatisticModel } from '../../dto/form/form.statistic.model' import { FormStatisticService } from '../../service/form/form.statistic.service' @@ -11,14 +10,9 @@ export class FormStatisticResolver { ) { } - @Query(() => FormStatisticModel) - getFormStatistic(): FormStatisticModel { - return new FormStatisticModel() - } - - @ResolveField('total', () => GraphQLInt) + @ResolveField(() => Int) @Roles('admin') - getTotal(): Promise { + total(): Promise { return this.statisticService.getTotal() } } diff --git a/src/resolver/form/index.ts b/src/resolver/form/index.ts index 2231cf8..440848f 100644 --- a/src/resolver/form/index.ts +++ b/src/resolver/form/index.ts @@ -1,8 +1,9 @@ import { FormCreateMutation } from './form.create.mutation' import { FormDeleteMutation } from './form.delete.mutation' +import { FormListQuery } from './form.list.query' import { FormQuery } from './form.query' import { FormResolver } from './form.resolver' -import { FormSearchResolver } from './form.search.resolver' +import { FormStatisticQuery } from './form.statistic.query' import { FormStatisticResolver } from './form.statistic.resolver' import { FormUpdateMutation } from './form.update.mutation' @@ -11,7 +12,8 @@ export const formResolvers = [ FormDeleteMutation, FormQuery, FormResolver, - FormSearchResolver, + FormListQuery, + FormStatisticQuery, FormStatisticResolver, FormUpdateMutation, ] diff --git a/src/resolver/profile/index.ts b/src/resolver/profile/index.ts index 9c4403b..409c650 100644 --- a/src/resolver/profile/index.ts +++ b/src/resolver/profile/index.ts @@ -1,7 +1,7 @@ -import { ProfileResolver } from './profile.resolver' +import { ProfileQuery } from './profile.query' import { ProfileUpdateMutation } from './profile.update.mutation' export const profileResolvers = [ - ProfileResolver, + ProfileQuery, ProfileUpdateMutation, ] diff --git a/src/resolver/profile/profile.resolver.ts b/src/resolver/profile/profile.query.ts similarity index 87% rename from src/resolver/profile/profile.resolver.ts rename to src/resolver/profile/profile.query.ts index 36be407..41d425b 100644 --- a/src/resolver/profile/profile.resolver.ts +++ b/src/resolver/profile/profile.query.ts @@ -1,3 +1,4 @@ +import { Injectable } from '@nestjs/common' import { Context, Query } from '@nestjs/graphql' import { Roles } from '../../decorator/roles.decorator' import { User } from '../../decorator/user.decorator' @@ -5,7 +6,8 @@ import { ProfileModel } from '../../dto/profile/profile.model' import { UserEntity } from '../../entity/user.entity' import { ContextCache } from '../context.cache' -export class ProfileResolver { +@Injectable() +export class ProfileQuery { @Query(() => ProfileModel) @Roles('user') public me( diff --git a/src/resolver/setting/index.ts b/src/resolver/setting/index.ts index 80cc7ef..e4fbe62 100644 --- a/src/resolver/setting/index.ts +++ b/src/resolver/setting/index.ts @@ -1,7 +1,7 @@ import { SettingMutation } from './setting.mutation' -import { SettingResolver } from './setting.resolver' +import { SettingQuery } from './setting.query' export const settingsResolvers = [ - SettingResolver, + SettingQuery, SettingMutation, ] diff --git a/src/resolver/setting/setting.resolver.ts b/src/resolver/setting/setting.query.ts similarity index 97% rename from src/resolver/setting/setting.resolver.ts rename to src/resolver/setting/setting.query.ts index 7abf806..d896441 100644 --- a/src/resolver/setting/setting.resolver.ts +++ b/src/resolver/setting/setting.query.ts @@ -8,7 +8,7 @@ import { UserEntity } from '../../entity/user.entity' import { SettingService } from '../../service/setting.service' @Injectable() -export class SettingResolver { +export class SettingQuery { constructor( private readonly settingService: SettingService, ) { diff --git a/src/resolver/submission/index.ts b/src/resolver/submission/index.ts index bcff27f..eb9790c 100644 --- a/src/resolver/submission/index.ts +++ b/src/resolver/submission/index.ts @@ -1,17 +1,21 @@ import { SubmissionFieldResolver } from './submission.field.resolver' +import { SubmissionListQuery } from './submission.list.query' import { SubmissionProgressResolver } from './submission.progress.resolver' +import { SubmissionQuery } from './submission.query' import { SubmissionResolver } from './submission.resolver' -import { SubmissionSearchResolver } from './submission.search.resolver' import { SubmissionSetFieldMutation } from './submission.set.field.mutation' import { SubmissionStartMutation } from './submission.start.mutation' +import { SubmissionStatisticQuery } from './submission.statistic.query' import { SubmissionStatisticResolver } from './submission.statistic.resolver' export const submissionResolvers = [ SubmissionFieldResolver, + SubmissionListQuery, SubmissionProgressResolver, + SubmissionQuery, SubmissionResolver, - SubmissionSearchResolver, SubmissionSetFieldMutation, SubmissionStartMutation, + SubmissionStatisticQuery, SubmissionStatisticResolver, ] diff --git a/src/resolver/submission/submission.field.resolver.ts b/src/resolver/submission/submission.field.resolver.ts index dbaa15f..c310408 100644 --- a/src/resolver/submission/submission.field.resolver.ts +++ b/src/resolver/submission/submission.field.resolver.ts @@ -13,8 +13,8 @@ export class SubmissionFieldResolver { ) { } - @ResolveField('field', () => FormFieldModel, { nullable: true }) - async getFields( + @ResolveField(() => FormFieldModel, { nullable: true }) + async field( @Parent() parent: SubmissionFieldModel, @Context('cache') cache: ContextCache, ): Promise { diff --git a/src/resolver/submission/submission.search.resolver.ts b/src/resolver/submission/submission.list.query.ts similarity index 78% rename from src/resolver/submission/submission.search.resolver.ts rename to src/resolver/submission/submission.list.query.ts index 50ec908..4d814d2 100644 --- a/src/resolver/submission/submission.search.resolver.ts +++ b/src/resolver/submission/submission.list.query.ts @@ -1,5 +1,5 @@ -import { Args, Context, ID, Query, Resolver } from '@nestjs/graphql' -import { GraphQLInt } from 'graphql' +import { Injectable } from '@nestjs/common' +import { Args, Context, ID, Int, Query } from '@nestjs/graphql' import { User } from '../../decorator/user.decorator' import { SubmissionModel } from '../../dto/submission/submission.model' import { SubmissionPagerModel } from '../../dto/submission/submission.pager.model' @@ -9,8 +9,8 @@ import { FormService } from '../../service/form/form.service' import { SubmissionService } from '../../service/submission/submission.service' import { ContextCache } from '../context.cache' -@Resolver(() => SubmissionPagerModel) -export class SubmissionSearchResolver { +@Injectable() +export class SubmissionListQuery { constructor( private readonly formService: FormService, private readonly submissionService: SubmissionService, @@ -21,8 +21,8 @@ export class SubmissionSearchResolver { async listSubmissions( @User() user: UserEntity, @Args('form', {type: () => ID}) id: string, - @Args('start', {type: () => GraphQLInt, defaultValue: 0, nullable: true}) start: number, - @Args('limit', {type: () => GraphQLInt, defaultValue: 50, nullable: true}) limit: number, + @Args('start', {type: () => Int, defaultValue: 0, nullable: true}) start: number, + @Args('limit', {type: () => Int, defaultValue: 50, nullable: true}) limit: number, @Context('cache') cache: ContextCache, ): Promise { const form = await this.formService.findById(id) diff --git a/src/resolver/submission/submission.query.ts b/src/resolver/submission/submission.query.ts new file mode 100644 index 0000000..274a5f2 --- /dev/null +++ b/src/resolver/submission/submission.query.ts @@ -0,0 +1,41 @@ +import { Injectable } from '@nestjs/common' +import { Args, Context, ID, Query } from '@nestjs/graphql' +import { User } from '../../decorator/user.decorator' +import { SubmissionModel } from '../../dto/submission/submission.model' +import { SubmissionEntity } from '../../entity/submission.entity' +import { UserEntity } from '../../entity/user.entity' +import { FormService } from '../../service/form/form.service' +import { SubmissionService } from '../../service/submission/submission.service' +import { SubmissionTokenService } from '../../service/submission/submission.token.service' +import { ContextCache } from '../context.cache' + +@Injectable() +export class SubmissionQuery { + constructor( + private readonly formService: FormService, + private readonly submissionService: SubmissionService, + private readonly tokenService: SubmissionTokenService, + ) { + } + + @Query(() => SubmissionModel) + async getSubmissionById( + @User() user: UserEntity, + @Args('id', {type: () => ID}) id: string, + @Args('token', {nullable: true}) token: string, + @Context('cache') cache: ContextCache, + ): Promise { + const submission = await this.submissionService.findById(id) + + if ( + !await this.tokenService.verify(token, submission.tokenHash) + && !this.formService.isAdmin(submission.form, user) + ) { + throw new Error('invalid form') + } + + cache.add(cache.getCacheKey(SubmissionEntity.name, submission.id), submission) + + return new SubmissionModel(submission) + } +} diff --git a/src/resolver/submission/submission.resolver.ts b/src/resolver/submission/submission.resolver.ts index f4bc0d9..cfaaef7 100644 --- a/src/resolver/submission/submission.resolver.ts +++ b/src/resolver/submission/submission.resolver.ts @@ -9,8 +9,8 @@ import { ContextCache } from '../context.cache' @Resolver(() => SubmissionModel) export class SubmissionResolver { - @ResolveField('fields', () => [SubmissionFieldModel]) - async getFields( + @ResolveField(() => [SubmissionFieldModel]) + async fields( @User() user: UserEntity, @Parent() parent: SubmissionModel, @Context('cache') cache: ContextCache, diff --git a/src/resolver/submission/submission.statistic.query.ts b/src/resolver/submission/submission.statistic.query.ts new file mode 100644 index 0000000..5c7714f --- /dev/null +++ b/src/resolver/submission/submission.statistic.query.ts @@ -0,0 +1,11 @@ +import { Injectable } from '@nestjs/common' +import { Query } from '@nestjs/graphql' +import { SubmissionStatisticModel } from '../../dto/submission/submission.statistic.model' + +@Injectable() +export class SubmissionStatisticQuery { + @Query(() => SubmissionStatisticModel) + getSubmissionStatistic(): SubmissionStatisticModel { + return new SubmissionStatisticModel() + } +} diff --git a/src/resolver/submission/submission.statistic.resolver.ts b/src/resolver/submission/submission.statistic.resolver.ts index 7349d26..2f77169 100644 --- a/src/resolver/submission/submission.statistic.resolver.ts +++ b/src/resolver/submission/submission.statistic.resolver.ts @@ -1,4 +1,4 @@ -import { Query, ResolveField, Resolver } from '@nestjs/graphql' +import { ResolveField, Resolver } from '@nestjs/graphql' import { GraphQLInt } from 'graphql' import { Roles } from '../../decorator/roles.decorator' import { SubmissionStatisticModel } from '../../dto/submission/submission.statistic.model' @@ -11,15 +11,9 @@ export class SubmissionStatisticResolver { ) { } - - @Query(() => SubmissionStatisticModel) - getSubmissionStatistic(): SubmissionStatisticModel { - return new SubmissionStatisticModel() - } - - @ResolveField('total', () => GraphQLInt) + @ResolveField(() => GraphQLInt) @Roles('admin') - getTotal(): Promise { + total(): Promise { return this.statisticService.getTotal() } } diff --git a/src/resolver/user/index.ts b/src/resolver/user/index.ts index f3bcdda..9e9e254 100644 --- a/src/resolver/user/index.ts +++ b/src/resolver/user/index.ts @@ -1,13 +1,17 @@ import { UserDeleteMutation } from './user.delete.mutation' +import { UserListQuery } from './user.list.query' +import { UserQuery } from './user.query' import { UserResolver } from './user.resolver' -import { UserSearchResolver } from './user.search.resolver' +import { UserStatisticQuery } from './user.statistic.query' import { UserStatisticResolver } from './user.statistic.resolver' import { UserUpdateMutation } from './user.update.mutation' export const userResolvers = [ UserDeleteMutation, + UserListQuery, + UserQuery, UserResolver, - UserSearchResolver, + UserStatisticQuery, UserStatisticResolver, UserUpdateMutation, ] diff --git a/src/resolver/user/user.search.resolver.ts b/src/resolver/user/user.list.query.ts similarity index 73% rename from src/resolver/user/user.search.resolver.ts rename to src/resolver/user/user.list.query.ts index ce4b9d4..7ffbdfe 100644 --- a/src/resolver/user/user.search.resolver.ts +++ b/src/resolver/user/user.list.query.ts @@ -1,5 +1,4 @@ -import { Args, Context, Query, Resolver } from '@nestjs/graphql' -import { GraphQLInt } from 'graphql' +import { Args, Context, Int, Query, Resolver } from '@nestjs/graphql' import { Roles } from '../../decorator/roles.decorator' import { UserModel } from '../../dto/user/user.model' import { UserPagerModel } from '../../dto/user/user.pager.model' @@ -8,7 +7,7 @@ import { UserService } from '../../service/user/user.service' import { ContextCache } from '../context.cache' @Resolver(() => UserPagerModel) -export class UserSearchResolver { +export class UserListQuery { constructor( private readonly userService: UserService, ) { @@ -17,8 +16,8 @@ export class UserSearchResolver { @Query(() => UserPagerModel) @Roles('superuser') async listUsers( - @Args('start', {type: () => GraphQLInt, defaultValue: 0, nullable: true}) start: number, - @Args('limit', {type: () => GraphQLInt, defaultValue: 50, nullable: true}) limit: number, + @Args('start', {type: () => Int, defaultValue: 0, nullable: true}) start: number, + @Args('limit', {type: () => Int, defaultValue: 50, nullable: true}) limit: number, @Context('cache') cache: ContextCache, ): Promise { const [entities, total] = await this.userService.find(start, limit) diff --git a/src/resolver/user/user.query.ts b/src/resolver/user/user.query.ts new file mode 100644 index 0000000..77539be --- /dev/null +++ b/src/resolver/user/user.query.ts @@ -0,0 +1,28 @@ +import { Injectable } from '@nestjs/common' +import { Args, Context, ID, Query } from '@nestjs/graphql' +import { Roles } from '../../decorator/roles.decorator' +import { UserModel } from '../../dto/user/user.model' +import { UserEntity } from '../../entity/user.entity' +import { UserService } from '../../service/user/user.service' +import { ContextCache } from '../context.cache' + +@Injectable() +export class UserQuery { + constructor( + private readonly userService: UserService, + ) { + } + + @Query(() => UserModel) + @Roles('admin') + public async getUserById( + @Args('id', {type: () => ID}) id: string, + @Context('cache') cache: ContextCache, + ): Promise { + const user = await this.userService.findById(id) + + cache.add(cache.getCacheKey(UserEntity.name, user.id), user) + + return new UserModel(user) + } +} diff --git a/src/resolver/user/user.resolver.ts b/src/resolver/user/user.resolver.ts index ba4d2aa..9d5af8c 100644 --- a/src/resolver/user/user.resolver.ts +++ b/src/resolver/user/user.resolver.ts @@ -1,4 +1,4 @@ -import { Args, Context, ID, Parent, Query, ResolveField, Resolver } from '@nestjs/graphql' +import { Context, Parent, ResolveField, Resolver } from '@nestjs/graphql' import { Roles } from '../../decorator/roles.decorator' import { User } from '../../decorator/user.decorator' import { UserModel } from '../../dto/user/user.model' @@ -13,22 +13,9 @@ export class UserResolver { ) { } - @Query(() => UserModel) - @Roles('admin') - public async getUserById( - @Args('id', {type: () => ID}) id: string, - @Context('cache') cache: ContextCache, - ): Promise { - const user = await this.userService.findById(id) - - cache.add(cache.getCacheKey(UserEntity.name, user.id), user) - - return new UserModel(user) - } - - @ResolveField('roles', () => [String]) + @ResolveField(() => [String]) @Roles('user') - async getRoles( + async roles( @User() user: UserEntity, @Parent() parent: UserModel, @Context('cache') cache: ContextCache, @@ -40,7 +27,7 @@ export class UserResolver { ) } - returnFieldForSuperuser( + private returnFieldForSuperuser( parent: UserEntity, user: UserEntity, callback: (user: UserEntity) => T diff --git a/src/resolver/user/user.statistic.query.ts b/src/resolver/user/user.statistic.query.ts new file mode 100644 index 0000000..f023a59 --- /dev/null +++ b/src/resolver/user/user.statistic.query.ts @@ -0,0 +1,11 @@ +import { Injectable } from '@nestjs/common' +import { Query } from '@nestjs/graphql' +import { UserStatisticModel } from '../../dto/user/user.statistic.model' + +@Injectable() +export class UserStatisticQuery { + @Query(() => UserStatisticModel) + getUserStatistic(): UserStatisticModel { + return new UserStatisticModel() + } +} diff --git a/src/resolver/user/user.statistic.resolver.ts b/src/resolver/user/user.statistic.resolver.ts index fc56186..7c779d3 100644 --- a/src/resolver/user/user.statistic.resolver.ts +++ b/src/resolver/user/user.statistic.resolver.ts @@ -1,4 +1,4 @@ -import { Int, Query, ResolveField, Resolver } from '@nestjs/graphql' +import { Int, ResolveField, Resolver } from '@nestjs/graphql' import { Roles } from '../../decorator/roles.decorator' import { UserStatisticModel } from '../../dto/user/user.statistic.model' import { UserStatisticService } from '../../service/user/user.statistic.service' @@ -10,14 +10,9 @@ export class UserStatisticResolver { ) { } - @Query(() => UserStatisticModel) - getUserStatistic(): UserStatisticModel { - return new UserStatisticModel() - } - - @ResolveField('total', () => Int) + @ResolveField(() => Int) @Roles('admin') - getTotal(): Promise { + total(): Promise { return this.statisticService.getTotal() } } diff --git a/src/service/submission/submission.service.ts b/src/service/submission/submission.service.ts index ba3ac1e..b763108 100644 --- a/src/service/submission/submission.service.ts +++ b/src/service/submission/submission.service.ts @@ -43,7 +43,15 @@ export class SubmissionService { } async findById(id: string): Promise { - const submission = await this.submissionRepository.findOne(id); + const submission = await this.submissionRepository.findOne( + id, + { + relations: [ + 'form', + 'form.admin', + ], + } + ); if (!submission) { throw new Error('no form found')