strapi-identity 0.0.1-debug.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.
Files changed (124) hide show
  1. package/README.md +112 -0
  2. package/dist/_chunks/AdminReset-B7_r8Jh1.mjs +112 -0
  3. package/dist/_chunks/AdminReset-BohoWW_F.js +112 -0
  4. package/dist/_chunks/ProfileToggle-CHVH6P3j.js +339 -0
  5. package/dist/_chunks/ProfileToggle-DIVxRCbJ.mjs +337 -0
  6. package/dist/_chunks/SettingsPage-C_Ke-Agb.mjs +5752 -0
  7. package/dist/_chunks/SettingsPage-IAGo8KRd.js +5752 -0
  8. package/dist/_chunks/WarningAlert-DFE5euMk.js +33 -0
  9. package/dist/_chunks/WarningAlert-VU011LVF.mjs +34 -0
  10. package/dist/_chunks/ar-BXaam37U.mjs +36 -0
  11. package/dist/_chunks/ar-i2eiMZkz.js +36 -0
  12. package/dist/_chunks/ca-BVpGzY8r.js +36 -0
  13. package/dist/_chunks/ca-DZ9DbEcQ.mjs +36 -0
  14. package/dist/_chunks/cs-Gok16KLy.mjs +36 -0
  15. package/dist/_chunks/cs-_PZVkwt0.js +36 -0
  16. package/dist/_chunks/de-BuYn1AYX.mjs +26 -0
  17. package/dist/_chunks/de-GItli7en.js +26 -0
  18. package/dist/_chunks/dk-B7EOsAdU.js +36 -0
  19. package/dist/_chunks/dk-CI64Xmli.mjs +36 -0
  20. package/dist/_chunks/en-B_vJwdfS.mjs +36 -0
  21. package/dist/_chunks/en-D4KP9t1Y.js +36 -0
  22. package/dist/_chunks/es-CHwF7YK-.js +36 -0
  23. package/dist/_chunks/es-CqJcXo4j.mjs +36 -0
  24. package/dist/_chunks/eu-D-snytN8.mjs +36 -0
  25. package/dist/_chunks/eu-DvdbwE5E.js +36 -0
  26. package/dist/_chunks/fr-Bt6sS5GX.mjs +26 -0
  27. package/dist/_chunks/fr-CbCW6hVD.js +26 -0
  28. package/dist/_chunks/gu-3wJbbAmw.mjs +36 -0
  29. package/dist/_chunks/gu-D2LgVfMp.js +36 -0
  30. package/dist/_chunks/he-Bjv7eygt.mjs +36 -0
  31. package/dist/_chunks/he-DnhYpbvN.js +36 -0
  32. package/dist/_chunks/hi-CNiDezU7.mjs +36 -0
  33. package/dist/_chunks/hi-DDD2E3A3.js +36 -0
  34. package/dist/_chunks/hu-C1_YkZHU.js +36 -0
  35. package/dist/_chunks/hu-aLaIWmGw.mjs +36 -0
  36. package/dist/_chunks/id-C8WRgGm1.mjs +36 -0
  37. package/dist/_chunks/id-u3wVE6Rv.js +36 -0
  38. package/dist/_chunks/index-CeYv7uJ3.js +1448 -0
  39. package/dist/_chunks/index-Df5ytRzw.mjs +1430 -0
  40. package/dist/_chunks/it-CDw6dG9Z.js +36 -0
  41. package/dist/_chunks/it-CjoRoJj1.mjs +36 -0
  42. package/dist/_chunks/ja-CbMXy2ym.js +36 -0
  43. package/dist/_chunks/ja-CewucIUY.mjs +36 -0
  44. package/dist/_chunks/ko-BEtJPpfJ.js +36 -0
  45. package/dist/_chunks/ko-D-kAxDtd.mjs +36 -0
  46. package/dist/_chunks/ml-0fR2_MmA.js +36 -0
  47. package/dist/_chunks/ml-DR3AaofF.mjs +36 -0
  48. package/dist/_chunks/ms-COHLS5e5.mjs +36 -0
  49. package/dist/_chunks/ms-DLvuGSlk.js +36 -0
  50. package/dist/_chunks/nl-DVtHsM2H.mjs +36 -0
  51. package/dist/_chunks/nl-wj6kn642.js +36 -0
  52. package/dist/_chunks/no-DVBgWt8q.js +36 -0
  53. package/dist/_chunks/no-D_0yjyCy.mjs +36 -0
  54. package/dist/_chunks/pl-B2ghisbC.js +36 -0
  55. package/dist/_chunks/pl-C3GNxjVX.mjs +36 -0
  56. package/dist/_chunks/pt-BR-BbKV8YoX.mjs +36 -0
  57. package/dist/_chunks/pt-BR-CfgNaB1-.js +36 -0
  58. package/dist/_chunks/pt-DKe8rRWa.js +36 -0
  59. package/dist/_chunks/pt-z4K3cCjf.mjs +36 -0
  60. package/dist/_chunks/ru-BFSm68HC.js +36 -0
  61. package/dist/_chunks/ru-C85izLFa.mjs +36 -0
  62. package/dist/_chunks/sa-B1XoTTrE.mjs +36 -0
  63. package/dist/_chunks/sa-BOPaqylt.js +36 -0
  64. package/dist/_chunks/sk-C48lUPuC.mjs +36 -0
  65. package/dist/_chunks/sk-Dd-S1612.js +36 -0
  66. package/dist/_chunks/sv-BLma_kJl.mjs +36 -0
  67. package/dist/_chunks/sv-lg64Cw78.js +36 -0
  68. package/dist/_chunks/th-BJEu5n7q.mjs +36 -0
  69. package/dist/_chunks/th-DPbm5NrX.js +36 -0
  70. package/dist/_chunks/tokenHelpers-DagDzpso.mjs +22 -0
  71. package/dist/_chunks/tokenHelpers-jtoRu0q5.js +21 -0
  72. package/dist/_chunks/tr-Bm1QZr4v.js +36 -0
  73. package/dist/_chunks/tr-DkIUODKq.mjs +36 -0
  74. package/dist/_chunks/uk-D7ArtSe3.mjs +36 -0
  75. package/dist/_chunks/uk-FARzIGx4.js +36 -0
  76. package/dist/_chunks/vi-Bi9B6eTY.js +36 -0
  77. package/dist/_chunks/vi-DS0yslPP.mjs +36 -0
  78. package/dist/_chunks/zh-DkEx28ZA.js +36 -0
  79. package/dist/_chunks/zh-DwCvIPSz.mjs +36 -0
  80. package/dist/_chunks/zh-Hans-BwwKCR6_.js +36 -0
  81. package/dist/_chunks/zh-Hans-DP2xZyda.mjs +36 -0
  82. package/dist/admin/index.js +4 -0
  83. package/dist/admin/index.mjs +5 -0
  84. package/dist/admin/src/components/ConfirmModal/ConfirmModal.d.ts +10 -0
  85. package/dist/admin/src/components/ConfirmModal/index.d.ts +1 -0
  86. package/dist/admin/src/components/Initializer.d.ts +5 -0
  87. package/dist/admin/src/components/InputOTP.d.ts +11 -0
  88. package/dist/admin/src/components/RemoveModal/RemoveModal.d.ts +7 -0
  89. package/dist/admin/src/components/RemoveModal/index.d.ts +1 -0
  90. package/dist/admin/src/components/WarningAlert/WarningAlert.d.ts +11 -0
  91. package/dist/admin/src/components/WarningAlert/index.d.ts +1 -0
  92. package/dist/admin/src/index.d.ts +3 -0
  93. package/dist/admin/src/injection/AdminReset.d.ts +4 -0
  94. package/dist/admin/src/injection/ProfileToggle.d.ts +2 -0
  95. package/dist/admin/src/pluginId.d.ts +1 -0
  96. package/dist/admin/src/public/VerifyPage.d.ts +12 -0
  97. package/dist/admin/src/settings/SettingsPage.d.ts +1 -0
  98. package/dist/admin/src/utils/getTranslation.d.ts +2 -0
  99. package/dist/admin/src/utils/tokenHelpers.d.ts +12 -0
  100. package/dist/server/index.js +11765 -0
  101. package/dist/server/index.mjs +11761 -0
  102. package/dist/server/src/bootstrap.d.ts +3 -0
  103. package/dist/server/src/config/index.d.ts +3 -0
  104. package/dist/server/src/content-types/config/index.d.ts +38 -0
  105. package/dist/server/src/content-types/index.d.ts +3 -0
  106. package/dist/server/src/content-types/mfa/index.d.ts +56 -0
  107. package/dist/server/src/content-types/temp-mfa/index.d.ts +35 -0
  108. package/dist/server/src/controllers/admin.d.ts +3 -0
  109. package/dist/server/src/controllers/config.d.ts +3 -0
  110. package/dist/server/src/controllers/controller.d.ts +3 -0
  111. package/dist/server/src/controllers/index.d.ts +3 -0
  112. package/dist/server/src/destroy.d.ts +3 -0
  113. package/dist/server/src/index.d.ts +26 -0
  114. package/dist/server/src/middlewares/index.d.ts +3 -0
  115. package/dist/server/src/policies/has-mfa.d.ts +3 -0
  116. package/dist/server/src/policies/index.d.ts +3 -0
  117. package/dist/server/src/register.d.ts +3 -0
  118. package/dist/server/src/routes/admin/index.d.ts +2 -0
  119. package/dist/server/src/routes/index.d.ts +3 -0
  120. package/dist/server/src/services/admin.d.ts +11 -0
  121. package/dist/server/src/services/config.d.ts +28 -0
  122. package/dist/server/src/services/index.d.ts +3 -0
  123. package/dist/server/src/services/mfa.d.ts +50 -0
  124. package/package.json +88 -0
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '@strapi/types';
2
+ declare const bootstrap: Plugin.LoadedPlugin['bootstrap'];
3
+ export default bootstrap;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '@strapi/types';
2
+ declare const config: Plugin.LoadedPlugin['config'];
3
+ export default config;
@@ -0,0 +1,38 @@
1
+ declare const _default: {
2
+ schema: {
3
+ kind: string;
4
+ collectionName: string;
5
+ info: {
6
+ singularName: string;
7
+ pluralName: string;
8
+ displayName: string;
9
+ };
10
+ options: {
11
+ draftAndPublish: boolean;
12
+ };
13
+ pluginOptions: {
14
+ "content-manager": {
15
+ visible: boolean;
16
+ };
17
+ "content-type-builder": {
18
+ visible: boolean;
19
+ };
20
+ };
21
+ attributes: {
22
+ enabled: {
23
+ type: string;
24
+ default: boolean;
25
+ };
26
+ enforce: {
27
+ type: string;
28
+ default: boolean;
29
+ };
30
+ issuer: {
31
+ type: string;
32
+ required: boolean;
33
+ default: string;
34
+ };
35
+ };
36
+ };
37
+ };
38
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '@strapi/types';
2
+ declare const contentTypes: Plugin.LoadedPlugin['contentTypes'];
3
+ export default contentTypes;
@@ -0,0 +1,56 @@
1
+ declare const _default: {
2
+ schema: {
3
+ kind: string;
4
+ collectionName: string;
5
+ info: {
6
+ singularName: string;
7
+ pluralName: string;
8
+ displayName: string;
9
+ };
10
+ options: {
11
+ draftAndPublish: boolean;
12
+ };
13
+ pluginOptions: {
14
+ "content-manager": {
15
+ visible: boolean;
16
+ };
17
+ "content-type-builder": {
18
+ visible: boolean;
19
+ };
20
+ };
21
+ attributes: {
22
+ admin_user: {
23
+ type: string;
24
+ relation: string;
25
+ target: string;
26
+ };
27
+ enabled: {
28
+ type: string;
29
+ default: boolean;
30
+ };
31
+ type: {
32
+ type: string;
33
+ enum: string[];
34
+ default: string;
35
+ };
36
+ secret: {
37
+ type: string;
38
+ required: boolean;
39
+ private: boolean;
40
+ };
41
+ counter: {
42
+ type: string;
43
+ default: string;
44
+ };
45
+ digits: {
46
+ type: string;
47
+ default: number;
48
+ };
49
+ recovery_codes: {
50
+ type: string;
51
+ private: boolean;
52
+ };
53
+ };
54
+ };
55
+ };
56
+ export default _default;
@@ -0,0 +1,35 @@
1
+ declare const _default: {
2
+ schema: {
3
+ kind: string;
4
+ collectionName: string;
5
+ info: {
6
+ singularName: string;
7
+ pluralName: string;
8
+ displayName: string;
9
+ };
10
+ options: {
11
+ draftAndPublish: boolean;
12
+ };
13
+ pluginOptions: {
14
+ "content-manager": {
15
+ visible: boolean;
16
+ };
17
+ "content-type-builder": {
18
+ visible: boolean;
19
+ };
20
+ };
21
+ attributes: {
22
+ admin_user: {
23
+ type: string;
24
+ relation: string;
25
+ target: string;
26
+ };
27
+ secret: {
28
+ type: string;
29
+ required: boolean;
30
+ private: boolean;
31
+ };
32
+ };
33
+ };
34
+ };
35
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { Core } from '@strapi/strapi';
2
+ declare const _default: Core.Controller;
3
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { Core } from '@strapi/strapi';
2
+ declare const _default: Core.Controller;
3
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { Core } from '@strapi/strapi';
2
+ declare const _default: Core.Controller;
3
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '@strapi/strapi';
2
+ declare const controllers: Plugin.LoadedPlugin['controllers'];
3
+ export default controllers;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '@strapi/types';
2
+ declare const destroy: Plugin.LoadedPlugin['destroy'];
3
+ export default destroy;
@@ -0,0 +1,26 @@
1
+ declare const _default: {
2
+ register: ({ strapi }: {
3
+ strapi: import("@strapi/types/dist/core").Strapi;
4
+ }) => void | Promise<void>;
5
+ bootstrap: ({ strapi }: {
6
+ strapi: import("@strapi/types/dist/core").Strapi;
7
+ }) => void | Promise<void>;
8
+ destroy: ({ strapi }: {
9
+ strapi: import("@strapi/types/dist/core").Strapi;
10
+ }) => void | Promise<void>;
11
+ config: {
12
+ default: Record<string, unknown> | ((opts: {
13
+ env: import("@strapi/utils/dist/env-helper").Env;
14
+ }) => Record<string, unknown>);
15
+ validator: (config: Record<string, unknown>) => void;
16
+ };
17
+ controllers: Record<string, import("@strapi/types/dist/core").Controller>;
18
+ routes: Record<string, import("@strapi/types/dist/core").Router>;
19
+ services: Record<string, import("@strapi/types/dist/core").Service>;
20
+ contentTypes: Record<string, {
21
+ schema: import("@strapi/types/dist/struct").ContentTypeSchema;
22
+ }>;
23
+ policies: Record<string, import("@strapi/types/dist/core").Policy>;
24
+ middlewares: Record<string, import("@strapi/types/dist/core").Middleware>;
25
+ };
26
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '@strapi/types';
2
+ declare const middlewares: Plugin.LoadedPlugin['middlewares'];
3
+ export default middlewares;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '@strapi/types';
2
+ declare const policy: Plugin.LoadedPlugin['policies'][string];
3
+ export default policy;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '@strapi/types';
2
+ declare const policies: Plugin.LoadedPlugin['policies'];
3
+ export default policies;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '@strapi/types';
2
+ declare const register: Plugin.LoadedPlugin['register'];
3
+ export default register;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("@strapi/types/dist/core").Router;
2
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '@strapi/types';
2
+ declare const routes: Plugin.LoadedPlugin['routes'];
3
+ export default routes;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Check if 2FA is enabled for a user by looking for an associated MFA token.
3
+ * @param id the user's ID to check for an associated MFA token, indicating that 2FA is enabled for that user
4
+ * @returns a boolean indicating whether 2FA is enabled for the user (true if an MFA token exists, false otherwise)
5
+ */
6
+ export declare const isEnabled: (id: string) => false | Promise<boolean>;
7
+ /**
8
+ * Resets 2FA for a user by deleting any existing MFA token and temporary secret associated with that user.
9
+ * @param id the user's ID for which to reset 2FA, which will delete any associated MFA token and temporary secret, effectively disabling 2FA for that user until they set it up again
10
+ */
11
+ export declare const reset: (id: string) => Promise<void>;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Service for managing the Strapi Identity plugin configuration
3
+ * @returns an object containing functions to get and update the plugin configuration
4
+ */
5
+ export declare const isEnabled: () => Promise<unknown>;
6
+ /**
7
+ * Retrieves the current configuration for the Strapi Identity plugin
8
+ * @returns the current configuration
9
+ */
10
+ export declare const getConfig: () => Promise<{
11
+ enabled: unknown;
12
+ enforce: unknown;
13
+ issuer: unknown;
14
+ }>;
15
+ /**
16
+ * Updates the Strapi Identity plugin configuration with the provided data
17
+ * @param data partial configuration data to update
18
+ * @returns the updated configuration
19
+ */
20
+ export declare const updateConfig: (data: Partial<{
21
+ enabled: boolean;
22
+ enforce: boolean;
23
+ issuer: string;
24
+ }>) => Promise<{
25
+ enabled: unknown;
26
+ enforce: unknown;
27
+ issuer: unknown;
28
+ }>;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '@strapi/types';
2
+ declare const services: Plugin.LoadedPlugin['services'];
3
+ export default services;
@@ -0,0 +1,50 @@
1
+ import { Secret } from 'otpauth';
2
+ /**
3
+ * Validates a TOTP token against the temporary secret for a given user
4
+ * @param userId id of the user to validate against
5
+ * @param token TOTP token to validate
6
+ * @returns {Promise<boolean>} is the token valid
7
+ */
8
+ export declare const validateTempToken: (userId: string, token: string) => Promise<boolean>;
9
+ /**
10
+ * Validates a code against both the user's active TOTP secret and their recovery codes
11
+ * @param userId id of the user to validate against
12
+ * @param code code to validate (either TOTP token or recovery code)
13
+ * @returns {Promise<boolean>} is the code valid
14
+ */
15
+ export declare const validateTokenOrRecoveryCode: (userId: string, code: string) => Promise<boolean>;
16
+ /**
17
+ * Sets up a temporary secret for a user during MFA setup
18
+ * @param userId id of the user to set up MFA for
19
+ * @return {Promise<Secret>} the generated temporary secret
20
+ */
21
+ export declare const setupTemporarySecret: (userId: string) => Promise<Secret>;
22
+ /**
23
+ * Finalizes MFA setup by moving the temporary secret to the main token document and generating recovery codes
24
+ * @param userId id of the user to finalize MFA setup for
25
+ * @returns {Promise<string[]>} the generated recovery codes
26
+ */
27
+ export declare const setupFullSecret: (userId: string) => Promise<string[]>;
28
+ /**
29
+ * Disables MFA for a user after validating the provided TOTP token or recovery code
30
+ * @param userId id of the user to disable MFA for
31
+ * @param code a valid TOTP token or recovery code for the user
32
+ */
33
+ export declare const disableSecret: (userId: string, code: string) => Promise<void>;
34
+ /**
35
+ * Disables the temporary secret for a user, effectively canceling the MFA setup process
36
+ * @param userId id of the user to disable the temporary secret for
37
+ */
38
+ export declare const disableTempSecret: (userId: string) => Promise<void>;
39
+ /**
40
+ * Checks if MFA is currently enabled for a given user
41
+ * @param userId id of the user to check
42
+ * @returns {Promise<'full' | null>} is MFA enabled for the user
43
+ */
44
+ export declare const isMFAEnabled: (userId: string) => Promise<'full' | null>;
45
+ /**
46
+ * Generates a secure random recovery code of the specified length
47
+ * @param length length of the recovery code to generate (default: 8)
48
+ * @returns {string} the generated recovery code
49
+ */
50
+ export declare const generateRecoveryCode: (length?: number) => string;
package/package.json ADDED
@@ -0,0 +1,88 @@
1
+ {
2
+ "version": "0.0.1-debug.0",
3
+ "keywords": [
4
+ "strapi",
5
+ "plugin",
6
+ "authentication",
7
+ "2FA",
8
+ "MFA"
9
+ ],
10
+ "type": "commonjs",
11
+ "exports": {
12
+ "./package.json": "./package.json",
13
+ "./strapi-admin": {
14
+ "types": "./dist/admin/src/index.d.ts",
15
+ "source": "./admin/src/index.ts",
16
+ "import": "./dist/admin/index.mjs",
17
+ "require": "./dist/admin/index.js",
18
+ "default": "./dist/admin/index.js"
19
+ },
20
+ "./strapi-server": {
21
+ "types": "./dist/server/src/index.d.ts",
22
+ "source": "./server/src/index.ts",
23
+ "import": "./dist/server/index.mjs",
24
+ "require": "./dist/server/index.js",
25
+ "default": "./dist/server/index.js"
26
+ }
27
+ },
28
+ "files": [
29
+ "dist"
30
+ ],
31
+ "scripts": {
32
+ "build": "strapi-plugin build",
33
+ "watch": "strapi-plugin watch",
34
+ "watch:link": "strapi-plugin watch:link",
35
+ "verify": "strapi-plugin verify",
36
+ "test:ts:front": "run -T tsc -p admin/tsconfig.json",
37
+ "test:ts:back": "run -T tsc -p server/tsconfig.json"
38
+ },
39
+ "dependencies": {
40
+ "input-otp": "^1.4.2",
41
+ "otpauth": "^9.5.0",
42
+ "react-qr-code": "^2.0.18",
43
+ "strapi-admin-portal": "^0.0.3"
44
+ },
45
+ "devDependencies": {
46
+ "@strapi/sdk-plugin": "^5.4.0",
47
+ "@strapi/strapi": "^5.35.0",
48
+ "@strapi/typescript-utils": "^5.35.0",
49
+ "@types/bcryptjs": "^2.4.6",
50
+ "@types/react": "^18.3.27",
51
+ "@types/react-dom": "^18.3.7",
52
+ "prettier": "^3.8.1",
53
+ "react": "^18.3.1",
54
+ "react-dom": "^18.3.1",
55
+ "react-router-dom": "^6.30.3",
56
+ "styled-components": "^6.3.8",
57
+ "typescript": "^5.9.3"
58
+ },
59
+ "peerDependencies": {
60
+ "@strapi/design-system": "^2.1.2",
61
+ "@strapi/icons": "^2.1.2",
62
+ "@strapi/sdk-plugin": "^5.4.0",
63
+ "@strapi/strapi": "^5.34.0",
64
+ "react": "^18.3.1",
65
+ "react-dom": "^18.3.1",
66
+ "react-intl": "^6.6.2",
67
+ "react-router-dom": "^6.30.3",
68
+ "styled-components": "^6.3.8"
69
+ },
70
+ "strapi": {
71
+ "kind": "plugin",
72
+ "name": "strapi-identity",
73
+ "displayName": "Strapi Identity",
74
+ "description": "Strapi plugin to add missing features to the strapi auth system"
75
+ },
76
+ "name": "strapi-identity",
77
+ "description": "Strapi plugin to add missing features to the strapi auth system",
78
+ "license": "MIT",
79
+ "repository": {
80
+ "type": "git",
81
+ "url": "git+ssh://git@github.com/Link2Twenty/strapi-identity.git"
82
+ },
83
+ "bugs": {
84
+ "url": "https://github.com/Link2Twenty/strapi-identity/issues"
85
+ },
86
+ "homepage": "https://github.com/Link2Twenty/strapi-identity#readme",
87
+ "author": "Andrew Bone <AndrewB05+strapi@gmail.com>"
88
+ }