-
Notifications
You must be signed in to change notification settings - Fork 5
/
util.ts
100 lines (93 loc) · 2.74 KB
/
util.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import crypto from "crypto"
import { NotFoundError } from "./../../util/error"
import knex from "../../../database/knex"
import { UserCourseRole, Course } from "../../models"
import { UserInfo } from "../../types"
import { ForbiddenError } from "../../util/error"
import redis from "../../../config/redis"
export const checkAccessOrThrow = async (
userInfo: UserInfo,
courseId: string,
operation: string,
) => {
if (courseId && operation) {
const role = userInfo.administrator
? "admin"
: (
await UserCourseRole.query()
.where("user_id", userInfo.id)
.andWhere("course_id", courseId)
.limit(1)
)[0]?.role || "none"
if (abilitiesByRole[role]?.includes(operation)) {
return
}
}
throw new ForbiddenError("forbidden")
}
export const getAccessibleCourses = async (
userInfo: UserInfo,
operation: string,
) => {
if (userInfo.administrator) {
return await Course.getAll()
}
const userCourseRoles = await UserCourseRole.getByUserId(userInfo.id)
const courses = await Promise.all(
userCourseRoles.map(async userCourseRole => {
if (abilitiesByRole[userCourseRole.role]?.includes(operation)) {
return await Course.getById(userCourseRole.courseId)
}
}),
)
if (courses.length === 0) {
throw new ForbiddenError("forbidden")
}
return courses
}
export const abilitiesByRole: { [role: string]: string[] } = {
admin: ["view", "edit", "grade", "download", "duplicate", "delete-answer"],
assistant: ["view", "edit", "grade", "delete-answer"],
teacher: ["view", "edit", "grade", "delete-answer"],
reviewer: ["view", "grade"],
}
export const getCourseIdByAnswerId = async (answerId: string) => {
let courses
try {
courses = await knex("quiz")
.select("course_id")
.innerJoin("quiz_answer", "quiz.id", "quiz_answer.quiz_id")
.where("quiz_answer.id", answerId)
} catch (error) {
throw error
}
if (courses[0]) {
return courses[0].course_id
} else {
throw new NotFoundError(`No course found for answer id: ${answerId}`)
}
}
export const getCourseIdByQuizId = async (quizId: string) => {
return (
await knex("quiz")
.select("course_id")
.where("quiz.id", quizId)
)[0].course_id
}
export const getDownloadTokenFromRedis = async (
userId: string,
): Promise<string> => {
let downloadToken = ""
if (redis.client) {
const cachedToken = await redis.client.get(userId)
if (cachedToken) {
downloadToken = cachedToken
} else {
const randomToken = `dl_tkn_${crypto.randomBytes(100).toString("hex")}`
await redis.client.set(userId, randomToken, "EX", 600)
downloadToken = randomToken
}
}
// will return empty string if redis unavailable
return downloadToken
}