strapi-plugin-firebase-authentication 1.2.5 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{App-DjamRMm8.mjs → App-BetYshSi.mjs} +480 -160
- package/dist/_chunks/{App-BmP-duLn.js → App-CvU_Hs6w.js} +592 -251
- package/dist/_chunks/{api-Bg075IIT.js → api-e13nzvp3.js} +2 -1
- package/dist/_chunks/{api-CLQa5PFi.mjs → api-ut3LjIwN.mjs} +2 -1
- package/dist/_chunks/{index-B2NvsXdF.mjs → index-CciifEG2.mjs} +13 -14
- package/dist/_chunks/{index-B4ptk_Em.js → index-Cdk5SnH2.js} +1 -1
- package/dist/_chunks/{index-CyOVjVQb.js → index-DG0-IQtm.js} +4 -5
- package/dist/_chunks/{index-CAZnRswo.mjs → index-LLF37Cdh.mjs} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +2 -2
- package/dist/admin/src/components/ActivityLog/ActivityLog.d.ts +6 -0
- package/dist/admin/src/components/ActivityLog/index.d.ts +1 -0
- package/dist/admin/src/pages/utils/api.d.ts +18 -1
- package/dist/server/index.js +8171 -30542
- package/dist/server/index.mjs +8131 -30497
- package/dist/server/src/config/index.d.ts +8 -0
- package/dist/server/src/content-types/index.d.ts +74 -0
- package/dist/server/src/controllers/activityLogController.d.ts +8 -0
- package/dist/server/src/controllers/firebaseController.d.ts +9 -0
- package/dist/server/src/controllers/index.d.ts +4 -0
- package/dist/server/src/index.d.ts +97 -1
- package/dist/server/src/middlewares/activity-logger.d.ts +9 -0
- package/dist/server/src/middlewares/index.d.ts +5 -1
- package/dist/server/src/services/activityLogService.d.ts +58 -0
- package/dist/server/src/services/firebaseService.d.ts +12 -0
- package/dist/server/src/services/firebaseUserDataService.d.ts +1 -0
- package/dist/server/src/services/index.d.ts +13 -0
- package/dist/server/src/services/userService.d.ts +1 -0
- package/package.json +2 -1
|
@@ -41,6 +41,13 @@ export type FirebaseAuthConfig = {
|
|
|
41
41
|
* @default '{randomString}@phone-user.firebase.local'
|
|
42
42
|
*/
|
|
43
43
|
emailPattern?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Number of days to retain activity logs. If not set, logs are kept forever.
|
|
46
|
+
* Set via FIREBASE_ACTIVITY_LOG_RETENTION_DAYS environment variable.
|
|
47
|
+
*
|
|
48
|
+
* @default null (never delete)
|
|
49
|
+
*/
|
|
50
|
+
activityLogRetentionDays?: number | null;
|
|
44
51
|
};
|
|
45
52
|
declare const _default: {
|
|
46
53
|
default: ({ env }: {
|
|
@@ -49,6 +56,7 @@ declare const _default: {
|
|
|
49
56
|
firebaseJsonEncryptionKey: any;
|
|
50
57
|
emailRequired: any;
|
|
51
58
|
emailPattern: string;
|
|
59
|
+
activityLogRetentionDays: any;
|
|
52
60
|
};
|
|
53
61
|
validator(config: FirebaseAuthConfig): void;
|
|
54
62
|
};
|
|
@@ -141,5 +141,79 @@ declare const _default: {
|
|
|
141
141
|
};
|
|
142
142
|
};
|
|
143
143
|
};
|
|
144
|
+
"firebase-activity-log": {
|
|
145
|
+
schema: {
|
|
146
|
+
kind: string;
|
|
147
|
+
collectionName: string;
|
|
148
|
+
info: {
|
|
149
|
+
singularName: string;
|
|
150
|
+
pluralName: string;
|
|
151
|
+
displayName: string;
|
|
152
|
+
description: string;
|
|
153
|
+
};
|
|
154
|
+
options: {
|
|
155
|
+
draftAndPublish: boolean;
|
|
156
|
+
};
|
|
157
|
+
pluginOptions: {
|
|
158
|
+
"content-manager": {
|
|
159
|
+
visible: boolean;
|
|
160
|
+
};
|
|
161
|
+
"content-type-builder": {
|
|
162
|
+
visible: boolean;
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
attributes: {
|
|
166
|
+
firebaseUserId: {
|
|
167
|
+
type: string;
|
|
168
|
+
required: boolean;
|
|
169
|
+
};
|
|
170
|
+
strapiUserId: {
|
|
171
|
+
type: string;
|
|
172
|
+
};
|
|
173
|
+
activityType: {
|
|
174
|
+
type: string;
|
|
175
|
+
enum: string[];
|
|
176
|
+
required: boolean;
|
|
177
|
+
};
|
|
178
|
+
action: {
|
|
179
|
+
type: string;
|
|
180
|
+
required: boolean;
|
|
181
|
+
};
|
|
182
|
+
endpoint: {
|
|
183
|
+
type: string;
|
|
184
|
+
};
|
|
185
|
+
method: {
|
|
186
|
+
type: string;
|
|
187
|
+
};
|
|
188
|
+
ipAddress: {
|
|
189
|
+
type: string;
|
|
190
|
+
};
|
|
191
|
+
userAgent: {
|
|
192
|
+
type: string;
|
|
193
|
+
};
|
|
194
|
+
changes: {
|
|
195
|
+
type: string;
|
|
196
|
+
};
|
|
197
|
+
metadata: {
|
|
198
|
+
type: string;
|
|
199
|
+
};
|
|
200
|
+
success: {
|
|
201
|
+
type: string;
|
|
202
|
+
default: boolean;
|
|
203
|
+
};
|
|
204
|
+
errorMessage: {
|
|
205
|
+
type: string;
|
|
206
|
+
};
|
|
207
|
+
performedBy: {
|
|
208
|
+
type: string;
|
|
209
|
+
};
|
|
210
|
+
performedByType: {
|
|
211
|
+
type: string;
|
|
212
|
+
enum: string[];
|
|
213
|
+
default: string;
|
|
214
|
+
};
|
|
215
|
+
};
|
|
216
|
+
};
|
|
217
|
+
};
|
|
144
218
|
};
|
|
145
219
|
export default _default;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Context, DefaultContext } from "koa";
|
|
2
|
+
declare const _default: {
|
|
3
|
+
/**
|
|
4
|
+
* GET /activity-logs?firebaseUserId=xxx&page=1&pageSize=20&activityType=...&startDate=...&endDate=...
|
|
5
|
+
*/
|
|
6
|
+
list(ctx: DefaultContext | Context): Promise<void>;
|
|
7
|
+
};
|
|
8
|
+
export default _default;
|
|
@@ -58,5 +58,14 @@ declare const firebaseController: {
|
|
|
58
58
|
* @returns { success: true, message: "Email verified successfully" }
|
|
59
59
|
*/
|
|
60
60
|
verifyEmail(ctx: Context): Promise<Context>;
|
|
61
|
+
/**
|
|
62
|
+
* Check password - validates a password against the authenticated user's Firebase account
|
|
63
|
+
* POST /api/firebase-authentication/checkPassword
|
|
64
|
+
* Authenticated endpoint - requires valid JWT (enforced by is-authenticated policy)
|
|
65
|
+
*
|
|
66
|
+
* @param ctx - Koa context with { password } in body
|
|
67
|
+
* @returns { valid: true } or { valid: false }
|
|
68
|
+
*/
|
|
69
|
+
checkPassword(ctx: Context): Promise<void>;
|
|
61
70
|
};
|
|
62
71
|
export default firebaseController;
|
|
@@ -10,6 +10,7 @@ declare const _default: {
|
|
|
10
10
|
resetPasswordWithToken(ctx: import("koa").Context): Promise<void>;
|
|
11
11
|
sendVerificationEmail(ctx: import("koa").Context): Promise<void>;
|
|
12
12
|
verifyEmail(ctx: import("koa").Context): Promise<import("koa").Context>;
|
|
13
|
+
checkPassword(ctx: import("koa").Context): Promise<void>;
|
|
13
14
|
};
|
|
14
15
|
userController: {
|
|
15
16
|
list: (ctx: import("koa").Context | import("koa").DefaultContext) => Promise<void>;
|
|
@@ -30,5 +31,8 @@ declare const _default: {
|
|
|
30
31
|
getPublicConfig(ctx: import("koa").Context | import("koa").DefaultContext): Promise<any>;
|
|
31
32
|
savePasswordConfig(ctx: import("koa").Context | import("koa").DefaultContext): Promise<void>;
|
|
32
33
|
};
|
|
34
|
+
activityLogController: {
|
|
35
|
+
list(ctx: import("koa").Context | import("koa").DefaultContext): Promise<void>;
|
|
36
|
+
};
|
|
33
37
|
};
|
|
34
38
|
export default _default;
|
|
@@ -16,6 +16,7 @@ declare const _default: {
|
|
|
16
16
|
firebaseJsonEncryptionKey: any;
|
|
17
17
|
emailRequired: any;
|
|
18
18
|
emailPattern: string;
|
|
19
|
+
activityLogRetentionDays: any;
|
|
19
20
|
};
|
|
20
21
|
validator(config: import("./config").FirebaseAuthConfig): void;
|
|
21
22
|
};
|
|
@@ -31,6 +32,7 @@ declare const _default: {
|
|
|
31
32
|
resetPasswordWithToken(ctx: import("koa").Context): Promise<void>;
|
|
32
33
|
sendVerificationEmail(ctx: import("koa").Context): Promise<void>;
|
|
33
34
|
verifyEmail(ctx: import("koa").Context): Promise<import("koa").Context>;
|
|
35
|
+
checkPassword(ctx: import("koa").Context): Promise<void>;
|
|
34
36
|
};
|
|
35
37
|
userController: {
|
|
36
38
|
list: (ctx: import("koa").Context | import("koa").DefaultContext) => Promise<void>;
|
|
@@ -51,6 +53,9 @@ declare const _default: {
|
|
|
51
53
|
getPublicConfig(ctx: import("koa").Context | import("koa").DefaultContext): Promise<any>;
|
|
52
54
|
savePasswordConfig(ctx: import("koa").Context | import("koa").DefaultContext): Promise<void>;
|
|
53
55
|
};
|
|
56
|
+
activityLogController: {
|
|
57
|
+
list(ctx: import("koa").Context | import("koa").DefaultContext): Promise<void>;
|
|
58
|
+
};
|
|
54
59
|
};
|
|
55
60
|
routes: {
|
|
56
61
|
admin: {
|
|
@@ -152,6 +157,7 @@ declare const _default: {
|
|
|
152
157
|
resetPasswordWithToken: (token: string, newPassword: string) => Promise<{
|
|
153
158
|
success: boolean;
|
|
154
159
|
message: string;
|
|
160
|
+
uid: any;
|
|
155
161
|
}>;
|
|
156
162
|
sendVerificationEmail: (entityId: string) => Promise<any>;
|
|
157
163
|
};
|
|
@@ -209,6 +215,10 @@ declare const _default: {
|
|
|
209
215
|
verifyEmail(token: string): Promise<{
|
|
210
216
|
success: boolean;
|
|
211
217
|
message: string;
|
|
218
|
+
uid: any;
|
|
219
|
+
}>;
|
|
220
|
+
checkPassword(user: any, password: string): Promise<{
|
|
221
|
+
valid: boolean;
|
|
212
222
|
}>;
|
|
213
223
|
};
|
|
214
224
|
templateService: ({ strapi }: {
|
|
@@ -268,6 +278,14 @@ declare const _default: {
|
|
|
268
278
|
validateVerificationToken(token: string): Promise<import("./services/tokenService").VerificationTokenValidationResult>;
|
|
269
279
|
invalidateVerificationToken(firebaseUserDataDocumentId: string): Promise<void>;
|
|
270
280
|
};
|
|
281
|
+
activityLogService: ({ strapi }: {
|
|
282
|
+
strapi: import("@strapi/types/dist/core").Strapi;
|
|
283
|
+
}) => {
|
|
284
|
+
logActivity(params: import("./services/activityLogService").LogActivityParams): Promise<import("@strapi/types/dist/modules/documents").AnyDocument>;
|
|
285
|
+
getActivityLogs(firebaseUserId: string, options?: import("./services/activityLogService").GetActivityLogsOptions): Promise<import("@strapi/types/dist/modules/documents").AnyDocument[]>;
|
|
286
|
+
getActivityCount(firebaseUserId: string, options?: import("./services/activityLogService").GetActivityLogsOptions): Promise<number>;
|
|
287
|
+
cleanupOldLogs(retentionDays: number): Promise<number>;
|
|
288
|
+
};
|
|
271
289
|
};
|
|
272
290
|
contentTypes: {
|
|
273
291
|
"firebase-authentication-configuration": {
|
|
@@ -412,10 +430,88 @@ declare const _default: {
|
|
|
412
430
|
};
|
|
413
431
|
};
|
|
414
432
|
};
|
|
433
|
+
"firebase-activity-log": {
|
|
434
|
+
schema: {
|
|
435
|
+
kind: string;
|
|
436
|
+
collectionName: string;
|
|
437
|
+
info: {
|
|
438
|
+
singularName: string;
|
|
439
|
+
pluralName: string;
|
|
440
|
+
displayName: string;
|
|
441
|
+
description: string;
|
|
442
|
+
};
|
|
443
|
+
options: {
|
|
444
|
+
draftAndPublish: boolean;
|
|
445
|
+
};
|
|
446
|
+
pluginOptions: {
|
|
447
|
+
"content-manager": {
|
|
448
|
+
visible: boolean;
|
|
449
|
+
};
|
|
450
|
+
"content-type-builder": {
|
|
451
|
+
visible: boolean;
|
|
452
|
+
};
|
|
453
|
+
};
|
|
454
|
+
attributes: {
|
|
455
|
+
firebaseUserId: {
|
|
456
|
+
type: string;
|
|
457
|
+
required: boolean;
|
|
458
|
+
};
|
|
459
|
+
strapiUserId: {
|
|
460
|
+
type: string;
|
|
461
|
+
};
|
|
462
|
+
activityType: {
|
|
463
|
+
type: string;
|
|
464
|
+
enum: string[];
|
|
465
|
+
required: boolean;
|
|
466
|
+
};
|
|
467
|
+
action: {
|
|
468
|
+
type: string;
|
|
469
|
+
required: boolean;
|
|
470
|
+
};
|
|
471
|
+
endpoint: {
|
|
472
|
+
type: string;
|
|
473
|
+
};
|
|
474
|
+
method: {
|
|
475
|
+
type: string;
|
|
476
|
+
};
|
|
477
|
+
ipAddress: {
|
|
478
|
+
type: string;
|
|
479
|
+
};
|
|
480
|
+
userAgent: {
|
|
481
|
+
type: string;
|
|
482
|
+
};
|
|
483
|
+
changes: {
|
|
484
|
+
type: string;
|
|
485
|
+
};
|
|
486
|
+
metadata: {
|
|
487
|
+
type: string;
|
|
488
|
+
};
|
|
489
|
+
success: {
|
|
490
|
+
type: string;
|
|
491
|
+
default: boolean;
|
|
492
|
+
};
|
|
493
|
+
errorMessage: {
|
|
494
|
+
type: string;
|
|
495
|
+
};
|
|
496
|
+
performedBy: {
|
|
497
|
+
type: string;
|
|
498
|
+
};
|
|
499
|
+
performedByType: {
|
|
500
|
+
type: string;
|
|
501
|
+
enum: string[];
|
|
502
|
+
default: string;
|
|
503
|
+
};
|
|
504
|
+
};
|
|
505
|
+
};
|
|
506
|
+
};
|
|
415
507
|
};
|
|
416
508
|
policies: {
|
|
417
509
|
"is-authenticated": (policyContext: any) => Promise<boolean>;
|
|
418
510
|
};
|
|
419
|
-
middlewares: {
|
|
511
|
+
middlewares: {
|
|
512
|
+
"activity-logger": ({ strapi }: {
|
|
513
|
+
strapi: import("@strapi/types/dist/core").Strapi;
|
|
514
|
+
}) => (ctx: import("koa").Context, next: import("koa").Next) => Promise<void>;
|
|
515
|
+
};
|
|
420
516
|
};
|
|
421
517
|
export default _default;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Core } from "@strapi/strapi";
|
|
2
|
+
import type Koa from "koa";
|
|
3
|
+
/**
|
|
4
|
+
* Factory function that creates the activity logger middleware
|
|
5
|
+
*/
|
|
6
|
+
declare const _default: ({ strapi }: {
|
|
7
|
+
strapi: Core.Strapi;
|
|
8
|
+
}) => (ctx: Koa.Context, next: Koa.Next) => Promise<void>;
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Core } from "@strapi/strapi";
|
|
2
|
+
export interface LogActivityParams {
|
|
3
|
+
firebaseUserId: string;
|
|
4
|
+
strapiUserId?: string;
|
|
5
|
+
activityType: "authentication" | "tokenValidation" | "fieldUpdate" | "passwordReset" | "emailVerification" | "accountCreation" | "accountDeletion" | "adminAction";
|
|
6
|
+
action: string;
|
|
7
|
+
endpoint?: string;
|
|
8
|
+
method?: string;
|
|
9
|
+
ipAddress?: string;
|
|
10
|
+
userAgent?: string;
|
|
11
|
+
changes?: Record<string, {
|
|
12
|
+
old: any;
|
|
13
|
+
new: any;
|
|
14
|
+
}>;
|
|
15
|
+
metadata?: Record<string, any>;
|
|
16
|
+
success?: boolean;
|
|
17
|
+
errorMessage?: string;
|
|
18
|
+
performedBy?: string;
|
|
19
|
+
performedByType?: "user" | "admin" | "system";
|
|
20
|
+
}
|
|
21
|
+
export interface GetActivityLogsOptions {
|
|
22
|
+
page?: number;
|
|
23
|
+
pageSize?: number;
|
|
24
|
+
activityType?: string;
|
|
25
|
+
startDate?: string;
|
|
26
|
+
endDate?: string;
|
|
27
|
+
}
|
|
28
|
+
declare const _default: ({ strapi }: {
|
|
29
|
+
strapi: Core.Strapi;
|
|
30
|
+
}) => {
|
|
31
|
+
/**
|
|
32
|
+
* Log an activity (non-blocking - errors are caught internally)
|
|
33
|
+
* @param params - Activity log parameters
|
|
34
|
+
* @returns Created activity log or undefined on error
|
|
35
|
+
*/
|
|
36
|
+
logActivity(params: LogActivityParams): Promise<import("@strapi/types/dist/modules/documents").AnyDocument>;
|
|
37
|
+
/**
|
|
38
|
+
* Get paginated activity logs for a user with optional filters
|
|
39
|
+
* @param firebaseUserId - Firebase UID
|
|
40
|
+
* @param options - Pagination and filter options
|
|
41
|
+
* @returns Array of activity logs
|
|
42
|
+
*/
|
|
43
|
+
getActivityLogs(firebaseUserId: string, options?: GetActivityLogsOptions): Promise<import("@strapi/types/dist/modules/documents").AnyDocument[]>;
|
|
44
|
+
/**
|
|
45
|
+
* Get total count for pagination
|
|
46
|
+
* @param firebaseUserId - Firebase UID
|
|
47
|
+
* @param options - Filter options
|
|
48
|
+
* @returns Total count of matching logs
|
|
49
|
+
*/
|
|
50
|
+
getActivityCount(firebaseUserId: string, options?: GetActivityLogsOptions): Promise<number>;
|
|
51
|
+
/**
|
|
52
|
+
* Delete logs older than specified days
|
|
53
|
+
* @param retentionDays - Number of days to retain logs
|
|
54
|
+
* @returns Number of deleted entries
|
|
55
|
+
*/
|
|
56
|
+
cleanupOldLogs(retentionDays: number): Promise<number>;
|
|
57
|
+
};
|
|
58
|
+
export default _default;
|
|
@@ -130,6 +130,18 @@ declare const _default: ({ strapi }: {
|
|
|
130
130
|
verifyEmail(token: string): Promise<{
|
|
131
131
|
success: boolean;
|
|
132
132
|
message: string;
|
|
133
|
+
uid: any;
|
|
134
|
+
}>;
|
|
135
|
+
/**
|
|
136
|
+
* Check if a password is valid for the authenticated user
|
|
137
|
+
* Uses Firebase Identity Toolkit API to verify the password
|
|
138
|
+
*
|
|
139
|
+
* @param user - Authenticated user from ctx.state.user
|
|
140
|
+
* @param password - Password to check
|
|
141
|
+
* @returns { valid: true } or { valid: false }
|
|
142
|
+
*/
|
|
143
|
+
checkPassword(user: any, password: string): Promise<{
|
|
144
|
+
valid: boolean;
|
|
133
145
|
}>;
|
|
134
146
|
};
|
|
135
147
|
export default _default;
|
|
@@ -15,6 +15,7 @@ declare const _default: ({ strapi }: {
|
|
|
15
15
|
getByFirebaseUID(firebaseUID: string): Promise<any>;
|
|
16
16
|
/**
|
|
17
17
|
* Update Firebase-specific fields for a user (creates if doesn't exist)
|
|
18
|
+
* Handles orphaned records and race conditions gracefully
|
|
18
19
|
* @param userId - Strapi user documentId
|
|
19
20
|
* @param data - Fields to update
|
|
20
21
|
*/
|
|
@@ -63,6 +63,7 @@ declare const _default: {
|
|
|
63
63
|
resetPasswordWithToken: (token: string, newPassword: string) => Promise<{
|
|
64
64
|
success: boolean;
|
|
65
65
|
message: string;
|
|
66
|
+
uid: any;
|
|
66
67
|
}>;
|
|
67
68
|
sendVerificationEmail: (entityId: string) => Promise<any>;
|
|
68
69
|
};
|
|
@@ -120,6 +121,10 @@ declare const _default: {
|
|
|
120
121
|
verifyEmail(token: string): Promise<{
|
|
121
122
|
success: boolean;
|
|
122
123
|
message: string;
|
|
124
|
+
uid: any;
|
|
125
|
+
}>;
|
|
126
|
+
checkPassword(user: any, password: string): Promise<{
|
|
127
|
+
valid: boolean;
|
|
123
128
|
}>;
|
|
124
129
|
};
|
|
125
130
|
templateService: ({ strapi }: {
|
|
@@ -179,5 +184,13 @@ declare const _default: {
|
|
|
179
184
|
validateVerificationToken(token: string): Promise<import("./tokenService").VerificationTokenValidationResult>;
|
|
180
185
|
invalidateVerificationToken(firebaseUserDataDocumentId: string): Promise<void>;
|
|
181
186
|
};
|
|
187
|
+
activityLogService: ({ strapi }: {
|
|
188
|
+
strapi: import("@strapi/types/dist/core").Strapi;
|
|
189
|
+
}) => {
|
|
190
|
+
logActivity(params: import("./activityLogService").LogActivityParams): Promise<import("@strapi/types/dist/modules/documents").AnyDocument>;
|
|
191
|
+
getActivityLogs(firebaseUserId: string, options?: import("./activityLogService").GetActivityLogsOptions): Promise<import("@strapi/types/dist/modules/documents").AnyDocument[]>;
|
|
192
|
+
getActivityCount(firebaseUserId: string, options?: import("./activityLogService").GetActivityLogsOptions): Promise<number>;
|
|
193
|
+
cleanupOldLogs(retentionDays: number): Promise<number>;
|
|
194
|
+
};
|
|
182
195
|
};
|
|
183
196
|
export default _default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "strapi-plugin-firebase-authentication",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Allows easy integration between clients utilizing Firebase for authentication and Strapi",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -85,6 +85,7 @@
|
|
|
85
85
|
},
|
|
86
86
|
"peerDependencies": {
|
|
87
87
|
"@strapi/strapi": "^5.0.0",
|
|
88
|
+
"@strapi/utils": "^5.0.0",
|
|
88
89
|
"react": "^18.0.0",
|
|
89
90
|
"react-dom": "^18.0.0",
|
|
90
91
|
"react-router-dom": "^6.0.0",
|