@raclettejs/core 0.1.16 → 0.1.18
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 +28 -1
- package/package.json +2 -2
- package/services/backend/package.json +2 -2
- package/services/backend/src/core/backgroundTasks/taskManager.ts +1 -1
- package/services/backend/src/core/config/configService.ts +4 -0
- package/services/backend/src/core/sockets/socketManager.ts +2 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/account/account.service.ts +7 -3
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/account/routes/route.account.hardDelete.ts +16 -11
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/composition.service.ts +11 -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.hardDelete.ts +16 -11
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/routes/route.composition.restore.ts +55 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/interactionLink.service.ts +14 -6
- 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.hardDelete.ts +14 -7
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/routes/route.interactionLink.restore.ts +55 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/project.model.ts +17 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/project.schema.ts +18 -6
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/project.service.ts +8 -4
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/routes/index.ts +5 -5
- 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.hardDelete.ts +14 -7
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/routes/route.tag.restore.ts +55 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/tag.service.ts +12 -3
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/index.ts +4 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/route.user.hardDelete.ts +55 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/route.user.restore.ts +55 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/user.service.ts +33 -0
- package/services/backend/src/domains/system/routes/route.user.login.ts +4 -2
- package/services/backend/src/shared/types/core/ProjectUpdate.types.ts +1 -0
- package/services/backend/src/shared/types/dataTypes/tags.ts +1 -0
- package/services/frontend/package.json +8 -8
- package/services/frontend/src/core/lib/configService.ts +1 -1
- package/services/frontend/src/core/lib/data/fetchDataHandler.ts +7 -19
- package/services/frontend/src/core/lib/data/responseTypeHandler.ts +1 -1
- package/services/frontend/src/core/lib/data/writeDataHandler.ts +8 -13
- package/services/frontend/src/core/lib/dataHelper.ts +15 -0
- package/services/frontend/src/core/lib/eventWhitelist.ts +4 -13
- package/services/frontend/src/core/lib/userNotifier.ts +2 -1
- package/services/frontend/src/core/main.ts +7 -1
- package/services/frontend/src/orchestrator/LoginApp.vue +0 -1
- package/services/frontend/src/orchestrator/ProductOrchestrator.vue +40 -5
- package/services/frontend/src/orchestrator/components/composition/CompositionOverlay.vue +7 -3
- package/services/frontend/src/orchestrator/components/composition/WidgetsLayoutLoader.vue +12 -24
- package/services/frontend/src/orchestrator/components/input/SimpleSearchInput.vue +16 -4
- package/services/frontend/src/orchestrator/components/menu/AppBarMenu.vue +184 -0
- package/services/frontend/src/orchestrator/components/menu/UserMenu.vue +62 -46
- package/services/frontend/src/orchestrator/components/navigation/PageNavigationSidebar.vue +11 -1
- package/services/frontend/src/orchestrator/composables/usePageNavigation.ts +10 -1
- package/services/frontend/src/orchestrator/i18n/de-DE.json +1 -0
- package/services/frontend/src/orchestrator/i18n/en-EU.json +1 -0
- package/services/frontend/src/orchestrator/i18n/sk.json +1 -0
- package/services/frontend/src/orchestrator/router/index.ts +16 -0
- package/yarn.lock +4 -4
- package/services/frontend/src/orchestrator/setup/loginApp.ts +0 -27
package/CHANGELOG.md
CHANGED
|
@@ -7,15 +7,42 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
-
## [0.1.
|
|
10
|
+
## [0.1.18] - 05.12.2025 <a href="https://gitlab.com/raclettejs/core/-/compare/v0.1.17...v0.1.18" target="_blank" rel="noopener"><b>Overview of all changes</b></a>
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Backend: project data type deletion routes temporarily disabled. Will be reenabled soon
|
|
15
|
+
- Frontend: updated dependencies
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Frontend: usermenu - added alternate render mode for inline composition if no trigger id/title is set
|
|
20
|
+
- Frontend: Appbar can now house interactionLinks and inline compositions
|
|
21
|
+
- Frontend: appbar can now launch compositions in a floating window
|
|
22
|
+
- Backend: added restore endpoints for tag/user/composition/interactionLink
|
|
23
|
+
- Frontend: Token expiry will now redirect automatically to login. Last location during auth loss will be used for redirect later
|
|
24
|
+
- Frontend: Simple search input can now receive custom label and uses debounce before model update
|
|
25
|
+
- Frontend: PageNavigation can now rail
|
|
26
|
+
- Backend: Project dataType can now hold config values
|
|
27
|
+
- Global: Added new Tagtype "event"
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- Backend: isDeleted handling in getAll routes. isDeleted needs to be explicitly true to see deleted entries
|
|
32
|
+
- Backend: TTL for auth token is not derived from raclette.config
|
|
33
|
+
|
|
34
|
+
## [0.1.17] - 06.11.2025 <a href="https://gitlab.com/raclettejs/core/-/compare/v0.1.15...v0.1.17" target="_blank" rel="noopener"><b>Overview of all changes</b></a>
|
|
11
35
|
|
|
12
36
|
### Fixed
|
|
13
37
|
|
|
14
38
|
- Frontend: axios Delete handling
|
|
39
|
+
- Frontend: retrieval of deleted compositions/interactionLinks during socket join
|
|
40
|
+
- Frontend: notifications for delete events now show name
|
|
15
41
|
|
|
16
42
|
### Added
|
|
17
43
|
|
|
18
44
|
- Frontend: added i18n keys
|
|
45
|
+
- Frontend: hard delete of core datatypes
|
|
19
46
|
- Backend: getAll routes for core datatypes do now respect set filters
|
|
20
47
|
|
|
21
48
|
## [0.1.15] - 02.11.2025 <a href="https://gitlab.com/raclettejs/core/-/compare/v0.1.13...v0.1.15" target="_blank" rel="noopener"><b>Overview of all changes</b></a>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@raclettejs/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18",
|
|
4
4
|
"description": "racletteJS core package",
|
|
5
5
|
"repository": "https://gitlab.com/raclettejs/core",
|
|
6
6
|
"author": "Pacifico Digital Explorations GmbH <info@raclettejs.com>",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@eslint/js": "9.35.0",
|
|
72
|
-
"@raclettejs/types": "0.1.
|
|
72
|
+
"@raclettejs/types": "^0.1.18",
|
|
73
73
|
"@types/fs-extra": "11.0.4",
|
|
74
74
|
"@types/js-yaml": "4.0.9",
|
|
75
75
|
"@types/node": "24.5.1",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@fastify/sensible": "6.0.3",
|
|
31
31
|
"@sinclair/typebox": "0.34.41",
|
|
32
32
|
"@types/vary": "1.1.3",
|
|
33
|
-
"axios": "1.
|
|
33
|
+
"axios": "1.13.2",
|
|
34
34
|
"bcrypt": "6.0.0",
|
|
35
35
|
"copyfiles": "2.4.1",
|
|
36
36
|
"fastify": "5.6.0",
|
|
@@ -62,4 +62,4 @@
|
|
|
62
62
|
"typescript": "5.9.2",
|
|
63
63
|
"typescript-eslint": "8.44.0"
|
|
64
64
|
}
|
|
65
|
-
}
|
|
65
|
+
}
|
|
@@ -122,7 +122,7 @@ const setupTaskManager = (fastify: FastifyInstance) => {
|
|
|
122
122
|
|
|
123
123
|
if (removed) {
|
|
124
124
|
taskMetadata.delete(name)
|
|
125
|
-
fastify.log.info(`
|
|
125
|
+
fastify.log.info(`Canceled task: ${name}`)
|
|
126
126
|
} else {
|
|
127
127
|
fastify.log.warn(`Task not found: ${name}`)
|
|
128
128
|
}
|
|
@@ -13,6 +13,7 @@ type RacletteBackendConfig = {
|
|
|
13
13
|
plugins?: string[]
|
|
14
14
|
global?: {
|
|
15
15
|
requireAuthentication?: boolean
|
|
16
|
+
authTokenExpiryDays?: number
|
|
16
17
|
}
|
|
17
18
|
additionalPluginPaths?: string[]
|
|
18
19
|
}
|
|
@@ -130,6 +131,9 @@ export class ConfigService {
|
|
|
130
131
|
public isAuthRequired(): boolean {
|
|
131
132
|
return this.config?.global?.requireAuthentication ?? true
|
|
132
133
|
}
|
|
134
|
+
public getAuthTokenExpiryDays(): number {
|
|
135
|
+
return this.config?.global?.authTokenExpiryDays ?? 30
|
|
136
|
+
}
|
|
133
137
|
public isAdminTagRequired(): boolean {
|
|
134
138
|
return this.config?.onlyAllowLoginWithAdminTag ?? false
|
|
135
139
|
}
|
|
@@ -93,6 +93,7 @@ const registerSocketEvents = (fastify: FastifyInstance): void => {
|
|
|
93
93
|
"composition",
|
|
94
94
|
"readAll",
|
|
95
95
|
fastify,
|
|
96
|
+
{ isDeleted: false },
|
|
96
97
|
)
|
|
97
98
|
}
|
|
98
99
|
|
|
@@ -103,6 +104,7 @@ const registerSocketEvents = (fastify: FastifyInstance): void => {
|
|
|
103
104
|
"interactionLink",
|
|
104
105
|
"readAll",
|
|
105
106
|
fastify,
|
|
107
|
+
{ isDeleted: false },
|
|
106
108
|
)
|
|
107
109
|
}
|
|
108
110
|
|
package/services/backend/src/corePlugins/raclette__core/backend/datatypes/account/account.service.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
import type { PluginFastifyInstance } from "types"
|
|
7
7
|
import { v4 as uuidv4, validate } from "uuid"
|
|
8
8
|
import { createAccountPayload } from "./helpers/payload"
|
|
9
|
-
import { Model } from "mongoose"
|
|
9
|
+
import type { Model } from "mongoose"
|
|
10
10
|
|
|
11
11
|
export type AccountBody = Partial<Omit<AccountType, "_id">> & {
|
|
12
12
|
_id?: string
|
|
@@ -277,9 +277,13 @@ export class AccountService {
|
|
|
277
277
|
)
|
|
278
278
|
}
|
|
279
279
|
|
|
280
|
-
await
|
|
280
|
+
const res = await account.deleteOne()
|
|
281
281
|
|
|
282
|
-
|
|
282
|
+
if (res?.deletedCount === 1) {
|
|
283
|
+
return account.toObject ? account.toObject() : account
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
throw new Error(`Deletion of Account with ID ${id} was not successful.`)
|
|
283
287
|
} catch (error: any) {
|
|
284
288
|
fastify.log.error(error.message)
|
|
285
289
|
throw error
|
|
@@ -2,6 +2,7 @@ import type { Static } from "@sinclair/typebox"
|
|
|
2
2
|
import type { FastifyReply, FastifyRequest } from "fastify"
|
|
3
3
|
import type { 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(),
|
|
@@ -17,19 +18,23 @@ export default (fastify: PluginFastifyInstance) => {
|
|
|
17
18
|
}>,
|
|
18
19
|
reply: FastifyReply,
|
|
19
20
|
) => {
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
if (req.user.isAdmin) {
|
|
22
|
+
try {
|
|
23
|
+
const { _id } = req.params
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
const payload = await accountService.hardDeleteAccount(
|
|
26
|
+
fastify,
|
|
27
|
+
req.requestParams,
|
|
28
|
+
_id,
|
|
29
|
+
)
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
return payload
|
|
32
|
+
} catch (error: any) {
|
|
33
|
+
fastify.log.error(error.message)
|
|
34
|
+
return reply.internalServerError(error.message)
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
throw new ForbiddenError("Only admins can hard delete this core datatype")
|
|
33
38
|
}
|
|
34
39
|
}
|
|
35
40
|
|
|
@@ -97,6 +97,8 @@ export class CompositionService {
|
|
|
97
97
|
filters: Record<string, any> = {},
|
|
98
98
|
): Promise<CompositionType[]> {
|
|
99
99
|
try {
|
|
100
|
+
if (filters.isDeleted !== true && filters.isDeleted !== "true")
|
|
101
|
+
filters.isDeleted = false
|
|
100
102
|
return await this.compositionModel
|
|
101
103
|
.find({
|
|
102
104
|
...filters,
|
|
@@ -292,7 +294,7 @@ export class CompositionService {
|
|
|
292
294
|
): Promise<CompositionType> {
|
|
293
295
|
try {
|
|
294
296
|
const composition = await this.compositionModel.findOne({
|
|
295
|
-
id,
|
|
297
|
+
_id: id,
|
|
296
298
|
isDeleted: true,
|
|
297
299
|
})
|
|
298
300
|
|
|
@@ -302,9 +304,15 @@ export class CompositionService {
|
|
|
302
304
|
)
|
|
303
305
|
}
|
|
304
306
|
|
|
305
|
-
await
|
|
307
|
+
const res = await composition.deleteOne()
|
|
306
308
|
|
|
307
|
-
|
|
309
|
+
if (res?.deletedCount === 1) {
|
|
310
|
+
return composition.toObject ? composition.toObject() : composition
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
throw new Error(
|
|
314
|
+
`Deletion of Composition with ID ${id} was not successful.`,
|
|
315
|
+
)
|
|
308
316
|
} catch (error: any) {
|
|
309
317
|
fastify.log.error(error.message)
|
|
310
318
|
throw error
|
|
@@ -5,11 +5,13 @@ import hardDelete from "./route.composition.hardDelete"
|
|
|
5
5
|
import patch from "./route.composition.patch"
|
|
6
6
|
import post from "./route.composition.post"
|
|
7
7
|
import remove from "./route.composition.remove"
|
|
8
|
+
import restore from "./route.composition.restore"
|
|
8
9
|
|
|
9
10
|
const registerRoutes = async (fastify: PluginFastifyInstance) => {
|
|
10
11
|
await fastify.get("/composition/all", getAll(fastify))
|
|
11
12
|
await fastify.get("/composition/:_id", get(fastify))
|
|
12
13
|
await fastify.patch("/composition/:_id", patch(fastify))
|
|
14
|
+
await fastify.patch("/composition/:_id/restore", restore(fastify))
|
|
13
15
|
await fastify.post("/composition", post(fastify))
|
|
14
16
|
await fastify.delete("/composition/:_id", remove(fastify))
|
|
15
17
|
await fastify.delete("/composition/:_id/hard", hardDelete(fastify))
|
|
@@ -2,6 +2,7 @@ import type { Static } from "@sinclair/typebox"
|
|
|
2
2
|
import type { FastifyReply, FastifyRequest } from "fastify"
|
|
3
3
|
import type { 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(),
|
|
@@ -17,19 +18,23 @@ export default (fastify: PluginFastifyInstance) => {
|
|
|
17
18
|
}>,
|
|
18
19
|
reply: FastifyReply,
|
|
19
20
|
) => {
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
if (req.user.isAdmin) {
|
|
22
|
+
try {
|
|
23
|
+
const { _id } = req.params
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
const payload = await compositionService.hardDeleteComposition(
|
|
26
|
+
fastify,
|
|
27
|
+
req.requestParams,
|
|
28
|
+
_id,
|
|
29
|
+
)
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
return payload
|
|
32
|
+
} catch (error: any) {
|
|
33
|
+
fastify.log.error(error.message)
|
|
34
|
+
return reply.internalServerError(error.message)
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
throw new ForbiddenError("Only admins can hard delete this core datatype")
|
|
33
38
|
}
|
|
34
39
|
}
|
|
35
40
|
|
|
@@ -0,0 +1,55 @@
|
|
|
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
|
+
import { ForbiddenError } from "@/utils/errors"
|
|
6
|
+
|
|
7
|
+
const ParamsSchema = Type.Object({
|
|
8
|
+
_id: Type.String(),
|
|
9
|
+
})
|
|
10
|
+
type Params = Static<typeof ParamsSchema>
|
|
11
|
+
|
|
12
|
+
export default (fastify: PluginFastifyInstance) => {
|
|
13
|
+
const compositionService = fastify.custom.compositionService
|
|
14
|
+
|
|
15
|
+
const handler = async (
|
|
16
|
+
req: FastifyRequest<{ Params: Params }>,
|
|
17
|
+
reply: FastifyReply,
|
|
18
|
+
) => {
|
|
19
|
+
try {
|
|
20
|
+
if (req.user.isAdmin) {
|
|
21
|
+
const { _id } = req.params
|
|
22
|
+
|
|
23
|
+
const payload = await compositionService.updateComposition(
|
|
24
|
+
fastify,
|
|
25
|
+
req.requestParams,
|
|
26
|
+
_id,
|
|
27
|
+
{ isDeleted: false },
|
|
28
|
+
req.user._id,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
return payload
|
|
32
|
+
} else {
|
|
33
|
+
throw new ForbiddenError("Only admins can restore this core datatype")
|
|
34
|
+
}
|
|
35
|
+
} catch (error: any) {
|
|
36
|
+
fastify.log.error(error.message)
|
|
37
|
+
return reply.internalServerError(error.message)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
handler,
|
|
43
|
+
onRequest: [fastify.authenticate],
|
|
44
|
+
config: {
|
|
45
|
+
type: "dataRestore",
|
|
46
|
+
broadcastChannels: ["compositionRestored"],
|
|
47
|
+
},
|
|
48
|
+
schema: {
|
|
49
|
+
summary: "restore a composition by id",
|
|
50
|
+
description: "Restore a composition",
|
|
51
|
+
tags: ["core/composition"],
|
|
52
|
+
params: ParamsSchema,
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -5,8 +5,8 @@ import type {
|
|
|
5
5
|
} from "@c/payload/payloadTypes"
|
|
6
6
|
import { v4 as uuidv4, validate } from "uuid"
|
|
7
7
|
import { createInteractionLinkPayload } from "./helpers/payload"
|
|
8
|
-
import { PluginFastifyInstance } from "types"
|
|
9
|
-
import { Model } from "mongoose"
|
|
8
|
+
import type { PluginFastifyInstance } from "types"
|
|
9
|
+
import type { Model } from "mongoose"
|
|
10
10
|
|
|
11
11
|
export type InteractionLinkBody = Partial<Omit<InteractionLinkType, "_id">> & {
|
|
12
12
|
_id?: string
|
|
@@ -100,6 +100,8 @@ export class InteractionLinkService {
|
|
|
100
100
|
filters: Record<string, any> = {},
|
|
101
101
|
): Promise<InteractionLinkType[]> {
|
|
102
102
|
try {
|
|
103
|
+
if (filters.isDeleted !== true && filters.isDeleted !== "true")
|
|
104
|
+
filters.isDeleted = false
|
|
103
105
|
return await this.interactionLinkModel
|
|
104
106
|
.find({
|
|
105
107
|
...filters,
|
|
@@ -352,11 +354,17 @@ export class InteractionLinkService {
|
|
|
352
354
|
)
|
|
353
355
|
}
|
|
354
356
|
|
|
355
|
-
await
|
|
357
|
+
const res = await interactionLink.deleteOne()
|
|
356
358
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
359
|
+
if (res?.deletedCount === 1) {
|
|
360
|
+
return interactionLink.toObject
|
|
361
|
+
? interactionLink.toObject()
|
|
362
|
+
: interactionLink
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
throw new Error(
|
|
366
|
+
`Deletion of InteractionLink with ID ${id} was not successful.`,
|
|
367
|
+
)
|
|
360
368
|
} catch (error: any) {
|
|
361
369
|
fastify.log.error(error.message)
|
|
362
370
|
throw error
|
|
@@ -5,11 +5,13 @@ import hardDelete from "./route.interactionLink.hardDelete"
|
|
|
5
5
|
import patch from "./route.interactionLink.patch"
|
|
6
6
|
import post from "./route.interactionLink.post"
|
|
7
7
|
import remove from "./route.interactionLink.remove"
|
|
8
|
+
import restore from "./route.interactionLink.restore"
|
|
8
9
|
|
|
9
10
|
const registerRoutes = async (fastify: PluginFastifyInstance) => {
|
|
10
11
|
await fastify.get("/interactionLink/all", getAll(fastify))
|
|
11
12
|
await fastify.get("/interactionLink/:_id", get(fastify))
|
|
12
13
|
await fastify.patch("/interactionLink/:_id", patch(fastify))
|
|
14
|
+
await fastify.patch("/interactionLink/:_id/restore", restore(fastify))
|
|
13
15
|
await fastify.post("/interactionLink", post(fastify))
|
|
14
16
|
await fastify.delete("/interactionLink/:_id", remove(fastify))
|
|
15
17
|
await fastify.delete("/interactionLink/:_id/hard", hardDelete(fastify))
|
|
@@ -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(),
|
|
@@ -18,15 +19,21 @@ export default (fastify: PluginFastifyInstance) => {
|
|
|
18
19
|
reply: FastifyReply,
|
|
19
20
|
) => {
|
|
20
21
|
try {
|
|
21
|
-
|
|
22
|
+
if (req.user.isAdmin) {
|
|
23
|
+
const { _id } = req.params
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
const payload = await interactionLinkService.hardDeleteInteractionLink(
|
|
26
|
+
fastify,
|
|
27
|
+
req.requestParams,
|
|
28
|
+
_id,
|
|
29
|
+
)
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
return payload
|
|
32
|
+
} else {
|
|
33
|
+
throw new ForbiddenError(
|
|
34
|
+
"Only admins can hard delete this core datatype",
|
|
35
|
+
)
|
|
36
|
+
}
|
|
30
37
|
} catch (error: any) {
|
|
31
38
|
fastify.log.error(error.message)
|
|
32
39
|
return reply.internalServerError(error.message)
|
|
@@ -0,0 +1,55 @@
|
|
|
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
|
+
import { ForbiddenError } from "@/utils/errors"
|
|
6
|
+
|
|
7
|
+
const ParamsSchema = Type.Object({
|
|
8
|
+
_id: Type.String(),
|
|
9
|
+
})
|
|
10
|
+
type Params = Static<typeof ParamsSchema>
|
|
11
|
+
|
|
12
|
+
export default (fastify: PluginFastifyInstance) => {
|
|
13
|
+
const interactionLinkService = fastify.custom.interactionLinkService
|
|
14
|
+
|
|
15
|
+
const handler = async (
|
|
16
|
+
req: FastifyRequest<{ Params: Params }>,
|
|
17
|
+
reply: FastifyReply,
|
|
18
|
+
) => {
|
|
19
|
+
try {
|
|
20
|
+
if (req.user.isAdmin) {
|
|
21
|
+
const { _id } = req.params
|
|
22
|
+
|
|
23
|
+
const payload = await interactionLinkService.updateInteractionLink(
|
|
24
|
+
fastify,
|
|
25
|
+
req.requestParams,
|
|
26
|
+
_id,
|
|
27
|
+
{ isDeleted: false },
|
|
28
|
+
req.user._id,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
return payload
|
|
32
|
+
} else {
|
|
33
|
+
throw new ForbiddenError("Only admins can restore this core datatype")
|
|
34
|
+
}
|
|
35
|
+
} catch (error: any) {
|
|
36
|
+
fastify.log.error(error.message)
|
|
37
|
+
return reply.internalServerError(error.message)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
handler,
|
|
43
|
+
onRequest: [fastify.authenticate],
|
|
44
|
+
config: {
|
|
45
|
+
type: "dataRestore",
|
|
46
|
+
broadcastChannels: ["interactionLinkRestored"],
|
|
47
|
+
},
|
|
48
|
+
schema: {
|
|
49
|
+
summary: "restore a interactionLink by id",
|
|
50
|
+
description: "Restore a interactionLink",
|
|
51
|
+
tags: ["core/interactionLink"],
|
|
52
|
+
params: ParamsSchema,
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
}
|
package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/project.model.ts
CHANGED
|
@@ -34,6 +34,23 @@ const projectSchema = new Schema(
|
|
|
34
34
|
|
|
35
35
|
// soft delete
|
|
36
36
|
isDeleted: { type: Boolean, default: false },
|
|
37
|
+
config: {
|
|
38
|
+
type: {
|
|
39
|
+
tags: {
|
|
40
|
+
type: [Schema.Types.String],
|
|
41
|
+
ref: "raclette__core-tag",
|
|
42
|
+
default: [],
|
|
43
|
+
},
|
|
44
|
+
railPageNavigation: {
|
|
45
|
+
type: Boolean,
|
|
46
|
+
default: false,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
default: () => ({
|
|
50
|
+
tags: [],
|
|
51
|
+
railPageNavigation: false,
|
|
52
|
+
}),
|
|
53
|
+
},
|
|
37
54
|
},
|
|
38
55
|
{ timestamps: true },
|
|
39
56
|
)
|
package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/project.schema.ts
CHANGED
|
@@ -2,16 +2,28 @@ import type { Static } from "@sinclair/typebox"
|
|
|
2
2
|
import type { Document } from "mongoose"
|
|
3
3
|
import { Type } from "@sinclair/typebox"
|
|
4
4
|
import { PluginFastifyInstance } from "types"
|
|
5
|
-
|
|
6
5
|
/**
|
|
7
6
|
* Base Project Schema - Fields common to all operations
|
|
8
7
|
*/
|
|
8
|
+
const projectConfigSchema = Type.Optional(
|
|
9
|
+
Type.Object(
|
|
10
|
+
{
|
|
11
|
+
tags: Type.Array(Type.String(), { default: [] }),
|
|
12
|
+
railPageNavigation: Type.Boolean({ default: false }),
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
$id: "#project/config",
|
|
16
|
+
title: "core/project-config",
|
|
17
|
+
},
|
|
18
|
+
),
|
|
19
|
+
)
|
|
9
20
|
const baseProjectSchema = {
|
|
10
21
|
title: Type.Optional(Type.String({ maxLength: 200 })),
|
|
11
22
|
account: Type.Optional(Type.String({ default: null })),
|
|
12
23
|
tags: Type.Optional(Type.Array(Type.String(), { default: [] })),
|
|
13
24
|
description: Type.Optional(Type.String()),
|
|
14
25
|
isDefault: Type.Optional(Type.Boolean({ default: false })),
|
|
26
|
+
config: projectConfigSchema,
|
|
15
27
|
}
|
|
16
28
|
|
|
17
29
|
/**
|
|
@@ -51,11 +63,7 @@ export const projectCreateSchema = Type.Object(
|
|
|
51
63
|
export const projectUpdateSchema = Type.Object(
|
|
52
64
|
{
|
|
53
65
|
_id: Type.Optional(Type.String()),
|
|
54
|
-
|
|
55
|
-
account: Type.Optional(Type.String()),
|
|
56
|
-
tags: Type.Optional(Type.Array(Type.String())),
|
|
57
|
-
description: Type.Optional(Type.String()),
|
|
58
|
-
isDefault: Type.Optional(Type.Boolean()),
|
|
66
|
+
...baseProjectSchema,
|
|
59
67
|
},
|
|
60
68
|
{
|
|
61
69
|
$id: "#project/update",
|
|
@@ -104,4 +112,8 @@ export const registerSchemas = (fastify: PluginFastifyInstance) => {
|
|
|
104
112
|
schema: projectUpdateSchema,
|
|
105
113
|
name: "ProjectUpdate",
|
|
106
114
|
})
|
|
115
|
+
fastify.registerSchema({
|
|
116
|
+
schema: projectConfigSchema,
|
|
117
|
+
name: "ProjectConfig",
|
|
118
|
+
})
|
|
107
119
|
}
|
package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/project.service.ts
CHANGED
|
@@ -10,8 +10,8 @@ import type {
|
|
|
10
10
|
import type { QueryOptions } from "@m/database/providers/mongodb/service"
|
|
11
11
|
import { v4 as uuidv4, validate } from "uuid"
|
|
12
12
|
import { createProjectPayload } from "./helpers/payload"
|
|
13
|
-
import { Model } from "mongoose"
|
|
14
|
-
import { PluginFastifyInstance } from "types"
|
|
13
|
+
import type { Model } from "mongoose"
|
|
14
|
+
import type { PluginFastifyInstance } from "types"
|
|
15
15
|
|
|
16
16
|
export type ProjectBody = Partial<Omit<ProjectType, "_id">> & { _id?: string }
|
|
17
17
|
|
|
@@ -316,9 +316,13 @@ export class ProjectService {
|
|
|
316
316
|
)
|
|
317
317
|
}
|
|
318
318
|
|
|
319
|
-
await
|
|
319
|
+
const res = await project.deleteOne()
|
|
320
320
|
|
|
321
|
-
|
|
321
|
+
if (res?.deletedCount === 1) {
|
|
322
|
+
return project.toObject ? project.toObject() : project
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
throw new Error(`Deletion of Project with ID ${id} was not successful.`)
|
|
322
326
|
} catch (error: any) {
|
|
323
327
|
fastify.log.error(error.message)
|
|
324
328
|
throw error
|
package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/routes/index.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { PluginFastifyInstance } from "types"
|
|
2
2
|
import get from "./route.project.get"
|
|
3
3
|
import getAll from "./route.project.getAll"
|
|
4
|
-
import hardDelete from "./route.project.hardDelete"
|
|
5
4
|
import patch from "./route.project.patch"
|
|
6
5
|
import post from "./route.project.post"
|
|
7
|
-
import
|
|
6
|
+
//import hardDelete from "./route.project.hardDelete"
|
|
7
|
+
//import remove from "./route.project.remove"
|
|
8
8
|
|
|
9
9
|
const registerRoutes = async (fastify: PluginFastifyInstance) => {
|
|
10
10
|
await fastify.get("/project/all", getAll(fastify))
|
|
@@ -12,9 +12,9 @@ const registerRoutes = async (fastify: PluginFastifyInstance) => {
|
|
|
12
12
|
|
|
13
13
|
await fastify.post("/project", post(fastify))
|
|
14
14
|
await fastify.patch("/project/:_id", patch(fastify))
|
|
15
|
-
|
|
16
|
-
await fastify.delete("/project/:_id", remove(fastify))
|
|
17
|
-
await fastify.delete("/project/:_id/hard", hardDelete(fastify))
|
|
15
|
+
// TODO reenable once we have deletion concept and space datatype implemented
|
|
16
|
+
//await fastify.delete("/project/:_id", remove(fastify))
|
|
17
|
+
//await fastify.delete("/project/:_id/hard", hardDelete(fastify))
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export default registerRoutes
|
package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/routes/index.ts
CHANGED
|
@@ -5,11 +5,13 @@ import hardDelete from "./route.tag.hardDelete"
|
|
|
5
5
|
import patch from "./route.tag.patch"
|
|
6
6
|
import post from "./route.tag.post"
|
|
7
7
|
import remove from "./route.tag.remove"
|
|
8
|
+
import restore from "./route.tag.restore"
|
|
8
9
|
|
|
9
10
|
const registerRoutes = async (fastify: PluginFastifyInstance) => {
|
|
10
11
|
await fastify.get("/tag/all", getAll(fastify))
|
|
11
12
|
await fastify.get("/tag/:_id", get(fastify))
|
|
12
13
|
await fastify.patch("/tag/:_id", patch(fastify))
|
|
14
|
+
await fastify.patch("/tag/:_id/restore", restore(fastify))
|
|
13
15
|
await fastify.post("/tag/:project/:_id", post(fastify))
|
|
14
16
|
await fastify.delete("/tag/:_id", remove(fastify))
|
|
15
17
|
await fastify.delete("/tag/:_id/hard", hardDelete(fastify))
|