studiocms 0.2.0 → 0.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.
Files changed (293) hide show
  1. package/CHANGELOG.md +122 -0
  2. package/dist/cli/add/index.d.ts +2 -2
  3. package/dist/cli/add/index.js +4 -3
  4. package/dist/cli/add/npm-utils.d.ts +6 -6
  5. package/dist/cli/add/tryToInstallPlugins.d.ts +1 -1
  6. package/dist/cli/add/tryToInstallPlugins.js +6 -5
  7. package/dist/cli/add/updateStudioCMSConfig.d.ts +1 -1
  8. package/dist/cli/add/updateStudioCMSConfig.js +3 -4
  9. package/dist/cli/add/validatePlugins.d.ts +1 -2
  10. package/dist/cli/add/validatePlugins.js +15 -9
  11. package/dist/cli/crypto/genJWT/index.d.ts +1 -1
  12. package/dist/cli/crypto/genJWT/index.js +8 -9
  13. package/dist/cli/crypto/index.d.ts +1 -1
  14. package/dist/cli/init/steps/env.js +14 -4
  15. package/dist/cli/init/steps/next.d.ts +1 -1
  16. package/dist/cli/init/steps/next.js +6 -5
  17. package/dist/cli/migrator/index.d.ts +1 -1
  18. package/dist/cli/migrator/index.js +2 -2
  19. package/dist/cli/users/index.d.ts +1 -1
  20. package/dist/cli/users/shared.js +2 -2
  21. package/dist/cli/users/steps/createUsers.js +7 -7
  22. package/dist/cli/users/steps/modifyUsers.js +2 -2
  23. package/dist/cli/users/steps/next.d.ts +1 -1
  24. package/dist/cli/utils/checkRequiredEnvVars.js +2 -2
  25. package/dist/cli/utils/context.d.ts +2 -4
  26. package/dist/cli/utils/context.js +1 -3
  27. package/dist/cli/utils/getCliDbClient.d.ts +1 -1
  28. package/dist/cli/utils/intro.d.ts +1 -1
  29. package/dist/cli/utils/loadConfig.d.ts +54 -49
  30. package/dist/cli/utils/loadConfig.js +5 -8
  31. package/dist/cli/utils/logger.js +3 -3
  32. package/dist/cli/utils/user-utils.d.ts +1 -1
  33. package/dist/cli/utils/user-utils.js +4 -3
  34. package/dist/client/apiClient.d.ts +4923 -0
  35. package/dist/client/apiClient.js +72 -0
  36. package/dist/config.d.ts +1734 -1
  37. package/dist/consts.d.ts +5 -5
  38. package/dist/consts.js +3 -2
  39. package/dist/db/plugins.d.ts +1 -1
  40. package/dist/db/plugins.js +5 -8
  41. package/dist/handlers/frontend/routes.d.ts +4 -18
  42. package/dist/handlers/frontend/routes.js +13 -152
  43. package/dist/handlers/frontend/types.d.ts +1 -1
  44. package/dist/handlers/frontend/utils.js +0 -18
  45. package/dist/handlers/pluginHandler.d.ts +34 -257
  46. package/dist/handlers/pluginHandler.js +92 -46
  47. package/dist/handlers/routeHandler.js +32 -11
  48. package/dist/handlers/setupDbStudio.d.ts +3 -1
  49. package/dist/handlers/setupDbStudio.js +19 -10
  50. package/dist/handlers/storage-manager/core/effectify-astro-context.d.ts +25 -0
  51. package/dist/handlers/storage-manager/core/effectify-astro-context.js +78 -0
  52. package/dist/handlers/storage-manager/no-op.d.ts +2 -2
  53. package/dist/handlers/storage-manager/no-op.js +2 -3
  54. package/dist/index.d.ts +0 -1
  55. package/dist/index.js +10 -20
  56. package/dist/integrations/robots/index.d.ts +2 -2
  57. package/dist/integrations/robots/index.js +1 -3
  58. package/dist/integrations/robots/schema.d.ts +102 -273
  59. package/dist/integrations/robots/schema.js +220 -209
  60. package/dist/plugins/analytics/assets/schemas.d.ts +14 -9
  61. package/dist/plugins/analytics/assets/schemas.js +25 -17
  62. package/dist/plugins/analytics/db-client.d.ts +1 -1
  63. package/dist/plugins/analytics/index.d.ts +823 -3
  64. package/dist/plugins/analytics/index.js +4 -5
  65. package/dist/plugins/analytics/schemas.d.ts +54 -62
  66. package/dist/plugins/analytics/schemas.js +64 -13
  67. package/dist/plugins/analytics/table.d.ts +1 -1
  68. package/dist/plugins.d.ts +0 -1
  69. package/dist/schemas/config/api.d.ts +17 -0
  70. package/dist/schemas/config/api.js +14 -0
  71. package/dist/schemas/config/auth.d.ts +55 -59
  72. package/dist/schemas/config/auth.js +34 -11
  73. package/dist/schemas/config/dashboard.d.ts +43 -79
  74. package/dist/schemas/config/dashboard.js +43 -12
  75. package/dist/schemas/config/db.d.ts +15 -17
  76. package/dist/schemas/config/db.js +13 -5
  77. package/dist/schemas/config/developer.d.ts +33 -45
  78. package/dist/schemas/config/developer.js +22 -5
  79. package/dist/schemas/config/index.d.ts +398 -521
  80. package/dist/schemas/config/index.js +115 -57
  81. package/dist/schemas/config/sdk.d.ts +50 -196
  82. package/dist/schemas/config/sdk.js +61 -73
  83. package/dist/schemas/custom.d.ts +40 -0
  84. package/dist/schemas/custom.js +41 -0
  85. package/dist/schemas/external-schemas.d.ts +171 -0
  86. package/dist/schemas/external-schemas.js +179 -0
  87. package/dist/schemas/index.d.ts +2 -0
  88. package/dist/schemas/index.js +2 -0
  89. package/dist/schemas/plugins/i18n.d.ts +59 -39
  90. package/dist/schemas/plugins/i18n.js +42 -5
  91. package/dist/schemas/plugins/index.d.ts +7126 -10296
  92. package/dist/schemas/plugins/index.js +260 -276
  93. package/dist/schemas/plugins/shared.d.ts +1293 -3718
  94. package/dist/schemas/plugins/shared.js +320 -329
  95. package/dist/test-utils.d.ts +15 -4
  96. package/dist/test-utils.js +27 -11
  97. package/dist/toolbar/db-viewer/db-shared-types.d.ts +6 -6
  98. package/dist/toolbar/db-viewer/studio/connection.d.ts +8 -4
  99. package/dist/toolbar/db-viewer/studio/connection.js +2 -28
  100. package/dist/toolbar/db-viewer/studio/env/libsql.d.ts +7 -0
  101. package/dist/toolbar/db-viewer/studio/env/libsql.js +17 -0
  102. package/dist/toolbar/db-viewer/studio/env/mysql.d.ts +7 -0
  103. package/dist/toolbar/db-viewer/studio/env/mysql.js +23 -0
  104. package/dist/toolbar/db-viewer/studio/env/postgres.d.ts +7 -0
  105. package/dist/toolbar/db-viewer/studio/env/postgres.js +23 -0
  106. package/dist/toolbar/db-viewer/studio/index.js +20 -56
  107. package/dist/toolbar/db-viewer/studio/type.d.ts +1 -2
  108. package/dist/toolbar/db-viewer/studio/virtual-connection/libsql.d.ts +3 -0
  109. package/dist/toolbar/db-viewer/studio/virtual-connection/libsql.js +24 -0
  110. package/dist/toolbar/db-viewer/studio/virtual-connection/mysql.d.ts +3 -0
  111. package/dist/toolbar/db-viewer/studio/virtual-connection/mysql.js +9 -0
  112. package/dist/toolbar/db-viewer/studio/virtual-connection/postgres.d.ts +3 -0
  113. package/dist/toolbar/db-viewer/studio/virtual-connection/postgres.js +9 -0
  114. package/dist/toolbar/db-viewer/viewer.js +20 -21
  115. package/dist/types.d.ts +30 -0
  116. package/dist/utils/effects/smtp.d.ts +1 -1
  117. package/dist/utils/lang-helper.d.ts +10 -2
  118. package/dist/virtual.d.ts +35 -28
  119. package/dist/virtuals/auth/core.d.ts +5 -5
  120. package/dist/virtuals/auth/verify-email.d.ts +6 -6
  121. package/dist/virtuals/components/Generator.astro +2 -2
  122. package/dist/virtuals/components/Renderer.astro +9 -1
  123. package/dist/virtuals/components/renderFn.d.ts +3 -1
  124. package/dist/virtuals/components/renderFn.js +18 -0
  125. package/dist/virtuals/lib/headDefaults.d.ts +4 -2
  126. package/dist/virtuals/lib/headDefaults.js +0 -2
  127. package/dist/virtuals/lib/routeMap.d.ts +0 -12
  128. package/dist/virtuals/lib/routeMap.js +2 -14
  129. package/dist/virtuals/mailer/index.d.ts +3 -3
  130. package/dist/virtuals/notifier/index.d.ts +5 -5
  131. package/dist/virtuals/plugins/dashboard-pages.d.ts +2 -64
  132. package/dist/virtuals/scripts/StorageFileBrowser.d.ts +1 -172
  133. package/dist/virtuals/scripts/StorageFileBrowser.js +216 -119
  134. package/dist/virtuals/template-engine/index.d.ts +4 -4
  135. package/frontend/components/dashboard/configuration/ConfigForm.astro +218 -110
  136. package/frontend/components/dashboard/content-mgmt/ContentSearch.astro +21 -22
  137. package/frontend/components/dashboard/content-mgmt/CreateFolder.astro +66 -54
  138. package/frontend/components/dashboard/content-mgmt/CreatePage.astro +58 -104
  139. package/frontend/components/dashboard/content-mgmt/EditFolder.astro +65 -67
  140. package/frontend/components/dashboard/content-mgmt/EditPage.astro +86 -134
  141. package/frontend/components/dashboard/content-mgmt/InnerSidebarElement.astro +0 -1
  142. package/frontend/components/dashboard/content-mgmt/PageHeader.astro +33 -52
  143. package/frontend/components/dashboard/content-mgmt/PageTypeHandler.astro +2 -2
  144. package/frontend/components/dashboard/profile/APITokens.astro +219 -158
  145. package/frontend/components/dashboard/profile/BasicInfo.astro +165 -106
  146. package/frontend/components/dashboard/profile/Notifications.astro +27 -18
  147. package/frontend/components/dashboard/profile/UpdatePassword.astro +134 -94
  148. package/frontend/components/dashboard/sidebar/VersionCheck.astro +31 -16
  149. package/frontend/components/dashboard/sidebar/VersionCheckChangelog.astro +18 -11
  150. package/frontend/components/dashboard/sidebar-modals/VersionModal.astro +2 -2
  151. package/frontend/components/dashboard/smtp-config/TemplateEditor.astro +14 -14
  152. package/frontend/components/dashboard/taxonomy/InnerSidebarElement.astro +0 -1
  153. package/frontend/components/dashboard/taxonomy/MetaContainer.astro +0 -2
  154. package/frontend/components/dashboard/taxonomy/PageHeader.astro +16 -24
  155. package/frontend/components/dashboard/taxonomy/TaxonomySearch.astro +23 -27
  156. package/frontend/components/dashboard/user-mgmt/InnerSidebarElement.astro +111 -104
  157. package/frontend/components/dashboard/user-mgmt/UserListItem.astro +9 -22
  158. package/frontend/components/dashboard/user-mgmt/UserListItems.astro +18 -0
  159. package/frontend/components/first-time-setup/snippets/{opt2-studiocms.config.diff → studiocms.config.diff} +1 -0
  160. package/frontend/components/shared/Code.astro +1 -4
  161. package/frontend/components/shared/DynamicSettingsRenderer.astro +1 -1
  162. package/frontend/components/shared/SSRUser.astro +2 -4
  163. package/frontend/components/shared/foldertree/FolderTreeNode.astro +0 -6
  164. package/frontend/components/shared/storage-manager/StorageCopyOutput.astro +0 -1
  165. package/frontend/components/shared/taxonomy/TaxonomyTreeNode.astro +0 -6
  166. package/frontend/layouts/DashboardLayout.astro +1 -10
  167. package/frontend/layouts/TaxonomyLayout.astro +0 -1
  168. package/frontend/middleware/index.ts +102 -61
  169. package/frontend/pages/404.astro +5 -9
  170. package/frontend/pages/[dashboard]/[...pluginPage].astro +10 -1
  171. package/frontend/pages/[dashboard]/configuration.astro +10 -1
  172. package/frontend/pages/[dashboard]/content-management/createfolder.astro +10 -1
  173. package/frontend/pages/[dashboard]/content-management/createpage.astro +10 -1
  174. package/frontend/pages/[dashboard]/content-management/diff.astro +39 -14
  175. package/frontend/pages/[dashboard]/content-management/editfolder.astro +10 -1
  176. package/frontend/pages/[dashboard]/content-management/editpage.astro +10 -1
  177. package/frontend/pages/[dashboard]/content-management/index.astro +10 -1
  178. package/frontend/pages/[dashboard]/index.astro +10 -1
  179. package/frontend/pages/[dashboard]/login.astro +86 -25
  180. package/frontend/pages/[dashboard]/password-reset.astro +22 -16
  181. package/frontend/pages/[dashboard]/plugins/[plugin].astro +10 -1
  182. package/frontend/pages/[dashboard]/profile.astro +10 -1
  183. package/frontend/pages/[dashboard]/signup.astro +153 -52
  184. package/frontend/pages/[dashboard]/smtp-configuration.astro +77 -75
  185. package/frontend/pages/[dashboard]/system-management.astro +10 -1
  186. package/frontend/pages/[dashboard]/taxonomy/categories.astro +30 -41
  187. package/frontend/pages/[dashboard]/taxonomy/index.astro +10 -0
  188. package/frontend/pages/[dashboard]/taxonomy/tags.astro +33 -43
  189. package/frontend/pages/[dashboard]/unverified-email.astro +29 -21
  190. package/frontend/pages/[dashboard]/user-management/edit.astro +170 -90
  191. package/frontend/pages/[dashboard]/user-management/index.astro +10 -1
  192. package/frontend/pages/studiocms_api/[...all].ts +106 -0
  193. package/frontend/pages/studiocms_api/_handlers/_utils/auth.ts +26 -0
  194. package/frontend/pages/studiocms_api/_handlers/_utils/changelog.ts +147 -0
  195. package/frontend/pages/studiocms_api/_handlers/_utils/db-studio-driver.ts +46 -0
  196. package/frontend/pages/studiocms_api/_handlers/_utils/parseLogLevel.ts +27 -0
  197. package/frontend/pages/studiocms_api/_handlers/auth/auth.ts +459 -0
  198. package/frontend/pages/studiocms_api/_handlers/auth/index.ts +17 -0
  199. package/frontend/pages/studiocms_api/_handlers/auth/oauth.ts +91 -0
  200. package/frontend/pages/studiocms_api/_handlers/dashboard/_shared.ts +57 -0
  201. package/frontend/pages/studiocms_api/_handlers/dashboard/apiTokens.ts +134 -0
  202. package/frontend/pages/studiocms_api/_handlers/dashboard/config.ts +64 -0
  203. package/frontend/pages/studiocms_api/_handlers/dashboard/content.ts +741 -0
  204. package/frontend/pages/studiocms_api/_handlers/dashboard/create.ts +480 -0
  205. package/frontend/pages/studiocms_api/_handlers/dashboard/emailNotifications.ts +49 -0
  206. package/frontend/pages/studiocms_api/_handlers/dashboard/index.ts +45 -0
  207. package/frontend/pages/studiocms_api/_handlers/dashboard/mailer.ts +136 -0
  208. package/frontend/pages/studiocms_api/_handlers/dashboard/plugins.ts +80 -0
  209. package/frontend/pages/studiocms_api/_handlers/dashboard/profile.ts +275 -0
  210. package/frontend/pages/studiocms_api/_handlers/dashboard/resetPassword.ts +140 -0
  211. package/frontend/pages/studiocms_api/_handlers/dashboard/search.ts +63 -0
  212. package/frontend/pages/studiocms_api/_handlers/dashboard/taxonomy.ts +285 -0
  213. package/frontend/pages/studiocms_api/_handlers/dashboard/templates.ts +75 -0
  214. package/frontend/pages/studiocms_api/_handlers/dashboard/users.ts +312 -0
  215. package/frontend/pages/studiocms_api/_handlers/dashboard/verifyEndpoints.ts +307 -0
  216. package/frontend/pages/studiocms_api/_handlers/integration/dbStudio.ts +98 -0
  217. package/frontend/pages/studiocms_api/_handlers/integration/index.ts +17 -0
  218. package/frontend/pages/studiocms_api/_handlers/integration/storageManager.ts +107 -0
  219. package/frontend/pages/studiocms_api/_handlers/rest-api/index.ts +8 -0
  220. package/frontend/pages/studiocms_api/_handlers/rest-api/v1/_shared.ts +41 -0
  221. package/frontend/pages/studiocms_api/_handlers/rest-api/v1/index.ts +17 -0
  222. package/frontend/pages/studiocms_api/_handlers/rest-api/v1/public.ts +195 -0
  223. package/frontend/pages/studiocms_api/_handlers/rest-api/v1/secure.ts +1726 -0
  224. package/frontend/pages/studiocms_api/_handlers/sdk.ts +129 -0
  225. package/frontend/pages/studiocms_api/_middleware/astroLocals.ts +36 -0
  226. package/frontend/pages/studiocms_api/_middleware/restApi.ts +56 -0
  227. package/frontend/pages/studiocms_api/integrations/[...all].ts +8 -0
  228. package/frontend/scripts/formdata.ts +219 -0
  229. package/frontend/setup-pages/3-done.astro +4 -20
  230. package/frontend/setup-pages/studiocms_api/dashboard/step-2.ts +3 -6
  231. package/frontend/styles/dashboard-base.css +0 -1
  232. package/frontend/web-vitals/endpoint.ts +2 -1
  233. package/package.json +35 -31
  234. package/dist/global.d.ts +0 -9
  235. package/frontend/components/dashboard/LoginChecker.astro +0 -68
  236. package/frontend/components/dashboard/user-mgmt/RankCheck.astro +0 -57
  237. package/frontend/components/first-time-setup/snippets/opt1-astro.config.diff +0 -14
  238. package/frontend/components/first-time-setup/snippets/opt2-astro.config.diff +0 -9
  239. package/frontend/middleware/_authmap.ts +0 -63
  240. package/frontend/pages/studiocms_api/auth/[path].ts +0 -390
  241. package/frontend/pages/studiocms_api/auth/[provider]/[...id].ts +0 -64
  242. package/frontend/pages/studiocms_api/auth/[provider]/_effects/index.ts +0 -101
  243. package/frontend/pages/studiocms_api/auth/_shared.ts +0 -52
  244. package/frontend/pages/studiocms_api/dashboard/api-tokens.ts +0 -115
  245. package/frontend/pages/studiocms_api/dashboard/config.ts +0 -74
  246. package/frontend/pages/studiocms_api/dashboard/content/diff.ts +0 -73
  247. package/frontend/pages/studiocms_api/dashboard/content/folder.ts +0 -220
  248. package/frontend/pages/studiocms_api/dashboard/content/page.ts +0 -359
  249. package/frontend/pages/studiocms_api/dashboard/create-reset-link.ts +0 -77
  250. package/frontend/pages/studiocms_api/dashboard/create-user-invite.ts +0 -231
  251. package/frontend/pages/studiocms_api/dashboard/create-user.ts +0 -186
  252. package/frontend/pages/studiocms_api/dashboard/email-notification-settings-site.ts +0 -74
  253. package/frontend/pages/studiocms_api/dashboard/mailer/check-email.ts +0 -75
  254. package/frontend/pages/studiocms_api/dashboard/mailer/config.ts +0 -136
  255. package/frontend/pages/studiocms_api/dashboard/plugins/[plugin].ts +0 -80
  256. package/frontend/pages/studiocms_api/dashboard/profile.ts +0 -245
  257. package/frontend/pages/studiocms_api/dashboard/resend-verify-email.ts +0 -77
  258. package/frontend/pages/studiocms_api/dashboard/reset-password.ts +0 -124
  259. package/frontend/pages/studiocms_api/dashboard/search-list.ts +0 -59
  260. package/frontend/pages/studiocms_api/dashboard/taxonomy-search.ts +0 -47
  261. package/frontend/pages/studiocms_api/dashboard/taxonomy.ts +0 -230
  262. package/frontend/pages/studiocms_api/dashboard/templates.ts +0 -74
  263. package/frontend/pages/studiocms_api/dashboard/update-user-notifications.ts +0 -86
  264. package/frontend/pages/studiocms_api/dashboard/users.ts +0 -236
  265. package/frontend/pages/studiocms_api/dashboard/verify-email.ts +0 -83
  266. package/frontend/pages/studiocms_api/dashboard/verify-session.ts +0 -187
  267. package/frontend/pages/studiocms_api/integrations/[type]/[...id].ts +0 -15
  268. package/frontend/pages/studiocms_api/integrations/[type]/_routes/db-studio.ts +0 -173
  269. package/frontend/pages/studiocms_api/integrations/[type]/_routes/storage.ts +0 -88
  270. package/frontend/pages/studiocms_api/partials/editor.astro +0 -74
  271. package/frontend/pages/studiocms_api/partials/render.astro +0 -39
  272. package/frontend/pages/studiocms_api/partials/user-list-items.astro +0 -43
  273. package/frontend/pages/studiocms_api/rest/utils/auth-token.ts +0 -59
  274. package/frontend/pages/studiocms_api/rest/v1/[type]/[...id].ts +0 -23
  275. package/frontend/pages/studiocms_api/rest/v1/[type]/_routes/categories.ts +0 -267
  276. package/frontend/pages/studiocms_api/rest/v1/[type]/_routes/folders.ts +0 -283
  277. package/frontend/pages/studiocms_api/rest/v1/[type]/_routes/pages.ts +0 -505
  278. package/frontend/pages/studiocms_api/rest/v1/[type]/_routes/settings.ts +0 -100
  279. package/frontend/pages/studiocms_api/rest/v1/[type]/_routes/tags.ts +0 -229
  280. package/frontend/pages/studiocms_api/rest/v1/[type]/_routes/users.ts +0 -553
  281. package/frontend/pages/studiocms_api/rest/v1/public/[type]/[...id].ts +0 -19
  282. package/frontend/pages/studiocms_api/rest/v1/public/[type]/_routes/categories.ts +0 -74
  283. package/frontend/pages/studiocms_api/rest/v1/public/[type]/_routes/folders.ts +0 -85
  284. package/frontend/pages/studiocms_api/rest/v1/public/[type]/_routes/pages.ts +0 -103
  285. package/frontend/pages/studiocms_api/rest/v1/public/[type]/_routes/tags.ts +0 -67
  286. package/frontend/pages/studiocms_api/sdk/[...path].ts +0 -97
  287. package/frontend/pages/studiocms_api/sdk/utils/changelog.ts +0 -119
  288. package/frontend/scripts/auth/formListener.ts +0 -81
  289. package/frontend/scripts/formdata-utils.ts +0 -116
  290. package/frontend/utils/build-partial-schema.ts +0 -46
  291. package/frontend/utils/errors.ts +0 -6
  292. package/frontend/utils/param-extractor.ts +0 -83
  293. package/frontend/utils/rest-router.ts +0 -444
