@headless-lms/server 0.4.0 → 0.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.
- package/README.md +14 -0
- package/dist/app/community-mail.d.ts +5 -3
- package/dist/app/community-mail.js +60 -12
- package/dist/app/community-mail.js.map +1 -1
- package/dist/app/container.d.ts +24 -3
- package/dist/app/container.js +102 -38
- package/dist/app/container.js.map +1 -1
- package/dist/app/notification-channels.js +1 -0
- package/dist/app/notification-channels.js.map +1 -1
- package/dist/app/notification-reads.d.ts +3 -3
- package/dist/app/notification-reads.js +7 -28
- package/dist/app/notification-reads.js.map +1 -1
- package/dist/app/platform.d.ts +14 -0
- package/dist/app/platform.js +14 -0
- package/dist/app/platform.js.map +1 -0
- package/dist/http/config.d.ts +4 -0
- package/dist/http/errors.js +9 -4
- package/dist/http/errors.js.map +1 -1
- package/dist/http/fastify.d.ts +8 -0
- package/dist/http/mcp/catalogue.d.ts +11 -9
- package/dist/http/mcp/catalogue.js +15 -21
- package/dist/http/mcp/catalogue.js.map +1 -1
- package/dist/http/mcp/challenge.js +3 -3
- package/dist/http/mcp/challenge.js.map +1 -1
- package/dist/http/mcp/route.js +7 -7
- package/dist/http/mcp/route.js.map +1 -1
- package/dist/http/mcp/test-support.d.ts +6 -5
- package/dist/http/mcp/test-support.js +32 -11
- package/dist/http/mcp/test-support.js.map +1 -1
- package/dist/http/mcp/tool.d.ts +3 -9
- package/dist/http/mcp/tool.js +14 -6
- package/dist/http/mcp/tool.js.map +1 -1
- package/dist/http/mcp/tools/automations.js +10 -20
- package/dist/http/mcp/tools/automations.js.map +1 -1
- package/dist/http/mcp/tools/catalog.js +25 -42
- package/dist/http/mcp/tools/catalog.js.map +1 -1
- package/dist/http/mcp/tools/comments.js +9 -19
- package/dist/http/mcp/tools/comments.js.map +1 -1
- package/dist/http/mcp/tools/communities.js +16 -31
- package/dist/http/mcp/tools/communities.js.map +1 -1
- package/dist/http/mcp/tools/community-members.js +9 -16
- package/dist/http/mcp/tools/community-members.js.map +1 -1
- package/dist/http/mcp/tools/community-moderation.js +13 -25
- package/dist/http/mcp/tools/community-moderation.js.map +1 -1
- package/dist/http/mcp/tools/courses.js +11 -21
- package/dist/http/mcp/tools/courses.js.map +1 -1
- package/dist/http/mcp/tools/events.d.ts +6 -0
- package/dist/http/mcp/tools/events.js +170 -0
- package/dist/http/mcp/tools/events.js.map +1 -0
- package/dist/http/mcp/tools/index.d.ts +5 -1
- package/dist/http/mcp/tools/index.js +45 -10
- package/dist/http/mcp/tools/index.js.map +1 -1
- package/dist/http/mcp/tools/organization.d.ts +6 -0
- package/dist/http/mcp/tools/organization.js +214 -0
- package/dist/http/mcp/tools/organization.js.map +1 -0
- package/dist/http/mcp/tools/people.js +30 -49
- package/dist/http/mcp/tools/people.js.map +1 -1
- package/dist/http/plugins/auth.js +37 -8
- package/dist/http/plugins/auth.js.map +1 -1
- package/dist/http/plugins/error-handler.d.ts +5 -1
- package/dist/http/plugins/error-handler.js +10 -2
- package/dist/http/plugins/error-handler.js.map +1 -1
- package/dist/http/plugins/openapi.js +18 -2
- package/dist/http/plugins/openapi.js.map +1 -1
- package/dist/http/plugins/platform.d.ts +7 -0
- package/dist/http/plugins/platform.js +13 -0
- package/dist/http/plugins/platform.js.map +1 -0
- package/dist/http/routes/access.js +54 -36
- package/dist/http/routes/access.js.map +1 -1
- package/dist/http/routes/activities.js +45 -45
- package/dist/http/routes/activities.js.map +1 -1
- package/dist/http/routes/assets.js +30 -65
- package/dist/http/routes/assets.js.map +1 -1
- package/dist/http/routes/automations.js +37 -42
- package/dist/http/routes/automations.js.map +1 -1
- package/dist/http/routes/bundles.js +33 -36
- package/dist/http/routes/bundles.js.map +1 -1
- package/dist/http/routes/communities.js +93 -145
- package/dist/http/routes/communities.js.map +1 -1
- package/dist/http/routes/community-moderation.js +83 -137
- package/dist/http/routes/community-moderation.js.map +1 -1
- package/dist/http/routes/course-analytics.js +32 -15
- package/dist/http/routes/course-analytics.js.map +1 -1
- package/dist/http/routes/courses.js +25 -32
- package/dist/http/routes/courses.js.map +1 -1
- package/dist/http/routes/dashboard.js +9 -9
- package/dist/http/routes/dashboard.js.map +1 -1
- package/dist/http/routes/discussion.js +21 -39
- package/dist/http/routes/discussion.js.map +1 -1
- package/dist/http/routes/downloads.js +41 -47
- package/dist/http/routes/downloads.js.map +1 -1
- package/dist/http/routes/entitlements.js +19 -23
- package/dist/http/routes/entitlements.js.map +1 -1
- package/dist/http/routes/events.d.ts +7 -0
- package/dist/http/routes/events.js +333 -0
- package/dist/http/routes/events.js.map +1 -0
- package/dist/http/routes/integrations.js +40 -73
- package/dist/http/routes/integrations.js.map +1 -1
- package/dist/http/routes/member/assets.js +10 -13
- package/dist/http/routes/member/assets.js.map +1 -1
- package/dist/http/routes/member/chats.js +170 -47
- package/dist/http/routes/member/chats.js.map +1 -1
- package/dist/http/routes/member/comments.js +65 -26
- package/dist/http/routes/member/comments.js.map +1 -1
- package/dist/http/routes/member/community.js +45 -52
- package/dist/http/routes/member/community.js.map +1 -1
- package/dist/http/routes/member/courses.js +12 -19
- package/dist/http/routes/member/courses.js.map +1 -1
- package/dist/http/routes/member/devices.js +9 -10
- package/dist/http/routes/member/devices.js.map +1 -1
- package/dist/http/routes/member/downloads.js +6 -9
- package/dist/http/routes/member/downloads.js.map +1 -1
- package/dist/http/routes/member/events.d.ts +7 -0
- package/dist/http/routes/member/events.js +386 -0
- package/dist/http/routes/member/events.js.map +1 -0
- package/dist/http/routes/member/files.js +71 -46
- package/dist/http/routes/member/files.js.map +1 -1
- package/dist/http/routes/member/index.js +2 -0
- package/dist/http/routes/member/index.js.map +1 -1
- package/dist/http/routes/member/notification-settings.js +15 -23
- package/dist/http/routes/member/notification-settings.js.map +1 -1
- package/dist/http/routes/member/notifications.js +16 -16
- package/dist/http/routes/member/notifications.js.map +1 -1
- package/dist/http/routes/member/org.js +5 -15
- package/dist/http/routes/member/org.js.map +1 -1
- package/dist/http/routes/member/posts.js +67 -68
- package/dist/http/routes/member/posts.js.map +1 -1
- package/dist/http/routes/member/profile.js +15 -6
- package/dist/http/routes/member/profile.js.map +1 -1
- package/dist/http/routes/member/progress.js +7 -11
- package/dist/http/routes/member/progress.js.map +1 -1
- package/dist/http/routes/organizations.js +319 -135
- package/dist/http/routes/organizations.js.map +1 -1
- package/dist/http/routes/platform.d.ts +7 -0
- package/dist/http/routes/platform.js +61 -0
- package/dist/http/routes/platform.js.map +1 -0
- package/dist/http/routes/students.js +12 -75
- package/dist/http/routes/students.js.map +1 -1
- package/dist/http/routes/webhooks.js +30 -39
- package/dist/http/routes/webhooks.js.map +1 -1
- package/dist/http/routes.js +9 -0
- package/dist/http/routes.js.map +1 -1
- package/dist/http/schemas/access.d.ts +346 -64
- package/dist/http/schemas/access.js +39 -12
- package/dist/http/schemas/access.js.map +1 -1
- package/dist/http/schemas/assets.d.ts +19 -14
- package/dist/http/schemas/assets.js +6 -5
- package/dist/http/schemas/assets.js.map +1 -1
- package/dist/http/schemas/automations.d.ts +4 -4
- package/dist/http/schemas/chats.d.ts +211 -32
- package/dist/http/schemas/chats.js +13 -4
- package/dist/http/schemas/chats.js.map +1 -1
- package/dist/http/schemas/community.d.ts +91 -44
- package/dist/http/schemas/community.js +21 -8
- package/dist/http/schemas/community.js.map +1 -1
- package/dist/http/schemas/course-analytics.d.ts +51 -1
- package/dist/http/schemas/course-analytics.js +19 -1
- package/dist/http/schemas/course-analytics.js.map +1 -1
- package/dist/http/schemas/dashboard.d.ts +1 -0
- package/dist/http/schemas/dashboard.js +2 -1
- package/dist/http/schemas/dashboard.js.map +1 -1
- package/dist/http/schemas/discussion.d.ts +22 -72
- package/dist/http/schemas/discussion.js +2 -2
- package/dist/http/schemas/discussion.js.map +1 -1
- package/dist/http/schemas/entitlements.d.ts +9 -12
- package/dist/http/schemas/entitlements.js +11 -5
- package/dist/http/schemas/entitlements.js.map +1 -1
- package/dist/http/schemas/events.d.ts +527 -0
- package/dist/http/schemas/events.js +64 -0
- package/dist/http/schemas/events.js.map +1 -0
- package/dist/http/schemas/files.d.ts +15 -5
- package/dist/http/schemas/files.js +10 -2
- package/dist/http/schemas/files.js.map +1 -1
- package/dist/http/schemas/index.d.ts +11 -9
- package/dist/http/schemas/index.js +11 -9
- package/dist/http/schemas/integrations.d.ts +4 -4
- package/dist/http/schemas/invites.d.ts +3 -47
- package/dist/http/schemas/invites.js +4 -25
- package/dist/http/schemas/invites.js.map +1 -1
- package/dist/http/schemas/member.d.ts +94 -7
- package/dist/http/schemas/member.js +7 -3
- package/dist/http/schemas/member.js.map +1 -1
- package/dist/http/schemas/members.d.ts +333 -69
- package/dist/http/schemas/members.js +67 -25
- package/dist/http/schemas/members.js.map +1 -1
- package/dist/http/schemas/notifications.d.ts +57 -53
- package/dist/http/schemas/platform.d.ts +37 -0
- package/dist/http/schemas/platform.js +19 -0
- package/dist/http/schemas/platform.js.map +1 -0
- package/dist/http/schemas/posts.d.ts +55 -35
- package/dist/http/schemas/posts.js +4 -4
- package/dist/http/schemas/posts.js.map +1 -1
- package/dist/http/schemas/profile.d.ts +1 -1
- package/dist/http/schemas/shared.d.ts +1 -11
- package/dist/http/schemas/shared.js +1 -10
- package/dist/http/schemas/shared.js.map +1 -1
- package/dist/http/schemas/students.d.ts +25 -3
- package/dist/http/schemas/students.js +3 -1
- package/dist/http/schemas/students.js.map +1 -1
- package/dist/http/scope.d.ts +9 -13
- package/dist/http/scope.js +29 -40
- package/dist/http/scope.js.map +1 -1
- package/dist/http/server.js +9 -0
- package/dist/http/server.js.map +1 -1
- package/dist/http/shutdown.d.ts +11 -0
- package/dist/http/shutdown.js +40 -0
- package/dist/http/shutdown.js.map +1 -0
- package/dist/http/sse.d.ts +19 -0
- package/dist/http/sse.js +104 -0
- package/dist/http/sse.js.map +1 -0
- package/dist/http/test-caller.d.ts +13 -0
- package/dist/http/test-caller.js +14 -0
- package/dist/http/test-caller.js.map +1 -0
- package/dist/http/well-known.js +2 -2
- package/dist/http/well-known.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/packages/server/package.js +1 -1
- package/package.json +7 -6
- package/dist/http/routes/member/actor.d.ts +0 -14
- package/dist/http/routes/member/actor.js +0 -11
- package/dist/http/routes/member/actor.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discussion.js","names":[],"sources":["../../../src/http/routes/discussion.ts"],"sourcesContent":["// Moderator-facing discussion routes. The learner surface (everything under\n// `/api/member`) lives in routes/member/comments.ts.\nimport type { FastifyInstance
|
|
1
|
+
{"version":3,"file":"discussion.js","names":[],"sources":["../../../src/http/routes/discussion.ts"],"sourcesContent":["// Moderator-facing discussion routes. The learner surface (everything under\n// `/api/member`) lives in routes/member/comments.ts.\nimport type { FastifyInstance } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport { z } from 'zod';\nimport {\n Comment,\n CommentIdParam,\n CommentsPage,\n CommentsQuery,\n CommentView,\n PatchComment,\n ReplyToComment,\n refusals,\n} from '../schemas/index.js';\nimport type { Container } from '../../app/container.js';\nimport { resolveActor } from '../scope.js';\n\nexport async function discussionRoutes(app: FastifyInstance, container: Container): Promise<void> {\n const r = app.withTypeProvider<ZodTypeProvider>();\n const discussion = container.discussion;\n\n r.route({\n method: 'GET',\n url: '/api/comments',\n schema: {\n operationId: 'listComments',\n tags: ['Discussion'],\n summary: 'List course comments for moderation',\n description: `Requires \\`courses:moderate\\`. Comments on the activities of the courses you moderate, filtered by course, activity, author, status or open reports; each row carries the author's email and the open reports.`,\n querystring: CommentsQuery,\n response: { 200: CommentsPage, ...refusals(403) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return discussion.listComments(req.query, actor);\n },\n });\n\n r.route({\n method: 'DELETE',\n url: '/api/comments/:commentId',\n schema: {\n operationId: 'moderateRemoveComment',\n tags: ['Discussion'],\n summary: 'Remove a course comment',\n description:\n 'Needs `courses:moderate` on the course, unless it is your own comment. Hides the comment and resolves its open reports as `removed`. Removing a removed comment returns it unchanged.',\n params: CommentIdParam,\n response: { 200: CommentView, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return discussion.remove(req.params.commentId, 'lesson', actor);\n },\n });\n\n r.route({\n method: 'PATCH',\n url: '/api/comments/:commentId',\n schema: {\n operationId: 'publishComment',\n tags: ['Discussion'],\n summary: 'Publish a course comment',\n description:\n 'Needs `courses:moderate` on the course. Approves a pending comment or restores a removed one; a published comment is returned unchanged.',\n params: CommentIdParam,\n body: PatchComment,\n response: { 200: Comment, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return discussion.publish(req.params.commentId, 'lesson', actor);\n },\n });\n\n r.route({\n method: 'DELETE',\n url: '/api/comments/:commentId/reports',\n schema: {\n operationId: 'dismissCommentReports',\n tags: ['Discussion'],\n summary: 'Dismiss every open report on a course comment',\n description: 'Needs `courses:moderate` on the course. The comment stays up.',\n params: CommentIdParam,\n response: { 204: z.void(), ...refusals(403, 404) },\n },\n handler: async (req, reply) => {\n const actor = await resolveActor(container, req);\n await discussion.resolveReports(req.params.commentId, 'lesson', actor);\n return reply.code(204).send();\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/comments/:commentId/replies',\n schema: {\n operationId: 'replyToComment',\n tags: ['Discussion'],\n summary: 'Reply to a course comment from the moderation queue',\n description: `Requires \\`courses:moderate\\`. Needed on the comment's course. Replies nest one level: answering a reply attaches to its root comment.`,\n params: CommentIdParam,\n body: ReplyToComment,\n response: { 200: CommentView, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return discussion.replyToComment(req.params.commentId, req.body.body, actor);\n },\n });\n}\n"],"mappings":";;;;;;AAkBA,eAAsB,iBAAiB,KAAsB,WAAqC;CAChG,MAAM,IAAI,IAAI,iBAAkC;CAChD,MAAM,aAAa,UAAU;CAE7B,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,YAAY;GACnB,SAAS;GACT,aAAa;GACb,aAAa;GACb,UAAU;IAAE,KAAK;IAAc,GAAG,SAAS,GAAG;GAAE;EAClD;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,OAAO,WAAW,aAAa,IAAI,OAAO,KAAK;EACjD;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,YAAY;GACnB,SAAS;GACT,aACE;GACF,QAAQ;GACR,UAAU;IAAE,KAAK;IAAa,GAAG,SAAS,KAAK,GAAG;GAAE;EACtD;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,OAAO,WAAW,OAAO,IAAI,OAAO,WAAW,UAAU,KAAK;EAChE;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,YAAY;GACnB,SAAS;GACT,aACE;GACF,QAAQ;GACR,MAAM;GACN,UAAU;IAAE,KAAK;IAAS,GAAG,SAAS,KAAK,GAAG;GAAE;EAClD;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,OAAO,WAAW,QAAQ,IAAI,OAAO,WAAW,UAAU,KAAK;EACjE;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,YAAY;GACnB,SAAS;GACT,aAAa;GACb,QAAQ;GACR,UAAU;IAAE,KAAK,EAAE,KAAK;IAAG,GAAG,SAAS,KAAK,GAAG;GAAE;EACnD;EACA,SAAS,OAAO,KAAK,UAAU;GAC7B,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,MAAM,WAAW,eAAe,IAAI,OAAO,WAAW,UAAU,KAAK;GACrE,OAAO,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK;EAC9B;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,YAAY;GACnB,SAAS;GACT,aAAa;GACb,QAAQ;GACR,MAAM;GACN,UAAU;IAAE,KAAK;IAAa,GAAG,SAAS,KAAK,GAAG;GAAE;EACtD;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,OAAO,WAAW,eAAe,IAAI,OAAO,WAAW,IAAI,KAAK,MAAM,KAAK;EAC7E;CACF,CAAC;AACH"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { refusals } from "../schemas/shared.js";
|
|
2
|
-
import {
|
|
2
|
+
import { resolveActor } from "../scope.js";
|
|
3
3
|
import { AddDownloadAsset, CreateDownload, Download, DownloadAssetParams, DownloadFile, DownloadIdParam, DownloadsPage, DownloadsQuery, RenameDownloadAsset, ReorderDownloadAssets, UpdateDownload } from "../schemas/downloads.js";
|
|
4
4
|
import "../schemas/index.js";
|
|
5
5
|
import { z } from "zod";
|
|
6
|
-
import { NotFoundError } from "@headless-lms/core/shared/errors";
|
|
7
6
|
//#region src/http/routes/downloads.ts
|
|
8
7
|
async function downloadsRoutes(app, container) {
|
|
9
8
|
const r = app.withTypeProvider();
|
|
@@ -15,8 +14,8 @@ async function downloadsRoutes(app, container) {
|
|
|
15
14
|
schema: {
|
|
16
15
|
operationId: "listDownloads",
|
|
17
16
|
tags: ["Content"],
|
|
18
|
-
summary: "List downloads
|
|
19
|
-
description:
|
|
17
|
+
summary: "List downloads",
|
|
18
|
+
description: `Requires \`downloads:read\`. Every download, drafts included, filtered by status and category and searched by title.`,
|
|
20
19
|
querystring: DownloadsQuery,
|
|
21
20
|
response: {
|
|
22
21
|
200: DownloadsPage,
|
|
@@ -24,8 +23,8 @@ async function downloadsRoutes(app, container) {
|
|
|
24
23
|
}
|
|
25
24
|
},
|
|
26
25
|
handler: async (req) => {
|
|
27
|
-
const
|
|
28
|
-
return content.listDownloads(
|
|
26
|
+
const actor = await resolveActor(container, req);
|
|
27
|
+
return content.listDownloads(req.query, actor);
|
|
29
28
|
}
|
|
30
29
|
});
|
|
31
30
|
r.route({
|
|
@@ -35,8 +34,8 @@ async function downloadsRoutes(app, container) {
|
|
|
35
34
|
schema: {
|
|
36
35
|
operationId: "getDownload",
|
|
37
36
|
tags: ["Content"],
|
|
38
|
-
summary: "Get a download
|
|
39
|
-
description: "
|
|
37
|
+
summary: "Get a download",
|
|
38
|
+
description: "Requires `downloads:read`.",
|
|
40
39
|
params: DownloadIdParam,
|
|
41
40
|
response: {
|
|
42
41
|
200: Download,
|
|
@@ -44,10 +43,8 @@ async function downloadsRoutes(app, container) {
|
|
|
44
43
|
}
|
|
45
44
|
},
|
|
46
45
|
handler: async (req) => {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
if (!download) throw new NotFoundError("Download", req.params.downloadId);
|
|
50
|
-
return download;
|
|
46
|
+
const actor = await resolveActor(container, req);
|
|
47
|
+
return content.getDownload(req.params.downloadId, actor);
|
|
51
48
|
}
|
|
52
49
|
});
|
|
53
50
|
r.route({
|
|
@@ -57,8 +54,8 @@ async function downloadsRoutes(app, container) {
|
|
|
57
54
|
schema: {
|
|
58
55
|
operationId: "createDownload",
|
|
59
56
|
tags: ["Content"],
|
|
60
|
-
summary: "Create a download
|
|
61
|
-
description:
|
|
57
|
+
summary: "Create a download",
|
|
58
|
+
description: `Requires \`downloads:write\`. The download starts as a draft. 409 when its slug is taken.`,
|
|
62
59
|
body: CreateDownload,
|
|
63
60
|
response: {
|
|
64
61
|
201: Download,
|
|
@@ -66,8 +63,8 @@ async function downloadsRoutes(app, container) {
|
|
|
66
63
|
}
|
|
67
64
|
},
|
|
68
65
|
handler: async (req, reply) => {
|
|
69
|
-
const
|
|
70
|
-
const download = await content.createDownload(
|
|
66
|
+
const actor = await resolveActor(container, req);
|
|
67
|
+
const download = await content.createDownload(req.body, actor);
|
|
71
68
|
return reply.code(201).send(download);
|
|
72
69
|
}
|
|
73
70
|
});
|
|
@@ -78,8 +75,8 @@ async function downloadsRoutes(app, container) {
|
|
|
78
75
|
schema: {
|
|
79
76
|
operationId: "updateDownload",
|
|
80
77
|
tags: ["Content"],
|
|
81
|
-
summary: "Update a download
|
|
82
|
-
description:
|
|
78
|
+
summary: "Update a download",
|
|
79
|
+
description: `Requires \`downloads:write\`. Changes only the fields sent. \`thumbnailAssetId\` must be a ready library image (409 otherwise); null clears it. A file it does not already use must be uploaded for it, or the caller needs \`media:read\` (403 otherwise).`,
|
|
83
80
|
params: DownloadIdParam,
|
|
84
81
|
body: UpdateDownload,
|
|
85
82
|
response: {
|
|
@@ -88,8 +85,8 @@ async function downloadsRoutes(app, container) {
|
|
|
88
85
|
}
|
|
89
86
|
},
|
|
90
87
|
handler: async (req) => {
|
|
91
|
-
const
|
|
92
|
-
return content.updateDownload(
|
|
88
|
+
const actor = await resolveActor(container, req);
|
|
89
|
+
return content.updateDownload(req.params.downloadId, req.body, actor);
|
|
93
90
|
}
|
|
94
91
|
});
|
|
95
92
|
r.route({
|
|
@@ -99,8 +96,8 @@ async function downloadsRoutes(app, container) {
|
|
|
99
96
|
schema: {
|
|
100
97
|
operationId: "deleteDownload",
|
|
101
98
|
tags: ["Content"],
|
|
102
|
-
summary: "Delete a download
|
|
103
|
-
description:
|
|
99
|
+
summary: "Delete a download",
|
|
100
|
+
description: `Requires \`downloads:delete\`. Its library files survive.`,
|
|
104
101
|
params: DownloadIdParam,
|
|
105
102
|
response: {
|
|
106
103
|
204: z.void(),
|
|
@@ -108,11 +105,8 @@ async function downloadsRoutes(app, container) {
|
|
|
108
105
|
}
|
|
109
106
|
},
|
|
110
107
|
handler: async (req, reply) => {
|
|
111
|
-
const
|
|
112
|
-
await content.removeDownload(
|
|
113
|
-
id: scope.orgUserId,
|
|
114
|
-
role: scope.role
|
|
115
|
-
});
|
|
108
|
+
const actor = await resolveActor(container, req);
|
|
109
|
+
await content.removeDownload(req.params.downloadId, actor);
|
|
116
110
|
return reply.code(204).send();
|
|
117
111
|
}
|
|
118
112
|
});
|
|
@@ -123,8 +117,8 @@ async function downloadsRoutes(app, container) {
|
|
|
123
117
|
schema: {
|
|
124
118
|
operationId: "listDownloadAssets",
|
|
125
119
|
tags: ["Content"],
|
|
126
|
-
summary: "List a download's files in order
|
|
127
|
-
description: "
|
|
120
|
+
summary: "List a download's files in order",
|
|
121
|
+
description: "Requires `downloads:read`.",
|
|
128
122
|
params: DownloadIdParam,
|
|
129
123
|
response: {
|
|
130
124
|
200: z.array(DownloadFile),
|
|
@@ -132,8 +126,8 @@ async function downloadsRoutes(app, container) {
|
|
|
132
126
|
}
|
|
133
127
|
},
|
|
134
128
|
handler: async (req) => {
|
|
135
|
-
const
|
|
136
|
-
return content.listDownloadAssets(
|
|
129
|
+
const actor = await resolveActor(container, req);
|
|
130
|
+
return content.listDownloadAssets(req.params.downloadId, actor);
|
|
137
131
|
}
|
|
138
132
|
});
|
|
139
133
|
r.route({
|
|
@@ -143,8 +137,8 @@ async function downloadsRoutes(app, container) {
|
|
|
143
137
|
schema: {
|
|
144
138
|
operationId: "addDownloadAsset",
|
|
145
139
|
tags: ["Content"],
|
|
146
|
-
summary: "Add a library file to a download
|
|
147
|
-
description:
|
|
140
|
+
summary: "Add a library file to a download",
|
|
141
|
+
description: `Requires \`downloads:write\`. Added last. 409 when the file is not a ready library file or is already in the download. A file not uploaded for the download needs \`media:read\` (403 otherwise). Returns the download's files.`,
|
|
148
142
|
params: DownloadIdParam,
|
|
149
143
|
body: AddDownloadAsset,
|
|
150
144
|
response: {
|
|
@@ -153,8 +147,8 @@ async function downloadsRoutes(app, container) {
|
|
|
153
147
|
}
|
|
154
148
|
},
|
|
155
149
|
handler: async (req) => {
|
|
156
|
-
const
|
|
157
|
-
return content.addDownloadAsset(
|
|
150
|
+
const actor = await resolveActor(container, req);
|
|
151
|
+
return content.addDownloadAsset(req.params.downloadId, req.body, actor);
|
|
158
152
|
}
|
|
159
153
|
});
|
|
160
154
|
r.route({
|
|
@@ -164,8 +158,8 @@ async function downloadsRoutes(app, container) {
|
|
|
164
158
|
schema: {
|
|
165
159
|
operationId: "reorderDownloadAssets",
|
|
166
160
|
tags: ["Content"],
|
|
167
|
-
summary: "Reorder a download's files
|
|
168
|
-
description:
|
|
161
|
+
summary: "Reorder a download's files",
|
|
162
|
+
description: `Requires \`downloads:write\`. Send every file id of the download exactly once (409 otherwise). Returns the download's files.`,
|
|
169
163
|
params: DownloadIdParam,
|
|
170
164
|
body: ReorderDownloadAssets,
|
|
171
165
|
response: {
|
|
@@ -174,8 +168,8 @@ async function downloadsRoutes(app, container) {
|
|
|
174
168
|
}
|
|
175
169
|
},
|
|
176
170
|
handler: async (req) => {
|
|
177
|
-
const
|
|
178
|
-
return content.reorderDownloadAssets(
|
|
171
|
+
const actor = await resolveActor(container, req);
|
|
172
|
+
return content.reorderDownloadAssets(req.params.downloadId, req.body.assetIds, actor);
|
|
179
173
|
}
|
|
180
174
|
});
|
|
181
175
|
r.route({
|
|
@@ -185,8 +179,8 @@ async function downloadsRoutes(app, container) {
|
|
|
185
179
|
schema: {
|
|
186
180
|
operationId: "renameDownloadAsset",
|
|
187
181
|
tags: ["Content"],
|
|
188
|
-
summary: "Set a file's display name within a download
|
|
189
|
-
description:
|
|
182
|
+
summary: "Set a file's display name within a download",
|
|
183
|
+
description: `Requires \`downloads:write\`. Null falls back to the filename. Returns the download's files.`,
|
|
190
184
|
params: DownloadAssetParams,
|
|
191
185
|
body: RenameDownloadAsset,
|
|
192
186
|
response: {
|
|
@@ -195,8 +189,8 @@ async function downloadsRoutes(app, container) {
|
|
|
195
189
|
}
|
|
196
190
|
},
|
|
197
191
|
handler: async (req) => {
|
|
198
|
-
const
|
|
199
|
-
return content.renameDownloadAsset(
|
|
192
|
+
const actor = await resolveActor(container, req);
|
|
193
|
+
return content.renameDownloadAsset(req.params.downloadId, req.params.assetId, req.body.displayName, actor);
|
|
200
194
|
}
|
|
201
195
|
});
|
|
202
196
|
r.route({
|
|
@@ -206,8 +200,8 @@ async function downloadsRoutes(app, container) {
|
|
|
206
200
|
schema: {
|
|
207
201
|
operationId: "removeDownloadAsset",
|
|
208
202
|
tags: ["Content"],
|
|
209
|
-
summary: "Remove a file from a download
|
|
210
|
-
description:
|
|
203
|
+
summary: "Remove a file from a download",
|
|
204
|
+
description: `Requires \`downloads:write\`. The library file itself survives. Returns the download's files.`,
|
|
211
205
|
params: DownloadAssetParams,
|
|
212
206
|
response: {
|
|
213
207
|
200: z.array(DownloadFile),
|
|
@@ -215,8 +209,8 @@ async function downloadsRoutes(app, container) {
|
|
|
215
209
|
}
|
|
216
210
|
},
|
|
217
211
|
handler: async (req) => {
|
|
218
|
-
const
|
|
219
|
-
return content.removeDownloadAsset(
|
|
212
|
+
const actor = await resolveActor(container, req);
|
|
213
|
+
return content.removeDownloadAsset(req.params.downloadId, req.params.assetId, actor);
|
|
220
214
|
}
|
|
221
215
|
});
|
|
222
216
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"downloads.js","names":[],"sources":["../../../src/http/routes/downloads.ts"],"sourcesContent":["// HTTP routes for the download content type. Request + response are validated\n// against the shared contract schemas by the Zod type provider, and\n// @fastify/swagger reads the same schemas to build the OpenAPI spec.\nimport type { FastifyInstance } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport {\n AddDownloadAsset,\n Download,\n DownloadFile,\n DownloadAssetParams,\n DownloadIdParam,\n DownloadsPage,\n DownloadsQuery,\n CreateDownload,\n RenameDownloadAsset,\n ReorderDownloadAssets,\n UpdateDownload,\n refusals,\n} from '../schemas/index.js';\nimport { z } from 'zod';\nimport type { Container } from '../../app/container.js';\nimport { NotFoundError } from '@headless-lms/core/shared/errors';\nimport { resolveScope } from '../scope.js';\n\nexport async function downloadsRoutes(app: FastifyInstance, container: Container): Promise<void> {\n const r = app.withTypeProvider<ZodTypeProvider>();\n const content = container.content;\n\n r.route({\n method: 'GET',\n url: '/api/downloads',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listDownloads',\n tags: ['Content'],\n summary: 'List downloads (staff)',\n description:\n 'Staff only (owner, admin, instructor). Every download, drafts included, filtered by status and category and searched by title.',\n querystring: DownloadsQuery,\n response: { 200: DownloadsPage, ...refusals(403) },\n },\n handler: async (req) => {\n const scope = await resolveScope(container, req);\n return content.listDownloads(scope.orgId, req.query);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/downloads/:downloadId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getDownload',\n tags: ['Content'],\n summary: 'Get a download (staff)',\n description: 'Staff only (owner, admin, instructor).',\n params: DownloadIdParam,\n response: { 200: Download, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const scope = await resolveScope(container, req);\n const download = await content.getDownload(scope.orgId, req.params.downloadId);\n if (!download) {\n throw new NotFoundError('Download', req.params.downloadId);\n }\n return download;\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/downloads',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'createDownload',\n tags: ['Content'],\n summary: 'Create a download (staff)',\n description:\n 'Staff only (owner, admin, instructor). The download starts as a draft. 409 when its slug is taken.',\n body: CreateDownload,\n response: { 201: Download, ...refusals(403, 409) },\n },\n handler: async (req, reply) => {\n const scope = await resolveScope(container, req);\n const download = await content.createDownload(scope.orgId, req.body);\n return reply.code(201).send(download);\n },\n });\n\n r.route({\n method: 'PATCH',\n url: '/api/downloads/:downloadId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'updateDownload',\n tags: ['Content'],\n summary: 'Update a download (staff)',\n description:\n 'Staff only (owner, admin, instructor). Changes only the fields sent. `thumbnailAssetId` must be a ready library image (409 otherwise); null clears it.',\n params: DownloadIdParam,\n body: UpdateDownload,\n response: { 200: Download, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const scope = await resolveScope(container, req);\n return content.updateDownload(scope.orgId, req.params.downloadId, req.body);\n },\n });\n\n r.route({\n method: 'DELETE',\n url: '/api/downloads/:downloadId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'deleteDownload',\n tags: ['Content'],\n summary: 'Delete a download (staff)',\n description: 'Staff only (owner, admin, instructor). Its library files survive.',\n params: DownloadIdParam,\n response: { 204: z.void(), ...refusals(403, 404) },\n },\n handler: async (req, reply) => {\n const scope = await resolveScope(container, req);\n await content.removeDownload(scope.orgId, req.params.downloadId, {\n id: scope.orgUserId,\n role: scope.role,\n });\n return reply.code(204).send();\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/downloads/:downloadId/assets',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listDownloadAssets',\n tags: ['Content'],\n summary: \"List a download's files in order (staff)\",\n description: 'Staff only (owner, admin, instructor).',\n params: DownloadIdParam,\n response: { 200: z.array(DownloadFile), ...refusals(403) },\n },\n handler: async (req) => {\n const scope = await resolveScope(container, req);\n return content.listDownloadAssets(scope.orgId, req.params.downloadId);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/downloads/:downloadId/assets',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'addDownloadAsset',\n tags: ['Content'],\n summary: 'Add a library file to a download (staff)',\n description:\n \"Staff only (owner, admin, instructor). Added last. 409 when the file is not a ready library file or is already in the download. Returns the download's files.\",\n params: DownloadIdParam,\n body: AddDownloadAsset,\n response: { 200: z.array(DownloadFile), ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const scope = await resolveScope(container, req);\n return content.addDownloadAsset(scope.orgId, req.params.downloadId, req.body);\n },\n });\n\n // Static segment before the parameterised sibling. Fastify's radix router\n // prefers static either way; the ordering documents the intent.\n r.route({\n method: 'PUT',\n url: '/api/downloads/:downloadId/assets/order',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'reorderDownloadAssets',\n tags: ['Content'],\n summary: \"Reorder a download's files (staff)\",\n description:\n \"Staff only (owner, admin, instructor). Send every file id of the download exactly once (409 otherwise). Returns the download's files.\",\n params: DownloadIdParam,\n body: ReorderDownloadAssets,\n response: { 200: z.array(DownloadFile), ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const scope = await resolveScope(container, req);\n return content.reorderDownloadAssets(scope.orgId, req.params.downloadId, req.body.assetIds);\n },\n });\n\n r.route({\n method: 'PATCH',\n url: '/api/downloads/:downloadId/assets/:assetId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'renameDownloadAsset',\n tags: ['Content'],\n summary: \"Set a file's display name within a download (staff)\",\n description:\n \"Staff only (owner, admin, instructor). Null falls back to the filename. Returns the download's files.\",\n params: DownloadAssetParams,\n body: RenameDownloadAsset,\n response: { 200: z.array(DownloadFile), ...refusals(403, 404) },\n },\n handler: async (req) => {\n const scope = await resolveScope(container, req);\n return content.renameDownloadAsset(\n scope.orgId,\n req.params.downloadId,\n req.params.assetId,\n req.body.displayName,\n );\n },\n });\n\n r.route({\n method: 'DELETE',\n url: '/api/downloads/:downloadId/assets/:assetId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'removeDownloadAsset',\n tags: ['Content'],\n summary: 'Remove a file from a download (staff)',\n description:\n \"Staff only (owner, admin, instructor). The library file itself survives. Returns the download's files.\",\n params: DownloadAssetParams,\n response: { 200: z.array(DownloadFile), ...refusals(403, 404) },\n },\n handler: async (req) => {\n const scope = await resolveScope(container, req);\n return content.removeDownloadAsset(scope.orgId, req.params.downloadId, req.params.assetId);\n },\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"downloads.js","names":[],"sources":["../../../src/http/routes/downloads.ts"],"sourcesContent":["// HTTP routes for the download content type. Request + response are validated\n// against the shared contract schemas by the Zod type provider, and\n// @fastify/swagger reads the same schemas to build the OpenAPI spec.\nimport type { FastifyInstance } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport {\n AddDownloadAsset,\n Download,\n DownloadFile,\n DownloadAssetParams,\n DownloadIdParam,\n DownloadsPage,\n DownloadsQuery,\n CreateDownload,\n RenameDownloadAsset,\n ReorderDownloadAssets,\n UpdateDownload,\n refusals,\n} from '../schemas/index.js';\nimport { z } from 'zod';\nimport type { Container } from '../../app/container.js';\nimport { resolveActor } from '../scope.js';\n\nexport async function downloadsRoutes(app: FastifyInstance, container: Container): Promise<void> {\n const r = app.withTypeProvider<ZodTypeProvider>();\n const content = container.content;\n\n r.route({\n method: 'GET',\n url: '/api/downloads',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listDownloads',\n tags: ['Content'],\n summary: 'List downloads',\n description: `Requires \\`downloads:read\\`. Every download, drafts included, filtered by status and category and searched by title.`,\n querystring: DownloadsQuery,\n response: { 200: DownloadsPage, ...refusals(403) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return content.listDownloads(req.query, actor);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/downloads/:downloadId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getDownload',\n tags: ['Content'],\n summary: 'Get a download',\n description: 'Requires `downloads:read`.',\n params: DownloadIdParam,\n response: { 200: Download, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return content.getDownload(req.params.downloadId, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/downloads',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'createDownload',\n tags: ['Content'],\n summary: 'Create a download',\n description: `Requires \\`downloads:write\\`. The download starts as a draft. 409 when its slug is taken.`,\n body: CreateDownload,\n response: { 201: Download, ...refusals(403, 409) },\n },\n handler: async (req, reply) => {\n const actor = await resolveActor(container, req);\n const download = await content.createDownload(req.body, actor);\n return reply.code(201).send(download);\n },\n });\n\n r.route({\n method: 'PATCH',\n url: '/api/downloads/:downloadId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'updateDownload',\n tags: ['Content'],\n summary: 'Update a download',\n description: `Requires \\`downloads:write\\`. Changes only the fields sent. \\`thumbnailAssetId\\` must be a ready library image (409 otherwise); null clears it. A file it does not already use must be uploaded for it, or the caller needs \\`media:read\\` (403 otherwise).`,\n params: DownloadIdParam,\n body: UpdateDownload,\n response: { 200: Download, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return content.updateDownload(req.params.downloadId, req.body, actor);\n },\n });\n\n r.route({\n method: 'DELETE',\n url: '/api/downloads/:downloadId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'deleteDownload',\n tags: ['Content'],\n summary: 'Delete a download',\n description: `Requires \\`downloads:delete\\`. Its library files survive.`,\n params: DownloadIdParam,\n response: { 204: z.void(), ...refusals(403, 404) },\n },\n handler: async (req, reply) => {\n const actor = await resolveActor(container, req);\n await content.removeDownload(req.params.downloadId, actor);\n return reply.code(204).send();\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/downloads/:downloadId/assets',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listDownloadAssets',\n tags: ['Content'],\n summary: \"List a download's files in order\",\n description: 'Requires `downloads:read`.',\n params: DownloadIdParam,\n response: { 200: z.array(DownloadFile), ...refusals(403) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return content.listDownloadAssets(req.params.downloadId, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/downloads/:downloadId/assets',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'addDownloadAsset',\n tags: ['Content'],\n summary: 'Add a library file to a download',\n description: `Requires \\`downloads:write\\`. Added last. 409 when the file is not a ready library file or is already in the download. A file not uploaded for the download needs \\`media:read\\` (403 otherwise). Returns the download's files.`,\n params: DownloadIdParam,\n body: AddDownloadAsset,\n response: { 200: z.array(DownloadFile), ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return content.addDownloadAsset(req.params.downloadId, req.body, actor);\n },\n });\n\n // Static segment before the parameterised sibling. Fastify's radix router\n // prefers static either way; the ordering documents the intent.\n r.route({\n method: 'PUT',\n url: '/api/downloads/:downloadId/assets/order',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'reorderDownloadAssets',\n tags: ['Content'],\n summary: \"Reorder a download's files\",\n description: `Requires \\`downloads:write\\`. Send every file id of the download exactly once (409 otherwise). Returns the download's files.`,\n params: DownloadIdParam,\n body: ReorderDownloadAssets,\n response: { 200: z.array(DownloadFile), ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return content.reorderDownloadAssets(req.params.downloadId, req.body.assetIds, actor);\n },\n });\n\n r.route({\n method: 'PATCH',\n url: '/api/downloads/:downloadId/assets/:assetId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'renameDownloadAsset',\n tags: ['Content'],\n summary: \"Set a file's display name within a download\",\n description: `Requires \\`downloads:write\\`. Null falls back to the filename. Returns the download's files.`,\n params: DownloadAssetParams,\n body: RenameDownloadAsset,\n response: { 200: z.array(DownloadFile), ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return content.renameDownloadAsset(\n req.params.downloadId,\n req.params.assetId,\n req.body.displayName,\n actor,\n );\n },\n });\n\n r.route({\n method: 'DELETE',\n url: '/api/downloads/:downloadId/assets/:assetId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'removeDownloadAsset',\n tags: ['Content'],\n summary: 'Remove a file from a download',\n description: `Requires \\`downloads:write\\`. The library file itself survives. Returns the download's files.`,\n params: DownloadAssetParams,\n response: { 200: z.array(DownloadFile), ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return content.removeDownloadAsset(req.params.downloadId, req.params.assetId, actor);\n },\n });\n}\n"],"mappings":";;;;;;AAuBA,eAAsB,gBAAgB,KAAsB,WAAqC;CAC/F,MAAM,IAAI,IAAI,iBAAkC;CAChD,MAAM,UAAU,UAAU;CAE1B,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,SAAS;GAChB,SAAS;GACT,aAAa;GACb,aAAa;GACb,UAAU;IAAE,KAAK;IAAe,GAAG,SAAS,GAAG;GAAE;EACnD;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,OAAO,QAAQ,cAAc,IAAI,OAAO,KAAK;EAC/C;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,SAAS;GAChB,SAAS;GACT,aAAa;GACb,QAAQ;GACR,UAAU;IAAE,KAAK;IAAU,GAAG,SAAS,KAAK,GAAG;GAAE;EACnD;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,OAAO,QAAQ,YAAY,IAAI,OAAO,YAAY,KAAK;EACzD;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,SAAS;GAChB,SAAS;GACT,aAAa;GACb,MAAM;GACN,UAAU;IAAE,KAAK;IAAU,GAAG,SAAS,KAAK,GAAG;GAAE;EACnD;EACA,SAAS,OAAO,KAAK,UAAU;GAC7B,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,MAAM,WAAW,MAAM,QAAQ,eAAe,IAAI,MAAM,KAAK;GAC7D,OAAO,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,QAAQ;EACtC;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,SAAS;GAChB,SAAS;GACT,aAAa;GACb,QAAQ;GACR,MAAM;GACN,UAAU;IAAE,KAAK;IAAU,GAAG,SAAS,KAAK,KAAK,GAAG;GAAE;EACxD;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,OAAO,QAAQ,eAAe,IAAI,OAAO,YAAY,IAAI,MAAM,KAAK;EACtE;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,SAAS;GAChB,SAAS;GACT,aAAa;GACb,QAAQ;GACR,UAAU;IAAE,KAAK,EAAE,KAAK;IAAG,GAAG,SAAS,KAAK,GAAG;GAAE;EACnD;EACA,SAAS,OAAO,KAAK,UAAU;GAC7B,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,MAAM,QAAQ,eAAe,IAAI,OAAO,YAAY,KAAK;GACzD,OAAO,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK;EAC9B;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,SAAS;GAChB,SAAS;GACT,aAAa;GACb,QAAQ;GACR,UAAU;IAAE,KAAK,EAAE,MAAM,YAAY;IAAG,GAAG,SAAS,GAAG;GAAE;EAC3D;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,OAAO,QAAQ,mBAAmB,IAAI,OAAO,YAAY,KAAK;EAChE;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,SAAS;GAChB,SAAS;GACT,aAAa;GACb,QAAQ;GACR,MAAM;GACN,UAAU;IAAE,KAAK,EAAE,MAAM,YAAY;IAAG,GAAG,SAAS,KAAK,KAAK,GAAG;GAAE;EACrE;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,OAAO,QAAQ,iBAAiB,IAAI,OAAO,YAAY,IAAI,MAAM,KAAK;EACxE;CACF,CAAC;CAID,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,SAAS;GAChB,SAAS;GACT,aAAa;GACb,QAAQ;GACR,MAAM;GACN,UAAU;IAAE,KAAK,EAAE,MAAM,YAAY;IAAG,GAAG,SAAS,KAAK,KAAK,GAAG;GAAE;EACrE;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,OAAO,QAAQ,sBAAsB,IAAI,OAAO,YAAY,IAAI,KAAK,UAAU,KAAK;EACtF;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,SAAS;GAChB,SAAS;GACT,aAAa;GACb,QAAQ;GACR,MAAM;GACN,UAAU;IAAE,KAAK,EAAE,MAAM,YAAY;IAAG,GAAG,SAAS,KAAK,GAAG;GAAE;EAChE;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,OAAO,QAAQ,oBACb,IAAI,OAAO,YACX,IAAI,OAAO,SACX,IAAI,KAAK,aACT,KACF;EACF;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,SAAS;GAChB,SAAS;GACT,aAAa;GACb,QAAQ;GACR,UAAU;IAAE,KAAK,EAAE,MAAM,YAAY;IAAG,GAAG,SAAS,KAAK,GAAG;GAAE;EAChE;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,OAAO,QAAQ,oBAAoB,IAAI,OAAO,YAAY,IAAI,OAAO,SAAS,KAAK;EACrF;CACF,CAAC;AACH"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { refusals } from "../schemas/shared.js";
|
|
2
|
-
import {
|
|
3
|
-
import { Entitlement,
|
|
2
|
+
import { resolveActor } from "../scope.js";
|
|
3
|
+
import { Entitlement, EntitlementsPage, EntitlementsQuery, GrantEntitlement, RevokeEntitlement } from "../schemas/entitlements.js";
|
|
4
4
|
import "../schemas/index.js";
|
|
5
|
-
import { NotFoundError } from "@headless-lms/core/shared/errors";
|
|
6
5
|
//#region src/http/routes/entitlements.ts
|
|
7
6
|
async function entitlementsRoutes(app, container) {
|
|
8
7
|
const r = app.withTypeProvider();
|
|
@@ -14,8 +13,8 @@ async function entitlementsRoutes(app, container) {
|
|
|
14
13
|
schema: {
|
|
15
14
|
operationId: "listEntitlements",
|
|
16
15
|
tags: ["Entitlements"],
|
|
17
|
-
summary: "List entitlements
|
|
18
|
-
description:
|
|
16
|
+
summary: "List entitlements",
|
|
17
|
+
description: `Requires one of \`access:read\`, \`progress:read\`. \`access:read\` lists every grant; \`progress:read\` on a course lists that course's grants when \`contentId\` names it.`,
|
|
19
18
|
querystring: EntitlementsQuery,
|
|
20
19
|
response: {
|
|
21
20
|
200: EntitlementsPage,
|
|
@@ -23,8 +22,8 @@ async function entitlementsRoutes(app, container) {
|
|
|
23
22
|
}
|
|
24
23
|
},
|
|
25
24
|
handler: async (req) => {
|
|
26
|
-
const
|
|
27
|
-
return entitlements.list(
|
|
25
|
+
const actor = await resolveActor(container, req);
|
|
26
|
+
return entitlements.list(req.query, actor);
|
|
28
27
|
}
|
|
29
28
|
});
|
|
30
29
|
r.route({
|
|
@@ -34,41 +33,38 @@ async function entitlementsRoutes(app, container) {
|
|
|
34
33
|
schema: {
|
|
35
34
|
operationId: "grantEntitlement",
|
|
36
35
|
tags: ["Entitlements"],
|
|
37
|
-
summary: "Grant a person access to content or a bundle
|
|
38
|
-
description:
|
|
36
|
+
summary: "Grant a person access to content or a bundle",
|
|
37
|
+
description: `Requires \`access:write\`; to grant an event, \`events:write\` on it is enough. Name exactly one of \`contentId\` and \`bundleId\`. A bundle grant covers whatever the bundle holds, now and later. Granting again makes a revoked or expired grant active with the new expiry. A grant to an event needs it published and not ended, with a place left when it has a capacity: 409 \`not_published\`, \`ended\` or \`full\` otherwise; granting it to someone who already holds it changes nothing. 404 when the content or the person does not exist.`,
|
|
39
38
|
body: GrantEntitlement,
|
|
40
39
|
response: {
|
|
41
40
|
201: Entitlement,
|
|
42
|
-
...refusals(403, 409)
|
|
41
|
+
...refusals(403, 404, 409)
|
|
43
42
|
}
|
|
44
43
|
},
|
|
45
44
|
handler: async (req, reply) => {
|
|
46
|
-
const
|
|
47
|
-
const entitlement = await entitlements.grant(
|
|
45
|
+
const actor = await resolveActor(container, req);
|
|
46
|
+
const entitlement = await entitlements.grant(req.body, actor);
|
|
48
47
|
return reply.code(201).send(entitlement);
|
|
49
48
|
}
|
|
50
49
|
});
|
|
51
50
|
r.route({
|
|
52
|
-
method: "
|
|
53
|
-
url: "/api/entitlements
|
|
51
|
+
method: "POST",
|
|
52
|
+
url: "/api/entitlements/revoke",
|
|
54
53
|
preHandler: app.requireOrgSession,
|
|
55
54
|
schema: {
|
|
56
|
-
operationId: "
|
|
55
|
+
operationId: "revokeEntitlement",
|
|
57
56
|
tags: ["Entitlements"],
|
|
58
|
-
summary: "Revoke
|
|
59
|
-
description:
|
|
60
|
-
|
|
61
|
-
body: SetEntitlementStatus,
|
|
57
|
+
summary: "Revoke a person's grant to content or a bundle",
|
|
58
|
+
description: `Requires \`access:write\`; to revoke an event, \`events:write\` on it is enough, and a person may revoke their own. Name exactly one of \`contentId\` and \`bundleId\`. Revokes the person's direct grant; access through a bundle stays. Granting again makes it active. 404 when they have no direct active grant.`,
|
|
59
|
+
body: RevokeEntitlement,
|
|
62
60
|
response: {
|
|
63
61
|
200: Entitlement,
|
|
64
62
|
...refusals(403, 404)
|
|
65
63
|
}
|
|
66
64
|
},
|
|
67
65
|
handler: async (req) => {
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
if (!entitlement) throw new NotFoundError("Entitlement", req.params.id);
|
|
71
|
-
return entitlement;
|
|
66
|
+
const actor = await resolveActor(container, req);
|
|
67
|
+
return entitlements.revoke(req.body, actor);
|
|
72
68
|
}
|
|
73
69
|
});
|
|
74
70
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entitlements.js","names":[],"sources":["../../../src/http/routes/entitlements.ts"],"sourcesContent":["// HTTP routes for the entitlements context (a student's access grant to a piece of content).\nimport type { FastifyInstance } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport {\n Entitlement,\n
|
|
1
|
+
{"version":3,"file":"entitlements.js","names":[],"sources":["../../../src/http/routes/entitlements.ts"],"sourcesContent":["// HTTP routes for the entitlements context (a student's access grant to a piece of content).\nimport type { FastifyInstance } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport {\n Entitlement,\n EntitlementsPage,\n EntitlementsQuery,\n GrantEntitlement,\n RevokeEntitlement,\n refusals,\n} from '../schemas/index.js';\nimport type { Container } from '../../app/container.js';\nimport { resolveActor } from '../scope.js';\n\nexport async function entitlementsRoutes(\n app: FastifyInstance,\n container: Container,\n): Promise<void> {\n const r = app.withTypeProvider<ZodTypeProvider>();\n const entitlements = container.entitlements;\n\n r.route({\n method: 'GET',\n url: '/api/entitlements',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listEntitlements',\n tags: ['Entitlements'],\n summary: 'List entitlements',\n description: `Requires one of \\`access:read\\`, \\`progress:read\\`. \\`access:read\\` lists every grant; \\`progress:read\\` on a course lists that course's grants when \\`contentId\\` names it.`,\n querystring: EntitlementsQuery,\n response: { 200: EntitlementsPage, ...refusals(403) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return entitlements.list(req.query, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/entitlements',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'grantEntitlement',\n tags: ['Entitlements'],\n summary: 'Grant a person access to content or a bundle',\n description: `Requires \\`access:write\\`; to grant an event, \\`events:write\\` on it is enough. Name exactly one of \\`contentId\\` and \\`bundleId\\`. A bundle grant covers whatever the bundle holds, now and later. Granting again makes a revoked or expired grant active with the new expiry. A grant to an event needs it published and not ended, with a place left when it has a capacity: 409 \\`not_published\\`, \\`ended\\` or \\`full\\` otherwise; granting it to someone who already holds it changes nothing. 404 when the content or the person does not exist.`,\n body: GrantEntitlement,\n response: { 201: Entitlement, ...refusals(403, 404, 409) },\n },\n handler: async (req, reply) => {\n const actor = await resolveActor(container, req);\n const entitlement = await entitlements.grant(req.body, actor);\n return reply.code(201).send(entitlement);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/entitlements/revoke',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'revokeEntitlement',\n tags: ['Entitlements'],\n summary: \"Revoke a person's grant to content or a bundle\",\n description: `Requires \\`access:write\\`; to revoke an event, \\`events:write\\` on it is enough, and a person may revoke their own. Name exactly one of \\`contentId\\` and \\`bundleId\\`. Revokes the person's direct grant; access through a bundle stays. Granting again makes it active. 404 when they have no direct active grant.`,\n body: RevokeEntitlement,\n response: { 200: Entitlement, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return entitlements.revoke(req.body, actor);\n },\n });\n}\n"],"mappings":";;;;;AAcA,eAAsB,mBACpB,KACA,WACe;CACf,MAAM,IAAI,IAAI,iBAAkC;CAChD,MAAM,eAAe,UAAU;CAE/B,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,cAAc;GACrB,SAAS;GACT,aAAa;GACb,aAAa;GACb,UAAU;IAAE,KAAK;IAAkB,GAAG,SAAS,GAAG;GAAE;EACtD;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,OAAO,aAAa,KAAK,IAAI,OAAO,KAAK;EAC3C;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,cAAc;GACrB,SAAS;GACT,aAAa;GACb,MAAM;GACN,UAAU;IAAE,KAAK;IAAa,GAAG,SAAS,KAAK,KAAK,GAAG;GAAE;EAC3D;EACA,SAAS,OAAO,KAAK,UAAU;GAC7B,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,MAAM,cAAc,MAAM,aAAa,MAAM,IAAI,MAAM,KAAK;GAC5D,OAAO,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,WAAW;EACzC;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,cAAc;GACrB,SAAS;GACT,aAAa;GACb,MAAM;GACN,UAAU;IAAE,KAAK;IAAa,GAAG,SAAS,KAAK,GAAG;GAAE;EACtD;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,OAAO,aAAa,OAAO,IAAI,MAAM,KAAK;EAC5C;CACF,CAAC;AACH"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Container } from "../../app/container.js";
|
|
2
|
+
import { FastifyInstance } from "fastify";
|
|
3
|
+
//#region src/http/routes/events.d.ts
|
|
4
|
+
declare function eventsRoutes(app: FastifyInstance, container: Container): Promise<void>;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { eventsRoutes };
|
|
7
|
+
//# sourceMappingURL=events.d.ts.map
|