@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
|
@@ -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(),
|
|
@@ -16,15 +17,21 @@ export default (fastify: PluginFastifyInstance) => {
|
|
|
16
17
|
reply: FastifyReply,
|
|
17
18
|
) => {
|
|
18
19
|
try {
|
|
19
|
-
|
|
20
|
+
if (req.user.isAdmin) {
|
|
21
|
+
const { _id } = req.params
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
const payloadWithTag = await tagService.hardDeleteTag(
|
|
24
|
+
fastify,
|
|
25
|
+
req.requestParams,
|
|
26
|
+
_id,
|
|
27
|
+
)
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
return payloadWithTag
|
|
30
|
+
} else {
|
|
31
|
+
throw new ForbiddenError(
|
|
32
|
+
"Only admins can hard delete this core datatype",
|
|
33
|
+
)
|
|
34
|
+
}
|
|
28
35
|
} catch (error: any) {
|
|
29
36
|
fastify.log.error(error.message)
|
|
30
37
|
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 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
|
|
|
@@ -318,7 +320,10 @@ export class TagService {
|
|
|
318
320
|
id: string,
|
|
319
321
|
): Promise<TagType> {
|
|
320
322
|
try {
|
|
321
|
-
const tag = await this.tagModel.findOne({
|
|
323
|
+
const tag = await this.tagModel.findOne({
|
|
324
|
+
_id: id,
|
|
325
|
+
isDeleted: true,
|
|
326
|
+
})
|
|
322
327
|
|
|
323
328
|
if (!tag) {
|
|
324
329
|
throw new Error(
|
|
@@ -326,9 +331,13 @@ export class TagService {
|
|
|
326
331
|
)
|
|
327
332
|
}
|
|
328
333
|
|
|
329
|
-
await
|
|
334
|
+
const res = await tag.deleteOne()
|
|
330
335
|
|
|
331
|
-
|
|
336
|
+
if (res?.deletedCount === 1) {
|
|
337
|
+
return tag.toObject ? tag.toObject() : tag
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
throw new Error(`Deletion of Tag with ID ${id} was not successful.`)
|
|
332
341
|
} catch (error: any) {
|
|
333
342
|
fastify.log.error(error.message)
|
|
334
343
|
throw error
|
package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/index.ts
CHANGED
|
@@ -5,13 +5,17 @@ import patch from "./route.user.patch"
|
|
|
5
5
|
import patchLastProject from "./route.user.patchLastProject"
|
|
6
6
|
import post from "./route.user.post"
|
|
7
7
|
import remove from "./route.user.remove"
|
|
8
|
+
import hardDelete from "./route.user.hardDelete"
|
|
9
|
+
import restore from "./route.user.restore"
|
|
8
10
|
|
|
9
11
|
const registerRoutes = async (fastify: PluginFastifyInstance) => {
|
|
10
12
|
await fastify.get("/user/all", getAll(fastify))
|
|
11
13
|
await fastify.get("/user/:_id", get(fastify))
|
|
12
14
|
await fastify.patch("/user/:_id", patch(fastify))
|
|
15
|
+
await fastify.patch("/user/:_id/restore", restore(fastify))
|
|
13
16
|
await fastify.post("/user", post(fastify))
|
|
14
17
|
await fastify.delete("/user/:_id", remove(fastify))
|
|
18
|
+
await fastify.delete("/user/:_id/hard", hardDelete(fastify))
|
|
15
19
|
await fastify.patch(
|
|
16
20
|
"/user/last-project/:projectId",
|
|
17
21
|
patchLastProject(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 payloadWithUser = await userService.hardDeleteUser(
|
|
24
|
+
fastify,
|
|
25
|
+
req.requestParams,
|
|
26
|
+
_id,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
return payloadWithUser
|
|
30
|
+
} else {
|
|
31
|
+
throw new ForbiddenError(
|
|
32
|
+
"Only admins can hard delete this core datatype",
|
|
33
|
+
)
|
|
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: "dataHardDeleted",
|
|
46
|
+
broadcastChannels: ["userHardDeleted"],
|
|
47
|
+
},
|
|
48
|
+
schema: {
|
|
49
|
+
summary: "Permanently delete a user by id",
|
|
50
|
+
description: "Hard delete a user",
|
|
51
|
+
tags: ["core/user"],
|
|
52
|
+
params: ParamsSchema,
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -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
|
|
|
@@ -287,6 +288,38 @@ export class UserService {
|
|
|
287
288
|
return payload
|
|
288
289
|
}
|
|
289
290
|
|
|
291
|
+
/**
|
|
292
|
+
* Core function to hard delete an interaction link (returns raw data)
|
|
293
|
+
*/
|
|
294
|
+
async _hardDeleteUser(
|
|
295
|
+
fastify: PluginFastifyInstance,
|
|
296
|
+
id: string,
|
|
297
|
+
): Promise<UserType> {
|
|
298
|
+
try {
|
|
299
|
+
const user = await this.userModel.findOne({
|
|
300
|
+
_id: id,
|
|
301
|
+
isDeleted: true,
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
if (!user) {
|
|
305
|
+
throw new Error(
|
|
306
|
+
`User with ID ${id} not found or not marked for deletion`,
|
|
307
|
+
)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const res = await user.deleteOne()
|
|
311
|
+
|
|
312
|
+
if (res?.deletedCount === 1) {
|
|
313
|
+
return user.toObject ? user.toObject() : user
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
throw new Error(`Deletion of User with ID ${id} was not successful.`)
|
|
317
|
+
} catch (error: any) {
|
|
318
|
+
fastify.log.error(error.message)
|
|
319
|
+
throw error
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
290
323
|
/**
|
|
291
324
|
* Core function to update user's last accessed project (returns raw data)
|
|
292
325
|
*/
|
|
@@ -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 {
|
|
@@ -164,11 +165,11 @@ const cacheOperations = {
|
|
|
164
165
|
},
|
|
165
166
|
}
|
|
166
167
|
|
|
167
|
-
const finishRemoteQuery = (actionIdentifier, result, params, options) => {
|
|
168
|
+
const finishRemoteQuery = (actionIdentifier, result = {}, params, options) => {
|
|
168
169
|
const { actionId, cacheKey } = actionIdentifier
|
|
169
170
|
log.api("finishRemoteQuery", { actionId, params, result })
|
|
170
171
|
|
|
171
|
-
if (!result
|
|
172
|
+
if (!result?.data) {
|
|
172
173
|
return
|
|
173
174
|
}
|
|
174
175
|
let resultBody = structuredClone(result.data.body)
|
|
@@ -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,20 +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
|
-
message: e.response.data.message,
|
|
243
|
-
color: "error",
|
|
244
|
-
})
|
|
245
|
-
throw e
|
|
246
|
-
})
|
|
247
|
-
: await $api.axios.post(target, params, config).catch((e) => {
|
|
248
|
-
$eventbus.emit("ui/addToSnackbar", {
|
|
249
|
-
message: e.response.data.message,
|
|
250
|
-
color: "error",
|
|
251
|
-
})
|
|
252
|
-
throw e
|
|
253
|
-
})
|
|
240
|
+
? await $api.axios.get(target, config).catch(handleErrors)
|
|
241
|
+
: await $api.axios.post(target, params, config).catch(handleErrors)
|
|
254
242
|
|
|
255
243
|
return {
|
|
256
244
|
response,
|
|
@@ -258,7 +246,7 @@ const handleRemoteRequest = async (
|
|
|
258
246
|
}
|
|
259
247
|
} catch (e) {
|
|
260
248
|
if (e.name === "AbortError" || e.name === "CanceledError") {
|
|
261
|
-
log.api(`${method} request was
|
|
249
|
+
log.api(`${method} request was canceled for actionId:`, actionIdentifier)
|
|
262
250
|
throw e
|
|
263
251
|
}
|
|
264
252
|
|
|
@@ -442,7 +430,7 @@ const executeRoute = async (actionIdentifier, validTarget, params, options) => {
|
|
|
442
430
|
|
|
443
431
|
if (error.name === "AbortError" || error.name === "CanceledError") {
|
|
444
432
|
log.api(
|
|
445
|
-
"HTTP request was
|
|
433
|
+
"HTTP request was canceled for actionId:",
|
|
446
434
|
actionIdentifier.actionId,
|
|
447
435
|
)
|
|
448
436
|
throw error
|
|
@@ -162,7 +162,7 @@ const handler = {
|
|
|
162
162
|
requestId,
|
|
163
163
|
data,
|
|
164
164
|
})
|
|
165
|
-
const deleted = data.
|
|
165
|
+
const deleted = data.items || []
|
|
166
166
|
$store.dispatch({ type: "data/hardDelete", payload: deleted })
|
|
167
167
|
if (notify) {
|
|
168
168
|
userNotifier.dataDelete(isOwnRequest, isSystemAction, deleted)
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import log from "@racletteCore/lib/logger"
|
|
2
|
-
import { $api, $store
|
|
3
|
-
import {
|
|
2
|
+
import { $api, $store } from "@racletteCore"
|
|
3
|
+
import {
|
|
4
|
+
removeCacheAttributes,
|
|
5
|
+
capitalize,
|
|
6
|
+
handleErrors,
|
|
7
|
+
} from "@racletteCore/lib/dataHelper"
|
|
4
8
|
import handleServerItem from "./responseTypeHandler"
|
|
5
9
|
import { handleOperationTarget } from "@racletteCore/setup/plugin-system"
|
|
6
10
|
|
|
@@ -25,16 +29,7 @@ const createAxiosConfig = (appRequestCode, pluginItemRequestConfig) => {
|
|
|
25
29
|
}
|
|
26
30
|
return config
|
|
27
31
|
}
|
|
28
|
-
const reportError = (error) => {
|
|
29
|
-
const message = error?.response?.data?.message || false
|
|
30
32
|
|
|
31
|
-
$eventbus.emit("ui/addToSnackbar", {
|
|
32
|
-
message,
|
|
33
|
-
i18n: message ? false : "core.error.noConnectionToServer",
|
|
34
|
-
color: "error",
|
|
35
|
-
})
|
|
36
|
-
throw error
|
|
37
|
-
}
|
|
38
33
|
const storeActions = {
|
|
39
34
|
dataMove: (actionId, payload) => {
|
|
40
35
|
const newParent = payload.item.newParent
|
|
@@ -128,7 +123,7 @@ const writeData = async (actionId, operationDefinition, item, options) => {
|
|
|
128
123
|
response: res,
|
|
129
124
|
}
|
|
130
125
|
})
|
|
131
|
-
.catch(
|
|
126
|
+
.catch(handleErrors)
|
|
132
127
|
} else {
|
|
133
128
|
return await getAxiosPromise(
|
|
134
129
|
operationDefinition.method,
|
|
@@ -142,7 +137,7 @@ const writeData = async (actionId, operationDefinition, item, options) => {
|
|
|
142
137
|
result: handleServerItem(res.data, notify, true),
|
|
143
138
|
}
|
|
144
139
|
})
|
|
145
|
-
.catch(
|
|
140
|
+
.catch(handleErrors)
|
|
146
141
|
}
|
|
147
142
|
}
|
|
148
143
|
|
|
@@ -7,6 +7,20 @@ import log from "@racletteCore/lib/logger"
|
|
|
7
7
|
import { $eventbus } from "@racletteCore/main"
|
|
8
8
|
import { $store } from "@racletteCore/main"
|
|
9
9
|
|
|
10
|
+
const handleErrors = (e) => {
|
|
11
|
+
$eventbus.emit("backend/error", e)
|
|
12
|
+
log.api("handleErrors", e)
|
|
13
|
+
// TODO expand error handling for other transports
|
|
14
|
+
if (e.name === "AxiosError") {
|
|
15
|
+
const errorResponse = e.response || {}
|
|
16
|
+
$eventbus.emit("ui/addToSnackbar", {
|
|
17
|
+
message: errorResponse.data?.message || "error",
|
|
18
|
+
color: "error",
|
|
19
|
+
})
|
|
20
|
+
throw e
|
|
21
|
+
}
|
|
22
|
+
return {}
|
|
23
|
+
}
|
|
10
24
|
const hasOwnProperty = (obj, prop) =>
|
|
11
25
|
Object.prototype.hasOwnProperty.call(obj, prop)
|
|
12
26
|
const fileExists = async (path: string): Promise<boolean> => {
|
|
@@ -468,4 +482,5 @@ export {
|
|
|
468
482
|
getCookie,
|
|
469
483
|
hasOwnProperty,
|
|
470
484
|
fileExists,
|
|
485
|
+
handleErrors,
|
|
471
486
|
}
|
|
@@ -6,19 +6,9 @@
|
|
|
6
6
|
* change of state, others represent a request addressed to a specific actor,
|
|
7
7
|
* e.g. 'asks the http client to get x'
|
|
8
8
|
*
|
|
9
|
-
* @TODO
|
|
10
|
-
* - find clear naming policy
|
|
11
|
-
* - use speaking event names, even though they are longer
|
|
12
|
-
* - distinguish between a information and request (e.g. store_dispatch is a request to the store)
|
|
13
9
|
*/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"socket_leaveRoom",
|
|
17
|
-
"socket_dataUpdated",
|
|
18
|
-
"ui_setupProject",
|
|
19
|
-
"ui_addToSnackBar",
|
|
20
|
-
]
|
|
21
|
-
const eventWhitelist = legacyEventWhitelist.concat([
|
|
10
|
+
|
|
11
|
+
const eventWhitelist = [
|
|
22
12
|
"forms/init",
|
|
23
13
|
"forms/validate",
|
|
24
14
|
"widgets/reset/workingState",
|
|
@@ -27,7 +17,8 @@ const eventWhitelist = legacyEventWhitelist.concat([
|
|
|
27
17
|
"socket/data/update",
|
|
28
18
|
"socket/join/room",
|
|
29
19
|
"socket/leave/room",
|
|
30
|
-
|
|
20
|
+
"backend/error",
|
|
21
|
+
]
|
|
31
22
|
const eventWildcards = [
|
|
32
23
|
"query_deleted",
|
|
33
24
|
"store_actionResolved",
|
|
@@ -129,7 +129,7 @@ const userConfigUpdate = (isAnswerToOwnRequest, isSystemAction, items) =>
|
|
|
129
129
|
color: "info",
|
|
130
130
|
})
|
|
131
131
|
|
|
132
|
-
const dataDelete = (isAnswerToOwnRequest, isSystemAction, deletedItems) =>
|
|
132
|
+
const dataDelete = (isAnswerToOwnRequest, isSystemAction, deletedItems) => {
|
|
133
133
|
deletedItems.forEach((item) => {
|
|
134
134
|
if (isAnswerToOwnRequest) {
|
|
135
135
|
$eventbus.emit("ui/addToSnackbar", {
|
|
@@ -153,6 +153,7 @@ const dataDelete = (isAnswerToOwnRequest, isSystemAction, deletedItems) =>
|
|
|
153
153
|
})
|
|
154
154
|
}
|
|
155
155
|
})
|
|
156
|
+
}
|
|
156
157
|
|
|
157
158
|
const dataMove = (isAnswerToOwnRequest, isSystemAction, items) => {
|
|
158
159
|
items.forEach((item) => {
|
|
@@ -159,12 +159,18 @@ const generateLoginCallback =
|
|
|
159
159
|
success: true,
|
|
160
160
|
token: token,
|
|
161
161
|
redirect: () => {
|
|
162
|
+
const params = new URLSearchParams(window.location.search)
|
|
163
|
+
const redirect = params.get("redirect") || ""
|
|
162
164
|
// If we're in the same origin, we keep the history
|
|
163
165
|
if (
|
|
164
166
|
_callbackUrl.startsWith(window.location.origin) ||
|
|
165
167
|
_callbackUrl.startsWith("/")
|
|
166
168
|
) {
|
|
167
|
-
|
|
169
|
+
if (redirect.length && redirect.startsWith("/:")) {
|
|
170
|
+
window.location.href = _callbackUrl + redirect
|
|
171
|
+
} else {
|
|
172
|
+
window.location.reload()
|
|
173
|
+
}
|
|
168
174
|
} else {
|
|
169
175
|
// Otherwise do a full page reload to the callback URL
|
|
170
176
|
window.location.replace(_callbackUrl)
|