@@ -1,245 +0,0 @@
1
- /** biome-ignore-all lint/style/noNonNullAssertion: This file uses valid use cases for non-null assertion */
2
- import { Password, User } from 'studiocms:auth/lib';
3
- import { developerConfig } from 'studiocms:config';
4
- import { apiResponseLogger } from 'studiocms:logger';
5
- import { Notifications } from 'studiocms:notifier';
6
- import { SDKCore } from 'studiocms:sdk';
7
- import type { tsUsers } from 'studiocms:sdk/types';
8
- import {
9
- AllResponse,
10
- createEffectAPIRoutes,
11
- createJsonResponse,
12
- Effect,
13
- genLogger,
14
- OptionsResponse,
15
- readAPIContextJson,
16
- } from '@withstudiocms/effect';
17
- import { z } from 'astro/zod';
18
-
19
- type tsUsersUpdate = tsUsers['Update']['Type'];
20
-
21
- type UserBasicUpdate = Omit<tsUsersUpdate, 'id'>;
22
-
23
- type UserPasswordUpdate = {
24
- currentPassword: string | null;
25
- newPassword: string;
26
- confirmNewPassword: string;
27
- };
28
-
29
- type BasicUserProfileUpdate = {
30
- mode: 'basic';
31
- data: UserBasicUpdate;
32
- };
33
-
34
- type PasswordProfileUpdate = {
35
- mode: 'password';
36
- data: UserPasswordUpdate;
37
- };
38
-
39
- type AvatarProfileUpdate = {
40
- mode: 'avatar';
41
- };
42
-
43
- type UserProfileUpdate = BasicUserProfileUpdate | PasswordProfileUpdate | AvatarProfileUpdate;
44
-
45
- export const { POST, OPTIONS, ALL } = createEffectAPIRoutes(
46
- {
47
- POST: (ctx) =>
48
- genLogger('studiocms/routes/api/dashboard/profile.POST')(function* () {
49
- const [pass, userHelper, notify, sdk] = yield* Effect.all([
50
- Password,
51
- User,
52
- Notifications,
53
- SDKCore,
54
- ]);
55
-
56
- // Check if demo mode is enabled
57
- if (developerConfig.demoMode !== false) {
58
- return apiResponseLogger(403, 'Demo mode is enabled, this action is not allowed.');
59
- }
60
-
61
- // Get user data
62
- const userData = ctx.locals.StudioCMS.security?.userSessionData;
63
-
64
- // Check if user is logged in
65
- if (!userData?.isLoggedIn) {
66
- return apiResponseLogger(401, 'Unauthorized');
67
- }
68
-
69
- // Check if user has permission
70
- if (!ctx.locals.StudioCMS.security?.userPermissionLevel.isVisitor) {
71
- return apiResponseLogger(403, 'Unauthorized');
72
- }
73
-
74
- // Get Json Data
75
- const userProfileUpdate = yield* readAPIContextJson<UserProfileUpdate>(ctx);
76
-
77
- switch (userProfileUpdate.mode) {
78
- case 'basic': {
79
- const { data: r } = userProfileUpdate;
80
-
81
- const data = r;
82
-
83
- if (!data.name) {
84
- return apiResponseLogger(400, 'Invalid form data, name is required');
85
- }
86
-
87
- if (!data.email) {
88
- return apiResponseLogger(400, 'Invalid form data, email is required');
89
- }
90
-
91
- if (!data.username) {
92
- return apiResponseLogger(400, 'Invalid form data, username is required');
93
- }
94
-
95
- // If the username is invalid, return an error
96
- const verifyUsernameResponse = yield* userHelper.verifyUsernameInput(data.username);
97
- if (verifyUsernameResponse !== true) {
98
- return apiResponseLogger(400, verifyUsernameResponse);
99
- }
100
-
101
- // If the email is invalid, return an error
102
- const checkEmail = z.coerce
103
- .string()
104
- .email({ message: 'Email address is invalid' })
105
- .safeParse(data.email);
106
-
107
- if (!checkEmail.success)
108
- return apiResponseLogger(400, `Invalid email: ${checkEmail.error.message}`);
109
-
110
- const { usernameSearch, emailSearch } =
111
- yield* sdk.AUTH.user.searchUsersForUsernameOrEmail(data.username, checkEmail.data);
112
-
113
- if (userData.user?.username !== data.username) {
114
- if (usernameSearch.length > 0)
115
- return apiResponseLogger(400, 'Invalid username: Username is already in use');
116
- }
117
- if (userData.user?.email !== data.email) {
118
- if (emailSearch.length > 0)
119
- return apiResponseLogger(400, 'Invalid email: Email is already in use');
120
- }
121
- yield* sdk.AUTH.user.update({
122
- userId: userData.user!.id!,
123
- userData: { ...data, id: userData.user!.id! },
124
- });
125
-
126
- return apiResponseLogger(200, 'User profile updated successfully');
127
- }
128
- case 'password': {
129
- const { data: r } = userProfileUpdate;
130
-
131
- const data = r;
132
-
133
- const { currentPassword, newPassword, confirmNewPassword } = data;
134
-
135
- if (!currentPassword) {
136
- if (userData.user?.password) {
137
- return apiResponseLogger(400, 'Invalid form data, current password is required');
138
- }
139
- }
140
-
141
- if (!newPassword) {
142
- return apiResponseLogger(400, 'Invalid form data, new password is required');
143
- }
144
-
145
- // Verify the current password matches the stored hash (when one exists)
146
- if (currentPassword && userData.user?.password) {
147
- const isValid = yield* pass.verifyPasswordHash(
148
- userData.user.password,
149
- currentPassword
150
- );
151
- if (!isValid) {
152
- return apiResponseLogger(400, 'Invalid current password');
153
- }
154
- }
155
-
156
- if (!confirmNewPassword) {
157
- return apiResponseLogger(400, 'Invalid form data, confirm new password is required');
158
- }
159
-
160
- if (newPassword !== confirmNewPassword) {
161
- return apiResponseLogger(
162
- 400,
163
- 'Invalid form data, new password and confirm new password do not match'
164
- );
165
- }
166
-
167
- // If the password is invalid, return an error
168
- const verifyPasswordResponse = yield* pass.verifyPasswordStrength(newPassword);
169
- if (verifyPasswordResponse !== true) {
170
- return apiResponseLogger(400, verifyPasswordResponse);
171
- }
172
-
173
- const userUpdate = {
174
- password: yield* pass.hashPassword(newPassword),
175
- };
176
-
177
- if (userData.user)
178
- yield* Effect.all([
179
- sdk.AUTH.user.update({
180
- userId: userData.user.id,
181
- userData: {
182
- id: userData.user.id,
183
- name: userData.user.name,
184
- username: userData.user.username,
185
- updatedAt: new Date().toISOString(),
186
- emailVerified: userData.user.emailVerified,
187
- createdAt: undefined,
188
- ...userUpdate,
189
- },
190
- }),
191
- notify.sendUserNotification('account_updated', userData.user.id),
192
- notify.sendAdminNotification('user_updated', userData.user.username),
193
- ]);
194
-
195
- return apiResponseLogger(200, 'User password updated successfully');
196
- }
197
- case 'avatar': {
198
- if (!userData.user?.email) {
199
- return apiResponseLogger(400, 'User email required');
200
- }
201
-
202
- if (userData.user)
203
- yield* userHelper.createUserAvatar(userData.user.email).pipe(
204
- Effect.flatMap((newAvatar) =>
205
- Effect.all([
206
- sdk.AUTH.user.update({
207
- userId: userData.user!.id,
208
- userData: {
209
- id: userData.user!.id,
210
- name: userData.user!.name,
211
- username: userData.user!.username,
212
- updatedAt: new Date().toISOString(),
213
- emailVerified: userData.user!.emailVerified,
214
- createdAt: undefined,
215
- avatar: newAvatar,
216
- },
217
- }),
218
- notify.sendUserNotification('account_updated', userData.user!.id),
219
- notify.sendAdminNotification('user_updated', userData.user!.username),
220
- ])
221
- )
222
- );
223
-
224
- return apiResponseLogger(200, 'User Avatar updated successfully');
225
- }
226
- default:
227
- return apiResponseLogger(400, 'Invalid form data, mode is required or unsupported');
228
- }
229
- }).pipe(Notifications.Provide),
230
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['POST'] })),
231
- ALL: () => Effect.try(() => AllResponse()),
232
- },
233
- {
234
- cors: { methods: ['POST', 'OPTIONS'] },
235
- onError: (error) => {
236
- console.error('API Error:', error);
237
- return createJsonResponse(
238
- { error: 'Internal Server Error' },
239
- {
240
- status: 500,
241
- }
242
- );
243
- },
244
- }
245
- );
@@ -1,77 +0,0 @@
1
- import { VerifyEmail } from 'studiocms:auth/lib';
2
- import { apiResponseLogger } from 'studiocms:logger';
3
- import { SDKCore } from 'studiocms:sdk';
4
- import {
5
- AllResponse,
6
- createEffectAPIRoutes,
7
- createJsonResponse,
8
- Effect,
9
- genLogger,
10
- OptionsResponse,
11
- readAPIContextJson,
12
- } from '@withstudiocms/effect';
13
-
14
- export const { POST, OPTIONS, ALL } = createEffectAPIRoutes(
15
- {
16
- POST: (ctx) =>
17
- genLogger('studiocms/routes/api/dashboard/resend-verify-email.POST')(function* () {
18
- const [sdk, verifier] = yield* Effect.all([SDKCore, VerifyEmail]);
19
-
20
- // Check if mailer is enabled
21
- if (!ctx.locals.StudioCMS.siteConfig.data.enableMailer) {
22
- return apiResponseLogger(400, 'Mailer is disabled, this action is disabled.');
23
- }
24
-
25
- // Require authentication
26
- const userData = ctx.locals.StudioCMS.security?.userSessionData;
27
- if (!userData?.isLoggedIn) {
28
- return apiResponseLogger(403, 'Unauthorized');
29
- }
30
- // Restrict to admins/owners (or relax below to allow "self" requests only)
31
- const isPrivileged =
32
- ctx.locals.StudioCMS.security?.userPermissionLevel.isAdmin ||
33
- ctx.locals.StudioCMS.security?.userPermissionLevel.isOwner;
34
- if (!isPrivileged) {
35
- return apiResponseLogger(403, 'Unauthorized');
36
- }
37
-
38
- const { userId } = yield* readAPIContextJson<{ userId: string }>(ctx);
39
-
40
- if (!userId) {
41
- return apiResponseLogger(400, 'Invalid request');
42
- }
43
-
44
- const newToken = yield* sdk.AUTH.verifyEmail.create(userId);
45
-
46
- if (!newToken) {
47
- return apiResponseLogger(500, 'Failed to create verification token');
48
- }
49
-
50
- const response = yield* verifier.sendVerificationEmail(userId);
51
-
52
- if (!response) {
53
- return apiResponseLogger(500, 'Failed to send verification email');
54
- }
55
-
56
- if ('error' in response) {
57
- return apiResponseLogger(500, response.error);
58
- }
59
-
60
- return apiResponseLogger(200, response.message);
61
- }).pipe(VerifyEmail.Provide),
62
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['POST'] })),
63
- ALL: () => Effect.try(() => AllResponse()),
64
- },
65
- {
66
- cors: { methods: ['POST', 'OPTIONS'] },
67
- onError: (error) => {
68
- console.error('API Error:', error);
69
- return createJsonResponse(
70
- { error: 'Internal Server Error' },
71
- {
72
- status: 500,
73
- }
74
- );
75
- },
76
- }
77
- );
@@ -1,124 +0,0 @@
1
- import { Password } from 'studiocms:auth/lib';
2
- import { developerConfig } from 'studiocms:config';
3
- import { apiResponseLogger } from 'studiocms:logger';
4
- import { Notifications } from 'studiocms:notifier';
5
- import { SDKCore } from 'studiocms:sdk';
6
- import {
7
- AllResponse,
8
- createEffectAPIRoutes,
9
- createJsonResponse,
10
- Effect,
11
- genLogger,
12
- OptionsResponse,
13
- readAPIContextJson,
14
- } from '@withstudiocms/effect';
15
-
16
- export const { POST, OPTIONS, ALL } = createEffectAPIRoutes(
17
- {
18
- POST: (ctx) =>
19
- genLogger('studiocms/routes/api/dashboard/reset-password.POST')(function* () {
20
- const [notify, sdk, pass] = yield* Effect.all([Notifications, SDKCore, Password]);
21
-
22
- // Check if demo mode is enabled
23
- if (developerConfig.demoMode !== false) {
24
- return apiResponseLogger(403, 'Demo mode is enabled, this action is not allowed.');
25
- }
26
-
27
- const { token, id, userid, password, confirm_password } = yield* readAPIContextJson<{
28
- token: string;
29
- id: string;
30
- userid: string;
31
- password: string;
32
- confirm_password: string;
33
- }>(ctx);
34
-
35
- if (!token) {
36
- return apiResponseLogger(400, 'Invalid form data, token is required');
37
- }
38
-
39
- if (!id) {
40
- return apiResponseLogger(400, 'Invalid form data, id is required');
41
- }
42
-
43
- if (!userid) {
44
- return apiResponseLogger(400, 'Invalid form data, userid is required');
45
- }
46
-
47
- if (!password) {
48
- return apiResponseLogger(400, 'Invalid form data, password is required');
49
- }
50
-
51
- if (!confirm_password) {
52
- return apiResponseLogger(400, 'Invalid form data, confirm_password is required');
53
- }
54
-
55
- if (password !== confirm_password) {
56
- return apiResponseLogger(400, 'Passwords do not match');
57
- }
58
-
59
- // If the password is invalid, return an error
60
- const verifyPasswordResponse = yield* pass.verifyPasswordStrength(password);
61
- if (verifyPasswordResponse !== true) {
62
- return apiResponseLogger(400, verifyPasswordResponse);
63
- }
64
-
65
- const hashedPassword = yield* pass.hashPassword(password);
66
-
67
- // Verify the reset token and derive the userId from it
68
- const isTokenValid = yield* sdk.resetTokenBucket.check(token);
69
- if (!isTokenValid) {
70
- return apiResponseLogger(403, 'Invalid or expired reset token');
71
- }
72
-
73
- const tokenInfo = yield* sdk.UTIL.Generators.testToken(token);
74
- if (!tokenInfo || !tokenInfo.userId) {
75
- return apiResponseLogger(403, 'Invalid or expired reset token');
76
- }
77
-
78
- const targetUserId = tokenInfo.userId as string;
79
-
80
- const userUpdate = { password: hashedPassword };
81
-
82
- const userData = yield* sdk.GET.users.byId(targetUserId);
83
-
84
- if (!userData) {
85
- return apiResponseLogger(404, 'User not found');
86
- }
87
-
88
- yield* sdk.AUTH.user.update({
89
- userId: targetUserId,
90
- userData: {
91
- id: targetUserId,
92
- name: userData.name,
93
- username: userData.username,
94
- updatedAt: new Date().toISOString(),
95
- emailVerified: userData.emailVerified,
96
- createdAt: undefined,
97
- ...userUpdate,
98
- },
99
- });
100
-
101
- yield* Effect.all([
102
- sdk.resetTokenBucket.delete(targetUserId),
103
- notify.sendUserNotification('account_updated', targetUserId),
104
- notify.sendAdminNotification('user_updated', userData.username),
105
- ]);
106
-
107
- return apiResponseLogger(200, 'User password updated successfully');
108
- }).pipe(Notifications.Provide),
109
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['POST'] })),
110
- ALL: () => Effect.try(() => AllResponse()),
111
- },
112
- {
113
- cors: { methods: ['POST', 'OPTIONS'] },
114
- onError: (error) => {
115
- console.error('API Error:', error);
116
- return createJsonResponse(
117
- { error: 'Internal Server Error' },
118
- {
119
- status: 500,
120
- }
121
- );
122
- },
123
- }
124
- );
@@ -1,59 +0,0 @@
1
- import { SDKCore } from 'studiocms:sdk';
2
- import {
3
- AllResponse,
4
- createEffectAPIRoutes,
5
- createJsonResponse,
6
- Effect,
7
- genLogger,
8
- OptionsResponse,
9
- } from '@withstudiocms/effect';
10
-
11
- type SearchItem = {
12
- id: string;
13
- name: string;
14
- slug?: string;
15
- type: 'folder' | 'page';
16
- isDraft?: boolean | null;
17
- };
18
-
19
- export const { GET, OPTIONS, ALL } = createEffectAPIRoutes(
20
- {
21
- GET: () =>
22
- genLogger('studiocms/routes/api/dashboard/search-list.GET')(function* () {
23
- const sdk = yield* SDKCore;
24
-
25
- const searchList = yield* Effect.all([
26
- sdk.GET.folderList().pipe(
27
- Effect.map((res) => res.map(({ id, name }) => ({ id, name, type: 'folder' })))
28
- ),
29
- sdk.GET.pages(true).pipe(
30
- Effect.map((res) =>
31
- res.map(({ id, title, slug, draft }) => ({
32
- id,
33
- name: title,
34
- slug,
35
- isDraft: draft,
36
- type: 'page',
37
- }))
38
- )
39
- ),
40
- ]).pipe(Effect.map(([folders, pages]) => [...folders, ...pages] as SearchItem[]));
41
-
42
- return createJsonResponse(searchList);
43
- }),
44
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['GET'] })),
45
- ALL: () => Effect.try(() => AllResponse()),
46
- },
47
- {
48
- cors: { methods: ['GET', 'OPTIONS'] },
49
- onError: (error) => {
50
- console.error('API Error:', error);
51
- return createJsonResponse(
52
- { error: 'Internal Server Error' },
53
- {
54
- status: 500,
55
- }
56
- );
57
- },
58
- }
59
- );
@@ -1,47 +0,0 @@
1
- import { SDKCore } from 'studiocms:sdk';
2
- import {
3
- AllResponse,
4
- createEffectAPIRoutes,
5
- createJsonResponse,
6
- Effect,
7
- genLogger,
8
- OptionsResponse,
9
- } from '@withstudiocms/effect';
10
- import {
11
- categoriesToTaxonomyNodes,
12
- tagsToTaxonomyNodes,
13
- } from '#frontend/components/shared/taxonomy/shared.js';
14
-
15
- export const { GET, OPTIONS, ALL } = createEffectAPIRoutes(
16
- {
17
- GET: () =>
18
- genLogger('studiocms/routes/api/dashboard/search-list.GET')(function* () {
19
- const sdk = yield* SDKCore;
20
-
21
- return yield* Effect.all([sdk.GET.categories.getAll(), sdk.GET.tags.getAll()]).pipe(
22
- Effect.map(([categories, tags]) => ({
23
- categories: categoriesToTaxonomyNodes(categories),
24
- tags: tagsToTaxonomyNodes(tags),
25
- })),
26
- Effect.map(({ categories, tags }) => {
27
- return [...categories, ...tags];
28
- }),
29
- Effect.map(createJsonResponse)
30
- );
31
- }),
32
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['GET'] })),
33
- ALL: () => Effect.try(() => AllResponse()),
34
- },
35
- {
36
- cors: { methods: ['GET', 'OPTIONS'] },
37
- onError: (error) => {
38
- console.error('API Error:', error);
39
- return createJsonResponse(
40
- { error: 'Internal Server Error' },
41
- {
42
- status: 500,
43
- }
44
- );
45
- },
46
- }
47
- );