MemberRouter.ts 7.33 KB
Newer Older
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
1
2
3
4
5
6
7
8
9
10
11
12
import { DeleteWriteOpResultObject } from 'mongodb';
import {
  BadRequestError, BodyParam, Delete, Get, HeaderParam, InternalServerError, JsonController, Param, Post, Put, UnauthorizedError,
} from 'routing-controllers';
import MemberDAO from '../../db/MemberDAO';
import QuizDAO from '../../db/quiz/QuizDAO';
import { MemberEntity } from '../../entities/member/MemberEntity';
import { MessageProtocol, StatusProtocol } from '../../enums/Message';
import { IMemberSerialized } from '../../interfaces/entities/Member/IMemberSerialized';
import { IQuizEntity } from '../../interfaces/quizzes/IQuizEntity';
import { MemberModel } from '../../models/member/MemberModel';
import { AuthService } from '../../services/AuthService';
13
import LoggerService from '../../services/LoggerService';
14
15
16
17
18
import { AbstractRouter } from './AbstractRouter';

@JsonController('/api/v1/member')
export class MemberRouter extends AbstractRouter {

Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  @Get('/')
  public getMembers(): Array<IMemberSerialized> {
    return MemberDAO.storage.map(member => member.serialize());
  }

  @Post('/token')
  public generateMemberToken(@BodyParam('name') name: string, @BodyParam('quizName') quizName: string): string {
    return AuthService.createToken({
      name,
      quizName,
    });
  }

