@studious-lms/server 1.7.0 → 1.9.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.
- package/dist/middleware/security.d.ts.map +1 -1
- package/dist/middleware/security.js +3 -3
- package/dist/middleware/security.js.map +1 -1
- package/dist/models/access.d.ts +21 -66
- package/dist/models/access.d.ts.map +1 -1
- package/dist/models/access.js +10 -26
- package/dist/models/access.js.map +1 -1
- package/dist/models/agenda.d.ts +4 -2
- package/dist/models/agenda.d.ts.map +1 -1
- package/dist/models/announcement.d.ts +4 -3
- package/dist/models/announcement.d.ts.map +1 -1
- package/dist/models/announcement.js +2 -3
- package/dist/models/announcement.js.map +1 -1
- package/dist/models/assignment.d.ts +40 -33
- package/dist/models/assignment.d.ts.map +1 -1
- package/dist/models/auth.d.ts +2 -4
- package/dist/models/auth.d.ts.map +1 -1
- package/dist/models/auth.js +2 -3
- package/dist/models/auth.js.map +1 -1
- package/dist/models/class.d.ts +34 -6
- package/dist/models/class.d.ts.map +1 -1
- package/dist/models/class.js +15 -2
- package/dist/models/class.js.map +1 -1
- package/dist/models/cloudStorage.d.ts +153 -0
- package/dist/models/cloudStorage.d.ts.map +1 -0
- package/dist/models/cloudStorage.js +295 -0
- package/dist/models/cloudStorage.js.map +1 -0
- package/dist/models/comment.d.ts +0 -24
- package/dist/models/comment.d.ts.map +1 -1
- package/dist/models/comment.js +2 -6
- package/dist/models/comment.js.map +1 -1
- package/dist/models/conversation.d.ts +22 -22
- package/dist/models/department.d.ts +154 -0
- package/dist/models/department.d.ts.map +1 -0
- package/dist/models/department.js +135 -0
- package/dist/models/department.js.map +1 -0
- package/dist/models/event.d.ts +10 -4
- package/dist/models/event.d.ts.map +1 -1
- package/dist/models/event.js +2 -5
- package/dist/models/event.js.map +1 -1
- package/dist/models/file.d.ts +52 -36
- package/dist/models/file.d.ts.map +1 -1
- package/dist/models/file.js +4 -42
- package/dist/models/file.js.map +1 -1
- package/dist/models/folder.d.ts +47 -0
- package/dist/models/folder.d.ts.map +1 -1
- package/dist/models/labChat.d.ts +11 -9
- package/dist/models/labChat.d.ts.map +1 -1
- package/dist/models/message.d.ts +46 -12
- package/dist/models/message.d.ts.map +1 -1
- package/dist/models/message.js +19 -10
- package/dist/models/message.js.map +1 -1
- package/dist/models/newtonChat.d.ts +2 -1
- package/dist/models/newtonChat.d.ts.map +1 -1
- package/dist/models/school.d.ts +45 -12
- package/dist/models/school.d.ts.map +1 -1
- package/dist/models/school.js +19 -2
- package/dist/models/school.js.map +1 -1
- package/dist/models/section.d.ts +2 -1
- package/dist/models/section.d.ts.map +1 -1
- package/dist/models/tag.d.ts +117 -0
- package/dist/models/tag.d.ts.map +1 -0
- package/dist/models/tag.js +113 -0
- package/dist/models/tag.js.map +1 -0
- package/dist/models/worksheet.d.ts +3 -0
- package/dist/models/worksheet.d.ts.map +1 -1
- package/dist/pipelines/aiLabChatContract.d.ts +8 -8
- package/dist/routers/_app.d.ts +6704 -5222
- package/dist/routers/_app.d.ts.map +1 -1
- package/dist/routers/_app.js +8 -2
- package/dist/routers/_app.js.map +1 -1
- package/dist/routers/agenda.d.ts +4 -2
- package/dist/routers/agenda.d.ts.map +1 -1
- package/dist/routers/announcement.d.ts.map +1 -1
- package/dist/routers/announcement.js +3 -5
- package/dist/routers/announcement.js.map +1 -1
- package/dist/routers/assignment.d.ts +49 -40
- package/dist/routers/assignment.d.ts.map +1 -1
- package/dist/routers/assignment.js +2 -3
- package/dist/routers/assignment.js.map +1 -1
- package/dist/routers/class.d.ts +92 -19
- package/dist/routers/class.d.ts.map +1 -1
- package/dist/routers/class.js +5 -2
- package/dist/routers/class.js.map +1 -1
- package/dist/routers/conversation.d.ts +5 -5
- package/dist/routers/department.d.ts +293 -0
- package/dist/routers/department.d.ts.map +1 -0
- package/dist/routers/department.js +93 -0
- package/dist/routers/department.js.map +1 -0
- package/dist/routers/event.d.ts +4 -3
- package/dist/routers/event.d.ts.map +1 -1
- package/dist/routers/file.d.ts +10 -8
- package/dist/routers/file.d.ts.map +1 -1
- package/dist/routers/file.js +26 -17
- package/dist/routers/file.js.map +1 -1
- package/dist/routers/folder.d.ts +163 -186
- package/dist/routers/folder.d.ts.map +1 -1
- package/dist/routers/folder.js +102 -88
- package/dist/routers/folder.js.map +1 -1
- package/dist/routers/labChat.d.ts +13 -4
- package/dist/routers/labChat.d.ts.map +1 -1
- package/dist/routers/message.d.ts +20 -2
- package/dist/routers/message.d.ts.map +1 -1
- package/dist/routers/newtonChat.d.ts +10 -1
- package/dist/routers/newtonChat.d.ts.map +1 -1
- package/dist/routers/permissions.d.ts +120 -0
- package/dist/routers/permissions.d.ts.map +1 -0
- package/dist/routers/permissions.js +50 -0
- package/dist/routers/permissions.js.map +1 -0
- package/dist/routers/school.d.ts +160 -17
- package/dist/routers/school.d.ts.map +1 -1
- package/dist/routers/school.js +46 -3
- package/dist/routers/school.js.map +1 -1
- package/dist/routers/tag.d.ts +119 -0
- package/dist/routers/tag.d.ts.map +1 -0
- package/dist/routers/tag.js +52 -0
- package/dist/routers/tag.js.map +1 -0
- package/dist/routers/worksheet.d.ts +1 -0
- package/dist/routers/worksheet.d.ts.map +1 -1
- package/dist/seedDatabase.d.ts +0 -1
- package/dist/seedDatabase.d.ts.map +1 -1
- package/dist/services/agenda.d.ts +4 -2
- package/dist/services/agenda.d.ts.map +1 -1
- package/dist/services/assignment.d.ts +49 -40
- package/dist/services/assignment.d.ts.map +1 -1
- package/dist/services/class.d.ts +92 -19
- package/dist/services/class.d.ts.map +1 -1
- package/dist/services/class.js +92 -5
- package/dist/services/class.js.map +1 -1
- package/dist/services/conversation.d.ts +5 -5
- package/dist/services/department.d.ts +200 -0
- package/dist/services/department.d.ts.map +1 -0
- package/dist/services/department.js +368 -0
- package/dist/services/department.js.map +1 -0
- package/dist/services/event.d.ts +4 -3
- package/dist/services/event.d.ts.map +1 -1
- package/dist/services/file.d.ts +105 -3
- package/dist/services/file.d.ts.map +1 -1
- package/dist/services/file.js +167 -41
- package/dist/services/file.js.map +1 -1
- package/dist/services/folder.d.ts +220 -149
- package/dist/services/folder.d.ts.map +1 -1
- package/dist/services/folder.js +326 -196
- package/dist/services/folder.js.map +1 -1
- package/dist/services/labChat.d.ts +13 -4
- package/dist/services/labChat.d.ts.map +1 -1
- package/dist/services/labChat.js +4 -3
- package/dist/services/labChat.js.map +1 -1
- package/dist/services/message.d.ts +20 -2
- package/dist/services/message.d.ts.map +1 -1
- package/dist/services/message.js +7 -23
- package/dist/services/message.js.map +1 -1
- package/dist/services/newtonChat.d.ts +9 -0
- package/dist/services/newtonChat.d.ts.map +1 -1
- package/dist/services/newtonChat.js +4 -3
- package/dist/services/newtonChat.js.map +1 -1
- package/dist/services/permissions.d.ts +188 -0
- package/dist/services/permissions.d.ts.map +1 -0
- package/dist/services/permissions.js +661 -0
- package/dist/services/permissions.js.map +1 -0
- package/dist/services/school.d.ts +142 -15
- package/dist/services/school.d.ts.map +1 -1
- package/dist/services/school.js +308 -54
- package/dist/services/school.js.map +1 -1
- package/dist/services/tag.d.ts +71 -0
- package/dist/services/tag.d.ts.map +1 -0
- package/dist/services/tag.js +178 -0
- package/dist/services/tag.js.map +1 -0
- package/dist/services/worksheet.d.ts +1 -0
- package/dist/services/worksheet.d.ts.map +1 -1
- package/dist/utils/aiUser.d.ts.map +1 -1
- package/dist/utils/aiUser.js +2 -3
- package/dist/utils/aiUser.js.map +1 -1
- package/package.json +1 -1
- package/prisma/migrations/20260509220000_institution_overhaul/migration.sql +184 -0
- package/prisma/migrations/20260510170000_add_folder_permissions/migration.sql +93 -0
- package/prisma/schema.prisma +193 -35
- package/src/middleware/security.ts +1 -1
- package/src/models/access.ts +8 -24
- package/src/models/announcement.ts +0 -1
- package/src/models/auth.ts +0 -1
- package/src/models/class.ts +13 -0
- package/src/models/cloudStorage.ts +327 -0
- package/src/models/comment.ts +0 -4
- package/src/models/department.ts +159 -0
- package/src/models/event.ts +0 -3
- package/src/models/file.ts +2 -40
- package/src/models/message.ts +19 -5
- package/src/models/school.ts +26 -0
- package/src/models/tag.ts +140 -0
- package/src/routers/_app.ts +6 -0
- package/src/routers/announcement.ts +1 -3
- package/src/routers/assignment.ts +0 -1
- package/src/routers/class.ts +3 -0
- package/src/routers/department.ts +174 -0
- package/src/routers/file.ts +29 -26
- package/src/routers/folder.ts +127 -118
- package/src/routers/permissions.ts +71 -0
- package/src/routers/school.ts +83 -0
- package/src/routers/tag.ts +78 -0
- package/src/services/class.ts +109 -4
- package/src/services/department.ts +478 -0
- package/src/services/file.ts +172 -43
- package/src/services/folder.ts +399 -237
- package/src/services/labChat.ts +2 -1
- package/src/services/message.ts +5 -21
- package/src/services/newtonChat.ts +2 -1
- package/src/services/permissions.ts +778 -0
- package/src/services/school.ts +369 -57
- package/src/services/tag.ts +229 -0
- package/src/utils/aiUser.ts +0 -1
- package/tests/unit/services/permissions.test.ts +463 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="26810bf7-c72f-5655-8994-96075d84b6fe")}catch(e){}}();
|
|
3
|
+
import { prisma } from "../lib/prisma.js";
|
|
4
|
+
const folderSelect = {
|
|
5
|
+
id: true,
|
|
6
|
+
name: true,
|
|
7
|
+
color: true,
|
|
8
|
+
scope: true,
|
|
9
|
+
classId: true,
|
|
10
|
+
schoolStorageId: true,
|
|
11
|
+
personalOwnerId: true,
|
|
12
|
+
parentFolderId: true,
|
|
13
|
+
};
|
|
14
|
+
export async function findOrCreateScopeRoot(scope) {
|
|
15
|
+
switch (scope.kind) {
|
|
16
|
+
case "CLASS": {
|
|
17
|
+
let root = await prisma.folder.findFirst({
|
|
18
|
+
where: { classId: scope.classId, parentFolderId: null },
|
|
19
|
+
});
|
|
20
|
+
if (!root) {
|
|
21
|
+
root = await prisma.folder.create({
|
|
22
|
+
data: {
|
|
23
|
+
name: "Class Files",
|
|
24
|
+
scope: "CLASS",
|
|
25
|
+
class: { connect: { id: scope.classId } },
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
else if (root.scope !== "CLASS") {
|
|
30
|
+
root = await prisma.folder.update({
|
|
31
|
+
where: { id: root.id },
|
|
32
|
+
data: { scope: "CLASS" },
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return root;
|
|
36
|
+
}
|
|
37
|
+
case "SCHOOL_STORAGE": {
|
|
38
|
+
let root = await prisma.folder.findFirst({
|
|
39
|
+
where: { schoolStorageId: scope.schoolId },
|
|
40
|
+
});
|
|
41
|
+
if (!root) {
|
|
42
|
+
root = await prisma.folder.create({
|
|
43
|
+
data: {
|
|
44
|
+
name: "Cloud Storage",
|
|
45
|
+
scope: "SCHOOL_STORAGE",
|
|
46
|
+
schoolStorage: { connect: { id: scope.schoolId } },
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return root;
|
|
51
|
+
}
|
|
52
|
+
case "PERSONAL": {
|
|
53
|
+
let root = await prisma.folder.findFirst({
|
|
54
|
+
where: { personalOwnerId: scope.userId },
|
|
55
|
+
});
|
|
56
|
+
if (!root) {
|
|
57
|
+
root = await prisma.folder.create({
|
|
58
|
+
data: {
|
|
59
|
+
name: "My Files",
|
|
60
|
+
scope: "PERSONAL",
|
|
61
|
+
personalOwner: { connect: { id: scope.userId } },
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return root;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Walk up the folder tree until we reach a root with a scope owner. Used to
|
|
71
|
+
* permission-check sub-folders (which only carry a parentFolderId).
|
|
72
|
+
*/
|
|
73
|
+
export async function resolveFolderScope(folderId) {
|
|
74
|
+
let currentId = folderId;
|
|
75
|
+
let visits = 0;
|
|
76
|
+
while (currentId && visits < 64) {
|
|
77
|
+
const folder = await prisma.folder.findUnique({
|
|
78
|
+
where: { id: currentId },
|
|
79
|
+
select: folderSelect,
|
|
80
|
+
});
|
|
81
|
+
if (!folder)
|
|
82
|
+
return null;
|
|
83
|
+
if (folder.classId)
|
|
84
|
+
return { kind: "CLASS", classId: folder.classId };
|
|
85
|
+
if (folder.schoolStorageId)
|
|
86
|
+
return { kind: "SCHOOL_STORAGE", schoolId: folder.schoolStorageId };
|
|
87
|
+
if (folder.personalOwnerId)
|
|
88
|
+
return { kind: "PERSONAL", userId: folder.personalOwnerId };
|
|
89
|
+
if (!folder.parentFolderId)
|
|
90
|
+
return null;
|
|
91
|
+
currentId = folder.parentFolderId;
|
|
92
|
+
visits += 1;
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
const fileSelect = {
|
|
97
|
+
id: true,
|
|
98
|
+
name: true,
|
|
99
|
+
type: true,
|
|
100
|
+
size: true,
|
|
101
|
+
path: true,
|
|
102
|
+
uploadedAt: true,
|
|
103
|
+
user: { select: { id: true, username: true } },
|
|
104
|
+
};
|
|
105
|
+
const childFolderSelect = {
|
|
106
|
+
id: true,
|
|
107
|
+
name: true,
|
|
108
|
+
color: true,
|
|
109
|
+
_count: { select: { files: true, childFolders: true } },
|
|
110
|
+
};
|
|
111
|
+
export function findFolderWithContents(folderId) {
|
|
112
|
+
return prisma.folder.findFirst({
|
|
113
|
+
where: { id: folderId },
|
|
114
|
+
include: {
|
|
115
|
+
files: {
|
|
116
|
+
where: { uploadStatus: "COMPLETED" },
|
|
117
|
+
select: fileSelect,
|
|
118
|
+
orderBy: { uploadedAt: "desc" },
|
|
119
|
+
},
|
|
120
|
+
childFolders: {
|
|
121
|
+
select: childFolderSelect,
|
|
122
|
+
orderBy: { name: "asc" },
|
|
123
|
+
},
|
|
124
|
+
parentFolder: { select: { id: true, name: true } },
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
export function createSubFolder(data) {
|
|
129
|
+
return prisma.folder.create({
|
|
130
|
+
data: {
|
|
131
|
+
name: data.name,
|
|
132
|
+
color: data.color,
|
|
133
|
+
parentFolder: { connect: { id: data.parentFolderId } },
|
|
134
|
+
},
|
|
135
|
+
select: folderSelect,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
export function findFolderById(folderId) {
|
|
139
|
+
return prisma.folder.findUnique({
|
|
140
|
+
where: { id: folderId },
|
|
141
|
+
select: folderSelect,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
export function deleteFolderById(folderId) {
|
|
145
|
+
return prisma.folder.delete({ where: { id: folderId } });
|
|
146
|
+
}
|
|
147
|
+
export function renameFolder(folderId, name, color) {
|
|
148
|
+
return prisma.folder.update({
|
|
149
|
+
where: { id: folderId },
|
|
150
|
+
data: {
|
|
151
|
+
name,
|
|
152
|
+
...(color ? { color } : {}),
|
|
153
|
+
},
|
|
154
|
+
select: folderSelect,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Build the breadcrumb chain for a folder.
|
|
159
|
+
*
|
|
160
|
+
* Without `viewerId`: walks all the way up to the scope root (owner-style
|
|
161
|
+
* view).
|
|
162
|
+
*
|
|
163
|
+
* With `viewerId`: walks up but stops at the highest folder the viewer is
|
|
164
|
+
* actually granted on, OR at the scope root if the viewer is a scope member.
|
|
165
|
+
* This is the Drive-style "Shared with me" behavior — a grantee never sees
|
|
166
|
+
* ancestor folders they weren't shared on. The result for a grantee browsing
|
|
167
|
+
* `Owner/PrivateA/SharedB/C` (granted on B) reads `SharedB / C` — the ancestor
|
|
168
|
+
* `PrivateA` is correctly hidden.
|
|
169
|
+
*/
|
|
170
|
+
export async function listFolderBreadcrumbs(folderId, viewerId) {
|
|
171
|
+
const breadcrumbs = [];
|
|
172
|
+
let currentId = folderId;
|
|
173
|
+
let visits = 0;
|
|
174
|
+
let viewerGrantedFolderIds = null;
|
|
175
|
+
let viewerScopeMember = false;
|
|
176
|
+
if (viewerId) {
|
|
177
|
+
const grants = await prisma.permission.findMany({
|
|
178
|
+
where: {
|
|
179
|
+
OR: [
|
|
180
|
+
{ principalType: "USER", userId: viewerId },
|
|
181
|
+
{
|
|
182
|
+
principalType: "TAG",
|
|
183
|
+
tag: { users: { some: { id: viewerId } } },
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
principalType: "CLASS",
|
|
187
|
+
class: {
|
|
188
|
+
OR: [
|
|
189
|
+
{ teachers: { some: { id: viewerId } } },
|
|
190
|
+
{ students: { some: { id: viewerId } } },
|
|
191
|
+
],
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
principalType: "CLASS_TEACHERS",
|
|
196
|
+
class: { teachers: { some: { id: viewerId } } },
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
principalType: "CLASS_STUDENTS",
|
|
200
|
+
class: { students: { some: { id: viewerId } } },
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
principalType: "DEPARTMENT",
|
|
204
|
+
department: { members: { some: { id: viewerId } } },
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
principalType: "SCHOOL",
|
|
208
|
+
school: {
|
|
209
|
+
memberships: { some: { userId: viewerId, status: "ACTIVE" } },
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
},
|
|
214
|
+
select: { folderId: true },
|
|
215
|
+
});
|
|
216
|
+
viewerGrantedFolderIds = new Set(grants.map((g) => g.folderId).filter((x) => Boolean(x)));
|
|
217
|
+
// Determine if the viewer is a member of the *target* folder's scope —
|
|
218
|
+
// if so, breadcrumbs go all the way to the scope root as normal.
|
|
219
|
+
const scope = await resolveFolderScope(folderId);
|
|
220
|
+
if (scope) {
|
|
221
|
+
switch (scope.kind) {
|
|
222
|
+
case "CLASS": {
|
|
223
|
+
const c = await prisma.class.findFirst({
|
|
224
|
+
where: {
|
|
225
|
+
id: scope.classId,
|
|
226
|
+
OR: [
|
|
227
|
+
{ teachers: { some: { id: viewerId } } },
|
|
228
|
+
{ students: { some: { id: viewerId } } },
|
|
229
|
+
],
|
|
230
|
+
},
|
|
231
|
+
select: { id: true },
|
|
232
|
+
});
|
|
233
|
+
viewerScopeMember = Boolean(c);
|
|
234
|
+
if (!viewerScopeMember && scope.classId) {
|
|
235
|
+
const klass = await prisma.class.findUnique({
|
|
236
|
+
where: { id: scope.classId },
|
|
237
|
+
select: { schoolId: true },
|
|
238
|
+
});
|
|
239
|
+
if (klass?.schoolId) {
|
|
240
|
+
const m = await prisma.schoolMembership.findFirst({
|
|
241
|
+
where: {
|
|
242
|
+
schoolId: klass.schoolId,
|
|
243
|
+
userId: viewerId,
|
|
244
|
+
role: "ADMIN",
|
|
245
|
+
status: "ACTIVE",
|
|
246
|
+
},
|
|
247
|
+
select: { id: true },
|
|
248
|
+
});
|
|
249
|
+
viewerScopeMember = Boolean(m);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
case "SCHOOL_STORAGE": {
|
|
255
|
+
const m = await prisma.schoolMembership.findFirst({
|
|
256
|
+
where: {
|
|
257
|
+
schoolId: scope.schoolId,
|
|
258
|
+
userId: viewerId,
|
|
259
|
+
status: "ACTIVE",
|
|
260
|
+
},
|
|
261
|
+
select: { id: true },
|
|
262
|
+
});
|
|
263
|
+
viewerScopeMember = Boolean(m);
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
case "PERSONAL":
|
|
267
|
+
viewerScopeMember = scope.userId === viewerId;
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
while (currentId && visits < 64) {
|
|
273
|
+
const folder = await prisma.folder.findUnique({
|
|
274
|
+
where: { id: currentId },
|
|
275
|
+
select: { id: true, name: true, parentFolderId: true },
|
|
276
|
+
});
|
|
277
|
+
if (!folder)
|
|
278
|
+
break;
|
|
279
|
+
breadcrumbs.unshift({ id: folder.id, name: folder.name });
|
|
280
|
+
// Viewer-aware truncation: when the viewer is *not* a scope member but
|
|
281
|
+
// is a grantee, stop at the highest granted ancestor (we walk up one
|
|
282
|
+
// more step into the granted folder, then stop there).
|
|
283
|
+
if (viewerId &&
|
|
284
|
+
!viewerScopeMember &&
|
|
285
|
+
viewerGrantedFolderIds &&
|
|
286
|
+
viewerGrantedFolderIds.has(folder.id)) {
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
currentId = folder.parentFolderId;
|
|
290
|
+
visits += 1;
|
|
291
|
+
}
|
|
292
|
+
return breadcrumbs;
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=cloudStorage.js.map
|
|
295
|
+
//# debugId=26810bf7-c72f-5655-8994-96075d84b6fe
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudStorage.js","sources":["models/cloudStorage.ts"],"sourceRoot":"/","sourcesContent":["/**\n * CloudStorage model — scope-aware folder helpers used by the institution and\n * personal cloud storage UI. Sits on top of the same Folder/File tables that\n * back class folders, but adds scope (school/personal) and ownership semantics.\n */\nimport type { FolderScope } from \"@prisma/client\";\nimport { prisma } from \"../lib/prisma.js\";\n\nexport type CloudScope =\n | { kind: \"CLASS\"; classId: string }\n | { kind: \"SCHOOL_STORAGE\"; schoolId: string }\n | { kind: \"PERSONAL\"; userId: string };\n\nconst folderSelect = {\n id: true,\n name: true,\n color: true,\n scope: true,\n classId: true,\n schoolStorageId: true,\n personalOwnerId: true,\n parentFolderId: true,\n} as const;\n\nexport async function findOrCreateScopeRoot(scope: CloudScope) {\n switch (scope.kind) {\n case \"CLASS\": {\n let root = await prisma.folder.findFirst({\n where: { classId: scope.classId, parentFolderId: null },\n });\n if (!root) {\n root = await prisma.folder.create({\n data: {\n name: \"Class Files\",\n scope: \"CLASS\" as FolderScope,\n class: { connect: { id: scope.classId } },\n },\n });\n } else if (root.scope !== \"CLASS\") {\n root = await prisma.folder.update({\n where: { id: root.id },\n data: { scope: \"CLASS\" as FolderScope },\n });\n }\n return root;\n }\n case \"SCHOOL_STORAGE\": {\n let root = await prisma.folder.findFirst({\n where: { schoolStorageId: scope.schoolId },\n });\n if (!root) {\n root = await prisma.folder.create({\n data: {\n name: \"Cloud Storage\",\n scope: \"SCHOOL_STORAGE\" as FolderScope,\n schoolStorage: { connect: { id: scope.schoolId } },\n },\n });\n }\n return root;\n }\n case \"PERSONAL\": {\n let root = await prisma.folder.findFirst({\n where: { personalOwnerId: scope.userId },\n });\n if (!root) {\n root = await prisma.folder.create({\n data: {\n name: \"My Files\",\n scope: \"PERSONAL\" as FolderScope,\n personalOwner: { connect: { id: scope.userId } },\n },\n });\n }\n return root;\n }\n }\n}\n\n/**\n * Walk up the folder tree until we reach a root with a scope owner. Used to\n * permission-check sub-folders (which only carry a parentFolderId).\n */\nexport async function resolveFolderScope(\n folderId: string\n): Promise<CloudScope | null> {\n let currentId: string | null = folderId;\n let visits = 0;\n while (currentId && visits < 64) {\n const folder = await prisma.folder.findUnique({\n where: { id: currentId },\n select: folderSelect,\n });\n if (!folder) return null;\n if (folder.classId) return { kind: \"CLASS\", classId: folder.classId };\n if (folder.schoolStorageId)\n return { kind: \"SCHOOL_STORAGE\", schoolId: folder.schoolStorageId };\n if (folder.personalOwnerId)\n return { kind: \"PERSONAL\", userId: folder.personalOwnerId };\n if (!folder.parentFolderId) return null;\n currentId = folder.parentFolderId;\n visits += 1;\n }\n return null;\n}\n\nconst fileSelect = {\n id: true,\n name: true,\n type: true,\n size: true,\n path: true,\n uploadedAt: true,\n user: { select: { id: true, username: true } },\n} as const;\n\nconst childFolderSelect = {\n id: true,\n name: true,\n color: true,\n _count: { select: { files: true, childFolders: true } },\n} as const;\n\nexport function findFolderWithContents(folderId: string) {\n return prisma.folder.findFirst({\n where: { id: folderId },\n include: {\n files: {\n where: { uploadStatus: \"COMPLETED\" },\n select: fileSelect,\n orderBy: { uploadedAt: \"desc\" },\n },\n childFolders: {\n select: childFolderSelect,\n orderBy: { name: \"asc\" },\n },\n parentFolder: { select: { id: true, name: true } },\n },\n });\n}\n\nexport function createSubFolder(data: {\n name: string;\n parentFolderId: string;\n color?: string;\n}) {\n return prisma.folder.create({\n data: {\n name: data.name,\n color: data.color,\n parentFolder: { connect: { id: data.parentFolderId } },\n },\n select: folderSelect,\n });\n}\n\nexport function findFolderById(folderId: string) {\n return prisma.folder.findUnique({\n where: { id: folderId },\n select: folderSelect,\n });\n}\n\nexport function deleteFolderById(folderId: string) {\n return prisma.folder.delete({ where: { id: folderId } });\n}\n\nexport function renameFolder(folderId: string, name: string, color?: string) {\n return prisma.folder.update({\n where: { id: folderId },\n data: {\n name,\n ...(color ? { color } : {}),\n },\n select: folderSelect,\n });\n}\n\n/**\n * Build the breadcrumb chain for a folder.\n *\n * Without `viewerId`: walks all the way up to the scope root (owner-style\n * view).\n *\n * With `viewerId`: walks up but stops at the highest folder the viewer is\n * actually granted on, OR at the scope root if the viewer is a scope member.\n * This is the Drive-style \"Shared with me\" behavior — a grantee never sees\n * ancestor folders they weren't shared on. The result for a grantee browsing\n * `Owner/PrivateA/SharedB/C` (granted on B) reads `SharedB / C` — the ancestor\n * `PrivateA` is correctly hidden.\n */\nexport async function listFolderBreadcrumbs(\n folderId: string,\n viewerId?: string\n) {\n const breadcrumbs: { id: string; name: string }[] = [];\n let currentId: string | null = folderId;\n let visits = 0;\n\n let viewerGrantedFolderIds: Set<string> | null = null;\n let viewerScopeMember = false;\n\n if (viewerId) {\n const grants = await prisma.permission.findMany({\n where: {\n OR: [\n { principalType: \"USER\", userId: viewerId },\n {\n principalType: \"TAG\",\n tag: { users: { some: { id: viewerId } } },\n },\n {\n principalType: \"CLASS\",\n class: {\n OR: [\n { teachers: { some: { id: viewerId } } },\n { students: { some: { id: viewerId } } },\n ],\n },\n },\n {\n principalType: \"CLASS_TEACHERS\",\n class: { teachers: { some: { id: viewerId } } },\n },\n {\n principalType: \"CLASS_STUDENTS\",\n class: { students: { some: { id: viewerId } } },\n },\n {\n principalType: \"DEPARTMENT\",\n department: { members: { some: { id: viewerId } } },\n },\n {\n principalType: \"SCHOOL\",\n school: {\n memberships: { some: { userId: viewerId, status: \"ACTIVE\" } },\n },\n },\n ],\n },\n select: { folderId: true },\n });\n viewerGrantedFolderIds = new Set(\n grants.map((g) => g.folderId).filter((x): x is string => Boolean(x))\n );\n\n // Determine if the viewer is a member of the *target* folder's scope —\n // if so, breadcrumbs go all the way to the scope root as normal.\n const scope = await resolveFolderScope(folderId);\n if (scope) {\n switch (scope.kind) {\n case \"CLASS\": {\n const c = await prisma.class.findFirst({\n where: {\n id: scope.classId,\n OR: [\n { teachers: { some: { id: viewerId } } },\n { students: { some: { id: viewerId } } },\n ],\n },\n select: { id: true },\n });\n viewerScopeMember = Boolean(c);\n if (!viewerScopeMember && scope.classId) {\n const klass = await prisma.class.findUnique({\n where: { id: scope.classId },\n select: { schoolId: true },\n });\n if (klass?.schoolId) {\n const m = await prisma.schoolMembership.findFirst({\n where: {\n schoolId: klass.schoolId,\n userId: viewerId,\n role: \"ADMIN\",\n status: \"ACTIVE\",\n },\n select: { id: true },\n });\n viewerScopeMember = Boolean(m);\n }\n }\n break;\n }\n case \"SCHOOL_STORAGE\": {\n const m = await prisma.schoolMembership.findFirst({\n where: {\n schoolId: scope.schoolId,\n userId: viewerId,\n status: \"ACTIVE\",\n },\n select: { id: true },\n });\n viewerScopeMember = Boolean(m);\n break;\n }\n case \"PERSONAL\":\n viewerScopeMember = scope.userId === viewerId;\n break;\n }\n }\n }\n\n while (currentId && visits < 64) {\n const folder = await prisma.folder.findUnique({\n where: { id: currentId },\n select: { id: true, name: true, parentFolderId: true },\n });\n if (!folder) break;\n breadcrumbs.unshift({ id: folder.id, name: folder.name });\n\n // Viewer-aware truncation: when the viewer is *not* a scope member but\n // is a grantee, stop at the highest granted ancestor (we walk up one\n // more step into the granted folder, then stop there).\n if (\n viewerId &&\n !viewerScopeMember &&\n viewerGrantedFolderIds &&\n viewerGrantedFolderIds.has(folder.id)\n ) {\n break;\n }\n\n currentId = folder.parentFolderId;\n visits += 1;\n }\n return breadcrumbs;\n}\n"],"names":[],"mappings":"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","debug_id":"26810bf7-c72f-5655-8994-96075d84b6fe"}
|
package/dist/models/comment.d.ts
CHANGED
|
@@ -214,9 +214,6 @@ export declare function findCommentWithContext(commentId: string): import(".pris
|
|
|
214
214
|
assignment: {
|
|
215
215
|
class: {
|
|
216
216
|
school: {
|
|
217
|
-
users: {
|
|
218
|
-
id: string;
|
|
219
|
-
}[];
|
|
220
217
|
memberships: {
|
|
221
218
|
userId: string;
|
|
222
219
|
}[];
|
|
@@ -234,9 +231,6 @@ export declare function findCommentWithContext(commentId: string): import(".pris
|
|
|
234
231
|
assignment: {
|
|
235
232
|
class: {
|
|
236
233
|
school: {
|
|
237
|
-
users: {
|
|
238
|
-
id: string;
|
|
239
|
-
}[];
|
|
240
234
|
memberships: {
|
|
241
235
|
userId: string;
|
|
242
236
|
}[];
|
|
@@ -255,9 +249,6 @@ export declare function findCommentWithContext(commentId: string): import(".pris
|
|
|
255
249
|
announcement: {
|
|
256
250
|
class: {
|
|
257
251
|
school: {
|
|
258
|
-
users: {
|
|
259
|
-
id: string;
|
|
260
|
-
}[];
|
|
261
252
|
memberships: {
|
|
262
253
|
userId: string;
|
|
263
254
|
}[];
|
|
@@ -278,9 +269,6 @@ export declare function findCommentWithContext(commentId: string): import(".pris
|
|
|
278
269
|
assignment: {
|
|
279
270
|
class: {
|
|
280
271
|
school: {
|
|
281
|
-
users: {
|
|
282
|
-
id: string;
|
|
283
|
-
}[];
|
|
284
272
|
memberships: {
|
|
285
273
|
userId: string;
|
|
286
274
|
}[];
|
|
@@ -302,9 +290,6 @@ export declare function findCommentWithContext(commentId: string): import(".pris
|
|
|
302
290
|
assignment: {
|
|
303
291
|
class: {
|
|
304
292
|
school: {
|
|
305
|
-
users: {
|
|
306
|
-
id: string;
|
|
307
|
-
}[];
|
|
308
293
|
memberships: {
|
|
309
294
|
userId: string;
|
|
310
295
|
}[];
|
|
@@ -322,9 +307,6 @@ export declare function findCommentWithContext(commentId: string): import(".pris
|
|
|
322
307
|
assignment: {
|
|
323
308
|
class: {
|
|
324
309
|
school: {
|
|
325
|
-
users: {
|
|
326
|
-
id: string;
|
|
327
|
-
}[];
|
|
328
310
|
memberships: {
|
|
329
311
|
userId: string;
|
|
330
312
|
}[];
|
|
@@ -343,9 +325,6 @@ export declare function findCommentWithContext(commentId: string): import(".pris
|
|
|
343
325
|
announcement: {
|
|
344
326
|
class: {
|
|
345
327
|
school: {
|
|
346
|
-
users: {
|
|
347
|
-
id: string;
|
|
348
|
-
}[];
|
|
349
328
|
memberships: {
|
|
350
329
|
userId: string;
|
|
351
330
|
}[];
|
|
@@ -366,9 +345,6 @@ export declare function findCommentWithContext(commentId: string): import(".pris
|
|
|
366
345
|
assignment: {
|
|
367
346
|
class: {
|
|
368
347
|
school: {
|
|
369
|
-
users: {
|
|
370
|
-
id: string;
|
|
371
|
-
}[];
|
|
372
348
|
memberships: {
|
|
373
349
|
userId: string;
|
|
374
350
|
}[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comment.d.ts","sourceRoot":"/","sources":["models/comment.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwChB,CAAC;
|
|
1
|
+
{"version":3,"file":"comment.d.ts","sourceRoot":"/","sources":["models/comment.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwChB,CAAC;AAmBX,wDAAwD;AACxD,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAKzC;AAED,qCAAqC;AACrC,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;MAmBvD;AAED,gCAAgC;AAChC,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,yBAAyB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3C;;;;;;;;;;;;;;;;;GAIA;AAED,6CAA6C;AAC7C,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;;;;;;;;;;;;;GAM7E;AAED,2CAA2C;AAC3C,wBAAgB,cAAc,CAAC,IAAI,EAAE;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;;;;;;;;;;;;;;;;;;;;;;;GA0BA;AAED,yBAAyB;AACzB,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;;GAI5C;AAED,kDAAkD;AAClD,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;GAO5D;AAED,wEAAwE;AACxE,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwGvD;AAED,sDAAsD;AACtD,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,MAAM;;;;;;;;GAM7D"}
|
package/dist/models/comment.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Comment model – comments, replies, and reactions.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
5
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="8dbc1c18-53a6-535e-8af0-25c781796a36")}catch(e){}}();
|
|
6
6
|
import { prisma } from "../lib/prisma.js";
|
|
7
7
|
export const commentSelect = {
|
|
8
8
|
id: true,
|
|
@@ -51,10 +51,6 @@ const commentClassAuthSelect = {
|
|
|
51
51
|
students: { select: { id: true } },
|
|
52
52
|
school: {
|
|
53
53
|
select: {
|
|
54
|
-
users: {
|
|
55
|
-
where: { role: "ADMIN" },
|
|
56
|
-
select: { id: true },
|
|
57
|
-
},
|
|
58
54
|
memberships: {
|
|
59
55
|
where: {
|
|
60
56
|
role: "ADMIN",
|
|
@@ -265,4 +261,4 @@ export function getReactionCountsByCommentId(commentId) {
|
|
|
265
261
|
});
|
|
266
262
|
}
|
|
267
263
|
//# sourceMappingURL=comment.js.map
|
|
268
|
-
//# debugId=
|
|
264
|
+
//# debugId=8dbc1c18-53a6-535e-8af0-25c781796a36
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comment.js","sources":["models/comment.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Comment model – comments, replies, and reactions.\n */\nimport { prisma } from \"../lib/prisma.js\";\nimport type { ReactionType } from \"@prisma/client\";\n\nexport const commentSelect = {\n id: true,\n content: true,\n announcementId: true,\n assignmentId: true,\n submissionId: true,\n parentCommentId: true,\n createdAt: true,\n modifiedAt: true,\n author: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n },\n },\n },\n },\n reactions: {\n select: {\n type: true,\n user: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n },\n },\n },\n },\n },\n },\n} as const;\n\nconst commentClassAuthSelect = {\n id: true,\n teachers: { select: { id: true } },\n students: { select: { id: true } },\n school: {\n select: {\n users: {\n where: { role: \"ADMIN\" as const },\n select: { id: true },\n },\n memberships: {\n where: {\n role: \"ADMIN\" as const,\n status: \"ACTIVE\" as const,\n },\n select: { userId: true },\n },\n },\n },\n} as const;\n\n/** @returns Comment by ID with author and reactions. */\nexport function findCommentById(id: string) {\n return prisma.comment.findUnique({\n where: { id },\n select: commentSelect,\n });\n}\n\n/** @returns Replies to a comment. */\nexport function findRepliesByCommentId(commentId: string) {\n return prisma.comment.findMany({\n where: { parentCommentId: commentId },\n include: {\n author: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n },\n },\n },\n },\n },\n });\n}\n\n/** Create a comment (reply). */\nexport function createComment(data: {\n parentCommentId: string;\n content: string;\n authorId: string;\n announcementId?: string | null;\n assignmentId?: string | null;\n submissionId?: string | null;\n studentQuestionProgressId?: string | null;\n}) {\n return prisma.comment.create({\n data,\n });\n}\n\n/** @returns User's reaction on a comment. */\nexport function findReactionByUserAndComment(userId: string, commentId: string) {\n return prisma.reaction.findUnique({\n where: {\n userId_commentId: { userId, commentId },\n },\n });\n}\n\n/** Add or update reaction on a comment. */\nexport function upsertReaction(data: {\n userId: string;\n commentId: string;\n type: string;\n}) {\n return prisma.reaction.upsert({\n where: {\n userId_commentId: {\n userId: data.userId,\n commentId: data.commentId,\n },\n },\n update: { type: data.type as ReactionType },\n create: { ...data, type: data.type as ReactionType },\n include: {\n user: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n },\n },\n },\n },\n },\n });\n}\n\n/** Delete a reaction. */\nexport function deleteReactionById(id: string) {\n return prisma.reaction.delete({\n where: { id },\n });\n}\n\n/** @returns Comment with announcement classId. */\nexport function findCommentWithAnnouncement(commentId: string) {\n return prisma.comment.findUnique({\n where: { id: commentId },\n include: {\n announcement: { select: { classId: true } },\n },\n });\n}\n\n/** @returns Comment with the owning class context for authorization. */\nexport function findCommentWithContext(commentId: string) {\n return prisma.comment.findUnique({\n where: { id: commentId },\n include: {\n announcement: {\n select: {\n class: {\n select: commentClassAuthSelect,\n },\n },\n },\n assignment: {\n select: {\n class: {\n select: commentClassAuthSelect,\n },\n },\n },\n submission: {\n select: {\n studentId: true,\n assignment: {\n select: {\n class: {\n select: commentClassAuthSelect,\n },\n },\n },\n },\n },\n studentQuestionProgress: {\n select: {\n studentId: true,\n studentWorksheetResponse: {\n select: {\n submission: {\n select: {\n studentId: true,\n assignment: {\n select: {\n class: {\n select: commentClassAuthSelect,\n },\n },\n },\n },\n },\n },\n },\n },\n },\n parentComment: {\n include: {\n announcement: {\n select: {\n class: {\n select: commentClassAuthSelect,\n },\n },\n },\n assignment: {\n select: {\n class: {\n select: commentClassAuthSelect,\n },\n },\n },\n submission: {\n select: {\n studentId: true,\n assignment: {\n select: {\n class: {\n select: commentClassAuthSelect,\n },\n },\n },\n },\n },\n studentQuestionProgress: {\n select: {\n studentId: true,\n studentWorksheetResponse: {\n select: {\n submission: {\n select: {\n studentId: true,\n assignment: {\n select: {\n class: {\n select: commentClassAuthSelect,\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n });\n}\n\n/** @returns Reaction counts by type for a comment. */\nexport function getReactionCountsByCommentId(commentId: string) {\n return prisma.reaction.groupBy({\n by: [\"type\"],\n where: { commentId },\n _count: { type: true },\n });\n}\n"],"names":[],"mappings":"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","debug_id":"4e10262a-c8cd-5388-9b97-3cf8d34902b6"}
|
|
1
|
+
{"version":3,"file":"comment.js","sources":["models/comment.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Comment model – comments, replies, and reactions.\n */\nimport { prisma } from \"../lib/prisma.js\";\nimport type { ReactionType } from \"@prisma/client\";\n\nexport const commentSelect = {\n id: true,\n content: true,\n announcementId: true,\n assignmentId: true,\n submissionId: true,\n parentCommentId: true,\n createdAt: true,\n modifiedAt: true,\n author: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n },\n },\n },\n },\n reactions: {\n select: {\n type: true,\n user: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n },\n },\n },\n },\n },\n },\n} as const;\n\nconst commentClassAuthSelect = {\n id: true,\n teachers: { select: { id: true } },\n students: { select: { id: true } },\n school: {\n select: {\n memberships: {\n where: {\n role: \"ADMIN\" as const,\n status: \"ACTIVE\" as const,\n },\n select: { userId: true },\n },\n },\n },\n} as const;\n\n/** @returns Comment by ID with author and reactions. */\nexport function findCommentById(id: string) {\n return prisma.comment.findUnique({\n where: { id },\n select: commentSelect,\n });\n}\n\n/** @returns Replies to a comment. */\nexport function findRepliesByCommentId(commentId: string) {\n return prisma.comment.findMany({\n where: { parentCommentId: commentId },\n include: {\n author: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n },\n },\n },\n },\n },\n });\n}\n\n/** Create a comment (reply). */\nexport function createComment(data: {\n parentCommentId: string;\n content: string;\n authorId: string;\n announcementId?: string | null;\n assignmentId?: string | null;\n submissionId?: string | null;\n studentQuestionProgressId?: string | null;\n}) {\n return prisma.comment.create({\n data,\n });\n}\n\n/** @returns User's reaction on a comment. */\nexport function findReactionByUserAndComment(userId: string, commentId: string) {\n return prisma.reaction.findUnique({\n where: {\n userId_commentId: { userId, commentId },\n },\n });\n}\n\n/** Add or update reaction on a comment. */\nexport function upsertReaction(data: {\n userId: string;\n commentId: string;\n type: string;\n}) {\n return prisma.reaction.upsert({\n where: {\n userId_commentId: {\n userId: data.userId,\n commentId: data.commentId,\n },\n },\n update: { type: data.type as ReactionType },\n create: { ...data, type: data.type as ReactionType },\n include: {\n user: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n },\n },\n },\n },\n },\n });\n}\n\n/** Delete a reaction. */\nexport function deleteReactionById(id: string) {\n return prisma.reaction.delete({\n where: { id },\n });\n}\n\n/** @returns Comment with announcement classId. */\nexport function findCommentWithAnnouncement(commentId: string) {\n return prisma.comment.findUnique({\n where: { id: commentId },\n include: {\n announcement: { select: { classId: true } },\n },\n });\n}\n\n/** @returns Comment with the owning class context for authorization. */\nexport function findCommentWithContext(commentId: string) {\n return prisma.comment.findUnique({\n where: { id: commentId },\n include: {\n announcement: {\n select: {\n class: {\n select: commentClassAuthSelect,\n },\n },\n },\n assignment: {\n select: {\n class: {\n select: commentClassAuthSelect,\n },\n },\n },\n submission: {\n select: {\n studentId: true,\n assignment: {\n select: {\n class: {\n select: commentClassAuthSelect,\n },\n },\n },\n },\n },\n studentQuestionProgress: {\n select: {\n studentId: true,\n studentWorksheetResponse: {\n select: {\n submission: {\n select: {\n studentId: true,\n assignment: {\n select: {\n class: {\n select: commentClassAuthSelect,\n },\n },\n },\n },\n },\n },\n },\n },\n },\n parentComment: {\n include: {\n announcement: {\n select: {\n class: {\n select: commentClassAuthSelect,\n },\n },\n },\n assignment: {\n select: {\n class: {\n select: commentClassAuthSelect,\n },\n },\n },\n submission: {\n select: {\n studentId: true,\n assignment: {\n select: {\n class: {\n select: commentClassAuthSelect,\n },\n },\n },\n },\n },\n studentQuestionProgress: {\n select: {\n studentId: true,\n studentWorksheetResponse: {\n select: {\n submission: {\n select: {\n studentId: true,\n assignment: {\n select: {\n class: {\n select: commentClassAuthSelect,\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n });\n}\n\n/** @returns Reaction counts by type for a comment. */\nexport function getReactionCountsByCommentId(commentId: string) {\n return prisma.reaction.groupBy({\n by: [\"type\"],\n where: { commentId },\n _count: { type: true },\n });\n}\n"],"names":[],"mappings":"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","debug_id":"8dbc1c18-53a6-535e-8af0-25c781796a36"}
|
|
@@ -4,42 +4,42 @@ export declare function findConversationsByUserId(userId: string): import(".pris
|
|
|
4
4
|
id: string;
|
|
5
5
|
title: string;
|
|
6
6
|
} | null;
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
members: ({
|
|
8
|
+
user: {
|
|
9
9
|
id: string;
|
|
10
10
|
username: string;
|
|
11
11
|
profile: {
|
|
12
12
|
displayName: string | null;
|
|
13
|
+
profilePicture: string | null;
|
|
13
14
|
} | null;
|
|
14
15
|
};
|
|
15
16
|
} & {
|
|
16
|
-
status: import(".prisma/client").$Enums.JobStatus | null;
|
|
17
|
-
meta: import("@prisma/client/runtime/library.js").JsonValue | null;
|
|
18
17
|
id: string;
|
|
19
|
-
|
|
18
|
+
userId: string;
|
|
19
|
+
role: import(".prisma/client").$Enums.ConversationRole;
|
|
20
20
|
conversationId: string;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
joinedAt: Date;
|
|
22
|
+
hiddenAt: Date | null;
|
|
23
|
+
lastViewedAt: Date | null;
|
|
24
|
+
lastViewedMentionAt: Date | null;
|
|
24
25
|
})[];
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
messages: ({
|
|
27
|
+
sender: {
|
|
27
28
|
id: string;
|
|
28
29
|
username: string;
|
|
29
30
|
profile: {
|
|
30
31
|
displayName: string | null;
|
|
31
|
-
profilePicture: string | null;
|
|
32
32
|
} | null;
|
|
33
33
|
};
|
|
34
34
|
} & {
|
|
35
|
+
status: import(".prisma/client").$Enums.JobStatus | null;
|
|
36
|
+
meta: import("@prisma/client/runtime/library.js").JsonValue | null;
|
|
35
37
|
id: string;
|
|
36
|
-
|
|
37
|
-
userId: string;
|
|
38
|
+
createdAt: Date;
|
|
38
39
|
conversationId: string;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
lastViewedMentionAt: Date | null;
|
|
40
|
+
content: string;
|
|
41
|
+
senderId: string;
|
|
42
|
+
runJobId: string | null;
|
|
43
43
|
})[];
|
|
44
44
|
} & {
|
|
45
45
|
type: import(".prisma/client").$Enums.ConversationType;
|
|
@@ -118,8 +118,8 @@ export declare function createConversation(data: {
|
|
|
118
118
|
};
|
|
119
119
|
} & {
|
|
120
120
|
id: string;
|
|
121
|
-
role: import(".prisma/client").$Enums.ConversationRole;
|
|
122
121
|
userId: string;
|
|
122
|
+
role: import(".prisma/client").$Enums.ConversationRole;
|
|
123
123
|
conversationId: string;
|
|
124
124
|
joinedAt: Date;
|
|
125
125
|
hiddenAt: Date | null;
|
|
@@ -153,8 +153,8 @@ export declare function findConversationByIdAndMember(conversationId: string, us
|
|
|
153
153
|
};
|
|
154
154
|
} & {
|
|
155
155
|
id: string;
|
|
156
|
-
role: import(".prisma/client").$Enums.ConversationRole;
|
|
157
156
|
userId: string;
|
|
157
|
+
role: import(".prisma/client").$Enums.ConversationRole;
|
|
158
158
|
conversationId: string;
|
|
159
159
|
joinedAt: Date;
|
|
160
160
|
hiddenAt: Date | null;
|
|
@@ -182,8 +182,8 @@ export declare function createConversationMember(data: {
|
|
|
182
182
|
role: string;
|
|
183
183
|
}): import(".prisma/client").Prisma.Prisma__ConversationMemberClient<{
|
|
184
184
|
id: string;
|
|
185
|
-
role: import(".prisma/client").$Enums.ConversationRole;
|
|
186
185
|
userId: string;
|
|
186
|
+
role: import(".prisma/client").$Enums.ConversationRole;
|
|
187
187
|
conversationId: string;
|
|
188
188
|
joinedAt: Date;
|
|
189
189
|
hiddenAt: Date | null;
|
|
@@ -199,8 +199,8 @@ export declare function createConversationMember(data: {
|
|
|
199
199
|
/** Hide a conversation for a single member until new activity occurs. */
|
|
200
200
|
export declare function hideConversationMember(userId: string, conversationId: string): import(".prisma/client").Prisma.Prisma__ConversationMemberClient<{
|
|
201
201
|
id: string;
|
|
202
|
-
role: import(".prisma/client").$Enums.ConversationRole;
|
|
203
202
|
userId: string;
|
|
203
|
+
role: import(".prisma/client").$Enums.ConversationRole;
|
|
204
204
|
conversationId: string;
|
|
205
205
|
joinedAt: Date;
|
|
206
206
|
hiddenAt: Date | null;
|
|
@@ -216,8 +216,8 @@ export declare function hideConversationMember(userId: string, conversationId: s
|
|
|
216
216
|
/** Remove a member from a conversation. */
|
|
217
217
|
export declare function deleteConversationMember(userId: string, conversationId: string): import(".prisma/client").Prisma.Prisma__ConversationMemberClient<{
|
|
218
218
|
id: string;
|
|
219
|
-
role: import(".prisma/client").$Enums.ConversationRole;
|
|
220
219
|
userId: string;
|
|
220
|
+
role: import(".prisma/client").$Enums.ConversationRole;
|
|
221
221
|
conversationId: string;
|
|
222
222
|
joinedAt: Date;
|
|
223
223
|
hiddenAt: Date | null;
|