您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

242 行
8.5KB

  1. import { Args, Context, Mutation, Resolver } from '@nestjs/graphql';
  2. import { Person } from '../models/Person';
  3. import { Client } from '../../client';
  4. import { PersonService } from '../person.service';
  5. import { HttpException } from '@nestjs/common';
  6. import {UUID} from '../../global/scalars/UUID'
  7. import {OrganizerService} from '../../organizer/organizer.service'
  8. import {EmailAddress} from '../../global/scalars/EmailAddress'
  9. import {checkPassword, secureHash} from '../../generate'
  10. import {pubsub} from '../../main'
  11. import {sendmail} from '../../mail'
  12. import {SERVERDATA, SYSDATA} from '../../config'
  13. import { v4 as uuid } from 'uuid'
  14. @Resolver(() => Person)
  15. export class PersonResolverM {
  16. constructor(
  17. private readonly service: PersonService,
  18. ) {}
  19. @Mutation(() => Person, { nullable: false })
  20. async login(
  21. @Context('client') client: Client,
  22. @Args('email', { nullable: true }) email?: string,
  23. @Args('passwort', { nullable: true }) passwort?: string,
  24. @Args('token', { nullable: true }) token?: string
  25. ): Promise<Person> {
  26. await client.login({email, passwort, token});
  27. const newtoken: string = client.getToken();
  28. if (!newtoken) {
  29. throw new HttpException('Logindaten falsch', 403);
  30. }
  31. const tmp = await this.service.findOneById(client.getUser()?._id);
  32. if (!!(tmp as unknown as any).confirmCode) {
  33. throw new HttpException('E-Mail-Adresse noch nicht bestätigt!', 403);
  34. }
  35. return tmp;
  36. }
  37. @Mutation(() => Person, { nullable: false })
  38. async PersonRegister(
  39. @Context('client') client: Client,
  40. @Args('organizer', { type: () => UUID, nullable: false }) organizer: UUID,
  41. @Args('givenName', { nullable: false }) givenName: string,
  42. @Args('familyName', { nullable: false }) familyName: string,
  43. @Args('email', { type: () => EmailAddress, nullable: false }) email: EmailAddress,
  44. @Args('passwort', { nullable: false }) passwort: string,
  45. ): Promise<Person> {
  46. const organizerService = new OrganizerService();
  47. const o = await organizerService.findOneById(organizer);
  48. if (!o) {
  49. throw new HttpException('Organizer-ID not found!', 404);
  50. }
  51. const tmp = await this.service.create(client, givenName, familyName, email, passwort);
  52. let isAdmin = false;
  53. if (!o._admins) {
  54. await organizerService.update(client, o._id, {$set: {_admins: [ tmp._id ] }}, {});
  55. isAdmin = true;
  56. } else if (o._admins.length === 0) {
  57. await organizerService.update(client, o._id, {$push: {_admins: tmp._id }}, {});
  58. isAdmin = true;
  59. } else if (!o._pending) {
  60. await organizerService.update(client, o._id, {$set: {_pending: [ tmp._id ] }}, {});
  61. } else {
  62. await organizerService.update(client, o._id, {$push: {_pending: tmp._id }}, {});
  63. }
  64. const link = `${SERVERDATA.host}/confirm/${(tmp as unknown as any).confirmCode}`
  65. const text = `Vielen Dank für Ihre Registrierung bei ${SYSDATA.name}
  66. Bitte bestätigen Sie unter folgendem Link Ihre Registrierung:
  67. ${link}` + (isAdmin?'':`
  68. Sie müssen außerdem zunächst von einem Administrator Ihrer Schule/Ihres Vereins freigeschaltet werden. Dieser erhält ebenfalls eine E-Mail über Ihre Registrierung.`);
  69. sendmail(email,`[${SYSDATA.name}] Neu-Registrierung`, text);
  70. if (!isAdmin) {
  71. const admintext = `${givenName} ${familyName} hat sich neu bei ${SYSDATA.name} für Ihre Schule/Ihren Verein ${o.name} registriert.
  72. Bitte melden Sie sich unter ${SERVERDATA.host} an und bearbeiten die Registrierung.`
  73. for (let i = 0; i < o._admins?.length; i++) {
  74. const p = await this.service.findOneById(o._admins[i]);
  75. sendmail(p.email, `[${SYSDATA.name}] Neu-Registrierung für ${o.name}`, admintext);
  76. }
  77. }
  78. pubsub.publish('PersonUpdated', { PersonUpdated: tmp });
  79. return tmp;
  80. }
  81. @Mutation(() => Person, { nullable: true })
  82. async PersonConfirmMail(
  83. @Context('client') client: Client,
  84. @Args('email') email: string,
  85. @Args('confirmCode') confirmCode: string,
  86. ): Promise<Person> {
  87. const tmp = await this.service.find({email, confirmCode});
  88. if (tmp.length !== 1) {
  89. throw new HttpException('E-Mail-Adresse oder Bestätigungscode ungültig', 403);
  90. }
  91. this.service.update(client, tmp[0]._id, { $unset: { confirmCode } })
  92. return tmp[0];
  93. }
  94. @Mutation(() => Boolean, { nullable: true })
  95. async PersonPasswordReset(
  96. @Context('client') client: Client,
  97. @Args('email') email: EmailAddress,
  98. @Args('resetCode', { type: () => String, nullable: true }) resetCode?: string,
  99. @Args('newPassword', { type: () => String, nullable: true }) newPassword?: string,
  100. ): Promise<boolean> {
  101. const tmp = await this.service.find({email});
  102. console.log((tmp[0] as unknown as any).resetCode)
  103. console.log(resetCode)
  104. if (tmp.length === 1) {
  105. if (!resetCode && !newPassword) {
  106. const code = uuid();
  107. this.service.update(client, tmp[0]._id, {$set: {resetCode: code}})
  108. const link = `${SERVERDATA.host}/reset/${code}`
  109. const text = `Unter folgendem Link können Sie Ihr Passwort zurücksetzen:
  110. ${link}
  111. Alternativ können Sie auch den folgenden Code in das Eingabefeld kopieren:
  112. ${code}`
  113. console.log(text);
  114. sendmail(email,`[${SYSDATA.name}] Passwort zurücksetzen`, text);
  115. } else if ((tmp[0] as unknown as any).resetCode === resetCode) {
  116. this.service.update(client, tmp[0]._id, {$set: { passwort: await secureHash(newPassword) }, $unset: { resetCode: '' } });
  117. return true;
  118. }
  119. }
  120. return null;
  121. }
  122. @Mutation(() => Boolean, { nullable: false })
  123. async ChangePassword(
  124. @Context('client') client: Client,
  125. @Args('oldPassword', { nullable: false }) oldPassword: string,
  126. @Args('newPassword', { nullable: false }) newPassword: string,
  127. ): Promise<boolean> {
  128. if (!client.getUser()) {
  129. throw new HttpException('you need to be logged in to change your password!', 403);
  130. }
  131. const tmp = await this.service.findOneById(client.getUser()._id);
  132. if (!(await checkPassword(oldPassword, (tmp as unknown as any).passwort))) {
  133. throw new HttpException('old password wrong!', 403);
  134. }
  135. this.service.update(client, tmp._id, {$set: { passwort: await secureHash(newPassword) }});
  136. return true;
  137. }
  138. @Mutation(() => Person, { nullable: false })
  139. async PersonUpdate(
  140. @Context('client') client: Client,
  141. @Args('id', { type: () => UUID, nullable: false }) id: UUID,
  142. @Args('givenName', { nullable: true }) givenName?: string,
  143. @Args('familyName', { nullable: true }) familyName?: string,
  144. @Args('email', { type: () => EmailAddress, nullable: true }) email?: EmailAddress,
  145. @Args('master', { nullable: true }) master?: boolean
  146. ): Promise<Person> {
  147. if (!client.isMaster() && !client.isSelf(id)) throw new HttpException('Access denied', 403);
  148. const tmp = await this.service.findOneById(id);
  149. const set: {
  150. givenName?: string
  151. familyName?: string
  152. email?: EmailAddress
  153. master?: boolean
  154. } = {};
  155. if (givenName !== undefined && givenName !== tmp.givenName) set.givenName = givenName
  156. if (familyName !== undefined && familyName !== tmp.familyName) set.familyName = familyName
  157. if (email !== undefined && email !== tmp.email) set.email = email
  158. if (client.isMaster() && master !== undefined && master !== tmp.master) set.master = master
  159. if (Object.values(set).length === 0) return tmp;
  160. const neu = await this.service.update(client, tmp._id, {$set: set});
  161. pubsub.publish('PersonUpdated', { PersonUpdated: neu });
  162. return neu;
  163. }
  164. @Mutation(() => Person, { nullable: false })
  165. async PersonCreate(
  166. @Context('client') client: Client,
  167. @Args('givenName', { nullable: false }) givenName: string,
  168. @Args('familyName', { nullable: false }) familyName: string,
  169. @Args('email', { type: () => EmailAddress, nullable: false }) email: EmailAddress,
  170. @Args('master', { nullable: true }) master?: boolean
  171. ): Promise<Person> {
  172. if (!client.isMaster()) throw new HttpException('Access denied', 403);
  173. const neu = await this.service.insert(client, { givenName, familyName, email, master });
  174. pubsub.publish('PersonUpdated', { PersonUpdated: neu });
  175. return neu;
  176. }
  177. @Mutation(() => UUID, { nullable: false })
  178. async PersonDelete(
  179. @Context('client') client: Client,
  180. @Args('id', { type: () => UUID, nullable: false }) id: UUID
  181. ): Promise<UUID> {
  182. if (!client.isMaster()) throw new HttpException('Access denied', 403);
  183. this.service.delete(client, id);
  184. pubsub.publish('PersonDeleted', { PersonDeleted: id });
  185. return id;
  186. }
  187. }