taleem-kernel 1.2.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,48 @@
1
+ export default class Group {
2
+ constructor(kernel) { this.kernel = kernel; }
3
+
4
+ async list(filters = {}) {
5
+ const where = {};
6
+ if (filters.courseSlug) where.courseSlug = filters.courseSlug;
7
+
8
+ return this.kernel.db.group.findMany({
9
+ where,
10
+ orderBy: { id: "asc" }
11
+ });
12
+ }
13
+
14
+ async listByCourse(courseSlug) {
15
+ return this.list({ courseSlug });
16
+ }
17
+
18
+ async get(courseSlug, slug) {
19
+ return this.kernel.db.group.findUnique({
20
+ where: {
21
+ courseSlug_slug: { courseSlug, slug }
22
+ }
23
+ });
24
+ }
25
+
26
+ async create(data) {
27
+ // throws if data.courseSlug doesn't resolve to an existing Course
28
+ return this.kernel.db.group.create({ data });
29
+ }
30
+
31
+ async update(courseSlug, slug, data) {
32
+ return this.kernel.db.group.update({
33
+ where: {
34
+ courseSlug_slug: { courseSlug, slug }
35
+ },
36
+ data
37
+ });
38
+ }
39
+
40
+ async delete(courseSlug, slug) {
41
+ // throws if any Library rows still reference this group (Restrict)
42
+ return this.kernel.db.group.delete({
43
+ where: {
44
+ courseSlug_slug: { courseSlug, slug }
45
+ }
46
+ });
47
+ }
48
+ }
@@ -1,12 +1,17 @@
1
+ const PUBLIC_STATUS = "PUBLISHED";
2
+
1
3
  export default class Library {
2
4
  constructor(kernel) { this.kernel = kernel; }
3
5
 
4
- async list(filters = {}) {
6
+ async list(filters = {}, { includeUnpublished = false } = {}) {
5
7
  const where = {};
6
8
  if (filters.type) where.type = filters.type;
7
9
  if (filters.courseSlug) where.courseSlug = filters.courseSlug;
8
10
  if (filters.groupSlug) where.groupSlug = filters.groupSlug;
9
11
 
12
+ if (!includeUnpublished) where.status = PUBLIC_STATUS;
13
+ else if (filters.status) where.status = filters.status;
14
+
10
15
  return this.kernel.db.library.findMany({
11
16
  where,
12
17
  select: {
@@ -15,6 +20,7 @@ export default class Library {
15
20
  description: true,
16
21
  thumbnail: true,
17
22
  type: true,
23
+ status: true,
18
24
  courseSlug: true,
19
25
  groupSlug: true,
20
26
  sortOrder: true,
@@ -26,17 +32,20 @@ export default class Library {
26
32
  });
27
33
  }
28
34
 
29
- async listByCourse(courseSlug) {
30
- return this.list({ courseSlug });
35
+ async listByCourse(courseSlug, opts) {
36
+ return this.list({ courseSlug }, opts);
31
37
  }
32
38
 
33
- async listByGroup(courseSlug, groupSlug) {
34
- return this.list({ courseSlug, groupSlug });
39
+ async listByGroup(courseSlug, groupSlug, opts) {
40
+ return this.list({ courseSlug, groupSlug }, opts);
35
41
  }
36
42
 
37
- async get(slug) {
43
+ async get(slug, { includeUnpublished = false } = {}) {
38
44
  return this.kernel.db.library.findUnique({
39
- where: { slug }
45
+ where: {
46
+ slug,
47
+ ...(includeUnpublished ? {} : { status: PUBLIC_STATUS })
48
+ }
40
49
  });
41
50
  }
42
51
 
@@ -52,11 +61,13 @@ export default class Library {
52
61
  }
53
62
 
54
63
  async delete(slug) {
64
+ // throws if Communication rows still reference this slug (Restrict)
55
65
  return this.kernel.db.library.delete({
56
66
  where: { slug }
57
67
  });
58
68
  }
59
- async createFromSlot(slug, courseSlug, groupSlug, type) {
69
+
70
+ async createFromSlot(slug, courseSlug, groupSlug, type) {
60
71
  return this.create({
61
72
  slug,
62
73
  courseSlug,
@@ -65,4 +76,5 @@ export default class Library {
65
76
  title: slug
66
77
  });
67
78
  }
79
+
68
80
  }
@@ -1,97 +1,48 @@
1
- // src/serverKernel/modules/Subscription.js
2
-
3
1
  export default class Subscription {
4
-
5
- constructor(kernel) {
6
- this.kernel = kernel;
7
- }
8
-
9
- // --------------------------------------------------
10
- // Queries
11
- // --------------------------------------------------
2
+ constructor(kernel) { this.kernel = kernel; }
12
3
 
13
4
  async list(filters = {}) {
14
-
15
5
  const where = {};
16
-
17
- if (filters.userId) {
18
- where.userId = filters.userId;
19
- }
20
-
21
- if (filters.courseId) {
22
- where.courseId = filters.courseId;
23
- }
24
-
25
- return this.kernel.db.subscription.findMany({
26
- where
27
- });
28
-
6
+ if (filters.userId) where.userId = filters.userId;
7
+ if (filters.courseSlug) where.courseSlug = filters.courseSlug;
8
+ return this.kernel.db.subscription.findMany({ where });
29
9
  }
30
10
 
31
11
  async get(id) {
32
-
33
- return this.kernel.db.subscription.findUnique({
34
- where: { id }
35
- });
36
-
12
+ return this.kernel.db.subscription.findUnique({ where: { id } });
37
13
  }
38
14
 
39
- // --------------------------------------------------
40
- // CRUD
41
- // --------------------------------------------------
42
-
43
15
  async create(data) {
44
-
45
- return this.kernel.db.subscription.create({
46
- data
47
- });
48
-
16
+ // throws if courseSlug doesn't resolve to an existing Course
17
+ return this.kernel.db.subscription.create({ data });
49
18
  }
50
19
 
51
20
  async update(id, data) {
52
-
53
- return this.kernel.db.subscription.update({
54
- where: { id },
55
- data
56
- });
57
-
21
+ return this.kernel.db.subscription.update({ where: { id }, data });
58
22
  }
59
23
 
60
24
  async delete(id) {
61
-
62
- return this.kernel.db.subscription.delete({
63
- where: { id }
64
- });
65
-
25
+ return this.kernel.db.subscription.delete({ where: { id } });
66
26
  }
67
27
 
68
- // --------------------------------------------------
69
- // Utilities
70
- // --------------------------------------------------
71
-
72
- async authorize(userId, courseId) {
73
- debugger;
28
+ async authorize(userId, courseSlug) {
74
29
  const now = new Date();
75
30
 
76
31
  const subscription = await this.kernel.db.subscription.findFirst({
77
-
78
32
  where: {
79
33
  userId,
80
- courseId,
34
+ courseSlug,
81
35
  startsAt: { lte: now },
82
36
  endsAt: { gte: now }
83
37
  }
84
-
85
38
  });
86
39
 
87
40
  if (!subscription) {
88
41
  throw new Error(
89
- `User "${userId}" does not have an active subscription for course "${courseId}".`
42
+ `User "${userId}" does not have an active subscription for course "${courseSlug}".`
90
43
  );
91
44
  }
92
45
 
93
46
  return subscription;
94
-
95
47
  }
96
-
97
48
  }
@@ -1,12 +1,8 @@
1
- // src/serverKernel/modules/Svg.js
2
-
3
1
  export default class Svg {
4
2
  constructor(kernel) { this.kernel = kernel; }
5
3
 
6
4
  async list() {
7
- return this.kernel.db.svg.findMany({
8
- orderBy: { title: "asc" }
9
- });
5
+ return this.kernel.db.svg.findMany({ orderBy: { title: "asc" } });
10
6
  }
11
7
 
12
8
  async get(slug) {
@@ -14,25 +10,11 @@ export default class Svg {
14
10
  }
15
11
 
16
12
  async create(data) {
17
- return this.kernel.db.svg.create({
18
- data: {
19
- slug: data.slug,
20
- title: data.title,
21
- body: data.body,
22
- tags: data.tags ?? "[]"
23
- }
24
- });
13
+ return this.kernel.db.svg.create({ data });
25
14
  }
26
15
 
27
16
  async update(slug, data) {
28
- return this.kernel.db.svg.update({
29
- where: { slug },
30
- data: {
31
- title: data.title,
32
- body: data.body,
33
- tags: data.tags
34
- }
35
- });
17
+ return this.kernel.db.svg.update({ where: { slug }, data });
36
18
  }
37
19
 
38
20
  async delete(slug) {
@@ -1,10 +1,12 @@
1
1
  // src/serverKernel/modules/User.js
2
2
 
3
3
  import bcrypt from "bcrypt";
4
+ import JWT from "../utils/JWT.js";
4
5
 
5
6
  export default class User {
6
7
  constructor(kernel) {
7
8
  this.kernel = kernel;
9
+ this.jwt = new JWT(kernel);
8
10
  }
9
11
 
10
12
  // Queries
@@ -31,28 +33,69 @@ export default class User {
31
33
 
32
34
  async register(data) {
33
35
  const password = await bcrypt.hash(data.password, 10);
34
- return this.kernel.db.user.create({ data: { ...data, password } });
36
+
37
+ return this.kernel.db.user.create({
38
+ data: { ...data, password }
39
+ });
35
40
  }
36
41
 
37
42
  async login(email, password) {
38
43
  const user = await this.getByEmail(email);
39
- if (!user) throw new Error(`User.login(): User '${email}' not found.`);
44
+
45
+ if (!user) {
46
+ throw new Error(`User.login(): User '${email}' not found.`);
47
+ }
40
48
 
41
49
  const ok = await bcrypt.compare(password, user.password);
42
- if (!ok) throw new Error(`User.login(): Invalid password.`);
43
50
 
44
- return this.kernel.auth.createUserToken(user);
51
+ if (!ok) {
52
+ throw new Error(`User.login(): Invalid password.`);
53
+ }
54
+
55
+ return this.createToken(user);
56
+ }
57
+
58
+ async createToken(user) {
59
+ return this.jwt.sign({
60
+ id: user.id,
61
+ type: "user"
62
+ });
63
+ }
64
+
65
+ async authenticate(token) {
66
+ const payload = this.jwt.verify(token);
67
+
68
+ if (payload.type !== "user") {
69
+ throw new Error("User token required.");
70
+ }
71
+
72
+ const user = await this.get(payload.id);
73
+
74
+ if (!user) {
75
+ throw new Error("User not found.");
76
+ }
77
+
78
+ return user;
45
79
  }
46
80
 
47
81
  // CRUD
48
82
 
49
83
  async update(id, data) {
50
84
  const updateData = { ...data };
51
- if (updateData.password) updateData.password = await bcrypt.hash(updateData.password, 10);
52
- return this.kernel.db.user.update({ where: { id }, data: updateData });
85
+
86
+ if (updateData.password) {
87
+ updateData.password = await bcrypt.hash(updateData.password, 10);
88
+ }
89
+
90
+ return this.kernel.db.user.update({
91
+ where: { id },
92
+ data: updateData
93
+ });
53
94
  }
54
95
 
55
96
  async delete(id) {
56
- return this.kernel.db.user.delete({ where: { id } });
97
+ return this.kernel.db.user.delete({
98
+ where: { id }
99
+ });
57
100
  }
58
101
  }
@@ -0,0 +1,31 @@
1
+ // /home/bilal-tariq/00--TALEEM/taleem-kernel/src/utils/JWT.js
2
+
3
+ import jwt from "jsonwebtoken";
4
+
5
+ export default class JWT {
6
+
7
+ constructor(kernel) {
8
+
9
+ this.kernel = kernel;
10
+
11
+ }
12
+
13
+ sign(payload) {
14
+
15
+ return jwt.sign(
16
+ payload,
17
+ this.kernel.config.jwtSecret
18
+ );
19
+
20
+ }
21
+
22
+ verify(token) {
23
+
24
+ return jwt.verify(
25
+ token,
26
+ this.kernel.config.jwtSecret
27
+ );
28
+
29
+ }
30
+
31
+ }
package/prisma/content.db DELETED
Binary file
package/src/Auth.js DELETED
@@ -1,105 +0,0 @@
1
- ///home/bilal-tariq/00--TALEEM/taleem-server/src/serverKernel/Auth.js
2
-
3
- import JWT from "./JWT.js";
4
-
5
- export default class Auth {
6
-
7
- constructor(kernel) {
8
- this.kernel = kernel;
9
- this.jwt = new JWT(kernel);
10
- }
11
- // --------------------------------------------------
12
- // Token Creation
13
- // --------------------------------------------------
14
- createUserToken(user) {
15
-
16
- return this.jwt.sign({ id: user.id, type: "user" });
17
-
18
- }
19
-
20
- createAdminToken(admin) {
21
-
22
- return this.jwt.sign({ id: admin.id, type: "admin" });
23
-
24
- }
25
-
26
- // --------------------------------------------------
27
- // Authentication
28
- // --------------------------------------------------
29
-
30
- async authenticate(token) {
31
-
32
- const { id, type } = this.verifyToken(token);
33
-
34
- if (type === "user") return this.authenticateUser(id);
35
-
36
- if (type === "admin") return this.authenticateAdmin(id);
37
-
38
- this.fail("authenticate()", `Unknown identity type '${type}'.`);
39
-
40
- }
41
-
42
- async authenticateUser(id) {
43
-
44
- const user = await this.kernel.user.get(id);
45
-
46
- if (!user)
47
- this.fail(
48
- "authenticateUser()",
49
- `User '${id}' does not exist.`
50
- );
51
-
52
- return user;
53
-
54
- }
55
-
56
- async authenticateAdmin(id) {
57
-
58
- const admin = await this.kernel.admin.get(id);
59
-
60
- if (!admin)
61
- this.fail(
62
- "authenticateAdmin()",
63
- `Admin '${id}' does not exist.`
64
- );
65
-
66
- return admin;
67
-
68
- }
69
-
70
- verifyToken(token) {
71
-
72
- try {
73
-
74
- return this.jwt.verify(token);
75
-
76
- }
77
- catch (error) {
78
-
79
- this.fail("verifyToken()", error.message);
80
-
81
- }
82
-
83
- }
84
-
85
- // --------------------------------------------------
86
- // Helpers
87
- // --------------------------------------------------
88
-
89
- fail(method, reason) {
90
-
91
- throw new Error(
92
- [
93
- "",
94
- "========================================",
95
- "AUTHENTICATION FAILED",
96
- "----------------------------------------",
97
- `Method : Auth.${method}`,
98
- `Reason : ${reason}`,
99
- "========================================"
100
- ].join("\n")
101
- );
102
-
103
- }
104
-
105
- }