Skip to content

Commit

Permalink
Adding event sign in endpoint (WIP).
Browse files Browse the repository at this point in the history
  • Loading branch information
Thai committed Aug 13, 2020
1 parent de256eb commit 648f7d9
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 8 deletions.
44 changes: 40 additions & 4 deletions src/controllers/EventController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,33 @@ import { JsonController, Param, Get, Post, Delete, Body } from 'routing-controll
import { singleton, inject } from 'tsyringe';
import { ResponseSchema } from 'routing-controllers-openapi';

import { Event } from '@Entities';
import { EventRequest, EventResponse, MultipleEventResponse } from '@Payloads';
import { EventService } from '@Services';
import { EventMapper } from '@Mappers';
import { Event, AppUser, AppUserRole } from '@Entities';
import {
EventRequest,
EventResponse,
MultipleEventResponse,
EventSignInRequest,
EventSignInResponse,
} from '@Payloads';
import { AppUserService, EventService } from '@Services';
import { AppUserMapper, EventMapper } from '@Mappers';

@singleton()
@JsonController('/api/events')
export class EventController {
private appUserService: AppUserService;
private appUserMapper: AppUserMapper;
private eventService: EventService;
private eventMapper: EventMapper;

constructor(
@inject(AppUserService) appUserService: AppUserService,
@inject(AppUserMapper) appUserMapper: AppUserMapper,
@inject(EventService) eventService: EventService,
@inject(EventMapper) eventMapper: EventMapper
) {
this.appUserService = appUserService;
this.appUserMapper = appUserMapper;
this.eventService = eventService;
this.eventMapper = eventMapper;
}
Expand Down Expand Up @@ -75,4 +87,28 @@ export class EventController {

return this.eventMapper.entityToResponse(deletedEvent);
}

@Post('/:eventID/signin')
@ResponseSchema(EventSignInResponse)
async signInToEvent(
@Param('eventID') eventID: number,
@Body() appUserRequest: EventSignInRequest
): Promise<EventSignInResponse> {
const { email } = appUserRequest;
const appUserFromEmail = await this.appUserService.getAppUserByEmail(email);

if (appUserFromEmail == undefined) {
const newAppUser = this.appUserMapper.requestToNewEntity(appUserRequest);
const savedAppUser = await this.appUserService.saveAppUser(newAppUser);
return this.appUserMapper.entityToResponse(savedAppUser);
} else {
const { role } = appUserFromEmail;

if (role !== AppUserRole.GUEST) {
// return HTTP error
} else {
// TODO
}
}
}
}
3 changes: 2 additions & 1 deletion src/entities/AppUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export enum AppUserRole {
OFFICER = 'officer',
MEMBER = 'member',
INDUCTEE = 'inductee',
GUEST = 'Guest',

This comment has been minimized.

Copy link
@godwinpang

godwinpang Aug 13, 2020

Contributor

ik this is wip but lowercase

This comment has been minimized.

Copy link
@thai-truong

thai-truong Aug 13, 2020

Contributor

oh shoot didn't notice, my bad!

}

/**
Expand Down Expand Up @@ -41,7 +42,7 @@ export class AppUser {
@Column({
type: 'enum',
enum: AppUserRole,
default: AppUserRole.INDUCTEE,
default: AppUserRole.GUEST,
})
role: string;
}
2 changes: 1 addition & 1 deletion src/entities/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { AppUser } from './AppUser';
export { AppUser, AppUserRole } from './AppUser';
export { Attendance } from './Attendance';
export { Event, EventStatus, EventType } from './Event';
export { InducteeStat } from './InducteeStat';
Expand Down
43 changes: 43 additions & 0 deletions src/mappers/AppUserMapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { EventSignInRequest, EventSignInResponse } from '@Payloads';
import { AppUser } from '@Entities';
import { AppUserRepositoryToken } from '@Repositories';

import { Repository } from 'typeorm';
import { classToPlain, plainToClass } from 'class-transformer';
import { singleton, inject } from 'tsyringe';

@singleton()
export class AppUserMapper {
private appUserRepository: Repository<AppUser>;

constructor(@inject(AppUserRepositoryToken) appUserRepository: Repository<AppUser>) {
this.appUserRepository = appUserRepository;
}

requestToNewEntity(appUserRequest: EventSignInRequest): AppUser {
const plainAppUserRequest: Object = classToPlain(appUserRequest);
return this.appUserRepository.create(plainAppUserRequest);
}

async requestToExistingEntity(
appUserRequest: EventSignInRequest,
appUserId: number
): Promise<AppUser | undefined> {
const appUserObj: AppUser = appUserRequest as AppUser;
appUserObj.id = appUserId;

const appUser: AppUser = await this.appUserRepository.preload(appUserObj);
if (appUser == undefined) {
return undefined;
}

return appUser;
}

entityToResponse(appUser: AppUser): EventSignInResponse {
const plainAppUser: Object = classToPlain(appUser);
const appUserResponse: EventSignInResponse = plainToClass(EventSignInResponse, plainAppUser);

return appUserResponse;
}
}
1 change: 1 addition & 0 deletions src/mappers/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { EventMapper } from './EventMapper';
export { AppUserMapper } from './AppUserMapper';
63 changes: 62 additions & 1 deletion src/payloads/AppUser.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,67 @@
import { IsInt } from 'class-validator';
import {
IsInt,
IsString,
IsEmail,
IsBoolean,
IsEnum,
IsOptional,
ValidateNested,
} from 'class-validator';
import { AppUserRole, InductionClass } from '@Entities';
import { Type } from 'class-transformer';

export class AppUserPKPayload {
@IsInt()
readonly id: number;
}

abstract class BaseAppUserPayload {
@IsString()
readonly firstName: string;

@IsString()
readonly lastName: string;

@IsEmail()
readonly email: string;

@IsString()
readonly major: string;

@IsEnum(AppUserRole)
readonly role: string;

@IsInt()
@IsOptional()
readonly graduationYear: number;

@ValidateNested({ each: true })
@Type(() => InductionClass)
@IsOptional()
readonly inductionClass: InductionClass;
}

export class EventSignInRequest extends BaseAppUserPayload {
@IsBoolean()
readonly agreeToPhotoRelease: boolean;
}

export class EventSignInResponse {
@IsInt()
id: number;

@IsString()
firstName: string;

@IsString()
lastName: string;

@IsEmail()
email: string;

@IsString()
major: string;

@IsEnum(AppUserRole)
role: string;
}
2 changes: 1 addition & 1 deletion src/payloads/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { EventRequest, EventResponse, MultipleEventResponse } from './Event';
export { AppUserPKPayload } from './AppUser';
export { AppUserPKPayload, EventSignInRequest, EventSignInResponse } from './AppUser';
8 changes: 8 additions & 0 deletions src/services/AppUserService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ export class AppUserService {
this.appUserRepository = getRepository(AppUser);
}

saveAppUser(appUser: AppUser): Promise<AppUser> {
return this.appUserRepository.save(appUser);
}

/**
* Get multiple app users.
*
Expand All @@ -18,4 +22,8 @@ export class AppUserService {
getMultipleAppUsers(ids: number[]): Promise<AppUser[]> {
return this.appUserRepository.find({ id: Any(ids) });
}

getAppUserByEmail(email: string): Promise<AppUser> {
return this.appUserRepository.findOne({ email });
}
}

0 comments on commit 648f7d9

Please sign in to comment.