@raclettejs/core 0.1.17 → 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 +24 -1
- package/package.json +2 -2
- package/services/backend/package.json +2 -2
- package/services/backend/src/core/config/configService.ts +4 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/composition.service.ts +2 -0
- 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.restore.ts +55 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/interactionLink.service.ts +2 -0
- 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.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/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.restore.ts +55 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/tag.service.ts +2 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/index.ts +2 -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 +1 -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 +3 -23
- 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/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,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
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
|
+
|
|
10
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
|
|
@@ -14,7 +38,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
14
38
|
- Frontend: axios Delete handling
|
|
15
39
|
- Frontend: retrieval of deleted compositions/interactionLinks during socket join
|
|
16
40
|
- Frontend: notifications for delete events now show name
|
|
17
|
-
-
|
|
18
41
|
|
|
19
42
|
### Added
|
|
20
43
|
|
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
|
+
}
|
|
@@ -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
|
}
|
|
@@ -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,
|
|
@@ -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))
|
|
@@ -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
|
+
}
|
|
@@ -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,
|
|
@@ -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))
|
|
@@ -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/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))
|
|
@@ -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 tagService = fastify.custom.tagService
|
|
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 tagService.updateTag(
|
|
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: ["tagRestored"],
|
|
47
|
+
},
|
|
48
|
+
schema: {
|
|
49
|
+
summary: "restore a tag by id",
|
|
50
|
+
description: "Restore a tag",
|
|
51
|
+
tags: ["core/tag"],
|
|
52
|
+
params: ParamsSchema,
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
}
|
package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/tag.service.ts
CHANGED
|
@@ -131,6 +131,8 @@ export class TagService {
|
|
|
131
131
|
options: QueryOptions = {},
|
|
132
132
|
): Promise<TagType[]> {
|
|
133
133
|
try {
|
|
134
|
+
if (filter.isDeleted !== true && filter.isDeleted !== "true")
|
|
135
|
+
filter.isDeleted = false
|
|
134
136
|
// Start building the query
|
|
135
137
|
let query = this.tagModel.find(filter)
|
|
136
138
|
|
package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/index.ts
CHANGED
|
@@ -6,11 +6,13 @@ import patchLastProject from "./route.user.patchLastProject"
|
|
|
6
6
|
import post from "./route.user.post"
|
|
7
7
|
import remove from "./route.user.remove"
|
|
8
8
|
import hardDelete from "./route.user.hardDelete"
|
|
9
|
+
import restore from "./route.user.restore"
|
|
9
10
|
|
|
10
11
|
const registerRoutes = async (fastify: PluginFastifyInstance) => {
|
|
11
12
|
await fastify.get("/user/all", getAll(fastify))
|
|
12
13
|
await fastify.get("/user/:_id", get(fastify))
|
|
13
14
|
await fastify.patch("/user/:_id", patch(fastify))
|
|
15
|
+
await fastify.patch("/user/:_id/restore", restore(fastify))
|
|
14
16
|
await fastify.post("/user", post(fastify))
|
|
15
17
|
await fastify.delete("/user/:_id", remove(fastify))
|
|
16
18
|
await fastify.delete("/user/:_id/hard", hardDelete(fastify))
|
|
@@ -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 userService = fastify.custom.userService
|
|
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 userService.updateUser(
|
|
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: ["userRestored"],
|
|
47
|
+
},
|
|
48
|
+
schema: {
|
|
49
|
+
summary: "restore a user by id",
|
|
50
|
+
description: "Restore a user",
|
|
51
|
+
tags: ["core/user"],
|
|
52
|
+
params: ParamsSchema,
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
}
|
package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/user.service.ts
CHANGED
|
@@ -135,6 +135,7 @@ export class UserService {
|
|
|
135
135
|
options: QueryOptions = {},
|
|
136
136
|
): Promise<UserType[]> {
|
|
137
137
|
try {
|
|
138
|
+
if (filter.isDeleted !== true && filter.isDeleted !=='true') filter.isDeleted = false
|
|
138
139
|
// Start building the query
|
|
139
140
|
let query = this.userModel.find(filter)
|
|
140
141
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { UserDoc } from "@/corePlugins/raclette__core/backend/datatypes/user/user.schema"
|
|
2
2
|
import type { Static } from "@sinclair/typebox"
|
|
3
|
+
import configService from "@/core/config/configService"
|
|
3
4
|
import type { FastifyRequest, FastifyReply, FastifyInstance } from "fastify"
|
|
4
5
|
import { Type } from "@sinclair/typebox"
|
|
5
6
|
import { toPublicUser } from "@/corePlugins/raclette__core/backend/datatypes/user/user.schema"
|
|
@@ -183,9 +184,10 @@ export default (fastify: FastifyInstance) => {
|
|
|
183
184
|
deviceId: deviceId || request.ip,
|
|
184
185
|
iat: Math.floor(Date.now() / 1000),
|
|
185
186
|
}
|
|
186
|
-
|
|
187
|
+
// Set the expiry time/TTL for the auth token to the configured value
|
|
188
|
+
const expiryDays = configService.getAuthTokenExpiryDays()
|
|
187
189
|
const token = fastify.jwt.sign(tokenPayload, {
|
|
188
|
-
expiresIn:
|
|
190
|
+
expiresIn: `${expiryDays}d`,
|
|
189
191
|
})
|
|
190
192
|
const decoded = fastify.jwt.decode(token)
|
|
191
193
|
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"@sinclair/typebox": "0.34.41",
|
|
22
22
|
"@tailwindcss/vite": "4.1.13",
|
|
23
23
|
"@tsconfig/node20": "20.1.6",
|
|
24
|
-
"@vueuse/core": "
|
|
25
|
-
"@vueuse/rxjs": "
|
|
26
|
-
"axios": "1.
|
|
24
|
+
"@vueuse/core": "14.1.0",
|
|
25
|
+
"@vueuse/rxjs": "14.1.0",
|
|
26
|
+
"axios": "1.13.2",
|
|
27
27
|
"date-fns": "4.1.0",
|
|
28
28
|
"esm": "3.x",
|
|
29
29
|
"interactjs": "1.10.27",
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
"socket.io-client": "4.x",
|
|
36
36
|
"tailwindcss": "4.1.13",
|
|
37
37
|
"uuid": "13.0.0",
|
|
38
|
-
"vue": "3.5.
|
|
39
|
-
"vue-i18n": "11.
|
|
40
|
-
"vue-router": "4.
|
|
41
|
-
"vuetify": "3.
|
|
38
|
+
"vue": "3.5.25",
|
|
39
|
+
"vue-i18n": "11.2.2",
|
|
40
|
+
"vue-router": "4.6.3",
|
|
41
|
+
"vuetify": "3.11.2"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/node": "24.5.1",
|
|
@@ -58,4 +58,4 @@
|
|
|
58
58
|
"vue-eslint-parser": "10.2.0",
|
|
59
59
|
"vue-tsc": "3.0.7"
|
|
60
60
|
}
|
|
61
|
-
}
|
|
61
|
+
}
|
|
@@ -71,7 +71,7 @@ export class ConfigService {
|
|
|
71
71
|
return this.config.plugins || []
|
|
72
72
|
}
|
|
73
73
|
public getAuthTokenExpiryDays(): number {
|
|
74
|
-
return this.config.global?.authTokenExpiryDays ??
|
|
74
|
+
return this.config.global?.authTokenExpiryDays ?? 30
|
|
75
75
|
}
|
|
76
76
|
public getAdditonalPluginPaths(): string[] {
|
|
77
77
|
return this.config.additionalPluginPaths?.map((e) => `${e}`) || []
|
|
@@ -2,6 +2,7 @@ import log from "@racletteCore/lib/logger"
|
|
|
2
2
|
import {
|
|
3
3
|
promisifyActionResolve,
|
|
4
4
|
markDataAsModified,
|
|
5
|
+
handleErrors,
|
|
5
6
|
} from "@racletteCore/lib/dataHelper"
|
|
6
7
|
import { $api, $store } from "@racletteCore"
|
|
7
8
|
import {
|
|
@@ -203,7 +204,6 @@ const finishRemoteQuery = (actionIdentifier, result = {}, params, options) => {
|
|
|
203
204
|
|
|
204
205
|
return itemDispatcher(actionIdentifier, resultObj, true)
|
|
205
206
|
}
|
|
206
|
-
|
|
207
207
|
// Unified remote data handler for both GET and POST
|
|
208
208
|
const handleRemoteRequest = async (
|
|
209
209
|
actionIdentifier,
|
|
@@ -237,28 +237,8 @@ const handleRemoteRequest = async (
|
|
|
237
237
|
try {
|
|
238
238
|
const response =
|
|
239
239
|
method === "GET"
|
|
240
|
-
? await $api.axios.get(target, config).catch(
|
|
241
|
-
|
|
242
|
-
$eventbus.emit("ui/addToSnackbar", {
|
|
243
|
-
message: e.response?.data?.message || "error",
|
|
244
|
-
color: "error",
|
|
245
|
-
})
|
|
246
|
-
throw e
|
|
247
|
-
}
|
|
248
|
-
log.api("axios/get/error", e)
|
|
249
|
-
return {}
|
|
250
|
-
})
|
|
251
|
-
: await $api.axios.post(target, params, config).catch((e) => {
|
|
252
|
-
if (e.name !== "CanceledError") {
|
|
253
|
-
$eventbus.emit("ui/addToSnackbar", {
|
|
254
|
-
message: e.response?.data?.message || "error",
|
|
255
|
-
color: "error",
|
|
256
|
-
})
|
|
257
|
-
throw e
|
|
258
|
-
}
|
|
259
|
-
log.api("axios/post/error", e)
|
|
260
|
-
return {}
|
|
261
|
-
})
|
|
240
|
+
? await $api.axios.get(target, config).catch(handleErrors)
|
|
241
|
+
: await $api.axios.post(target, params, config).catch(handleErrors)
|
|
262
242
|
|
|
263
243
|
return {
|
|
264
244
|
response,
|