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,186 +0,0 @@
1
- import { Password, User } from 'studiocms:auth/lib';
2
- import { apiResponseLogger } from 'studiocms:logger';
3
- import { Notifications } from 'studiocms:notifier';
4
- import { SDKCore } from 'studiocms:sdk';
5
- import { type AvailablePermissionRanks, UserPermissionLevel } from '@withstudiocms/auth-kit/types';
6
- import {
7
- AllResponse,
8
- createEffectAPIRoutes,
9
- createJsonResponse,
10
- Effect,
11
- genLogger,
12
- OptionsResponse,
13
- readAPIContextJson,
14
- } from '@withstudiocms/effect';
15
- import { z } from 'astro/zod';
16
- import { ValidRanks } from '#consts';
17
-
18
- type JSONData = {
19
- username: string | undefined;
20
- password: string | undefined;
21
- email: string | undefined;
22
- displayname: string | undefined;
23
- rank: AvailablePermissionRanks | undefined;
24
- };
25
-
26
- export const { POST, OPTIONS, ALL } = createEffectAPIRoutes(
27
- {
28
- POST: (ctx) =>
29
- genLogger('studiocms/routes/api/dashboard/create-user.POST')(function* () {
30
- const [pass, userHelper, notify, sdk] = yield* Effect.all([
31
- Password,
32
- User,
33
- Notifications,
34
- SDKCore,
35
- ]);
36
-
37
- // Get user data
38
- const userData = ctx.locals.StudioCMS.security?.userSessionData;
39
-
40
- // Check if user is logged in
41
- if (!userData?.isLoggedIn) {
42
- return apiResponseLogger(403, 'Unauthorized');
43
- }
44
-
45
- // Check if user has permission
46
- const isAuthorized = ctx.locals.StudioCMS.security?.userPermissionLevel.isAdmin;
47
- if (!isAuthorized) {
48
- return apiResponseLogger(403, 'Unauthorized');
49
- }
50
-
51
- let { username, password, email, displayname, rank } =
52
- yield* readAPIContextJson<JSONData>(ctx);
53
-
54
- // If the username, password, email, or display name is missing, return an error
55
- if (!username) {
56
- return apiResponseLogger(400, 'Missing field: Username is required');
57
- }
58
-
59
- if (!password) {
60
- password = yield* sdk.UTIL.Generators.generateRandomPassword(12);
61
- }
62
-
63
- if (!email) {
64
- return apiResponseLogger(400, 'Missing field: Email is required');
65
- }
66
-
67
- if (!displayname) {
68
- return apiResponseLogger(400, 'Missing field: Display name is required');
69
- }
70
-
71
- if (!rank) {
72
- return apiResponseLogger(400, 'Missing field: Rank is required');
73
- }
74
-
75
- // Validate target rank and ensure caller has sufficient privilege
76
- if (!ValidRanks.has(rank) || rank === 'unknown') {
77
- return apiResponseLogger(400, 'Invalid rank');
78
- }
79
- const callerPerm = yield* userHelper.getUserPermissionLevel(userData);
80
- const rankToPerm = (r: typeof rank) => {
81
- switch (r) {
82
- case 'owner':
83
- return UserPermissionLevel.owner;
84
- case 'admin':
85
- return UserPermissionLevel.admin;
86
- case 'editor':
87
- return UserPermissionLevel.editor;
88
- case 'visitor':
89
- return UserPermissionLevel.visitor;
90
- default:
91
- return UserPermissionLevel.unknown;
92
- }
93
- };
94
- const targetPerm = rankToPerm(rank);
95
- // Use explicit weights to avoid relying on enum ordinal
96
- const permWeight = (lvl: UserPermissionLevel) => {
97
- switch (lvl) {
98
- case UserPermissionLevel.owner:
99
- return 4;
100
- case UserPermissionLevel.admin:
101
- return 3;
102
- case UserPermissionLevel.editor:
103
- return 2;
104
- case UserPermissionLevel.visitor:
105
- return 1;
106
- default:
107
- return 0;
108
- }
109
- };
110
-
111
- // Only owners can assign 'owner'
112
- if (rank === 'owner' && callerPerm !== UserPermissionLevel.owner) {
113
- return createJsonResponse({ error: 'Forbidden' }, { status: 403 });
114
- }
115
- // Allow equality for owner→owner; otherwise require caller >= target
116
- if (permWeight(callerPerm) < permWeight(targetPerm)) {
117
- return createJsonResponse({ error: 'Forbidden' }, { status: 403 });
118
- }
119
-
120
- // If the email is invalid, return an error
121
- const checkEmail = z.coerce
122
- .string()
123
- .email({ message: 'Email address is invalid' })
124
- .safeParse(email);
125
-
126
- if (!checkEmail.success) {
127
- return apiResponseLogger(400, `Invalid email: ${checkEmail.error.message}`);
128
- }
129
-
130
- const [verifyUsernameResponse, verifyPasswordResponse, { usernameSearch, emailSearch }] =
131
- yield* Effect.all([
132
- userHelper.verifyUsernameInput(username),
133
- pass.verifyPasswordStrength(password),
134
- sdk.AUTH.user.searchUsersForUsernameOrEmail(username, checkEmail.data),
135
- ]);
136
-
137
- // If the username is invalid, return an error
138
- if (verifyUsernameResponse !== true) {
139
- return apiResponseLogger(400, verifyUsernameResponse);
140
- }
141
-
142
- // If the password is invalid, return an error
143
- if (verifyPasswordResponse !== true) {
144
- return apiResponseLogger(400, verifyPasswordResponse);
145
- }
146
-
147
- if (usernameSearch.length > 0) {
148
- return apiResponseLogger(400, 'Invalid username: Username is already in use');
149
- }
150
-
151
- if (emailSearch.length > 0) {
152
- return apiResponseLogger(400, 'Invalid email: Email is already in use');
153
- }
154
-
155
- // Create a new user
156
- yield* userHelper.createLocalUser(displayname, username, email, password).pipe(
157
- Effect.flatMap((newUser) =>
158
- sdk.UPDATE.permissions({
159
- user: newUser.id,
160
- rank: rank,
161
- })
162
- ),
163
- Effect.tap(() => notify.sendAdminNotification('new_user', username))
164
- );
165
-
166
- return apiResponseLogger(
167
- 200,
168
- JSON.stringify({ username, email, displayname, rank: rank, password })
169
- );
170
- }).pipe(Notifications.Provide),
171
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['POST'] })),
172
- ALL: () => Effect.try(() => AllResponse()),
173
- },
174
- {
175
- cors: { methods: ['POST', 'OPTIONS'] },
176
- onError: (error) => {
177
- console.error('API Error:', error);
178
- return createJsonResponse(
179
- { error: 'Internal Server Error' },
180
- {
181
- status: 500,
182
- }
183
- );
184
- },
185
- }
186
- );
@@ -1,74 +0,0 @@
1
- import { apiResponseLogger } from 'studiocms:logger';
2
- import { SDKCore } from 'studiocms:sdk';
3
- import type { ConfigFinal, StudioCMSNotificationSettings } from 'studiocms:sdk/types';
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/email-notification-settings-site.POST')(
18
- function* () {
19
- const sdk = yield* SDKCore;
20
-
21
- // Get user data
22
- const userData = ctx.locals.StudioCMS.security?.userSessionData;
23
-
24
- // Check if user is logged in
25
- if (!userData?.isLoggedIn) {
26
- return apiResponseLogger(403, 'Unauthorized');
27
- }
28
-
29
- // Check if user has permission
30
- const isAuthorized = ctx.locals.StudioCMS.security?.userPermissionLevel.isOwner;
31
- if (!isAuthorized) {
32
- return apiResponseLogger(403, 'Unauthorized');
33
- }
34
-
35
- yield* readAPIContextJson<unknown>(ctx).pipe(
36
- Effect.map((raw) => {
37
- const rawData = (raw ?? {}) as Record<string, unknown>;
38
- const safe = {
39
- emailVerification:
40
- typeof rawData.emailVerification === 'boolean'
41
- ? rawData.emailVerification
42
- : undefined,
43
- requireAdminVerification:
44
- typeof rawData.requireAdminVerification === 'boolean'
45
- ? rawData.requireAdminVerification
46
- : undefined,
47
- requireEditorVerification:
48
- typeof rawData.requireEditorVerification === 'boolean'
49
- ? rawData.requireEditorVerification
50
- : undefined,
51
- oAuthBypassVerification:
52
- typeof rawData.oAuthBypassVerification === 'boolean'
53
- ? rawData.oAuthBypassVerification
54
- : undefined,
55
- } as ConfigFinal<StudioCMSNotificationSettings>;
56
- return safe;
57
- }),
58
- Effect.flatMap((data) => sdk.notificationSettings.site.update(data))
59
- );
60
-
61
- return apiResponseLogger(200, 'Notification settings updated');
62
- }
63
- ),
64
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['POST'] })),
65
- ALL: () => Effect.try(() => AllResponse()),
66
- },
67
- {
68
- cors: { methods: ['POST', 'OPTIONS'] },
69
- onError: (error) => {
70
- console.error('API Error:', error);
71
- return createJsonResponse({ error: 'Internal Server Error' }, { status: 500 });
72
- },
73
- }
74
- );
@@ -1,75 +0,0 @@
1
- import { apiResponseLogger } from 'studiocms:logger';
2
- import { Mailer } from 'studiocms:mailer';
3
- import {
4
- AllResponse,
5
- createEffectAPIRoutes,
6
- createJsonResponse,
7
- Effect,
8
- genLogger,
9
- OptionsResponse,
10
- readAPIContextJson,
11
- } from '@withstudiocms/effect';
12
-
13
- export const { POST, OPTIONS, ALL } = createEffectAPIRoutes(
14
- {
15
- POST: (ctx) =>
16
- genLogger('routes/mailer/test-email/POST')(function* () {
17
- const mailer = yield* Mailer;
18
-
19
- // Check if mailer is enabled
20
- if (!ctx.locals.StudioCMS.siteConfig.data.enableMailer) {
21
- return apiResponseLogger(403, 'Mailer is disabled for this site');
22
- }
23
-
24
- // Check if user is logged in
25
- if (!ctx.locals.StudioCMS.security?.userSessionData.isLoggedIn) {
26
- return apiResponseLogger(403, 'Unauthorized');
27
- }
28
-
29
- // Check if user has permission
30
- if (!ctx.locals.StudioCMS.security?.userPermissionLevel.isOwner) {
31
- return apiResponseLogger(403, 'Unauthorized');
32
- }
33
-
34
- // Get JSON data safely
35
- let test_email: unknown;
36
- try {
37
- ({ test_email } = yield* readAPIContextJson<{ test_email?: unknown }>(ctx));
38
- } catch {
39
- return apiResponseLogger(400, 'Invalid JSON body');
40
- }
41
-
42
- // Validate form data
43
- if (typeof test_email !== 'string' || test_email.trim() === '') {
44
- return apiResponseLogger(400, 'Invalid form data, test_email is required');
45
- }
46
- const email = test_email.trim();
47
- // Basic email sanity-check
48
- if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
49
- return apiResponseLogger(400, 'Invalid email address');
50
- }
51
-
52
- // Send Test Email
53
- const response = yield* mailer.sendMail({
54
- to: test_email,
55
- subject: 'StudioCMS Test Email',
56
- text: 'This is a test email from StudioCMS.',
57
- });
58
-
59
- if ('error' in response) {
60
- console.error('Mailer test-email failed:', response.error);
61
- return apiResponseLogger(500, 'Failed to send test email');
62
- }
63
- return apiResponseLogger(200, 'Test email sent');
64
- }).pipe(Mailer.Provide),
65
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['POST'] })),
66
- ALL: () => Effect.try(() => AllResponse()),
67
- },
68
- {
69
- cors: { methods: ['POST', 'OPTIONS'] },
70
- onError: (error) => {
71
- console.error('API Error:', error);
72
- return createJsonResponse({ error: 'Internal Server Error' }, { status: 500 });
73
- },
74
- }
75
- );
@@ -1,136 +0,0 @@
1
- import { apiResponseLogger } from 'studiocms:logger';
2
- import { Mailer } from 'studiocms:mailer';
3
- import {
4
- AllResponse,
5
- createEffectAPIRoutes,
6
- createJsonResponse,
7
- Effect,
8
- genLogger,
9
- OptionsResponse,
10
- parseAPIContextJson,
11
- Schema,
12
- } from '@withstudiocms/effect';
13
-
14
- export class SmtpConfigSchema extends Schema.Class<SmtpConfigSchema>('SmtpConfigSchema')({
15
- port: Schema.Number,
16
- host: Schema.String,
17
- secure: Schema.Boolean,
18
- proxy: Schema.Union(Schema.String, Schema.Null),
19
- auth_user: Schema.Union(Schema.String, Schema.Null),
20
- auth_pass: Schema.Union(Schema.String, Schema.Null),
21
- tls_rejectUnauthorized: Schema.Union(Schema.Boolean, Schema.Null),
22
- tls_servername: Schema.Union(Schema.String, Schema.Null),
23
- default_sender: Schema.String,
24
- }) {}
25
-
26
- export const { POST, PATCH, OPTIONS, ALL } = createEffectAPIRoutes(
27
- {
28
- POST: (ctx) =>
29
- genLogger('routes/mailer/config/POST')(function* () {
30
- const mailer = yield* Mailer;
31
-
32
- // Check if user is logged in
33
- if (!ctx.locals.StudioCMS.security?.userSessionData.isLoggedIn) {
34
- return apiResponseLogger(401, 'Authentication required');
35
- }
36
-
37
- // Check if user has permission
38
- if (!ctx.locals.StudioCMS.security?.userPermissionLevel.isOwner) {
39
- return apiResponseLogger(403, 'Forbidden');
40
- }
41
-
42
- // Get Json Data
43
- const smtpConfig = yield* parseAPIContextJson(ctx, SmtpConfigSchema);
44
-
45
- // Validate form data
46
- if (!Number.isInteger(smtpConfig.port) || smtpConfig.port < 1 || smtpConfig.port > 65535) {
47
- return apiResponseLogger(
48
- 400,
49
- 'Invalid form data, port must be an integer between 1 and 65535'
50
- );
51
- }
52
-
53
- if (typeof smtpConfig.host !== 'string' || smtpConfig.host.trim() === '') {
54
- return apiResponseLogger(400, 'Invalid form data, host is required');
55
- }
56
-
57
- if (typeof smtpConfig.secure !== 'boolean') {
58
- return apiResponseLogger(400, 'Invalid form data, secure must be a boolean');
59
- }
60
-
61
- if (
62
- typeof smtpConfig.default_sender !== 'string' ||
63
- smtpConfig.default_sender.trim() === ''
64
- ) {
65
- return apiResponseLogger(400, 'Invalid form data, default_sender is required');
66
- }
67
-
68
- // Update Database
69
- const config = yield* mailer.createMailerConfigTable(smtpConfig);
70
-
71
- if (!config) {
72
- return apiResponseLogger(500, 'Error creating mailer config table');
73
- }
74
- return apiResponseLogger(200, 'Mailer config updated');
75
- }).pipe(Mailer.Provide),
76
- PATCH: (ctx) =>
77
- genLogger('routes/mailer/config/PATCH')(function* () {
78
- const mailer = yield* Mailer;
79
-
80
- // Check if user is logged in
81
- if (!ctx.locals.StudioCMS.security?.userSessionData.isLoggedIn) {
82
- return apiResponseLogger(403, 'Unauthorized');
83
- }
84
- // Check if user has permission
85
- if (!ctx.locals.StudioCMS.security?.userPermissionLevel.isOwner) {
86
- return apiResponseLogger(403, 'Unauthorized');
87
- }
88
-
89
- // Get Json Data
90
- const smtpConfig = yield* parseAPIContextJson(ctx, SmtpConfigSchema);
91
-
92
- // Validate form data
93
- if (!smtpConfig.port) {
94
- return apiResponseLogger(400, 'Invalid form data, port is required');
95
- }
96
-
97
- if (!smtpConfig.host) {
98
- return apiResponseLogger(400, 'Invalid form data, host is required');
99
- }
100
-
101
- if (!smtpConfig.secure) {
102
- return apiResponseLogger(400, 'Invalid form data, secure is required');
103
- }
104
-
105
- if (!smtpConfig.default_sender) {
106
- return apiResponseLogger(400, 'Invalid form data, default_sender is required');
107
- }
108
-
109
- // Update Database
110
- const config = yield* mailer.updateMailerConfigTable(smtpConfig);
111
- if (!config) {
112
- return apiResponseLogger(500, 'Error updating mailer config table');
113
- }
114
- return apiResponseLogger(200, 'Mailer config updated');
115
- }).pipe(Mailer.Provide),
116
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['POST', 'PATCH'] })),
117
- ALL: () => Effect.try(() => AllResponse()),
118
- },
119
- {
120
- cors: { methods: ['POST', 'PATCH', 'OPTIONS'] },
121
- // biome-ignore lint/suspicious/noExplicitAny: allows for better error handling
122
- onError: (error: any) => {
123
- console.error('API Error:', error);
124
- const isClientError =
125
- error?.status === 400 ||
126
- error?.name === 'SyntaxError' ||
127
- error?._tag === 'ParseError' ||
128
- error?._tag === 'JSONParseError' ||
129
- (typeof error?.name === 'string' && error.name.includes('Schema'));
130
- return createJsonResponse(
131
- { error: isClientError ? 'Invalid request body' : 'Internal Server Error' },
132
- { status: isClientError ? 400 : 500 }
133
- );
134
- },
135
- }
136
- );
@@ -1,80 +0,0 @@
1
- import { apiResponseLogger } from 'studiocms:logger';
2
- import pluginList from 'studiocms:plugins';
3
- import { settingsEndpoints } from 'studiocms:plugins/endpoints';
4
- import {
5
- AllResponse,
6
- createEffectAPIRoutes,
7
- createJsonResponse,
8
- Effect,
9
- genLogger,
10
- OptionsResponse,
11
- pipe,
12
- } from '@withstudiocms/effect';
13
- import { StudioCMSAPIError } from '#frontend/utils/errors.js';
14
-
15
- export const { POST, OPTIONS, ALL } = createEffectAPIRoutes(
16
- {
17
- POST: (ctx) =>
18
- genLogger('studiocms/routes/api/dashboard/plugins/[plugin].POST')(function* () {
19
- // Get user data
20
- const userData = ctx.locals.StudioCMS.security?.userSessionData;
21
-
22
- // Check if user is logged in
23
- if (!userData?.isLoggedIn) {
24
- return apiResponseLogger(403, 'Unauthorized');
25
- }
26
-
27
- // Check if user has permission
28
- const isAuthorized = ctx.locals.StudioCMS.security?.userPermissionLevel?.isAdmin === true;
29
- if (!isAuthorized) {
30
- return apiResponseLogger(403, 'Unauthorized');
31
- }
32
-
33
- const { plugin } = ctx.params;
34
-
35
- const settingsPage = yield* Effect.try({
36
- try: () =>
37
- pipe(
38
- pluginList.filter(({ settingsPage }) => !!settingsPage),
39
- (p) => p.find(({ identifier }) => identifier === plugin),
40
- (p) => {
41
- if (!p) {
42
- return apiResponseLogger(404, 'Plugin not found');
43
- }
44
- const settingsPage = settingsEndpoints.find(
45
- ({ identifier }) => identifier === plugin
46
- );
47
- if (!settingsPage) {
48
- return apiResponseLogger(404, 'Plugin does not have a settings page');
49
- }
50
- return settingsPage;
51
- }
52
- ),
53
- catch: (cause) =>
54
- new StudioCMSAPIError({
55
- message: 'An error occurred while fetching plugin settings page',
56
- cause,
57
- }),
58
- });
59
-
60
- if (settingsPage instanceof Response) {
61
- return settingsPage;
62
- }
63
-
64
- if (!settingsPage.onSave) {
65
- return apiResponseLogger(404, 'Plugin does not have a settings page');
66
- }
67
-
68
- return settingsPage.onSave(ctx);
69
- }),
70
- OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['POST'] })),
71
- ALL: () => Effect.try(() => AllResponse()),
72
- },
73
- {
74
- cors: { methods: ['POST', 'OPTIONS'] },
75
- onError: (error) => {
76
- console.error('API Error:', error);
77
- return createJsonResponse({ error: 'Internal Server Error' }, { status: 500 });
78
- },
79
- }
80
- );