@raclettejs/core 0.1.18 → 0.1.20
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/CHANGELOG.md +23 -0
- package/bin/cli.js +1 -1
- package/dev/README.md +4 -0
- package/dist/cli.js +135 -124
- package/dist/cli.js.map +4 -4
- package/dist/index.js +9 -8
- package/dist/index.js.map +4 -4
- package/package.json +9 -5
- package/services/backend/delay-api-debugger.sh +0 -0
- package/services/backend/package.json +1 -0
- package/services/backend/src/app.ts +4 -0
- package/services/backend/src/core/config/configService.ts +10 -1
- package/services/backend/src/core/events/eventEmitter.ts +32 -7
- package/services/backend/src/core/http/request-params.plugin.ts +2 -2
- package/services/backend/src/core/pluginSystem/pluginFastifyInstance.ts +4 -1
- package/services/backend/src/core/pluginSystem/pluginTypes.ts +3 -1
- package/services/backend/src/core/sockets/createSystemEventHandlers.ts +7 -0
- package/services/backend/src/core/sockets/index.ts +61 -13
- package/services/backend/src/core/sockets/socketManager.ts +452 -105
- package/services/backend/src/core/sockets/socketTypes.ts +13 -1
- package/services/backend/src/core/sockets/workSessionJoinPayload.ts +106 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/account/routes/route.account.get.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/account/routes/route.account.getAll.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/account/routes/route.account.hardDelete.ts +16 -19
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/account/routes/route.account.patch.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/account/routes/route.account.post.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/account/routes/route.account.remove.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/composition.service.ts +86 -3
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/routes/index.ts +2 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/routes/route.composition.get.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/routes/route.composition.getAll.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/routes/route.composition.hardDelete.ts +16 -19
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/routes/route.composition.patch.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/routes/route.composition.post.bulk.ts +60 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/routes/route.composition.post.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/routes/route.composition.remove.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/routes/route.composition.restore.ts +12 -15
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/interactionLink.service.ts +96 -12
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/routes/index.ts +2 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/routes/route.interactionLink.get.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/routes/route.interactionLink.getAll.ts +4 -2
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/routes/route.interactionLink.hardDelete.ts +12 -17
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/routes/route.interactionLink.patch.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/routes/route.interactionLink.post.bulk.ts +62 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/routes/route.interactionLink.post.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/routes/route.interactionLink.remove.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/routes/route.interactionLink.restore.ts +12 -15
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/project.service.ts +1 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/routes/route.project.get.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/routes/route.project.getAll.ts +4 -2
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/routes/route.project.hardDelete.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/routes/route.project.patch.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/routes/route.project.post.ts +4 -2
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/routes/route.project.remove.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/routes/index.ts +2 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/routes/route.tag.get.ts +1 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/routes/route.tag.getAll.ts +1 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/routes/route.tag.hardDelete.ts +10 -15
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/routes/route.tag.patch.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/routes/route.tag.post.bulk.ts +60 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/routes/route.tag.post.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/routes/route.tag.remove.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/routes/route.tag.restore.ts +12 -15
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/tag.service.ts +73 -3
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/route.user.get.ts +1 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/route.user.getAll.ts +1 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/route.user.hardDelete.ts +10 -15
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/route.user.patch.ts +4 -6
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/route.user.patchLastProject.ts +4 -2
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/route.user.post.ts +3 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/route.user.remove.ts +3 -4
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/route.user.restore.ts +12 -15
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/workSession/events/index.ts +45 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/workSession/helpers/crud.ts +12 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/workSession/helpers/payload.ts +21 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/workSession/index.ts +55 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/workSession/routes/index.ts +19 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/workSession/routes/route.workSession.get.ts +53 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/workSession/routes/route.workSession.getAll.ts +39 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/workSession/routes/route.workSession.hardDelete.ts +53 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/workSession/routes/route.workSession.patch.ts +58 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/workSession/routes/route.workSession.post.ts +53 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/workSession/routes/route.workSession.remove.ts +52 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/workSession/workSession.model.ts +65 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/workSession/workSession.schema.ts +125 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/workSession/workSession.service.ts +351 -0
- package/services/backend/src/corePlugins/raclette__core/backend/index.ts +2 -0
- package/services/backend/src/corePlugins/raclette__core/frontend/generated-config.ts +159 -24
- package/services/backend/src/modules/authentication/index.ts +255 -4
- package/services/backend/src/modules/hooks/rate-limiter.ts +21 -0
- package/services/backend/src/types/custom-fastify.d.ts +17 -0
- package/services/backend/src/utils/request.utils.ts +4 -1
- package/services/backend/types/index.d.ts +15 -1
- package/services/backend/yarn.lock +13 -4
- package/services/frontend/index.html +1 -1
- package/services/frontend/provision/entrypoint.sh +0 -0
- package/services/frontend/src/core/lib/configService.ts +1 -1
- package/services/frontend/src/core/lib/data/dataApi.ts +10 -1
- package/services/frontend/src/core/lib/dataHelper.ts +1 -1
- package/services/frontend/src/core/lib/eggs/snow.ts +66 -48
- package/services/frontend/src/core/lib/helpers/index.ts +1 -0
- package/services/frontend/src/core/lib/helpers/removeEmpty.ts +69 -0
- package/services/frontend/src/core/lib/httpClient.ts +19 -0
- package/services/frontend/src/core/main.ts +20 -10
- package/services/frontend/src/core/setup/socket.ts +4 -3
- package/services/frontend/src/core/setup/socketClient.ts +31 -3
- package/services/frontend/src/core/setup/socketEvents.ts +92 -8
- package/services/frontend/src/core/store/index.ts +5 -1
- package/services/frontend/src/core/store/reducers/compositions/index.ts +2 -2
- package/services/frontend/src/core/store/reducers/interactionLinks/index.ts +1 -1
- package/services/frontend/src/core/store/reducers/widgets/reducers.ts +1 -2
- package/services/frontend/src/core/store/types/index.ts +0 -1
- package/services/frontend/src/core/types/PluginRegistrar.ts +8 -6
- package/services/frontend/src/core/types/Store.ts +1 -0
- package/services/frontend/src/orchestrator/components/composition/WidgetsLayoutLoader.vue +68 -8
- package/services/frontend/src/orchestrator/components/menu/UserMenu.vue +17 -5
- package/services/frontend/src/orchestrator/components/welcomeScreen/AdminWelcomeScreen.vue +1 -1
- package/services/frontend/src/orchestrator/composables/index.ts +1 -0
- package/services/frontend/src/orchestrator/composables/usePluginApi.ts +0 -3
- package/services/frontend/src/orchestrator/composables/useRouteState.ts +23 -4
- package/services/frontend/src/orchestrator/composables/useWidgetLifecycle.ts +166 -0
- package/services/frontend/src/orchestrator/helpers/index.ts +1 -0
- package/services/frontend/src/orchestrator/i18n/de-DE.json +15 -1
- package/services/frontend/src/orchestrator/i18n/en-EU.json +15 -1
- package/services/frontend/src/orchestrator/i18n/sk.json +15 -1
- package/services/frontend/src/orchestrator/index.ts +34 -4
- package/services/frontend/src/orchestrator/router/routeParserHelper.ts +106 -1
- package/services/frontend/src/orchestrator/types/Widgets.ts +2 -0
- package/services/frontend/types.ts +1 -0
- package/src/README.md +404 -0
- package/src/types.ts +19 -5
- package/templates/README.md +0 -0
- package/types/index.ts +18 -4
- package/services/backend/.gitignore +0 -17
- package/services/frontend/.gitignore +0 -35
- package/yarn.lock +0 -2937
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { TagBody } from "../tag.service"
|
|
2
|
+
import type { FastifyReply, FastifyRequest } from "fastify"
|
|
3
|
+
import type { PluginFastifyInstance } from "types"
|
|
4
|
+
import { tagCreateSchema } from "../tag.schema"
|
|
5
|
+
|
|
6
|
+
const permissions = ["user.isAdmin"]
|
|
7
|
+
|
|
8
|
+
export default (fastify: PluginFastifyInstance) => {
|
|
9
|
+
const tagService = fastify.custom.tagService
|
|
10
|
+
|
|
11
|
+
const handler = async (
|
|
12
|
+
req: FastifyRequest<{
|
|
13
|
+
Body: TagBody[]
|
|
14
|
+
}>,
|
|
15
|
+
reply: FastifyReply,
|
|
16
|
+
) => {
|
|
17
|
+
try {
|
|
18
|
+
// Validate that body is an array
|
|
19
|
+
if (!Array.isArray(req.body)) {
|
|
20
|
+
return reply.badRequest("Request body must be an array of tags")
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Validate that array is not empty
|
|
24
|
+
if (req.body.length === 0) {
|
|
25
|
+
return reply.badRequest("Request body cannot be an empty array")
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const payload = await tagService.createTags(
|
|
29
|
+
fastify,
|
|
30
|
+
req.requestParams,
|
|
31
|
+
req.body,
|
|
32
|
+
req.user._id,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
return payload
|
|
36
|
+
} catch (error: any) {
|
|
37
|
+
fastify.log.error(error.message)
|
|
38
|
+
|
|
39
|
+
return reply.internalServerError(error.message)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
handler,
|
|
45
|
+
onRequest: [fastify.authenticate, fastify.checkPermissions(permissions)],
|
|
46
|
+
config: {
|
|
47
|
+
type: "dataCreate",
|
|
48
|
+
broadcastChannels: ["tagsCreated"],
|
|
49
|
+
},
|
|
50
|
+
schema: {
|
|
51
|
+
summary: "Create multiple tags in bulk",
|
|
52
|
+
tags: ["core/tag"],
|
|
53
|
+
body: {
|
|
54
|
+
type: "array",
|
|
55
|
+
items: tagCreateSchema,
|
|
56
|
+
minItems: 1,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -4,6 +4,8 @@ import { PluginFastifyInstance } from "types"
|
|
|
4
4
|
import { Type } from "@sinclair/typebox"
|
|
5
5
|
import { tagCreateSchema, type TagCreate } from "../tag.schema"
|
|
6
6
|
|
|
7
|
+
const permissions = ["user.isAdmin"]
|
|
8
|
+
|
|
7
9
|
const ParamsSchema = Type.Object({
|
|
8
10
|
_id: Type.String(),
|
|
9
11
|
project: Type.String(),
|
|
@@ -38,7 +40,7 @@ export default (fastify: PluginFastifyInstance) => {
|
|
|
38
40
|
|
|
39
41
|
return {
|
|
40
42
|
handler,
|
|
41
|
-
onRequest: [fastify.authenticate],
|
|
43
|
+
onRequest: [fastify.authenticate, fastify.checkPermissions(permissions)],
|
|
42
44
|
config: {
|
|
43
45
|
type: "dataCreate",
|
|
44
46
|
broadcastChannels: ["tagCreated"],
|
|
@@ -3,6 +3,8 @@ import type { FastifyReply, FastifyRequest } from "fastify"
|
|
|
3
3
|
import { PluginFastifyInstance } from "types"
|
|
4
4
|
import { Type } from "@sinclair/typebox"
|
|
5
5
|
|
|
6
|
+
const permissions = ["user.isAdmin"]
|
|
7
|
+
|
|
6
8
|
const ParamsSchema = Type.Object({
|
|
7
9
|
_id: Type.String(),
|
|
8
10
|
})
|
|
@@ -33,7 +35,7 @@ export default (fastify: PluginFastifyInstance) => {
|
|
|
33
35
|
|
|
34
36
|
return {
|
|
35
37
|
handler,
|
|
36
|
-
onRequest: [fastify.authenticate],
|
|
38
|
+
onRequest: [fastify.authenticate, fastify.checkPermissions(permissions)],
|
|
37
39
|
config: {
|
|
38
40
|
type: "dataUpdate",
|
|
39
41
|
broadcastChannels: ["tagDeleted"],
|
|
@@ -2,7 +2,8 @@ import type { Static } from "@sinclair/typebox"
|
|
|
2
2
|
import type { FastifyReply, FastifyRequest } from "fastify"
|
|
3
3
|
import { PluginFastifyInstance } from "types"
|
|
4
4
|
import { Type } from "@sinclair/typebox"
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
const permissions = ["user.isAdmin"]
|
|
6
7
|
|
|
7
8
|
const ParamsSchema = Type.Object({
|
|
8
9
|
_id: Type.String(),
|
|
@@ -17,21 +18,17 @@ export default (fastify: PluginFastifyInstance) => {
|
|
|
17
18
|
reply: FastifyReply,
|
|
18
19
|
) => {
|
|
19
20
|
try {
|
|
20
|
-
|
|
21
|
-
const { _id } = req.params
|
|
21
|
+
const { _id } = req.params
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
const payload = await tagService.updateTag(
|
|
24
|
+
fastify,
|
|
25
|
+
req.requestParams,
|
|
26
|
+
_id,
|
|
27
|
+
{ isDeleted: false },
|
|
28
|
+
req.user._id,
|
|
29
|
+
)
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
} else {
|
|
33
|
-
throw new ForbiddenError("Only admins can restore this core datatype")
|
|
34
|
-
}
|
|
31
|
+
return payload
|
|
35
32
|
} catch (error: any) {
|
|
36
33
|
fastify.log.error(error.message)
|
|
37
34
|
return reply.internalServerError(error.message)
|
|
@@ -40,7 +37,7 @@ export default (fastify: PluginFastifyInstance) => {
|
|
|
40
37
|
|
|
41
38
|
return {
|
|
42
39
|
handler,
|
|
43
|
-
onRequest: [fastify.authenticate],
|
|
40
|
+
onRequest: [fastify.authenticate, fastify.checkPermissions(permissions)],
|
|
44
41
|
config: {
|
|
45
42
|
type: "dataRestore",
|
|
46
43
|
broadcastChannels: ["tagRestored"],
|
package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/tag.service.ts
CHANGED
|
@@ -8,7 +8,9 @@ import type { PluginFastifyInstance } from "types"
|
|
|
8
8
|
import { v4 as uuidv4, validate } from "uuid"
|
|
9
9
|
import { createTagPayload } from "./helpers/payload"
|
|
10
10
|
import type { Model } from "mongoose"
|
|
11
|
-
|
|
11
|
+
export type TagBody = Partial<Omit<TagType, "_id">> & {
|
|
12
|
+
_id?: string
|
|
13
|
+
}
|
|
12
14
|
export class TagService {
|
|
13
15
|
private tagModel: Model<TagType>
|
|
14
16
|
|
|
@@ -131,8 +133,7 @@ export class TagService {
|
|
|
131
133
|
options: QueryOptions = {},
|
|
132
134
|
): Promise<TagType[]> {
|
|
133
135
|
try {
|
|
134
|
-
|
|
135
|
-
filter.isDeleted = false
|
|
136
|
+
filter = { isDeleted: false, ...filter }
|
|
136
137
|
// Start building the query
|
|
137
138
|
let query = this.tagModel.find(filter)
|
|
138
139
|
|
|
@@ -369,6 +370,75 @@ export class TagService {
|
|
|
369
370
|
|
|
370
371
|
fastify.emit("tagHardDeleted", payload)
|
|
371
372
|
|
|
373
|
+
return payload
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Core function to create multiple tags (returns raw data)
|
|
377
|
+
*/
|
|
378
|
+
async _createTags(
|
|
379
|
+
fastify: PluginFastifyInstance,
|
|
380
|
+
tagBodies: TagBody[],
|
|
381
|
+
userId: string,
|
|
382
|
+
): Promise<TagType[]> {
|
|
383
|
+
try {
|
|
384
|
+
const tagsToCreate: TagBody[] = []
|
|
385
|
+
|
|
386
|
+
// Validate and prepare all tags
|
|
387
|
+
for (const tagBody of tagBodies) {
|
|
388
|
+
if (tagBody._id) {
|
|
389
|
+
const uuidValid = validate(tagBody._id)
|
|
390
|
+
|
|
391
|
+
if (!uuidValid) {
|
|
392
|
+
throw new Error(`Invalid ID - not a valid uuid v4: ${tagBody._id}`)
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const duplicate = await this.tagModel.findOne({
|
|
396
|
+
_id: tagBody._id,
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
if (duplicate) {
|
|
400
|
+
throw new Error(
|
|
401
|
+
`An entry with this id already exists: ${tagBody._id}`,
|
|
402
|
+
)
|
|
403
|
+
}
|
|
404
|
+
} else {
|
|
405
|
+
tagBody._id = uuidv4()
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
tagsToCreate.push({
|
|
409
|
+
...tagBody,
|
|
410
|
+
author: userId,
|
|
411
|
+
lastEditor: userId,
|
|
412
|
+
})
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// Bulk insert
|
|
416
|
+
const tags = await this.tagModel.insertMany(tagsToCreate)
|
|
417
|
+
|
|
418
|
+
fastify.log.info(`[API] Created ${tags.length} tags in bulk`)
|
|
419
|
+
|
|
420
|
+
return tags.map((comp) => (comp.toObject ? comp.toObject() : comp))
|
|
421
|
+
} catch (error: any) {
|
|
422
|
+
fastify.log.error(error.message)
|
|
423
|
+
throw error
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Create multiple tags with payload wrapping and event emission
|
|
429
|
+
*/
|
|
430
|
+
async createTags(
|
|
431
|
+
fastify: PluginFastifyInstance,
|
|
432
|
+
requestData: FrontendPayloadRequestData,
|
|
433
|
+
tagBodies: TagBody[],
|
|
434
|
+
userId: string,
|
|
435
|
+
): Promise<FrontendPayload<TagType[]>> {
|
|
436
|
+
const tags = await this._createTags(fastify, tagBodies, userId)
|
|
437
|
+
|
|
438
|
+
const payload = await createTagPayload(fastify, tags, requestData)
|
|
439
|
+
|
|
440
|
+
fastify.emit("tagsCreated", payload)
|
|
441
|
+
|
|
372
442
|
return payload
|
|
373
443
|
}
|
|
374
444
|
}
|
|
@@ -2,6 +2,7 @@ import type { Static } from "@sinclair/typebox"
|
|
|
2
2
|
import type { FastifyReply, FastifyRequest } from "fastify"
|
|
3
3
|
import { PluginFastifyInstance } from "types"
|
|
4
4
|
import { Type } from "@sinclair/typebox"
|
|
5
|
+
import { ForbiddenError } from "@/utils/errors"
|
|
5
6
|
|
|
6
7
|
const ParamsSchema = Type.Object({
|
|
7
8
|
_id: Type.String(),
|
|
@@ -2,6 +2,7 @@ import type { Static } from "@sinclair/typebox"
|
|
|
2
2
|
import type { FastifyReply, FastifyRequest } from "fastify"
|
|
3
3
|
import { PluginFastifyInstance } from "types"
|
|
4
4
|
import { Type } from "@sinclair/typebox"
|
|
5
|
+
import { ForbiddenError } from "@/utils/errors"
|
|
5
6
|
|
|
6
7
|
const QuerySchema = Type.Object({
|
|
7
8
|
account: Type.Optional(Type.String()),
|
|
@@ -2,7 +2,8 @@ import type { Static } from "@sinclair/typebox"
|
|
|
2
2
|
import type { FastifyReply, FastifyRequest } from "fastify"
|
|
3
3
|
import { PluginFastifyInstance } from "types"
|
|
4
4
|
import { Type } from "@sinclair/typebox"
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
const permissions = ["user.isAdmin"]
|
|
6
7
|
|
|
7
8
|
const ParamsSchema = Type.Object({
|
|
8
9
|
_id: Type.String(),
|
|
@@ -17,21 +18,15 @@ export default (fastify: PluginFastifyInstance) => {
|
|
|
17
18
|
reply: FastifyReply,
|
|
18
19
|
) => {
|
|
19
20
|
try {
|
|
20
|
-
|
|
21
|
-
const { _id } = req.params
|
|
21
|
+
const { _id } = req.params
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
const payloadWithUser = await userService.hardDeleteUser(
|
|
24
|
+
fastify,
|
|
25
|
+
req.requestParams,
|
|
26
|
+
_id,
|
|
27
|
+
)
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
} else {
|
|
31
|
-
throw new ForbiddenError(
|
|
32
|
-
"Only admins can hard delete this core datatype",
|
|
33
|
-
)
|
|
34
|
-
}
|
|
29
|
+
return payloadWithUser
|
|
35
30
|
} catch (error: any) {
|
|
36
31
|
fastify.log.error(error.message)
|
|
37
32
|
return reply.internalServerError(error.message)
|
|
@@ -40,7 +35,7 @@ export default (fastify: PluginFastifyInstance) => {
|
|
|
40
35
|
|
|
41
36
|
return {
|
|
42
37
|
handler,
|
|
43
|
-
onRequest: [fastify.authenticate],
|
|
38
|
+
onRequest: [fastify.authenticate, fastify.checkPermissions(permissions)],
|
|
44
39
|
config: {
|
|
45
40
|
type: "dataHardDeleted",
|
|
46
41
|
broadcastChannels: ["userHardDeleted"],
|
|
@@ -4,6 +4,8 @@ import type { PluginFastifyInstance } from "types"
|
|
|
4
4
|
import { Type } from "@sinclair/typebox"
|
|
5
5
|
import { userUpdateSchema } from "../user.schema"
|
|
6
6
|
|
|
7
|
+
const permissions = ["user.isAdmin"]
|
|
8
|
+
|
|
7
9
|
const ParamsSchema = Type.Object({
|
|
8
10
|
_id: Type.String(),
|
|
9
11
|
})
|
|
@@ -22,15 +24,11 @@ export default (fastify: PluginFastifyInstance) => {
|
|
|
22
24
|
reply: FastifyReply,
|
|
23
25
|
) => {
|
|
24
26
|
try {
|
|
25
|
-
let cleanBody = req.body
|
|
26
|
-
if (!req.user.isAdmin) {
|
|
27
|
-
delete cleanBody.tags
|
|
28
|
-
}
|
|
29
27
|
const payloadWithUser = await userService.updateUser(
|
|
30
28
|
fastify,
|
|
31
29
|
req.requestParams,
|
|
32
30
|
req.params._id,
|
|
33
|
-
|
|
31
|
+
req.body,
|
|
34
32
|
)
|
|
35
33
|
|
|
36
34
|
return payloadWithUser
|
|
@@ -42,7 +40,7 @@ export default (fastify: PluginFastifyInstance) => {
|
|
|
42
40
|
|
|
43
41
|
return {
|
|
44
42
|
handler,
|
|
45
|
-
onRequest: [fastify.authenticate],
|
|
43
|
+
onRequest: [fastify.authenticate, fastify.checkPermissions(permissions)],
|
|
46
44
|
config: {
|
|
47
45
|
type: "dataUpdate",
|
|
48
46
|
broadcastChannels: ["userUpdated"],
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { FastifyReply, FastifyRequest } from "fastify"
|
|
2
|
-
import { PluginFastifyInstance } from "types"
|
|
2
|
+
import type { PluginFastifyInstance } from "types"
|
|
3
3
|
import { Type } from "@sinclair/typebox"
|
|
4
4
|
|
|
5
|
+
const permissions = ["user.isAdmin"]
|
|
6
|
+
|
|
5
7
|
export default (fastify: PluginFastifyInstance) => {
|
|
6
8
|
const userService = fastify.custom.userService
|
|
7
9
|
|
|
@@ -26,7 +28,7 @@ export default (fastify: PluginFastifyInstance) => {
|
|
|
26
28
|
|
|
27
29
|
return {
|
|
28
30
|
handler,
|
|
29
|
-
onRequest: [fastify.authenticate],
|
|
31
|
+
onRequest: [fastify.authenticate, fastify.checkPermissions(permissions)],
|
|
30
32
|
config: {
|
|
31
33
|
type: "dataUpdate",
|
|
32
34
|
broadcastChannels: ["userUpdated"],
|
|
@@ -2,6 +2,8 @@ import type { FastifyReply, FastifyRequest } from "fastify"
|
|
|
2
2
|
import { PluginFastifyInstance } from "types"
|
|
3
3
|
import { userCreateSchema, type UserCreate } from "../user.schema"
|
|
4
4
|
|
|
5
|
+
const permissions = ["user.isAdmin"]
|
|
6
|
+
|
|
5
7
|
export default (fastify: PluginFastifyInstance) => {
|
|
6
8
|
const userService = fastify.custom.userService
|
|
7
9
|
|
|
@@ -25,7 +27,7 @@ export default (fastify: PluginFastifyInstance) => {
|
|
|
25
27
|
|
|
26
28
|
return {
|
|
27
29
|
handler,
|
|
28
|
-
onRequest: [fastify.authenticate],
|
|
30
|
+
onRequest: [fastify.authenticate, fastify.checkPermissions(permissions)],
|
|
29
31
|
config: {
|
|
30
32
|
type: "dataCreate",
|
|
31
33
|
broadcastChannels: ["userCreated"],
|
|
@@ -4,6 +4,8 @@ import { PluginFastifyInstance } from "types"
|
|
|
4
4
|
import { Type } from "@sinclair/typebox"
|
|
5
5
|
import { ForbiddenError } from "@/utils/errors"
|
|
6
6
|
|
|
7
|
+
const permissions = ["user.isAdmin"]
|
|
8
|
+
|
|
7
9
|
const ParamsSchema = Type.Object({
|
|
8
10
|
_id: Type.String(),
|
|
9
11
|
})
|
|
@@ -19,9 +21,6 @@ export default (fastify: PluginFastifyInstance) => {
|
|
|
19
21
|
reply: FastifyReply,
|
|
20
22
|
) => {
|
|
21
23
|
try {
|
|
22
|
-
if (!req.user.isAdmin) {
|
|
23
|
-
throw new ForbiddenError("Only Admins can use this feature")
|
|
24
|
-
}
|
|
25
24
|
if (req.user._id === req.params._id) {
|
|
26
25
|
throw new ForbiddenError("A user cannot remove itself")
|
|
27
26
|
}
|
|
@@ -41,7 +40,7 @@ export default (fastify: PluginFastifyInstance) => {
|
|
|
41
40
|
|
|
42
41
|
return {
|
|
43
42
|
handler,
|
|
44
|
-
onRequest: [fastify.authenticate],
|
|
43
|
+
onRequest: [fastify.authenticate, fastify.checkPermissions(permissions)],
|
|
45
44
|
config: {
|
|
46
45
|
type: "dataDelete",
|
|
47
46
|
broadcastChannels: ["userDeleted"],
|
|
@@ -2,7 +2,8 @@ import type { Static } from "@sinclair/typebox"
|
|
|
2
2
|
import type { FastifyReply, FastifyRequest } from "fastify"
|
|
3
3
|
import { PluginFastifyInstance } from "types"
|
|
4
4
|
import { Type } from "@sinclair/typebox"
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
const permissions = ["user.isAdmin"]
|
|
6
7
|
|
|
7
8
|
const ParamsSchema = Type.Object({
|
|
8
9
|
_id: Type.String(),
|
|
@@ -17,21 +18,17 @@ export default (fastify: PluginFastifyInstance) => {
|
|
|
17
18
|
reply: FastifyReply,
|
|
18
19
|
) => {
|
|
19
20
|
try {
|
|
20
|
-
|
|
21
|
-
const { _id } = req.params
|
|
21
|
+
const { _id } = req.params
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
const payload = await userService.updateUser(
|
|
24
|
+
fastify,
|
|
25
|
+
req.requestParams,
|
|
26
|
+
_id,
|
|
27
|
+
{ isDeleted: false },
|
|
28
|
+
req.user._id,
|
|
29
|
+
)
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
} else {
|
|
33
|
-
throw new ForbiddenError("Only admins can restore this core datatype")
|
|
34
|
-
}
|
|
31
|
+
return payload
|
|
35
32
|
} catch (error: any) {
|
|
36
33
|
fastify.log.error(error.message)
|
|
37
34
|
return reply.internalServerError(error.message)
|
|
@@ -40,7 +37,7 @@ export default (fastify: PluginFastifyInstance) => {
|
|
|
40
37
|
|
|
41
38
|
return {
|
|
42
39
|
handler,
|
|
43
|
-
onRequest: [fastify.authenticate],
|
|
40
|
+
onRequest: [fastify.authenticate, fastify.checkPermissions(permissions)],
|
|
44
41
|
config: {
|
|
45
42
|
type: "dataRestore",
|
|
46
43
|
broadcastChannels: ["userRestored"],
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { AnyWorkSession } from "../workSession.schema"
|
|
2
|
+
import type { FrontendPayload } from "@c/payload/payloadTypes"
|
|
3
|
+
import { PluginFastifyInstance } from "types"
|
|
4
|
+
|
|
5
|
+
const registerEvents = (fastify: PluginFastifyInstance) => {
|
|
6
|
+
/**
|
|
7
|
+
* WorkSession created
|
|
8
|
+
*/
|
|
9
|
+
const created = async (payload: FrontendPayload<AnyWorkSession>) => {
|
|
10
|
+
fastify.eventbus.emit("broadcastDataUpdated", payload)
|
|
11
|
+
fastify.eventbus.emit("broadcastWorkSessionCreated", payload)
|
|
12
|
+
fastify.log.info(
|
|
13
|
+
`[eventbus] workSession broadcast created ${payload.body.item._id}`,
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* WorkSession updated
|
|
19
|
+
*/
|
|
20
|
+
const updated = async (payload: FrontendPayload<AnyWorkSession>) => {
|
|
21
|
+
fastify.eventbus.emit("broadcastDataUpdated", payload)
|
|
22
|
+
fastify.log.info(
|
|
23
|
+
`[eventbus] workSession broadcast updated ${payload.body.item._id}`,
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* WorkSession deleted
|
|
29
|
+
*/
|
|
30
|
+
const deleted = async (payload: FrontendPayload<AnyWorkSession>) => {
|
|
31
|
+
fastify.eventbus.emit("broadcastWorkSessionDeleted", payload)
|
|
32
|
+
fastify.log.info(
|
|
33
|
+
`[eventbus] workSession broadcast deleted ${payload.body.item._id}`,
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Register event handlers
|
|
39
|
+
*/
|
|
40
|
+
fastify.eventbus.on("coreWorkSessionCreated", created)
|
|
41
|
+
fastify.eventbus.on("coreWorkSessionUpdated", updated)
|
|
42
|
+
fastify.eventbus.on("coreWorkSessionDeleted", deleted)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export default registerEvents
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PluginFastifyInstance } from "@raclettejs/core"
|
|
2
|
+
|
|
3
|
+
export const registerCrud = (fastify: PluginFastifyInstance) => {
|
|
4
|
+
const workSessionService = fastify.custom.workSessionService
|
|
5
|
+
|
|
6
|
+
fastify.registerCrudHandlers("workSession", {
|
|
7
|
+
create: workSessionService.createWorkSession,
|
|
8
|
+
read: workSessionService.readWorkSession,
|
|
9
|
+
update: workSessionService.updateWorkSession,
|
|
10
|
+
delete: workSessionService.removeWorkSession,
|
|
11
|
+
})
|
|
12
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { WorkSession } from "../workSession.schema"
|
|
2
|
+
import type { FrontendPayloadRequestData, PluginFastifyInstance } from "types"
|
|
3
|
+
|
|
4
|
+
export const registerPayload = (fastify: PluginFastifyInstance) => {
|
|
5
|
+
fastify.registerPayloadHandler<WorkSession>("workSession", {
|
|
6
|
+
type: "workSession",
|
|
7
|
+
displayName: (workSession: WorkSession) => workSession._id || "",
|
|
8
|
+
completion: (workSession: WorkSession) => workSession._id || "",
|
|
9
|
+
fields: () => ({
|
|
10
|
+
owner: "NONE",
|
|
11
|
+
}),
|
|
12
|
+
})
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const createWorkSessionPayload = async (
|
|
16
|
+
fastify: PluginFastifyInstance,
|
|
17
|
+
items: WorkSession[],
|
|
18
|
+
requestData: FrontendPayloadRequestData,
|
|
19
|
+
) => {
|
|
20
|
+
return await fastify.createPayload("workSession", items, requestData)
|
|
21
|
+
}
|
package/services/backend/src/corePlugins/raclette__core/backend/datatypes/workSession/index.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { PluginFastifyInstance } from "types"
|
|
2
|
+
import registerRoutes from "./routes"
|
|
3
|
+
import { createModels } from "./workSession.model"
|
|
4
|
+
import { createWorkSessionService } from "./workSession.service"
|
|
5
|
+
import { registerPayload } from "./helpers/payload"
|
|
6
|
+
import { registerCrud } from "./helpers/crud"
|
|
7
|
+
import { registerSchemas } from "./workSession.schema"
|
|
8
|
+
|
|
9
|
+
const registerWorkSession = async (fastify: PluginFastifyInstance) => {
|
|
10
|
+
/*
|
|
11
|
+
* ---------------------------------------------------------------------
|
|
12
|
+
* CREATE AND REGISTER ALL YOUR MODELS
|
|
13
|
+
* ---------------------------------------------------------------------
|
|
14
|
+
*/
|
|
15
|
+
const workSessionModel = createModels(fastify)
|
|
16
|
+
|
|
17
|
+
// create and pass in the model to your service
|
|
18
|
+
const workSessionService = createWorkSessionService(workSessionModel)
|
|
19
|
+
|
|
20
|
+
// decorate the service to the instance, so we can easily call it everywhere
|
|
21
|
+
fastify.custom.workSessionService = workSessionService
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
* ---------------------------------------------------------------------
|
|
25
|
+
* REGISTER ALL YOUR ROUTES
|
|
26
|
+
* ---------------------------------------------------------------------
|
|
27
|
+
*/
|
|
28
|
+
try {
|
|
29
|
+
await fastify.register((instance) => registerRoutes(instance))
|
|
30
|
+
} catch (error) {
|
|
31
|
+
fastify.log.error(`Failed to register routes.`, error)
|
|
32
|
+
throw error // Let the application handle the error
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
registerPayload(fastify)
|
|
36
|
+
registerCrud(fastify)
|
|
37
|
+
registerSchemas(fastify)
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
workSession: {
|
|
41
|
+
operations: {
|
|
42
|
+
read: workSessionService._readWorkSession.bind(workSessionService),
|
|
43
|
+
readAll: workSessionService._readWorkSessions.bind(workSessionService),
|
|
44
|
+
create: workSessionService._createWorkSession.bind(workSessionService),
|
|
45
|
+
update: workSessionService._updateWorkSession.bind(workSessionService),
|
|
46
|
+
},
|
|
47
|
+
keywords: ["workSession", "session"],
|
|
48
|
+
metadata: {
|
|
49
|
+
description: "A work session for user interactions.",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export default registerWorkSession
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { PluginFastifyInstance } from "types"
|
|
2
|
+
import get from "./route.workSession.get"
|
|
3
|
+
import getAll from "./route.workSession.getAll"
|
|
4
|
+
import patch from "./route.workSession.patch"
|
|
5
|
+
import post from "./route.workSession.post"
|
|
6
|
+
import hardDelete from "./route.workSession.hardDelete"
|
|
7
|
+
import remove from "./route.workSession.remove"
|
|
8
|
+
|
|
9
|
+
const registerRoutes = async (fastify: PluginFastifyInstance) => {
|
|
10
|
+
await fastify.get("/workSession/all", getAll(fastify))
|
|
11
|
+
await fastify.get("/workSession/:_id", get(fastify))
|
|
12
|
+
|
|
13
|
+
await fastify.post("/workSession", post(fastify))
|
|
14
|
+
await fastify.patch("/workSession/:_id", patch(fastify))
|
|
15
|
+
await fastify.delete("/workSession/:_id", remove(fastify))
|
|
16
|
+
await fastify.delete("/workSession/:_id/hard", hardDelete(fastify))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default registerRoutes
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Static } from "@sinclair/typebox"
|
|
2
|
+
import type { FastifyReply, FastifyRequest } from "fastify"
|
|
3
|
+
import { PluginFastifyInstance } from "types"
|
|
4
|
+
import { Type } from "@sinclair/typebox"
|
|
5
|
+
|
|
6
|
+
const ParamsSchema = Type.Object({
|
|
7
|
+
_id: Type.String(),
|
|
8
|
+
})
|
|
9
|
+
type Params = Static<typeof ParamsSchema>
|
|
10
|
+
|
|
11
|
+
export default (fastify: PluginFastifyInstance) => {
|
|
12
|
+
const workSessionService = fastify.custom.workSessionService
|
|
13
|
+
|
|
14
|
+
const handler = async (
|
|
15
|
+
req: FastifyRequest<{
|
|
16
|
+
Params: Params
|
|
17
|
+
}>,
|
|
18
|
+
reply: FastifyReply,
|
|
19
|
+
) => {
|
|
20
|
+
try {
|
|
21
|
+
const { _id } = req.params
|
|
22
|
+
|
|
23
|
+
const payload = await workSessionService.readWorkSession(
|
|
24
|
+
fastify,
|
|
25
|
+
req.requestParams,
|
|
26
|
+
_id,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
if (!payload) {
|
|
30
|
+
return reply.notFound("WorkSession not found")
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return payload
|
|
34
|
+
} catch (error: any) {
|
|
35
|
+
fastify.log.error(error.message)
|
|
36
|
+
return reply.internalServerError(error.message)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
handler,
|
|
42
|
+
onRequest: [fastify.authenticate],
|
|
43
|
+
config: {
|
|
44
|
+
type: "dataRead",
|
|
45
|
+
},
|
|
46
|
+
schema: {
|
|
47
|
+
summary: "Get a workSession by id",
|
|
48
|
+
tags: ["core/workSession"],
|
|
49
|
+
|
|
50
|
+
params: ParamsSchema,
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
}
|