@@ -27,6 +27,8 @@ type Apparatus { | |||
type Organizer { | |||
_id: UUID! | |||
name: String! | |||
plz: Int | |||
ort: String | |||
logo: String | |||
_admins: [UUID!] | |||
_organizers: [UUID!] | |||
@@ -56,11 +58,15 @@ type Query { | |||
Apparatus(id: UUID!): Apparatus | |||
ApparatusFind(offset: Int, limit: Int, name: String): [Apparatus!] | |||
Organizer(id: UUID!): Organizer | |||
OrganizerFind(offset: Int, limit: Int, name: String): [Organizer!] | |||
OrganizerFind(offset: Int, limit: Int, ort: String, plz: Int, name: String): [Organizer!] | |||
Event(id: UUID!): Event | |||
EventFind(offset: Int, limit: Int, organizer: UUID, date: Date): [Event!] | |||
} | |||
type Mutation { | |||
login(token: String, passwort: String, email: String): Person | |||
PersonRegister(passwort: String!, email: EmailAddress!, familyName: String!, givenName: String!, organizer: UUID!): Person! | |||
ConfirmMail(confirmCode: String!, email: String!): Person | |||
ChangePassword(newPassword: String!, oldPassword: String!): Boolean! | |||
OrganizerRegister(ort: String, plz: Int, name: String!): Organizer! | |||
} |
@@ -45,7 +45,6 @@ export class Client { | |||
} | |||
if (data.email && data.passwort) { | |||
console.log(data); | |||
const entries: any[] = (await Promise.all( | |||
(await db.fetch('person', { 'email': data.email } )) | |||
.map(async (e) => ({ | |||
@@ -53,7 +52,6 @@ export class Client { | |||
authOK: await checkPassword(data.passwort, e.passwort) | |||
})))) | |||
.filter(e => e.authOK); | |||
console.log(entries); | |||
if (entries.length !== 1) { | |||
return this.LoginFailed(); | |||
} |
@@ -1,4 +1,4 @@ | |||
import { Field, ObjectType } from '@nestjs/graphql'; | |||
import {Field, Int, ObjectType} from '@nestjs/graphql'; | |||
import { UUID } from '../../global/scalars/UUID'; | |||
@ObjectType() | |||
@@ -9,6 +9,12 @@ export class Organizer { | |||
@Field(() => String, { nullable: false }) | |||
name: string | |||
@Field(() => Int, { nullable: true }) | |||
plz?: number | |||
@Field(() => String, { nullable: true }) | |||
ort?: string | |||
@Field(() => String, { nullable: true }) | |||
logo?: string | |||
@@ -3,6 +3,7 @@ import { db } from '../db'; | |||
import { Organizer } from './models/Organizer'; | |||
import { Client } from '../client'; | |||
import { UUID } from '../global/scalars/UUID'; | |||
import { v4 as uuid } from 'uuid'; | |||
@Injectable() | |||
export class OrganizerService { | |||
@@ -16,7 +17,18 @@ export class OrganizerService { | |||
return db.fetch('organizer', filter, limit, offset); | |||
} | |||
async update(id: UUID, ops: any, filter: any, client: Client): Promise<Organizer> { | |||
return db.doOps('organizer', id, ops, filter, client) | |||
async update(client: Client, id: UUID, ops: any, filter?: any): Promise<Organizer> { | |||
return db.doOps('organizer', id, ops, filter, client); | |||
} | |||
async create(client: Client, name: string, plz?: number, ort?: string): Promise<Organizer> { | |||
const neu = { | |||
_id: uuid(), | |||
name, | |||
plz: plz || null, | |||
ort: ort || null, | |||
} | |||
return db.insert('organizer', neu, client); | |||
} | |||
} |
@@ -1,4 +1,4 @@ | |||
import { Args, Context, Mutation, Resolver } from '@nestjs/graphql'; | |||
import {Args, Context, Int, Mutation, Resolver} from '@nestjs/graphql'; | |||
import { Organizer } from '../models/Organizer'; | |||
import { Client } from '../../client'; | |||
import { OrganizerService } from '../organizer.service'; | |||
@@ -9,4 +9,23 @@ export class OrganizerResolverM { | |||
constructor( | |||
private readonly service: OrganizerService, | |||
) {} | |||
@Mutation(() => Organizer, { nullable: false }) | |||
async OrganizerRegister( | |||
@Context('client') client: Client, | |||
@Args('name') name: string, | |||
@Args('plz', { type: () => Int, nullable: true }) plz?: number, | |||
@Args('ort', { nullable: true }) ort?: string, | |||
): Promise<Organizer> { | |||
const filter: any = {} | |||
if (name) filter.name = name; | |||
if (plz) filter.plz = plz; | |||
if (ort) filter.ort = ort; | |||
let tmp = await this.service.find(filter); | |||
if (tmp.length === 0) | |||
return this.service.create(client, name, plz, ort); | |||
return tmp[0]; | |||
} | |||
} |
@@ -23,12 +23,16 @@ export class OrganizerResolverQ { | |||
async OrganizerFind( | |||
@Context('client') client: Client, | |||
@Args('name', { nullable: true }) name?: string, | |||
@Args('plz', { type: () => Int, nullable: true }) plz?: number, | |||
@Args('ort', { nullable: true }) ort?: string, | |||
@Args('limit', { type: () => Int, nullable: true }) limit?: number, | |||
@Args('offset', { type: () => Int, nullable: true }) offset?: number, | |||
): Promise<Organizer[]> { | |||
const filter: any = {} | |||
if (name) filter.name = name; | |||
if (plz) filter.plz = plz; | |||
if (ort) filter.ort = ort; | |||
let tmp = await this.service.find(filter, limit, offset); | |||
if (tmp.length > 1000) throw new HttpException('too many results', 413); |
@@ -1,4 +1,4 @@ | |||
import { Context, Parent, ResolveField, Resolver } from '@nestjs/graphql'; | |||
import {Context, Int, Parent, ResolveField, Resolver} from '@nestjs/graphql'; | |||
import { Organizer } from '../models/Organizer'; | |||
import { Client } from '../../client'; | |||
import { UUID } from '../../global/scalars/UUID'; | |||
@@ -21,6 +21,22 @@ export class OrganizerResolver { | |||
return parent.name; | |||
} | |||
@ResolveField(() => Int, { nullable: true }) | |||
async plz( | |||
@Context('client') client: Client, | |||
@Parent() parent: Organizer | |||
): Promise<number> { | |||
return parent.plz; | |||
} | |||
@ResolveField(() => String, { nullable: true }) | |||
async ort( | |||
@Context('client') client: Client, | |||
@Parent() parent: Organizer | |||
): Promise<string> { | |||
return parent.ort; | |||
} | |||
@ResolveField(() => String, { nullable: true }) | |||
async logo( | |||
@Context('client') client: Client, |
@@ -3,6 +3,10 @@ import { db } from '../db'; | |||
import { Person } from './models/Person'; | |||
import { Client } from '../client'; | |||
import { UUID } from '../global/scalars/UUID'; | |||
import { Organizer } from '../organizer/models/Organizer' | |||
import { v4 as uuid } from 'uuid'; | |||
import {EmailAddress} from '../global/scalars/EmailAddress' | |||
import {secureHash} from '../generate' | |||
@Injectable() | |||
export class PersonService { | |||
@@ -16,7 +20,20 @@ export class PersonService { | |||
return db.fetch('person', filter, limit, offset); | |||
} | |||
async update(id: UUID, ops: any, filter: any, client: Client): Promise<Person> { | |||
async update(client: Client, id: UUID, ops: any, filter?: any): Promise<Person> { | |||
return db.doOps('person', id, ops, filter, client) | |||
} | |||
async create(client: Client, givenName: string, familyName: string, email: EmailAddress, passwort: string): Promise<Person> { | |||
const neu = { | |||
_id: uuid(), | |||
givenName, | |||
familyName, | |||
email, | |||
passwort: await secureHash(passwort), | |||
confirmCode: uuid(), | |||
} | |||
return db.insert('person', neu, client); | |||
} | |||
} |
@@ -3,6 +3,10 @@ import { Person } from '../models/Person'; | |||
import { Client } from '../../client'; | |||
import { PersonService } from '../person.service'; | |||
import { HttpException } from '@nestjs/common'; | |||
import {UUID} from '../../global/scalars/UUID' | |||
import {OrganizerService} from '../../organizer/organizer.service' | |||
import {EmailAddress} from '../../global/scalars/EmailAddress' | |||
import {checkPassword, secureHash} from '../../generate' | |||
@Resolver(() => Person) | |||
export class PersonResolverM { | |||
@@ -24,28 +28,81 @@ export class PersonResolverM { | |||
throw new HttpException('Logindaten falsch', 403); | |||
} | |||
return this.service.findOneById(client.getUser()?._id); | |||
const tmp = await this.service.findOneById(client.getUser()?._id); | |||
if (!!(tmp as unknown as any).confirmCode) { | |||
throw new HttpException('E-Mail-Adresse noch nicht bestätigt!', 403); | |||
} | |||
return tmp; | |||
} | |||
/* @Mutation(() => Person, { nullable: true }) | |||
async PersonUpdate( | |||
@Mutation(() => Person, { nullable: false }) | |||
async PersonRegister( | |||
@Context('client') client: Client, | |||
@Args('id', { type: () => UUID, nullable: false }) id: UUID, | |||
@Args('givenName', { nullable: true }) givenName?: string, | |||
@Args('familyName', { nullable: true }) familyName?: string, | |||
@Args('birthDate', { type: () => Date, nullable: true }) birthDate?: Date, | |||
@Args('organizer', { type: () => UUID, nullable: false }) organizer: UUID, | |||
@Args('givenName', { nullable: false }) givenName: string, | |||
@Args('familyName', { nullable: false }) familyName: string, | |||
@Args('email', { type: () => EmailAddress, nullable: false }) email: EmailAddress, | |||
@Args('passwort', { nullable: false }) passwort: string, | |||
): Promise<Person> { | |||
if (!client.isMaster() && !client.isSelf(id)) return null; | |||
const organizerService = new OrganizerService(); | |||
const o = await organizerService.findOneById(organizer); | |||
if (!o) { | |||
throw new HttpException('Organizer-ID not found!', 404); | |||
} | |||
const tmp = await this.service.create(client, givenName, familyName, email, passwort); | |||
const p = await this.service.findOneById(id); | |||
if (!p) return null; | |||
if (!o._admins) { | |||
organizerService.update(client, o._id, {$set: {_admins: [ tmp._id ] }}, {}); | |||
} else if (o._admins.length === 0) { | |||
organizerService.update(client, o._id, {$push: {_admins: tmp._id }}, {}); | |||
} else if (!o._organizers) { | |||
organizerService.update(client, o._id, {$set: {_organizers: [ tmp._id ] }}, {}); | |||
} else { | |||
organizerService.update(client, o._id, {$push: {_organizers: tmp._id }}, {}); | |||
} | |||
// TODO: Mail verschicken | |||
const ops: any = {$set:{}}; | |||
return tmp; | |||
} | |||
if (givenName) ops['$set'].givenName = givenName; | |||
if (familyName) ops['$set'].familyName = familyName; | |||
if (birthDate) ops['$set'].birthDate = birthDate; | |||
@Mutation(() => Person, { nullable: true }) | |||
async ConfirmMail( | |||
@Context('client') client: Client, | |||
@Args('email') email: string, | |||
@Args('confirmCode') confirmCode: string, | |||
): Promise<Person> { | |||
const tmp = await this.service.find({email, confirmCode}); | |||
return this.service.update(id, ops, null, client); | |||
} */ | |||
if (tmp.length !== 1) { | |||
throw new HttpException('confirmCode not correct', 403); | |||
} | |||
this.service.update(client, tmp[0]._id, { $unset: { confirmCode } }) | |||
return tmp[0]; | |||
} | |||
@Mutation(() => Boolean, { nullable: false }) | |||
async ChangePassword( | |||
@Context('client') client: Client, | |||
@Args('oldPassword', { nullable: false }) oldPassword: string, | |||
@Args('newPassword', { nullable: false }) newPassword: string, | |||
): Promise<boolean> { | |||
if (!client.getUser()) { | |||
throw new HttpException('you need to be logged in to change your password!', 403); | |||
} | |||
const tmp = await this.service.findOneById(client.getUser()._id); | |||
if (!(await checkPassword(oldPassword, (tmp as unknown as any).passwort))) { | |||
throw new HttpException('old password wrong!', 403); | |||
} | |||
this.service.update(client, tmp._id, {$set: { passwort: await secureHash(newPassword) }}); | |||
return true; | |||
} | |||
} |