  @Get('/available/:quizName')
  public getAvailableMemberNames(@Param('quizName') quizName: string): Array<string> {
    const quiz = QuizDAO.getQuizByName(quizName);
    const nicks = JSON.parse(JSON.stringify(quiz.sessionConfig.nicks.selectedNicks));

    MemberDAO.getMembersOfQuiz(quizName).forEach(val => nicks.splice(nicks.indexOf(val.name), 1));

    return nicks;
  }

42
  @Put('/')
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
43
44
45
46
47
  public async addMember(
    @BodyParam('member') member: IMemberSerialized, //
    @HeaderParam('authorization') token: string, //
  ): Promise<object> {
    const activeQuiz: IQuizEntity = QuizDAO.getActiveQuizByName(member.currentQuizName);
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
48

Fullarton's avatar
Fullarton committed
49
    if (!activeQuiz) {
50
      throw new InternalServerError(JSON.stringify({
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
51
52
        status: StatusProtocol.Failed,
        step: MessageProtocol.IsInactive,
53
        payload: {},
Fullarton's avatar
Fullarton committed
54
55
      }));
    }
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
56

Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
57
    if (!member.name || (activeQuiz.sessionConfig.nicks.restrictToCasLogin && !member.ticket)) {
58
      throw new InternalServerError(JSON.stringify({
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
59
60
        status: StatusProtocol.Failed,
        step: MessageProtocol.InvalidParameters,
61
        payload: {},
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
62
63
      }));
    }
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
64

Fullarton's avatar
Fullarton committed
65
    try {
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
66
67
      if (!member.groupName) {
        member.groupName = 'Default';
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
68
69
      }

Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
70
71
72
73
74
75
76
77
78
      member.token = token;

      const memberValidator = new MemberModel(new MemberEntity(member).serialize());

      const results = memberValidator.validateSync();

      if (results) {
        throw results;
      }
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
79

Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
80
      await memberValidator.save();
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
81

82
      return {
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
83
84
        status: StatusProtocol.Success,
        step: MessageProtocol.Added,
85
      };
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
86

Fullarton's avatar
Fullarton committed
87
    } catch (ex) {
88
      LoggerService.error('Cannot add member', ex.message);
89
      throw new InternalServerError(JSON.stringify({
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
90
91
        status: StatusProtocol.Failed,
        step: MessageProtocol.Added,
92
        payload: { message: ex.message },
Fullarton's avatar
Fullarton committed
93
94
95
96
      }));
    }
  }

97
  @Put('/reading-confirmation')
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
98
  public addReadingConfirmation(@HeaderParam('authorization') token: string, //
99
100
  ): object {

Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
101
102
103
104
    const member = MemberDAO.getMemberByToken(token);
    const quiz = QuizDAO.getActiveQuizByName(member.currentQuizName);
    if (!member || !quiz) {
      throw new UnauthorizedError(MessageProtocol.InsufficientPermissions);
Fullarton's avatar
Fullarton committed
105
    }
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
106
107
108

    member.setReadingConfirmation();

109
    return {
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
110
111
      status: StatusProtocol.Success,
      step: MessageProtocol.ReadingConfirmationRequested,
112
      payload: {},
113
    };
Fullarton's avatar
Fullarton committed
114
115
  }

116
117
  @Put('/confidence-value')
  public addConfidenceValue(
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
118
    @HeaderParam('authorization') token: string, //
119
120
121
    @BodyParam('confidenceValue') confidenceValue: number, //
  ): object {

Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
122
123
124
125
    const member = MemberDAO.getMemberByToken(token);
    const quiz = QuizDAO.getActiveQuizByName(member.currentQuizName);
    if (!member || !quiz) {
      throw new UnauthorizedError(MessageProtocol.InsufficientPermissions);
Fullarton's avatar
Fullarton committed
126
    }
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
127
128
129

    member.setConfidenceValue(confidenceValue);

130
    return {
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
131
132
      status: StatusProtocol.Success,
      step: MessageProtocol.ConfidenceValueRequested,
133
      payload: {},
134
    };
Fullarton's avatar
Fullarton committed
135
136
  }

137
138
139
  @Put('/response')
  public addResponse(
    @HeaderParam('authorization') token: string, //
140
    @BodyParam('response', { required: false }) value: string, //
141
142
143
144
145
146
147
148
149
150
151
152
  ): object {

    if (!Array.isArray(value) && !['string', 'number'].includes(typeof value)) {
      throw new BadRequestError(MessageProtocol.InvalidData);
    }

    const member = MemberDAO.getMemberByToken(token);
    const quiz = QuizDAO.getActiveQuizByName(member.currentQuizName);
    if (!member || !quiz) {
      throw new UnauthorizedError(MessageProtocol.InsufficientPermissions);
    }

153
154
155
156
157
    if (!member.responses[quiz.currentQuestionIndex]) {
      console.error(`No responses for questionIndex ${quiz.currentQuestionIndex} found for member ${member.name} of quiz ${quiz.name}.
        Quiz has ${quiz.questionList.length} questions.`);
      throw new BadRequestError(MessageProtocol.InvalidData);
    }
158
159
160
161
162
163
164
165
166
167
168
169
170
    if (member.responses[quiz.currentQuestionIndex].responseTime > 0) {
      throw new BadRequestError(MessageProtocol.DuplicateResponse);
    }

    member.addResponseValue(value);

    return {
      status: StatusProtocol.Success,
      step: MessageProtocol.UpdatedResponse,
      payload: {},
    };
  }

171
  @Delete('/:quizName/:nickname')
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
172
  public async deleteMember(
173
174
    @Param('quizName') quizName: string, //
    @Param('nickname') nickname: string, //
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
175
  ): Promise<object> {
176

Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
177
    const activeQuiz: IQuizEntity = QuizDAO.getActiveQuizByName(quizName);
178
    if (!activeQuiz || !nickname) {
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
179
      return;
Fullarton's avatar
Fullarton committed
180
    }
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
181
    const result: DeleteWriteOpResultObject = await activeQuiz.removeMember(nickname);
182
    const response: Object = { status: result.deletedCount ? StatusProtocol.Success : StatusProtocol.Failed };
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
183
    if (result && result.deletedCount) {
Fullarton's avatar
Fullarton committed
184
      Object.assign(response, {
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
185
        step: MessageProtocol.Removed,
186
        payload: {},
Fullarton's avatar
Fullarton committed
187
      });
188
189
190
191
    } else {
      Object.assign(response, {
        message: result,
      });
Fullarton's avatar
Fullarton committed
192
    }
193
    return response;
Fullarton's avatar
Fullarton committed
194
195
  }

196
  @Get('/:quizName')
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
197
  public getAllMembers(@Param('quizName') quizName: string, //
198
199
  ): object {

Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
200
    const activeQuiz: IQuizEntity = QuizDAO.getActiveQuizByName(quizName);
Fullarton's avatar
Fullarton committed
201
    if (!activeQuiz) {
202
      throw new InternalServerError(JSON.stringify({
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
203
204
        status: StatusProtocol.Failed,
        step: MessageProtocol.IsInactive,
205
        payload: {},
Fullarton's avatar
Fullarton committed
206
207
      }));
    }
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
208

209
    return {
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
210
211
      status: StatusProtocol.Success,
      step: MessageProtocol.GetPlayers,
212
      payload: {
213
        members: MemberDAO.getMembersOfQuiz(quizName).map(member => member.serialize()),
214
      },
215
    };
Fullarton's avatar
Fullarton committed
216
217
  }

Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
218
219
  @Get('/:quizName/available')
  public getRemainingNicks(@Param('quizName') quizName: string, //
220
221
  ): object {

Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
222
    const activeQuiz: IQuizEntity = QuizDAO.getActiveQuizByName(quizName);
Fullarton's avatar
Fullarton committed
223
    if (!activeQuiz) {
224
      throw new InternalServerError(JSON.stringify({
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
225
226
        status: StatusProtocol.Failed,
        step: MessageProtocol.IsInactive,
227
        payload: {},
Fullarton's avatar
Fullarton committed
228
229
      }));
    }
230
231
    const names: Array<string> = activeQuiz.sessionConfig.nicks.selectedNicks.filter((nick) => {
      return !MemberDAO.getMembersOfQuiz(activeQuiz.name).find(member => member.name === nick);
Fullarton's avatar
Fullarton committed
232
    });
233
    return {
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
234
235
      status: StatusProtocol.Success,
      step: MessageProtocol.GetRemainingNicks,
236
      payload: { nicknames: names },
237
    };
Fullarton's avatar
Fullarton committed
238
239
  }
}