@headless-lms/server 0.3.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 +10 -10
- package/dist/app/community-mail.js +72 -28
- package/dist/app/community-mail.js.map +1 -1
- package/dist/app/container.d.ts +48 -10
- package/dist/app/container.js +268 -48
- package/dist/app/container.js.map +1 -1
- package/dist/app/notification-channels.d.ts +47 -0
- package/dist/app/notification-channels.js +175 -0
- package/dist/app/notification-channels.js.map +1 -0
- package/dist/app/notification-reads.d.ts +23 -0
- package/dist/app/notification-reads.js +74 -0
- package/dist/app/notification-reads.js.map +1 -0
- 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.d.ts +1 -0
- package/dist/http/errors.js +24 -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 +13 -3
- 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 +144 -136
- 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 +177 -75
- 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 +68 -51
- 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.d.ts +7 -0
- package/dist/http/routes/member/devices.js +97 -0
- package/dist/http/routes/member/devices.js.map +1 -0
- 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 +6 -0
- package/dist/http/routes/member/index.js.map +1 -1
- package/dist/http/routes/member/notification-settings.d.ts +7 -0
- package/dist/http/routes/member/notification-settings.js +100 -0
- package/dist/http/routes/member/notification-settings.js.map +1 -0
- package/dist/http/routes/member/notifications.js +69 -45
- 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 +94 -95
- 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 +415 -110
- 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 +13 -8
- 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 -8
- package/dist/http/schemas/chats.d.ts +238 -36
- package/dist/http/schemas/chats.js +14 -7
- package/dist/http/schemas/chats.js.map +1 -1
- package/dist/http/schemas/community.d.ts +140 -33
- package/dist/http/schemas/community.js +25 -9
- 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 +45 -73
- package/dist/http/schemas/discussion.js +16 -4
- 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 +14 -12
- package/dist/http/schemas/index.js +14 -12
- 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 +329 -65
- package/dist/http/schemas/members.js +67 -25
- package/dist/http/schemas/members.js.map +1 -1
- package/dist/http/schemas/notifications.d.ts +502 -175
- package/dist/http/schemas/notifications.js +148 -28
- package/dist/http/schemas/notifications.js.map +1 -1
- 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 +92 -38
- 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 +10 -13
- package/dist/http/schemas/shared.js +3 -11
- package/dist/http/schemas/shared.js.map +1 -1
- package/dist/http/schemas/students.d.ts +22 -0
- package/dist/http/schemas/students.js +3 -1
- package/dist/http/schemas/students.js.map +1 -1
- package/dist/http/scope.d.ts +9 -12
- package/dist/http/scope.js +30 -35
- 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 +5 -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,10 +1,10 @@
|
|
|
1
1
|
import { refusals } from "../schemas/shared.js";
|
|
2
|
-
import {
|
|
3
|
-
import { CommunitiesPage, CommunitiesQuery, Community, CommunityAnalytics, CommunityIdParam, CommunitySpaceParam, CreateCommunity, CreateSpace, OrderedIds,
|
|
2
|
+
import { resolveActor } from "../scope.js";
|
|
3
|
+
import { CommunitiesPage, CommunitiesQuery, Community, CommunityAnalytics, CommunityIdParam, CommunitySpaceParam, CreateCommunity, CreateSpace, OrderedIds, PatchCommunitySettings, SetSpaceTopics, SpaceDetail, SpaceLinkBody, SpaceLinkParam, UpdateCommunity, UpdateSpace } from "../schemas/community.js";
|
|
4
4
|
import { MessageQueue } from "../schemas/chats.js";
|
|
5
|
+
import { NotificationCategoryList, ReplaceNotificationCategories } from "../schemas/notifications.js";
|
|
5
6
|
import "../schemas/index.js";
|
|
6
7
|
import { z } from "zod";
|
|
7
|
-
import { NotFoundError } from "@headless-lms/core/shared/errors";
|
|
8
8
|
//#region src/http/routes/communities.ts
|
|
9
9
|
async function communitiesRoutes(app, container) {
|
|
10
10
|
const r = app.withTypeProvider();
|
|
@@ -16,8 +16,8 @@ async function communitiesRoutes(app, container) {
|
|
|
16
16
|
schema: {
|
|
17
17
|
operationId: "listCommunities",
|
|
18
18
|
tags,
|
|
19
|
-
summary: "List communities
|
|
20
|
-
description:
|
|
19
|
+
summary: "List communities",
|
|
20
|
+
description: `Requires one of \`communities:read\`, \`communities:moderate\`. Pages every community in the organization, drafts included, filtered by \`status\` and searched by title.`,
|
|
21
21
|
querystring: CommunitiesQuery,
|
|
22
22
|
response: {
|
|
23
23
|
200: CommunitiesPage,
|
|
@@ -25,8 +25,8 @@ async function communitiesRoutes(app, container) {
|
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
27
|
handler: async (req) => {
|
|
28
|
-
const
|
|
29
|
-
return content.listCommunities(
|
|
28
|
+
const actor = await resolveActor(container, req);
|
|
29
|
+
return content.listCommunities(req.query, actor);
|
|
30
30
|
}
|
|
31
31
|
});
|
|
32
32
|
r.route({
|
|
@@ -35,8 +35,8 @@ async function communitiesRoutes(app, container) {
|
|
|
35
35
|
schema: {
|
|
36
36
|
operationId: "createCommunity",
|
|
37
37
|
tags,
|
|
38
|
-
summary: "Create a community
|
|
39
|
-
description:
|
|
38
|
+
summary: "Create a community",
|
|
39
|
+
description: `Requires \`communities:write\`. The community starts as a draft with the default direct-message settings and no spaces. Members see it once it is published and they hold it.`,
|
|
40
40
|
body: CreateCommunity,
|
|
41
41
|
response: {
|
|
42
42
|
201: Community,
|
|
@@ -44,11 +44,8 @@ async function communitiesRoutes(app, container) {
|
|
|
44
44
|
}
|
|
45
45
|
},
|
|
46
46
|
handler: async (req, reply) => {
|
|
47
|
-
const
|
|
48
|
-
const community = await content.createCommunity(
|
|
49
|
-
id: scope.orgUserId,
|
|
50
|
-
role: scope.role
|
|
51
|
-
});
|
|
47
|
+
const actor = await resolveActor(container, req);
|
|
48
|
+
const community = await content.createCommunity(req.body, actor);
|
|
52
49
|
req.log.info({ communityId: community.id }, "community created");
|
|
53
50
|
return reply.code(201).send(community);
|
|
54
51
|
}
|
|
@@ -59,8 +56,8 @@ async function communitiesRoutes(app, container) {
|
|
|
59
56
|
schema: {
|
|
60
57
|
operationId: "getCommunity",
|
|
61
58
|
tags,
|
|
62
|
-
summary: "Get a community
|
|
63
|
-
description:
|
|
59
|
+
summary: "Get a community",
|
|
60
|
+
description: `Requires one of \`communities:read\`, \`communities:moderate\`. Any community of the organization, drafts included.`,
|
|
64
61
|
params: CommunityIdParam,
|
|
65
62
|
response: {
|
|
66
63
|
200: Community,
|
|
@@ -68,10 +65,8 @@ async function communitiesRoutes(app, container) {
|
|
|
68
65
|
}
|
|
69
66
|
},
|
|
70
67
|
handler: async (req) => {
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
if (!community) throw new NotFoundError("Community", req.params.communityId);
|
|
74
|
-
return community;
|
|
68
|
+
const actor = await resolveActor(container, req);
|
|
69
|
+
return content.getCommunity(req.params.communityId, actor);
|
|
75
70
|
}
|
|
76
71
|
});
|
|
77
72
|
r.route({
|
|
@@ -80,8 +75,8 @@ async function communitiesRoutes(app, container) {
|
|
|
80
75
|
schema: {
|
|
81
76
|
operationId: "updateCommunity",
|
|
82
77
|
tags,
|
|
83
|
-
summary: "Update a community
|
|
84
|
-
description:
|
|
78
|
+
summary: "Update a community",
|
|
79
|
+
description: `Requires \`communities: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).`,
|
|
85
80
|
params: CommunityIdParam,
|
|
86
81
|
body: UpdateCommunity,
|
|
87
82
|
response: {
|
|
@@ -90,11 +85,8 @@ async function communitiesRoutes(app, container) {
|
|
|
90
85
|
}
|
|
91
86
|
},
|
|
92
87
|
handler: async (req) => {
|
|
93
|
-
const
|
|
94
|
-
return content.updateCommunity(
|
|
95
|
-
id: scope.orgUserId,
|
|
96
|
-
role: scope.role
|
|
97
|
-
});
|
|
88
|
+
const actor = await resolveActor(container, req);
|
|
89
|
+
return content.updateCommunity(req.params.communityId, req.body, actor);
|
|
98
90
|
}
|
|
99
91
|
});
|
|
100
92
|
r.route({
|
|
@@ -103,8 +95,8 @@ async function communitiesRoutes(app, container) {
|
|
|
103
95
|
schema: {
|
|
104
96
|
operationId: "deleteCommunity",
|
|
105
97
|
tags,
|
|
106
|
-
summary: "Delete a community
|
|
107
|
-
description:
|
|
98
|
+
summary: "Delete a community",
|
|
99
|
+
description: `Requires \`communities:delete\`. Links to the community from other spaces are removed with it.`,
|
|
108
100
|
params: CommunityIdParam,
|
|
109
101
|
response: {
|
|
110
102
|
204: z.void(),
|
|
@@ -112,11 +104,8 @@ async function communitiesRoutes(app, container) {
|
|
|
112
104
|
}
|
|
113
105
|
},
|
|
114
106
|
handler: async (req, reply) => {
|
|
115
|
-
const
|
|
116
|
-
await content.deleteCommunity(
|
|
117
|
-
id: scope.orgUserId,
|
|
118
|
-
role: scope.role
|
|
119
|
-
});
|
|
107
|
+
const actor = await resolveActor(container, req);
|
|
108
|
+
await content.deleteCommunity(req.params.communityId, actor);
|
|
120
109
|
return reply.code(204).send();
|
|
121
110
|
}
|
|
122
111
|
});
|
|
@@ -124,23 +113,79 @@ async function communitiesRoutes(app, container) {
|
|
|
124
113
|
method: "PATCH",
|
|
125
114
|
url: "/api/communities/:communityId/settings",
|
|
126
115
|
schema: {
|
|
127
|
-
operationId: "
|
|
116
|
+
operationId: "patchCommunitySettings",
|
|
128
117
|
tags,
|
|
129
|
-
summary: "Change direct-message settings
|
|
130
|
-
description:
|
|
118
|
+
summary: "Change the direct-message and digest settings of a community",
|
|
119
|
+
description: `Requires \`communities:write\`. Changes only the settings sent; the rest keep their values. The direct-message settings decide who may message whom from then on. \`digest\` sets when the community digest goes out, or \`null\` stops it; the first digest after a change goes out at the next slot.`,
|
|
131
120
|
params: CommunityIdParam,
|
|
132
|
-
body:
|
|
121
|
+
body: PatchCommunitySettings,
|
|
133
122
|
response: {
|
|
134
123
|
200: Community,
|
|
135
124
|
...refusals(403, 404)
|
|
136
125
|
}
|
|
137
126
|
},
|
|
138
127
|
handler: async (req) => {
|
|
139
|
-
const
|
|
140
|
-
return content.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
128
|
+
const actor = await resolveActor(container, req);
|
|
129
|
+
return content.patchCommunitySettings(req.params.communityId, req.body, actor);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
r.route({
|
|
133
|
+
method: "GET",
|
|
134
|
+
url: "/api/communities/:communityId/notification-categories",
|
|
135
|
+
schema: {
|
|
136
|
+
operationId: "getCommunityNotificationCategories",
|
|
137
|
+
tags: ["Notifications"],
|
|
138
|
+
summary: "Get a community's notification categories",
|
|
139
|
+
description: `Requires \`communities:read\`. On the community. The list in use for the community, with \`source\` saying whether it is the default or a stored list.`,
|
|
140
|
+
params: CommunityIdParam,
|
|
141
|
+
response: {
|
|
142
|
+
200: NotificationCategoryList,
|
|
143
|
+
...refusals(403, 404)
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
handler: async (req) => {
|
|
147
|
+
const actor = await resolveActor(container, req);
|
|
148
|
+
return container.notificationCategories.community.get(req.params.communityId, actor);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
r.route({
|
|
152
|
+
method: "PUT",
|
|
153
|
+
url: "/api/communities/:communityId/notification-categories",
|
|
154
|
+
schema: {
|
|
155
|
+
operationId: "replaceCommunityNotificationCategories",
|
|
156
|
+
tags: ["Notifications"],
|
|
157
|
+
summary: "Replace a community's notification categories",
|
|
158
|
+
description: `Requires \`communities:write\`. On the community. Stores the whole list for this community; other communities keep theirs. 422 when a key repeats, a type cannot be in a community list, a reason is not allowed for its type, a channel is not configured, \`perSpace\` is set on a type that cannot occur in a space, \`spaceDefaults\` appears without \`perSpace\` or names a channel the category does not offer, or earlier categories already cover everything a category covers.`,
|
|
159
|
+
params: CommunityIdParam,
|
|
160
|
+
body: ReplaceNotificationCategories,
|
|
161
|
+
response: {
|
|
162
|
+
200: NotificationCategoryList,
|
|
163
|
+
...refusals(400, 403, 404, 422)
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
handler: async (req) => {
|
|
167
|
+
const actor = await resolveActor(container, req);
|
|
168
|
+
return container.notificationCategories.community.replace(req.params.communityId, req.body.categories, actor);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
r.route({
|
|
172
|
+
method: "DELETE",
|
|
173
|
+
url: "/api/communities/:communityId/notification-categories",
|
|
174
|
+
schema: {
|
|
175
|
+
operationId: "resetCommunityNotificationCategories",
|
|
176
|
+
tags: ["Notifications"],
|
|
177
|
+
summary: "Go back to the default notification categories for a community",
|
|
178
|
+
description: `Requires \`communities:write\`. On the community. Removes the stored list; the default applies again.`,
|
|
179
|
+
params: CommunityIdParam,
|
|
180
|
+
response: {
|
|
181
|
+
204: z.void(),
|
|
182
|
+
...refusals(403, 404)
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
handler: async (req, reply) => {
|
|
186
|
+
const actor = await resolveActor(container, req);
|
|
187
|
+
await container.notificationCategories.community.reset(req.params.communityId, actor);
|
|
188
|
+
return reply.code(204).send();
|
|
144
189
|
}
|
|
145
190
|
});
|
|
146
191
|
r.route({
|
|
@@ -149,8 +194,8 @@ async function communitiesRoutes(app, container) {
|
|
|
149
194
|
schema: {
|
|
150
195
|
operationId: "publishCommunity",
|
|
151
196
|
tags,
|
|
152
|
-
summary: "Publish a community
|
|
153
|
-
description:
|
|
197
|
+
summary: "Publish a community",
|
|
198
|
+
description: `Requires \`communities:write\`. Makes the community visible to the people who hold it.`,
|
|
154
199
|
params: CommunityIdParam,
|
|
155
200
|
response: {
|
|
156
201
|
200: Community,
|
|
@@ -158,11 +203,8 @@ async function communitiesRoutes(app, container) {
|
|
|
158
203
|
}
|
|
159
204
|
},
|
|
160
205
|
handler: async (req) => {
|
|
161
|
-
const
|
|
162
|
-
return content.publishCommunity(
|
|
163
|
-
id: scope.orgUserId,
|
|
164
|
-
role: scope.role
|
|
165
|
-
});
|
|
206
|
+
const actor = await resolveActor(container, req);
|
|
207
|
+
return content.publishCommunity(req.params.communityId, actor);
|
|
166
208
|
}
|
|
167
209
|
});
|
|
168
210
|
r.route({
|
|
@@ -171,8 +213,8 @@ async function communitiesRoutes(app, container) {
|
|
|
171
213
|
schema: {
|
|
172
214
|
operationId: "unpublishCommunity",
|
|
173
215
|
tags,
|
|
174
|
-
summary: "Unpublish a community
|
|
175
|
-
description:
|
|
216
|
+
summary: "Unpublish a community",
|
|
217
|
+
description: `Requires \`communities:write\`. Hides the community from members again; nothing in it is deleted.`,
|
|
176
218
|
params: CommunityIdParam,
|
|
177
219
|
response: {
|
|
178
220
|
200: Community,
|
|
@@ -180,11 +222,8 @@ async function communitiesRoutes(app, container) {
|
|
|
180
222
|
}
|
|
181
223
|
},
|
|
182
224
|
handler: async (req) => {
|
|
183
|
-
const
|
|
184
|
-
return content.unpublishCommunity(
|
|
185
|
-
id: scope.orgUserId,
|
|
186
|
-
role: scope.role
|
|
187
|
-
});
|
|
225
|
+
const actor = await resolveActor(container, req);
|
|
226
|
+
return content.unpublishCommunity(req.params.communityId, actor);
|
|
188
227
|
}
|
|
189
228
|
});
|
|
190
229
|
r.route({
|
|
@@ -193,8 +232,8 @@ async function communitiesRoutes(app, container) {
|
|
|
193
232
|
schema: {
|
|
194
233
|
operationId: "getCommunityAnalytics",
|
|
195
234
|
tags,
|
|
196
|
-
summary: "
|
|
197
|
-
description:
|
|
235
|
+
summary: "Analytics for a community",
|
|
236
|
+
description: `Requires \`communities:read\`. Membership, activity and moderation counts for one community.`,
|
|
198
237
|
params: CommunityIdParam,
|
|
199
238
|
response: {
|
|
200
239
|
200: CommunityAnalytics,
|
|
@@ -202,10 +241,8 @@ async function communitiesRoutes(app, container) {
|
|
|
202
241
|
}
|
|
203
242
|
},
|
|
204
243
|
handler: async (req) => {
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
if (!stats) throw new NotFoundError("Community", req.params.communityId);
|
|
208
|
-
return stats;
|
|
244
|
+
const actor = await resolveActor(container, req);
|
|
245
|
+
return container.reporting.admin.communityAnalytics(req.params.communityId, actor);
|
|
209
246
|
}
|
|
210
247
|
});
|
|
211
248
|
r.route({
|
|
@@ -214,8 +251,8 @@ async function communitiesRoutes(app, container) {
|
|
|
214
251
|
schema: {
|
|
215
252
|
operationId: "getCommunityMessageQueue",
|
|
216
253
|
tags,
|
|
217
|
-
summary: "Open message flags in a community
|
|
218
|
-
description:
|
|
254
|
+
summary: "Open message flags in a community",
|
|
255
|
+
description: `Requires \`communities:moderate\`. The messages in the community's chats with open flags, with the flags and the chat each is in. Holds at most the 100 oldest open flags; working the queue brings in the next ones.`,
|
|
219
256
|
params: CommunityIdParam,
|
|
220
257
|
response: {
|
|
221
258
|
200: MessageQueue,
|
|
@@ -223,11 +260,8 @@ async function communitiesRoutes(app, container) {
|
|
|
223
260
|
}
|
|
224
261
|
},
|
|
225
262
|
handler: async (req) => {
|
|
226
|
-
const
|
|
227
|
-
return container.chats.messageQueue(
|
|
228
|
-
id: scope.orgUserId,
|
|
229
|
-
role: scope.role
|
|
230
|
-
}, req.params.communityId);
|
|
263
|
+
const actor = await resolveActor(container, req);
|
|
264
|
+
return container.chats.messageQueue(req.params.communityId, actor);
|
|
231
265
|
}
|
|
232
266
|
});
|
|
233
267
|
r.route({
|
|
@@ -236,8 +270,8 @@ async function communitiesRoutes(app, container) {
|
|
|
236
270
|
schema: {
|
|
237
271
|
operationId: "listCommunitySpaces",
|
|
238
272
|
tags,
|
|
239
|
-
summary: "List the spaces in a community
|
|
240
|
-
description:
|
|
273
|
+
summary: "List the spaces in a community",
|
|
274
|
+
description: `Requires one of \`communities:read\`, \`communities:moderate\`. Every space in order, with its topics and links.`,
|
|
241
275
|
params: CommunityIdParam,
|
|
242
276
|
response: {
|
|
243
277
|
200: z.array(SpaceDetail),
|
|
@@ -245,8 +279,8 @@ async function communitiesRoutes(app, container) {
|
|
|
245
279
|
}
|
|
246
280
|
},
|
|
247
281
|
handler: async (req) => {
|
|
248
|
-
const
|
|
249
|
-
return content.listSpaces(
|
|
282
|
+
const actor = await resolveActor(container, req);
|
|
283
|
+
return content.listSpaces(req.params.communityId, actor);
|
|
250
284
|
}
|
|
251
285
|
});
|
|
252
286
|
r.route({
|
|
@@ -255,8 +289,8 @@ async function communitiesRoutes(app, container) {
|
|
|
255
289
|
schema: {
|
|
256
290
|
operationId: "createSpace",
|
|
257
291
|
tags,
|
|
258
|
-
summary: "Create a space
|
|
259
|
-
description:
|
|
292
|
+
summary: "Create a space",
|
|
293
|
+
description: `Requires \`communities:write\`. The space is added last. An \`all_members\` space cannot have a capacity (409).`,
|
|
260
294
|
params: CommunityIdParam,
|
|
261
295
|
body: CreateSpace,
|
|
262
296
|
response: {
|
|
@@ -265,11 +299,8 @@ async function communitiesRoutes(app, container) {
|
|
|
265
299
|
}
|
|
266
300
|
},
|
|
267
301
|
handler: async (req, reply) => {
|
|
268
|
-
const
|
|
269
|
-
const space = await content.createSpace(
|
|
270
|
-
id: scope.orgUserId,
|
|
271
|
-
role: scope.role
|
|
272
|
-
});
|
|
302
|
+
const actor = await resolveActor(container, req);
|
|
303
|
+
const space = await content.createSpace(req.params.communityId, req.body, actor);
|
|
273
304
|
return reply.code(201).send(space);
|
|
274
305
|
}
|
|
275
306
|
});
|
|
@@ -279,8 +310,8 @@ async function communitiesRoutes(app, container) {
|
|
|
279
310
|
schema: {
|
|
280
311
|
operationId: "reorderSpaces",
|
|
281
312
|
tags,
|
|
282
|
-
summary: "Reorder the spaces in a community
|
|
283
|
-
description:
|
|
313
|
+
summary: "Reorder the spaces in a community",
|
|
314
|
+
description: `Requires \`communities:write\`. Send every space id of the community exactly once (409 otherwise).`,
|
|
284
315
|
params: CommunityIdParam,
|
|
285
316
|
body: OrderedIds,
|
|
286
317
|
response: {
|
|
@@ -289,11 +320,8 @@ async function communitiesRoutes(app, container) {
|
|
|
289
320
|
}
|
|
290
321
|
},
|
|
291
322
|
handler: async (req) => {
|
|
292
|
-
const
|
|
293
|
-
return content.reorderSpaces(
|
|
294
|
-
id: scope.orgUserId,
|
|
295
|
-
role: scope.role
|
|
296
|
-
});
|
|
323
|
+
const actor = await resolveActor(container, req);
|
|
324
|
+
return content.reorderSpaces(req.params.communityId, req.body.ids, actor);
|
|
297
325
|
}
|
|
298
326
|
});
|
|
299
327
|
r.route({
|
|
@@ -302,8 +330,8 @@ async function communitiesRoutes(app, container) {
|
|
|
302
330
|
schema: {
|
|
303
331
|
operationId: "getSpace",
|
|
304
332
|
tags,
|
|
305
|
-
summary: "Get a space
|
|
306
|
-
description:
|
|
333
|
+
summary: "Get a space",
|
|
334
|
+
description: `Requires \`communities:read\`. The space with its topics and links.`,
|
|
307
335
|
params: CommunitySpaceParam,
|
|
308
336
|
response: {
|
|
309
337
|
200: SpaceDetail,
|
|
@@ -311,10 +339,8 @@ async function communitiesRoutes(app, container) {
|
|
|
311
339
|
}
|
|
312
340
|
},
|
|
313
341
|
handler: async (req) => {
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
if (!space) throw new NotFoundError("Space", req.params.spaceId);
|
|
317
|
-
return space;
|
|
342
|
+
const actor = await resolveActor(container, req);
|
|
343
|
+
return content.getCommunitySpace(req.params.communityId, req.params.spaceId, actor);
|
|
318
344
|
}
|
|
319
345
|
});
|
|
320
346
|
r.route({
|
|
@@ -323,8 +349,8 @@ async function communitiesRoutes(app, container) {
|
|
|
323
349
|
schema: {
|
|
324
350
|
operationId: "updateSpace",
|
|
325
351
|
tags,
|
|
326
|
-
summary: "Update a space
|
|
327
|
-
description:
|
|
352
|
+
summary: "Update a space",
|
|
353
|
+
description: `Requires \`communities:write\`. Changes only the fields sent; \`settings\` merges into the current settings. An \`all_members\` space cannot have a capacity (409).`,
|
|
328
354
|
params: CommunitySpaceParam,
|
|
329
355
|
body: UpdateSpace,
|
|
330
356
|
response: {
|
|
@@ -333,11 +359,8 @@ async function communitiesRoutes(app, container) {
|
|
|
333
359
|
}
|
|
334
360
|
},
|
|
335
361
|
handler: async (req) => {
|
|
336
|
-
const
|
|
337
|
-
return content.updateSpace(
|
|
338
|
-
id: scope.orgUserId,
|
|
339
|
-
role: scope.role
|
|
340
|
-
});
|
|
362
|
+
const actor = await resolveActor(container, req);
|
|
363
|
+
return content.updateSpace(req.params.communityId, req.params.spaceId, req.body, actor);
|
|
341
364
|
}
|
|
342
365
|
});
|
|
343
366
|
r.route({
|
|
@@ -346,8 +369,8 @@ async function communitiesRoutes(app, container) {
|
|
|
346
369
|
schema: {
|
|
347
370
|
operationId: "deleteSpace",
|
|
348
371
|
tags,
|
|
349
|
-
summary: "Delete a space
|
|
350
|
-
description:
|
|
372
|
+
summary: "Delete a space",
|
|
373
|
+
description: `Requires \`communities:write\`. The space and everything in it go.`,
|
|
351
374
|
params: CommunitySpaceParam,
|
|
352
375
|
response: {
|
|
353
376
|
204: z.void(),
|
|
@@ -355,11 +378,8 @@ async function communitiesRoutes(app, container) {
|
|
|
355
378
|
}
|
|
356
379
|
},
|
|
357
380
|
handler: async (req, reply) => {
|
|
358
|
-
const
|
|
359
|
-
await content.deleteSpace(
|
|
360
|
-
id: scope.orgUserId,
|
|
361
|
-
role: scope.role
|
|
362
|
-
});
|
|
381
|
+
const actor = await resolveActor(container, req);
|
|
382
|
+
await content.deleteSpace(req.params.communityId, req.params.spaceId, actor);
|
|
363
383
|
return reply.code(204).send();
|
|
364
384
|
}
|
|
365
385
|
});
|
|
@@ -369,8 +389,8 @@ async function communitiesRoutes(app, container) {
|
|
|
369
389
|
schema: {
|
|
370
390
|
operationId: "setSpaceTopics",
|
|
371
391
|
tags,
|
|
372
|
-
summary: "Replace the topics on a space
|
|
373
|
-
description:
|
|
392
|
+
summary: "Replace the topics on a space",
|
|
393
|
+
description: `Requires \`communities:write\`. The list replaces the current topics: an entry with an \`id\` keeps and renames that topic, one without adds a topic, and a topic left out is deleted. Names must be unique (409), and a topic that posts use cannot be deleted (409).`,
|
|
374
394
|
params: CommunitySpaceParam,
|
|
375
395
|
body: SetSpaceTopics,
|
|
376
396
|
response: {
|
|
@@ -379,11 +399,8 @@ async function communitiesRoutes(app, container) {
|
|
|
379
399
|
}
|
|
380
400
|
},
|
|
381
401
|
handler: async (req) => {
|
|
382
|
-
const
|
|
383
|
-
return content.setSpaceTopics(
|
|
384
|
-
id: scope.orgUserId,
|
|
385
|
-
role: scope.role
|
|
386
|
-
});
|
|
402
|
+
const actor = await resolveActor(container, req);
|
|
403
|
+
return content.setSpaceTopics(req.params.communityId, req.params.spaceId, req.body, actor);
|
|
387
404
|
}
|
|
388
405
|
});
|
|
389
406
|
r.route({
|
|
@@ -392,8 +409,8 @@ async function communitiesRoutes(app, container) {
|
|
|
392
409
|
schema: {
|
|
393
410
|
operationId: "addSpaceLink",
|
|
394
411
|
tags,
|
|
395
|
-
summary: "Link a course, download, or community into a space
|
|
396
|
-
description:
|
|
412
|
+
summary: "Link a course, download, or community into a space",
|
|
413
|
+
description: `Requires \`communities:write\`. The link is added last. Linking the same content twice is a 409.`,
|
|
397
414
|
params: CommunitySpaceParam,
|
|
398
415
|
body: SpaceLinkBody,
|
|
399
416
|
response: {
|
|
@@ -402,11 +419,8 @@ async function communitiesRoutes(app, container) {
|
|
|
402
419
|
}
|
|
403
420
|
},
|
|
404
421
|
handler: async (req, reply) => {
|
|
405
|
-
const
|
|
406
|
-
const space = await content.addSpaceLink(
|
|
407
|
-
id: scope.orgUserId,
|
|
408
|
-
role: scope.role
|
|
409
|
-
});
|
|
422
|
+
const actor = await resolveActor(container, req);
|
|
423
|
+
const space = await content.addSpaceLink(req.params.communityId, req.params.spaceId, req.body.contentId, actor);
|
|
410
424
|
return reply.code(201).send(space);
|
|
411
425
|
}
|
|
412
426
|
});
|
|
@@ -416,8 +430,8 @@ async function communitiesRoutes(app, container) {
|
|
|
416
430
|
schema: {
|
|
417
431
|
operationId: "removeSpaceLink",
|
|
418
432
|
tags,
|
|
419
|
-
summary: "Remove a link from a space
|
|
420
|
-
description:
|
|
433
|
+
summary: "Remove a link from a space",
|
|
434
|
+
description: `Requires \`communities:write\`. The linked content itself is untouched.`,
|
|
421
435
|
params: SpaceLinkParam,
|
|
422
436
|
response: {
|
|
423
437
|
200: SpaceDetail,
|
|
@@ -425,11 +439,8 @@ async function communitiesRoutes(app, container) {
|
|
|
425
439
|
}
|
|
426
440
|
},
|
|
427
441
|
handler: async (req) => {
|
|
428
|
-
const
|
|
429
|
-
return content.removeSpaceLink(
|
|
430
|
-
id: scope.orgUserId,
|
|
431
|
-
role: scope.role
|
|
432
|
-
});
|
|
442
|
+
const actor = await resolveActor(container, req);
|
|
443
|
+
return content.removeSpaceLink(req.params.communityId, req.params.spaceId, req.params.linkId, actor);
|
|
433
444
|
}
|
|
434
445
|
});
|
|
435
446
|
r.route({
|
|
@@ -438,8 +449,8 @@ async function communitiesRoutes(app, container) {
|
|
|
438
449
|
schema: {
|
|
439
450
|
operationId: "reorderSpaceLinks",
|
|
440
451
|
tags,
|
|
441
|
-
summary: "Reorder the links in a space
|
|
442
|
-
description:
|
|
452
|
+
summary: "Reorder the links in a space",
|
|
453
|
+
description: `Requires \`communities:write\`. Send every link id of the space exactly once (409 otherwise).`,
|
|
443
454
|
params: CommunitySpaceParam,
|
|
444
455
|
body: OrderedIds,
|
|
445
456
|
response: {
|
|
@@ -448,11 +459,8 @@ async function communitiesRoutes(app, container) {
|
|
|
448
459
|
}
|
|
449
460
|
},
|
|
450
461
|
handler: async (req) => {
|
|
451
|
-
const
|
|
452
|
-
return content.reorderSpaceLinks(
|
|
453
|
-
id: scope.orgUserId,
|
|
454
|
-
role: scope.role
|
|
455
|
-
});
|
|
462
|
+
const actor = await resolveActor(container, req);
|
|
463
|
+
return content.reorderSpaceLinks(req.params.communityId, req.params.spaceId, req.body.ids, actor);
|
|
456
464
|
}
|
|
457
465
|
});
|
|
458
466
|
}
|