@@ -87,28 +87,7 @@ courseRouter.get('/statistics/:id', async (req, res) => {
87
87
courseRouter . get ( '/:id' , async ( req , res ) => {
88
88
const { id } = req . params
89
89
90
- const chatInstance = await ChatInstance . findOne ( {
91
- where : { courseId : id } ,
92
- include : [
93
- {
94
- model : Responsibility ,
95
- as : 'responsibilities' ,
96
- attributes : [ 'id' ] ,
97
- include : [
98
- {
99
- model : User ,
100
- as : 'user' ,
101
- attributes : [ 'id' , 'username' , 'last_name' , 'first_names' ] ,
102
- } ,
103
- ] ,
104
- } ,
105
- {
106
- model : Prompt ,
107
- as : 'prompts' ,
108
- } ,
109
- ] ,
110
- } )
111
-
90
+ const chatInstance = await getChatInstance ( id )
112
91
if ( ! chatInstance ) {
113
92
throw ApplicationError . NotFound ( 'Chat instance not found' )
114
93
}
@@ -165,22 +144,22 @@ courseRouter.get('/:id/enrolments', async (req: express.Request, res: express.Re
165
144
//checks if user is a admin or is responsible for the course, returns forbidden error if not
166
145
const enforceUserHasFullAccess = async ( user , chatInstance ) => {
167
146
const isResponsibleForCourse = userAssignedAsResponsible ( user . id , chatInstance )
168
- const hasFullAccess = user . isAdmin || isResponsibleForCourse
147
+ const hasFullAccess : boolean = user . isAdmin || isResponsibleForCourse
169
148
if ( ! hasFullAccess ) {
170
149
throw ApplicationError . Forbidden ( 'Unauthorized' )
171
150
}
172
151
return hasFullAccess
173
152
}
174
153
175
- // returns a chatInstance, throws an chat instacne not found if not found
154
+ // returns a chatInstance, throws an chat instance not found if not found
176
155
const getChatInstance = async ( id ) => {
177
156
const chatInstance = await ChatInstance . findOne ( {
178
157
where : { courseId : id } ,
179
158
include : [
180
159
{
181
160
model : Responsibility ,
182
161
as : 'responsibilities' ,
183
- attributes : [ 'id' ] ,
162
+ attributes : [ 'id' , 'createdByUserId' ] ,
184
163
include : [
185
164
{
186
165
model : User ,
@@ -320,7 +299,7 @@ const userAssignedAsResponsible = (userId, chatInstance) => {
320
299
return isResponsible
321
300
}
322
301
323
- const getUser = async ( id : string ) => {
302
+ const getUser = async ( id : string ) : Promise < User | null > => {
324
303
const user = await User . findByPk ( id )
325
304
if ( ! user ) {
326
305
throw ApplicationError . NotFound ( 'User not found' )
@@ -329,7 +308,7 @@ const getUser = async (id: string) => {
329
308
return user
330
309
}
331
310
332
- const getUserByUsername = async ( username : string ) => {
311
+ const getUserByUsername = async ( username : string ) : Promise < User | null > => {
333
312
const user = await User . findOne ( {
334
313
where : {
335
314
username : username ,
@@ -361,6 +340,10 @@ courseRouter.post('/:id/responsibilities/assign', async (req, res) => {
361
340
const { user } = request
362
341
const chatInstance = await getChatInstance ( chatInstanceId )
363
342
const hasPermission = await enforceUserHasFullAccess ( user , chatInstanceId )
343
+ if ( ! hasPermission ) {
344
+ res . status ( 401 ) . send ( 'Unauthorized' )
345
+ return
346
+ }
364
347
365
348
const userToAssign = await getUserByUsername ( assignedUserUsername )
366
349
if ( ! userToAssign ) {
@@ -375,17 +358,70 @@ courseRouter.post('/:id/responsibilities/assign', async (req, res) => {
375
358
return
376
359
}
377
360
378
- if ( hasPermission && userToAssign && ! userAssignedAlready ) {
379
- const createdResponsibility = await Responsibility . create ( {
380
- userId : assignedUserId ,
381
- chatInstanceId : chatInstance . id ,
382
- createdByUserId : user . id ,
383
- } )
361
+ const createdResponsibility = await Responsibility . create ( {
362
+ userId : assignedUserId ,
363
+ chatInstanceId : chatInstance . id ,
364
+ createdByUserId : user . id ,
365
+ } )
366
+
367
+ res . json ( createdResponsibility )
368
+ } )
384
369
385
- res . json ( createdResponsibility )
370
+ courseRouter . post ( '/:id/responsibilities/remove' , async ( req , res ) => {
371
+ const chatInstanceId = req . params . id
372
+ const body = req . body as {
373
+ username : string
374
+ }
375
+ const assignedUserUsername : string = body . username
376
+
377
+ const chatInstanceIdClean = cleanIdStringSchema . safeParse ( chatInstanceId )
378
+ if ( ! chatInstanceIdClean . success ) {
379
+ res . status ( 400 ) . send ( 'Malformed chat instance id' )
386
380
return
387
381
}
388
- res . status ( 500 ) . send ( 'Unknown error occurred' )
389
- } )
390
382
383
+ //username also must be of similar format as the id only letters and numbers
384
+ const assignedUserUsernameClean = cleanIdStringSchema . safeParse ( assignedUserUsername )
385
+ if ( ! assignedUserUsernameClean . success ) {
386
+ res . status ( 400 ) . send ( 'Malformed assigned user id' )
387
+ return
388
+ }
389
+
390
+ const request = req as unknown as RequestWithUser
391
+ const { user } = request
392
+ const chatInstance = await getChatInstance ( chatInstanceId )
393
+ const hasPermission = await enforceUserHasFullAccess ( user , chatInstanceId )
394
+ if ( ! hasPermission ) {
395
+ res . status ( 401 ) . send ( 'Unauthorized' )
396
+ return
397
+ }
398
+
399
+ const userToRemove : User | null = await getUserByUsername ( assignedUserUsername )
400
+ if ( ! userToRemove ) {
401
+ res . status ( 400 ) . send ( 'User not found with username' )
402
+ return
403
+ }
404
+
405
+ const assignedUserId :string = userToRemove . id
406
+ const userAssignedAlready :boolean = await userAssignedAsResponsible ( assignedUserId , chatInstance )
407
+ if ( ! userAssignedAlready ) {
408
+ res . status ( 400 ) . send ( 'User to remove not found' )
409
+ return
410
+ }
411
+
412
+ const responsibilityToRemove = await Responsibility . findOne ( {
413
+ where : {
414
+ userId : assignedUserId ,
415
+ chatInstanceId : chatInstanceId
416
+ } ,
417
+ } )
418
+
419
+ try {
420
+ await responsibilityToRemove ?. destroy ( )
421
+ res . json ( { result : "success" } )
422
+ }
423
+ catch {
424
+ res . status ( 500 ) . send ( 'Unknown error occurred' )
425
+ }
426
+ } )
391
427
export default courseRouter
0 commit comments