Skip to content

Commit 90725b7

Browse files
assigned user can be removed
1 parent 93871c9 commit 90725b7

File tree

2 files changed

+89
-37
lines changed

2 files changed

+89
-37
lines changed

src/client/components/Courses/Course/index.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const Course = () => {
3636
const { user, isLoading: userLoading } = useCurrentUser()
3737

3838
const { data: course, isSuccess: isCourseSuccess, error } = useCourse(id)
39+
console.log(course)
3940
if (error) {
4041
return <ApiErrorView error={error} />
4142
}
@@ -103,6 +104,9 @@ const Course = () => {
103104
const username = e.target.username.value
104105
apiClient.post(`/courses/${course.id}/responsibilities/assign`, { username: username })
105106
}
107+
const handleRemoveResponsibility = (responsibility) => {
108+
apiClient.post(`/courses/${course.id}/responsibilities/remove`, { username: responsibility.user?.username })
109+
}
106110
return (
107111
<Container sx={{ mt: '4rem', mb: '10rem' }} maxWidth="xl">
108112
<Alert severity={getInfoSeverity()}>
@@ -195,7 +199,7 @@ const Course = () => {
195199
<ul>
196200
{course.responsibilities.map((responsibility) => (
197201
<li key={responsibility.id}>
198-
{responsibility.user.last_name} {responsibility.user.first_names}
202+
{responsibility.user.last_name} {responsibility.user.first_names} <AssignedResponsibilityManagement handleRemove={() => {handleRemoveResponsibility(responsibility)}} responsibility={responsibility}/>
199203
</li>
200204
))}
201205
</ul>
@@ -229,6 +233,18 @@ const Course = () => {
229233
)
230234
}
231235

236+
const AssignedResponsibilityManagement = ({responsibility, handleRemove}) => {
237+
if(!responsibility.createdByUserId){
238+
return (<></>)
239+
}
240+
return (
241+
<Box>
242+
<Typography>manuaalisesti lisätty</Typography>
243+
<Button onClick={handleRemove}>poista</Button>
244+
</Box>
245+
)
246+
}
247+
232248
const Prompts = ({ courseId }: { courseId: string }) => {
233249
const { t } = useTranslation()
234250
const [name, setName] = useState('')

src/server/routes/course.ts

Lines changed: 72 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -87,28 +87,7 @@ courseRouter.get('/statistics/:id', async (req, res) => {
8787
courseRouter.get('/:id', async (req, res) => {
8888
const { id } = req.params
8989

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)
11291
if (!chatInstance) {
11392
throw ApplicationError.NotFound('Chat instance not found')
11493
}
@@ -165,22 +144,22 @@ courseRouter.get('/:id/enrolments', async (req: express.Request, res: express.Re
165144
//checks if user is a admin or is responsible for the course, returns forbidden error if not
166145
const enforceUserHasFullAccess = async (user, chatInstance) => {
167146
const isResponsibleForCourse = userAssignedAsResponsible(user.id, chatInstance)
168-
const hasFullAccess = user.isAdmin || isResponsibleForCourse
147+
const hasFullAccess: boolean = user.isAdmin || isResponsibleForCourse
169148
if (!hasFullAccess) {
170149
throw ApplicationError.Forbidden('Unauthorized')
171150
}
172151
return hasFullAccess
173152
}
174153

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
176155
const getChatInstance = async (id) => {
177156
const chatInstance = await ChatInstance.findOne({
178157
where: { courseId: id },
179158
include: [
180159
{
181160
model: Responsibility,
182161
as: 'responsibilities',
183-
attributes: ['id'],
162+
attributes: ['id', 'createdByUserId'],
184163
include: [
185164
{
186165
model: User,
@@ -320,7 +299,7 @@ const userAssignedAsResponsible = (userId, chatInstance) => {
320299
return isResponsible
321300
}
322301

323-
const getUser = async (id: string) => {
302+
const getUser = async (id: string):Promise<User | null> => {
324303
const user = await User.findByPk(id)
325304
if (!user) {
326305
throw ApplicationError.NotFound('User not found')
@@ -329,7 +308,7 @@ const getUser = async (id: string) => {
329308
return user
330309
}
331310

332-
const getUserByUsername = async (username: string) => {
311+
const getUserByUsername = async (username: string):Promise<User | null> => {
333312
const user = await User.findOne({
334313
where: {
335314
username: username,
@@ -361,6 +340,10 @@ courseRouter.post('/:id/responsibilities/assign', async (req, res) => {
361340
const { user } = request
362341
const chatInstance = await getChatInstance(chatInstanceId)
363342
const hasPermission = await enforceUserHasFullAccess(user, chatInstanceId)
343+
if(!hasPermission){
344+
res.status(401).send('Unauthorized')
345+
return
346+
}
364347

365348
const userToAssign = await getUserByUsername(assignedUserUsername)
366349
if (!userToAssign) {
@@ -375,17 +358,70 @@ courseRouter.post('/:id/responsibilities/assign', async (req, res) => {
375358
return
376359
}
377360

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+
})
384369

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')
386380
return
387381
}
388-
res.status(500).send('Unknown error occurred')
389-
})
390382

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+
})
391427
export default courseRouter

0 commit comments

Comments
 (0)