@vitnode/core 1.2.0-canary.60 → 1.2.0-canary.62

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 (274) hide show
  1. package/dist/scripts/get-config.js +15 -0
  2. package/dist/scripts/plugin.js +188 -0
  3. package/dist/scripts/prepare-database.js +177 -0
  4. package/dist/scripts/prepare-plugins-files.js +134 -0
  5. package/dist/scripts/run-interactive-shell-command.js +21 -0
  6. package/dist/scripts/scripts.js +39 -13
  7. package/dist/scripts/shared/file-utils.js +203 -0
  8. package/dist/src/api/adapters/sso/discord.js +1 -77
  9. package/dist/src/api/adapters/sso/facebook.js +1 -76
  10. package/dist/src/api/adapters/sso/google.js +1 -87
  11. package/dist/src/api/config.js +1 -67
  12. package/dist/src/api/lib/check-plugin-id.js +1 -43
  13. package/dist/src/api/lib/cron.js +1 -22
  14. package/dist/src/api/lib/logger-middleware.js +1 -35
  15. package/dist/src/api/lib/module.js +1 -22
  16. package/dist/src/api/lib/plugin.js +1 -22
  17. package/dist/src/api/lib/route.js +1 -27
  18. package/dist/src/api/lib/with-pagination.js +1 -83
  19. package/dist/src/api/middlewares/captcha.middleware.js +1 -63
  20. package/dist/src/api/middlewares/cron-auth.middleware.js +1 -19
  21. package/dist/src/api/middlewares/global.middleware.js +1 -93
  22. package/dist/src/api/middlewares/rate-limiter.middleware.js +1 -32
  23. package/dist/src/api/models/device.js +1 -61
  24. package/dist/src/api/models/email.js +1 -76
  25. package/dist/src/api/models/password.js +1 -36
  26. package/dist/src/api/models/session-admin.js +1 -106
  27. package/dist/src/api/models/session.js +1 -85
  28. package/dist/src/api/models/sso.js +1 -120
  29. package/dist/src/api/models/user/get-user-by-id.js +1 -19
  30. package/dist/src/api/models/user/sign-in-with-passwords.js +1 -22
  31. package/dist/src/api/models/user/sign-up.js +1 -73
  32. package/dist/src/api/models/user.js +1 -8
  33. package/dist/src/api/modules/admin/admin.module.js +1 -19
  34. package/dist/src/api/modules/admin/advanced/advanced.admin.module.js +1 -11
  35. package/dist/src/api/modules/admin/advanced/cron/cron.admin.module.js +1 -12
  36. package/dist/src/api/modules/admin/advanced/cron/routes/get.route.js +1 -66
  37. package/dist/src/api/modules/admin/advanced/cron/routes/run.route.js +1 -95
  38. package/dist/src/api/modules/admin/debug/debug.admin.module.js +1 -10
  39. package/dist/src/api/modules/admin/debug/routes/logs.route.js +1 -94
  40. package/dist/src/api/modules/admin/routes/session.route.js +1 -47
  41. package/dist/src/api/modules/admin/users/routes/list.route.js +1 -79
  42. package/dist/src/api/modules/admin/users/routes/users.route.js +1 -84
  43. package/dist/src/api/modules/admin/users/users.admin.module.js +1 -10
  44. package/dist/src/api/modules/cron/cron/clean.cron.js +1 -24
  45. package/dist/src/api/modules/cron/cron.module.js +1 -14
  46. package/dist/src/api/modules/cron/helpers/process-cron-jobs.d.ts.map +1 -1
  47. package/dist/src/api/modules/cron/helpers/process-cron-jobs.js +1 -76
  48. package/dist/src/api/modules/cron/routes/cron.route.js +1 -101
  49. package/dist/src/api/modules/middleware/middleware.module.js +1 -10
  50. package/dist/src/api/modules/middleware/route.js +1 -49
  51. package/dist/src/api/modules/users/avatar-color.js +1 -43
  52. package/dist/src/api/modules/users/routes/change-password.route.js +1 -58
  53. package/dist/src/api/modules/users/routes/reset-passowrd.route.js +1 -91
  54. package/dist/src/api/modules/users/routes/session.route.js +1 -46
  55. package/dist/src/api/modules/users/routes/sign-in.route.js +1 -71
  56. package/dist/src/api/modules/users/routes/sign-out.route.js +1 -43
  57. package/dist/src/api/modules/users/routes/sign-up.route.js +1 -77
  58. package/dist/src/api/modules/users/routes/test.route.js +1 -33
  59. package/dist/src/api/modules/users/sso/routes/callback.route.js +1 -52
  60. package/dist/src/api/modules/users/sso/routes/create-url.route.js +1 -36
  61. package/dist/src/api/modules/users/sso/sso.module.js +1 -12
  62. package/dist/src/api/modules/users/users.module.js +1 -26
  63. package/dist/src/api/plugin.js +1 -15
  64. package/dist/src/app/login/page.js +1 -16
  65. package/dist/src/app/login/reset-password/page.js +1 -18
  66. package/dist/src/app/login/sso/[providerId]/page.js +1 -10
  67. package/dist/src/app/register/page.js +1 -16
  68. package/dist/src/app_admin/core/advanced/cron/page.js +1 -42
  69. package/dist/src/app_admin/core/debug/page.js +1 -45
  70. package/dist/src/app_admin/core/page.js +1 -5
  71. package/dist/src/app_admin/core/test/page.js +1 -5
  72. package/dist/src/app_admin/core/users/page.js +1 -38
  73. package/dist/src/components/avatar.js +1 -14
  74. package/dist/src/components/confirm-action/confirm-action-alert-dialog.js +1 -42
  75. package/dist/src/components/confirm-action/content.js +1 -31
  76. package/dist/src/components/date-format.js +1 -41
  77. package/dist/src/components/form/auto-form.js +1 -103
  78. package/dist/src/components/form/common/desc.js +1 -9
  79. package/dist/src/components/form/common/label.js +1 -18
  80. package/dist/src/components/form/fields/checkbox.js +1 -37
  81. package/dist/src/components/form/fields/combobox-async.js +1 -123
  82. package/dist/src/components/form/fields/combobox.js +1 -87
  83. package/dist/src/components/form/fields/input.js +1 -39
  84. package/dist/src/components/form/fields/radio-group.js +1 -50
  85. package/dist/src/components/form/fields/select.js +1 -58
  86. package/dist/src/components/form/fields/switch.js +1 -36
  87. package/dist/src/components/form/fields/textarea.js +1 -36
  88. package/dist/src/components/i18n-provider.js +1 -43
  89. package/dist/src/components/logo-vitnode.js +1 -119
  90. package/dist/src/components/switchers/langs/language-switcher.js +1 -47
  91. package/dist/src/components/switchers/themes/theme-switcher.js +1 -28
  92. package/dist/src/components/table/content.js +1 -81
  93. package/dist/src/components/table/data-table.js +1 -68
  94. package/dist/src/components/table/order-table-head.js +1 -50
  95. package/dist/src/components/table/pagination.js +1 -122
  96. package/dist/src/components/tiptap/extension.js +1 -33
  97. package/dist/src/components/tiptap/toolbar/actions/alignment-action.js +1 -91
  98. package/dist/src/components/tiptap/toolbar/actions/bold-action.js +1 -39
  99. package/dist/src/components/tiptap/toolbar/actions/headings-action.js +1 -93
  100. package/dist/src/components/tiptap/toolbar/actions/italic-action.js +1 -38
  101. package/dist/src/components/tiptap/toolbar/actions/list-action.js +1 -61
  102. package/dist/src/components/tiptap/toolbar/actions/text-format-more/text-format-more.js +1 -59
  103. package/dist/src/components/tiptap/toolbar/actions/underline-action.js +1 -38
  104. package/dist/src/components/tiptap/toolbar/actions/undo-redo-actions.js +1 -63
  105. package/dist/src/components/tiptap/toolbar/actions/utils/tooltip-shortcut.js +1 -11
  106. package/dist/src/components/tiptap/toolbar/tiptap-toolbar.js +1 -55
  107. package/dist/src/components/tiptap/toolbar/use-toolbar-editor.js +1 -5
  108. package/dist/src/components/ui/accordion.js +1 -46
  109. package/dist/src/components/ui/alert-dialog.js +1 -123
  110. package/dist/src/components/ui/alert.js +1 -39
  111. package/dist/src/components/ui/badge.js +1 -28
  112. package/dist/src/components/ui/button-client.js +1 -57
  113. package/dist/src/components/ui/button.js +1 -32
  114. package/dist/src/components/ui/card.js +1 -52
  115. package/dist/src/components/ui/checkbox.js +1 -20
  116. package/dist/src/components/ui/collapsible.js +1 -22
  117. package/dist/src/components/ui/command.js +1 -98
  118. package/dist/src/components/ui/context-menu.js +1 -140
  119. package/dist/src/components/ui/dialog.js +1 -189
  120. package/dist/src/components/ui/drawer.js +1 -83
  121. package/dist/src/components/ui/dropdown-menu.js +1 -141
  122. package/dist/src/components/ui/editor-content.js +1 -10
  123. package/dist/src/components/ui/editor.js +1 -35
  124. package/dist/src/components/ui/form.js +1 -148
  125. package/dist/src/components/ui/header-content.js +1 -30
  126. package/dist/src/components/ui/hover-card.js +1 -29
  127. package/dist/src/components/ui/input-otp.js +1 -48
  128. package/dist/src/components/ui/input.js +1 -11
  129. package/dist/src/components/ui/label.js +1 -12
  130. package/dist/src/components/ui/loader.js +1 -16
  131. package/dist/src/components/ui/menubar.js +1 -151
  132. package/dist/src/components/ui/navigation-menu.js +1 -82
  133. package/dist/src/components/ui/popover.js +1 -35
  134. package/dist/src/components/ui/progress.js +1 -19
  135. package/dist/src/components/ui/radio-group.js +1 -27
  136. package/dist/src/components/ui/scroll-area.js +1 -33
  137. package/dist/src/components/ui/select.js +1 -113
  138. package/dist/src/components/ui/separator.js +1 -14
  139. package/dist/src/components/ui/sheet.js +1 -92
  140. package/dist/src/components/ui/sidebar.js +1 -433
  141. package/dist/src/components/ui/skeleton.js +1 -10
  142. package/dist/src/components/ui/slider.js +1 -50
  143. package/dist/src/components/ui/sonner.js +1 -26
  144. package/dist/src/components/ui/switch.js +1 -16
  145. package/dist/src/components/ui/table.js +1 -63
  146. package/dist/src/components/ui/tabs.js +1 -33
  147. package/dist/src/components/ui/textarea.js +1 -10
  148. package/dist/src/components/ui/toggle-group.js +1 -45
  149. package/dist/src/components/ui/toggle.js +1 -34
  150. package/dist/src/components/ui/tooltip.js +1 -57
  151. package/dist/src/config.js +1 -4
  152. package/dist/src/database/admins.js +1 -74
  153. package/dist/src/database/cron.js +1 -22
  154. package/dist/src/database/languages.js +1 -52
  155. package/dist/src/database/logs.js +1 -34
  156. package/dist/src/database/moderators.js +1 -37
  157. package/dist/src/database/roles.js +1 -13
  158. package/dist/src/database/sessions.js +1 -60
  159. package/dist/src/database/users.js +1 -145
  160. package/dist/src/drizzle.config.js +1 -67
  161. package/dist/src/emails/default-template.js +1 -99
  162. package/dist/src/emails/reset-password.js +1 -132
  163. package/dist/src/emails/ui/button.js +1 -36
  164. package/dist/src/emails/ui/card.js +1 -39
  165. package/dist/src/hooks/use-before-unload.js +1 -30
  166. package/dist/src/hooks/use-captcha.js +1 -122
  167. package/dist/src/hooks/use-mobile.js +1 -16
  168. package/dist/src/lib/api/get-middleware-api.js +1 -13
  169. package/dist/src/lib/api/get-next-cron-run-date.js +1 -14
  170. package/dist/src/lib/api/get-next-cron-run-date.test.js +1 -55
  171. package/dist/src/lib/api/get-session-admin-api.js +1 -19
  172. package/dist/src/lib/api/get-session-api.js +1 -14
  173. package/dist/src/lib/api/should-cron-job-run.js +1 -16
  174. package/dist/src/lib/api/should-cron-job-run.test.js +1 -213
  175. package/dist/src/lib/api/validate-cron-schedule.d.ts +2 -0
  176. package/dist/src/lib/api/validate-cron-schedule.d.ts.map +1 -0
  177. package/dist/src/lib/api/validate-cron-schedule.js +1 -0
  178. package/dist/src/lib/api/validate-cron-schedule.test.d.ts +2 -0
  179. package/dist/src/lib/api/validate-cron-schedule.test.d.ts.map +1 -0
  180. package/dist/src/lib/api/validate-cron-schedule.test.js +1 -0
  181. package/dist/src/lib/colors.js +1 -140
  182. package/dist/src/lib/colors.test.js +1 -173
  183. package/dist/src/lib/config.js +1 -14
  184. package/dist/src/lib/ctrl-or-command-character.js +1 -5
  185. package/dist/src/lib/fetcher/cookie-from-string-to-object.js +1 -12
  186. package/dist/src/lib/fetcher/cookie-from-string-to-object.test.js +1 -78
  187. package/dist/src/lib/fetcher/core.js +3 -48
  188. package/dist/src/lib/fetcher/helpers-server.js +1 -18
  189. package/dist/src/lib/fetcher/helpers.js +1 -16
  190. package/dist/src/lib/fetcher/helpers.test.js +1 -37
  191. package/dist/src/lib/fetcher/types.js +1 -1
  192. package/dist/src/lib/fetcher-client.js +1 -17
  193. package/dist/src/lib/fetcher.js +1 -33
  194. package/dist/src/lib/helpers/auto-form.js +1 -98
  195. package/dist/src/lib/helpers/auto-form.test.js +1 -336
  196. package/dist/src/lib/navigation.js +1 -11
  197. package/dist/src/lib/plugin.js +1 -3
  198. package/dist/src/lib/special-characters.js +1 -4
  199. package/dist/src/lib/special-characters.test.js +1 -56
  200. package/dist/src/lib/utils.js +1 -5
  201. package/dist/src/locales/en.json +308 -0
  202. package/dist/src/tests/setup.js +1 -6
  203. package/dist/src/views/admin/layouts/admin-layout.js +1 -73
  204. package/dist/src/views/admin/layouts/sidebar/nav/item.js +1 -98
  205. package/dist/src/views/admin/layouts/sidebar/nav/nav.js +1 -60
  206. package/dist/src/views/admin/layouts/sidebar/sidebar.js +1 -28
  207. package/dist/src/views/admin/layouts/sidebar/sign-out.js +1 -14
  208. package/dist/src/views/admin/layouts/user-bar/client.js +1 -69
  209. package/dist/src/views/admin/layouts/user-bar/user-bar.js +1 -32
  210. package/dist/src/views/admin/sign-in/sign-in-admin-view.js +1 -27
  211. package/dist/src/views/admin/views/core/advanced/cron/cron-table-view.js +1 -97
  212. package/dist/src/views/admin/views/core/advanced/cron/run-action/mutation-api.js +1 -23
  213. package/dist/src/views/admin/views/core/advanced/cron/run-action/run-action.js +1 -38
  214. package/dist/src/views/admin/views/core/dashboard/dashboard-admin-view.js +1 -44
  215. package/dist/src/views/admin/views/core/debug/actions/clear-cache/clear-cache.js +1 -35
  216. package/dist/src/views/admin/views/core/debug/actions/clear-cache/mutation-api.js +1 -5
  217. package/dist/src/views/admin/views/core/debug/system-logs/actions/more/content.js +1 -281
  218. package/dist/src/views/admin/views/core/debug/system-logs/actions/more/more.js +1 -67
  219. package/dist/src/views/admin/views/core/debug/system-logs/badges/badge-status.js +1 -14
  220. package/dist/src/views/admin/views/core/debug/system-logs/badges/badge-type-log.js +1 -30
  221. package/dist/src/views/admin/views/core/debug/system-logs/system-logs-view.js +1 -96
  222. package/dist/src/views/admin/views/core/test.js +1 -161
  223. package/dist/src/views/admin/views/core/users/users-admin-view.js +1 -89
  224. package/dist/src/views/auth/password-reset/change-password-form/form.js +1 -48
  225. package/dist/src/views/auth/password-reset/change-password-form/mutation-api.js +1 -22
  226. package/dist/src/views/auth/password-reset/change-password-form/use-form.js +1 -36
  227. package/dist/src/views/auth/password-reset/form/form.js +1 -104
  228. package/dist/src/views/auth/password-reset/form/mutation-api.js +1 -21
  229. package/dist/src/views/auth/password-reset/form/use-form.js +1 -33
  230. package/dist/src/views/auth/password-reset/password-reset-view.js +1 -37
  231. package/dist/src/views/auth/sign-in/form/form.js +1 -64
  232. package/dist/src/views/auth/sign-in/form/mutation-api.js +1 -33
  233. package/dist/src/views/auth/sign-in/form/use-form.js +1 -38
  234. package/dist/src/views/auth/sign-in/sign-in-view.js +1 -61
  235. package/dist/src/views/auth/sign-up/components/password-input.js +1 -96
  236. package/dist/src/views/auth/sign-up/email-confirmation-view.js +1 -55
  237. package/dist/src/views/auth/sign-up/form/form.js +1 -89
  238. package/dist/src/views/auth/sign-up/form/mutation-api.js +1 -30
  239. package/dist/src/views/auth/sign-up/form/use-form.js +1 -70
  240. package/dist/src/views/auth/sign-up/sign-up-view.js +1 -65
  241. package/dist/src/views/auth/sign-up/wrapper.js +1 -22
  242. package/dist/src/views/auth/sso/buttons/client.js +1 -22
  243. package/dist/src/views/auth/sso/buttons/mutation-api.js +1 -24
  244. package/dist/src/views/auth/sso/buttons/sso-buttons.js +1 -56
  245. package/dist/src/views/auth/sso/callback/callback-sso-view.js +1 -32
  246. package/dist/src/views/auth/sso/callback/client/client.js +1 -68
  247. package/dist/src/views/auth/sso/callback/client/mutation-api.js +1 -32
  248. package/dist/src/views/error/back-button.js +1 -14
  249. package/dist/src/views/error/error-view.js +1 -58
  250. package/dist/src/views/error/global-error-view.js +1 -50
  251. package/dist/src/views/layouts/provider.js +1 -44
  252. package/dist/src/views/layouts/root-layout.js +1 -25
  253. package/dist/src/views/layouts/theme/header/header.js +1 -38
  254. package/dist/src/views/layouts/theme/header/user/auth/auth.js +1 -33
  255. package/dist/src/views/layouts/theme/header/user/auth/client.js +1 -47
  256. package/dist/src/views/layouts/theme/header/user/auth/log-out-mutation-api.js +1 -27
  257. package/dist/src/views/layouts/theme/header/user/user.js +1 -32
  258. package/dist/src/views/layouts/theme/layout.js +1 -16
  259. package/dist/src/vitnode.config.js +1 -42
  260. package/dist/tsconfig.tsbuildinfo +1 -1
  261. package/dist/tsup.config.js +18 -0
  262. package/dist/vitest.config.d.ts.map +1 -1
  263. package/dist/vitest.config.js +49 -0
  264. package/eslint.config.mjs +2 -0
  265. package/package.json +6 -10
  266. package/dist/src/api/adapters/cron/node-cron.adapter.d.ts +0 -3
  267. package/dist/src/api/adapters/cron/node-cron.adapter.d.ts.map +0 -1
  268. package/dist/src/api/adapters/cron/node-cron.adapter.js +0 -11
  269. package/dist/src/api/adapters/email/nodemailer.d.ts +0 -10
  270. package/dist/src/api/adapters/email/nodemailer.d.ts.map +0 -1
  271. package/dist/src/api/adapters/email/nodemailer.js +0 -30
  272. package/dist/src/api/adapters/email/resend.d.ts +0 -6
  273. package/dist/src/api/adapters/email/resend.d.ts.map +0 -1
  274. package/dist/src/api/adapters/email/resend.js +0 -21
@@ -1,76 +1 @@
1
- import { render } from "@react-email/components";
2
- import { HTTPException } from "hono/http-exception";
3
- import { CONFIG } from "../../lib/config.js";
4
- export class EmailModel {
5
- constructor(c){
6
- this.c = c;
7
- }
8
- c;
9
- async send({ html, replyTo, subject, to, user, content, locale: localeFromArgs }) {
10
- const core = this.c.get("core");
11
- const provider = core.email?.adapter;
12
- if (!provider) {
13
- throw new HTTPException(500, {
14
- message: "Email provider not found"
15
- });
16
- }
17
- const locale = localeFromArgs ?? user?.language ?? "en";
18
- const pluginIds = [
19
- "@vitnode/core",
20
- ...this.c.get("core").plugins.map((plugin)=>plugin.id)
21
- ];
22
- const messagesPromises = pluginIds.map(async (pluginId)=>{
23
- try {
24
- const path = `${pluginId}/${locale}.json`;
25
- const messages = await core.pathToMessages(path);
26
- return messages.default;
27
- } catch {
28
- return {};
29
- }
30
- });
31
- const allMessages = await Promise.all(messagesPromises);
32
- // Optimize: Use Object.assign instead of reduce with spread operator
33
- // to avoid creating intermediate objects on each iteration
34
- const messages = Object.assign({}, ...allMessages);
35
- const htmlContent = html ?? content({
36
- i18n: {
37
- locale,
38
- messages
39
- },
40
- templateProps: {
41
- metadata: {
42
- ...core.metadata,
43
- url: CONFIG.web.href
44
- },
45
- logo: core.email?.logo
46
- },
47
- user
48
- });
49
- const emailTo = user?.email ?? to;
50
- if (!emailTo) {
51
- throw new HTTPException(400, {
52
- message: "Email address is required"
53
- });
54
- }
55
- try {
56
- await provider.sendEmail({
57
- html: await render(htmlContent),
58
- to: emailTo,
59
- subject: typeof subject === "function" ? subject({
60
- i18n: {
61
- locale,
62
- messages
63
- }
64
- }) : subject,
65
- replyTo,
66
- metadata: core.metadata,
67
- text: await render(htmlContent, {
68
- plainText: true
69
- })
70
- });
71
- } catch (err) {
72
- const error = err instanceof Error ? err : new Error("Unknown error from email provider");
73
- await this.c.get("log").error(`Failed to send email: ${error.message}`);
74
- }
75
- }
76
- }
1
+ import{render}from"@react-email/components";import{HTTPException}from"hono/http-exception";import{CONFIG}from"../../lib/config.js";export class EmailModel{constructor(c){this.c=c}c;async send({html,replyTo,subject,to,user,content,locale:localeFromArgs}){const core=this.c.get("core");const provider=core.email?.adapter;if(!provider){throw new HTTPException(500,{message:"Email provider not found"})}const locale=localeFromArgs??user?.language??"en";const pluginIds=["@vitnode/core",...this.c.get("core").plugins.map(plugin=>plugin.id)];const messagesPromises=pluginIds.map(async pluginId=>{try{const path=`${pluginId}/${locale}.json`;const messages=await core.pathToMessages(path);return messages.default}catch{return{}}});const allMessages=await Promise.all(messagesPromises);const messages=Object.assign({},...allMessages);const htmlContent=html??content({i18n:{locale,messages},templateProps:{metadata:{...core.metadata,url:CONFIG.web.href},logo:core.email?.logo},user});const emailTo=user?.email??to;if(!emailTo){throw new HTTPException(400,{message:"Email address is required"})}try{await provider.sendEmail({html:await render(htmlContent),to:emailTo,subject:typeof subject==="function"?subject({i18n:{locale,messages}}):subject,replyTo,metadata:core.metadata,text:await render(htmlContent,{plainText:true})})}catch(err){const error=err instanceof Error?err:new Error("Unknown error from email provider");await this.c.get("log").error(`Failed to send email: ${error.message}`)}}}
@@ -1,36 +1 @@
1
- import crypto from "node:crypto";
2
- export class PasswordModel {
3
- async encryptPassword(password) {
4
- return await new Promise((resolve, reject)=>{
5
- const salt = crypto.randomBytes(8).toString("hex");
6
- crypto.scrypt(password, salt, 64, (err, derivedKey)=>{
7
- if (err) reject(err);
8
- resolve(`${salt}:${derivedKey.toString("hex")}`);
9
- });
10
- });
11
- }
12
- async verifyPassword(password, hash) {
13
- return await new Promise((resolve, reject)=>{
14
- const [salt, key] = hash.split(":");
15
- const keyBuffer = Buffer.from(key, "hex");
16
- crypto.scrypt(password, salt, 64, (err, derivedKey)=>{
17
- if (err) reject(err);
18
- if (keyBuffer.length !== derivedKey.length) {
19
- crypto.timingSafeEqual(derivedKey, derivedKey);
20
- resolve(false);
21
- } else {
22
- const areEqual = crypto.timingSafeEqual(keyBuffer, derivedKey);
23
- resolve(areEqual);
24
- }
25
- });
26
- });
27
- }
28
- }
29
- export class ForgotPasswordTokenModel {
30
- generateResetToken() {
31
- return crypto.randomBytes(32).toString("base64url");
32
- }
33
- hashResetToken(token) {
34
- return crypto.createHash("sha256").update(token).digest("hex");
35
- }
36
- }
1
+ import crypto from"node:crypto";export class PasswordModel{async encryptPassword(password){return await new Promise((resolve,reject)=>{const salt=crypto.randomBytes(8).toString("hex");crypto.scrypt(password,salt,64,(err,derivedKey)=>{if(err)reject(err);resolve(`${salt}:${derivedKey.toString("hex")}`)})})}async verifyPassword(password,hash){return await new Promise((resolve,reject)=>{const[salt,key]=hash.split(":");const keyBuffer=Buffer.from(key,"hex");crypto.scrypt(password,salt,64,(err,derivedKey)=>{if(err)reject(err);if(keyBuffer.length!==derivedKey.length){crypto.timingSafeEqual(derivedKey,derivedKey);resolve(false)}else{const areEqual=crypto.timingSafeEqual(keyBuffer,derivedKey);resolve(areEqual)}})})}}export class ForgotPasswordTokenModel{generateResetToken(){return crypto.randomBytes(32).toString("base64url")}hashResetToken(token){return crypto.createHash("sha256").update(token).digest("hex")}}
@@ -1,106 +1 @@
1
- import { and, eq, gt, or } from "drizzle-orm"; // Removed 'or' as it's safer not to use it here
2
- import { deleteCookie, getCookie, setCookie } from "hono/cookie";
3
- import { HTTPException } from "hono/http-exception";
4
- import { core_admin_permissions, core_admin_sessions } from "../../database/admins.js";
5
- import { CONFIG } from "../../lib/config.js";
6
- import { DeviceModel } from "./device.js";
7
- import { UserModel } from "./user.js";
8
- export class SessionAdminModel {
9
- constructor(c){
10
- this.c = c;
11
- }
12
- c;
13
- async hashToken(token) {
14
- const encoder = new TextEncoder();
15
- const data = encoder.encode(token);
16
- const hashBuffer = await crypto.subtle.digest("SHA-256", data);
17
- const bytes = new Uint8Array(hashBuffer);
18
- // Optimize: Use direct iteration instead of Array.from + map
19
- let result = "";
20
- for (const byte of bytes){
21
- result += byte.toString(16).padStart(2, "0");
22
- }
23
- return result;
24
- }
25
- async checkIfUserIsAdmin(userId) {
26
- const user = await new UserModel().getUserById({
27
- id: userId,
28
- c: this.c
29
- });
30
- if (!user) return false;
31
- const [permission] = await this.c.get("db").select().from(core_admin_permissions).where(or(eq(core_admin_permissions.userId, user.id), eq(core_admin_permissions.roleId, user.roleId))).limit(1);
32
- return !!permission;
33
- }
34
- async createSessionByUserId(userId) {
35
- const isAdmin = await this.checkIfUserIsAdmin(userId);
36
- if (!isAdmin) {
37
- throw new HTTPException(403, {
38
- message: "Forbidden"
39
- });
40
- }
41
- const randomBytes = new Uint8Array(64);
42
- crypto.getRandomValues(randomBytes);
43
- // Optimize: Use direct iteration instead of Array.from + map
44
- let token = "";
45
- for (const byte of randomBytes){
46
- token += byte.toString(16).padStart(2, "0");
47
- }
48
- const hashedToken = await this.hashToken(token);
49
- const device = await new DeviceModel(this.c).getDeviceId();
50
- await this.c.get("db").insert(core_admin_sessions).values({
51
- token: hashedToken,
52
- userId,
53
- expiresAt: new Date(Date.now() + this.c.get("core").authorization.adminCookieExpires),
54
- deviceId: device.id
55
- });
56
- setCookie(this.c, this.c.get("core").authorization.adminCookieName, token, {
57
- httpOnly: true,
58
- secure: this.c.get("core").authorization.cookieSecure,
59
- path: "/",
60
- expires: new Date(Date.now() + this.c.get("core").authorization.adminCookieExpires),
61
- domain: CONFIG.web.hostname
62
- });
63
- return {
64
- token
65
- };
66
- }
67
- async deleteSession() {
68
- const token = getCookie(this.c, this.c.get("core").authorization.adminCookieName);
69
- if (!token) return;
70
- const hashedToken = await this.hashToken(token);
71
- await this.c.get("db").delete(core_admin_sessions).where(eq(core_admin_sessions.token, hashedToken));
72
- deleteCookie(this.c, this.c.get("core").authorization.adminCookieName, {
73
- path: "/",
74
- domain: CONFIG.web.hostname
75
- });
76
- }
77
- async getUser() {
78
- const { authorization } = this.c.get("core");
79
- const token = getCookie(this.c, authorization.adminCookieName);
80
- if (!token) return null;
81
- const device = await new DeviceModel(this.c).getDeviceId();
82
- if (!device) return null;
83
- const hashedToken = await this.hashToken(token);
84
- const [session] = await this.c.get("db").select({
85
- userId: core_admin_sessions.userId
86
- }).from(core_admin_sessions).where(and(eq(core_admin_sessions.token, hashedToken), eq(core_admin_sessions.deviceId, device.id), gt(core_admin_sessions.expiresAt, new Date()))).limit(1);
87
- if (!session) {
88
- deleteCookie(this.c, this.c.get("core").authorization.adminCookieName, {
89
- path: "/",
90
- domain: CONFIG.web.hostname
91
- });
92
- return null;
93
- }
94
- const user = await new UserModel().getUserById({
95
- id: session.userId,
96
- c: this.c
97
- });
98
- if (!user) return null;
99
- const isStillAdmin = await this.checkIfUserIsAdmin(user.id);
100
- if (!isStillAdmin) {
101
- await this.deleteSession();
102
- return null;
103
- }
104
- return user;
105
- }
106
- }
1
+ import{and,eq,gt,or}from"drizzle-orm";import{deleteCookie,getCookie,setCookie}from"hono/cookie";import{HTTPException}from"hono/http-exception";import{core_admin_permissions,core_admin_sessions}from"../../database/admins.js";import{CONFIG}from"../../lib/config.js";import{DeviceModel}from"./device.js";import{UserModel}from"./user.js";export class SessionAdminModel{constructor(c){this.c=c}c;async hashToken(token){const encoder=new TextEncoder;const data=encoder.encode(token);const hashBuffer=await crypto.subtle.digest("SHA-256",data);const bytes=new Uint8Array(hashBuffer);let result="";for(const byte of bytes){result+=byte.toString(16).padStart(2,"0")}return result}async checkIfUserIsAdmin(userId){const user=await new UserModel().getUserById({id:userId,c:this.c});if(!user)return false;const[permission]=await this.c.get("db").select().from(core_admin_permissions).where(or(eq(core_admin_permissions.userId,user.id),eq(core_admin_permissions.roleId,user.roleId))).limit(1);return!!permission}async createSessionByUserId(userId){const isAdmin=await this.checkIfUserIsAdmin(userId);if(!isAdmin){throw new HTTPException(403,{message:"Forbidden"})}const randomBytes=new Uint8Array(64);crypto.getRandomValues(randomBytes);let token="";for(const byte of randomBytes){token+=byte.toString(16).padStart(2,"0")}const hashedToken=await this.hashToken(token);const device=await new DeviceModel(this.c).getDeviceId();await this.c.get("db").insert(core_admin_sessions).values({token:hashedToken,userId,expiresAt:new Date(Date.now()+this.c.get("core").authorization.adminCookieExpires),deviceId:device.id});setCookie(this.c,this.c.get("core").authorization.adminCookieName,token,{httpOnly:true,secure:this.c.get("core").authorization.cookieSecure,path:"/",expires:new Date(Date.now()+this.c.get("core").authorization.adminCookieExpires),domain:CONFIG.web.hostname});return{token}}async deleteSession(){const token=getCookie(this.c,this.c.get("core").authorization.adminCookieName);if(!token)return;const hashedToken=await this.hashToken(token);await this.c.get("db").delete(core_admin_sessions).where(eq(core_admin_sessions.token,hashedToken));deleteCookie(this.c,this.c.get("core").authorization.adminCookieName,{path:"/",domain:CONFIG.web.hostname})}async getUser(){const{authorization}=this.c.get("core");const token=getCookie(this.c,authorization.adminCookieName);if(!token)return null;const device=await new DeviceModel(this.c).getDeviceId();if(!device)return null;const hashedToken=await this.hashToken(token);const[session]=await this.c.get("db").select({userId:core_admin_sessions.userId}).from(core_admin_sessions).where(and(eq(core_admin_sessions.token,hashedToken),eq(core_admin_sessions.deviceId,device.id),gt(core_admin_sessions.expiresAt,new Date))).limit(1);if(!session){deleteCookie(this.c,this.c.get("core").authorization.adminCookieName,{path:"/",domain:CONFIG.web.hostname});return null}const user=await new UserModel().getUserById({id:session.userId,c:this.c});if(!user)return null;const isStillAdmin=await this.checkIfUserIsAdmin(user.id);if(!isStillAdmin){await this.deleteSession();return null}return user}}
@@ -1,85 +1 @@
1
- import { and, eq, gt } from "drizzle-orm";
2
- import { deleteCookie, getCookie, setCookie } from "hono/cookie";
3
- import { core_sessions } from "../../database/sessions.js";
4
- import { CONFIG } from "../../lib/config.js";
5
- import { DeviceModel } from "./device.js";
6
- import { UserModel } from "./user.js";
7
- export class SessionModel {
8
- constructor(c){
9
- this.c = c;
10
- }
11
- c;
12
- async hashToken(token) {
13
- const encoder = new TextEncoder();
14
- const data = encoder.encode(token);
15
- const hashBuffer = await crypto.subtle.digest("SHA-256", data);
16
- const bytes = new Uint8Array(hashBuffer);
17
- // Optimize: Use direct iteration instead of Array.from + map
18
- let result = "";
19
- for (const byte of bytes){
20
- result += byte.toString(16).padStart(2, "0");
21
- }
22
- return result;
23
- }
24
- async createSessionByUserId(userId) {
25
- // Generate secure random bytes using Web Crypto API
26
- const randomBytes = new Uint8Array(64);
27
- crypto.getRandomValues(randomBytes);
28
- // Optimize: Use direct iteration instead of Array.from + map
29
- let token = "";
30
- for (const byte of randomBytes){
31
- token += byte.toString(16).padStart(2, "0");
32
- }
33
- const device = await new DeviceModel(this.c).getDeviceId();
34
- const hashedToken = await this.hashToken(token);
35
- await this.c.get("db").insert(core_sessions).values({
36
- token: hashedToken,
37
- userId,
38
- expiresAt: new Date(Date.now() + this.c.get("core").authorization.cookie_expires),
39
- deviceId: device.id
40
- });
41
- setCookie(this.c, this.c.get("core").authorization.cookieName, token, {
42
- httpOnly: true,
43
- secure: this.c.get("core").authorization.cookieSecure,
44
- path: "/",
45
- expires: this.c.get("core").authorization.cookie_expires > 0 ? new Date(Date.now() + this.c.get("core").authorization.cookie_expires) : undefined,
46
- domain: CONFIG.web.hostname
47
- });
48
- return {
49
- token
50
- };
51
- }
52
- async deleteSession() {
53
- const token = getCookie(this.c, this.c.get("core").authorization.cookieName);
54
- const device = await new DeviceModel(this.c).getDeviceId();
55
- // Ensure both token and deviceId exist before proceeding
56
- if (!(token && device.id)) {
57
- deleteCookie(this.c, this.c.get("core").authorization.cookieName);
58
- return;
59
- }
60
- const hashedToken = await this.hashToken(token);
61
- await this.c.get("db").delete(core_sessions)// Harden the query to ensure a user can only delete their own device's session
62
- .where(and(eq(core_sessions.token, hashedToken), eq(core_sessions.deviceId, device.id)));
63
- deleteCookie(this.c, this.c.get("core").authorization.cookieName);
64
- }
65
- async getUser() {
66
- const token = getCookie(this.c, this.c.get("core").authorization.cookieName);
67
- if (!token) return null;
68
- const device = await new DeviceModel(this.c).getDeviceId();
69
- if (!device) return null;
70
- const hashedToken = await this.hashToken(token);
71
- const [session] = await this.c.get("db").select({
72
- userId: core_sessions.userId
73
- }).from(core_sessions).where(and(eq(core_sessions.token, hashedToken), eq(core_sessions.deviceId, device.id), gt(core_sessions.expiresAt, new Date()))).limit(1);
74
- if (!session) {
75
- deleteCookie(this.c, this.c.get("core").authorization.cookieName);
76
- return null;
77
- }
78
- const user = await new UserModel().getUserById({
79
- id: session.userId,
80
- c: this.c
81
- });
82
- if (!user) return null;
83
- return user;
84
- }
85
- }
1
+ import{and,eq,gt}from"drizzle-orm";import{deleteCookie,getCookie,setCookie}from"hono/cookie";import{core_sessions}from"../../database/sessions.js";import{CONFIG}from"../../lib/config.js";import{DeviceModel}from"./device.js";import{UserModel}from"./user.js";export class SessionModel{constructor(c){this.c=c}c;async hashToken(token){const encoder=new TextEncoder;const data=encoder.encode(token);const hashBuffer=await crypto.subtle.digest("SHA-256",data);const bytes=new Uint8Array(hashBuffer);let result="";for(const byte of bytes){result+=byte.toString(16).padStart(2,"0")}return result}async createSessionByUserId(userId){const randomBytes=new Uint8Array(64);crypto.getRandomValues(randomBytes);let token="";for(const byte of randomBytes){token+=byte.toString(16).padStart(2,"0")}const device=await new DeviceModel(this.c).getDeviceId();const hashedToken=await this.hashToken(token);await this.c.get("db").insert(core_sessions).values({token:hashedToken,userId,expiresAt:new Date(Date.now()+this.c.get("core").authorization.cookie_expires),deviceId:device.id});setCookie(this.c,this.c.get("core").authorization.cookieName,token,{httpOnly:true,secure:this.c.get("core").authorization.cookieSecure,path:"/",expires:this.c.get("core").authorization.cookie_expires>0?new Date(Date.now()+this.c.get("core").authorization.cookie_expires):undefined,domain:CONFIG.web.hostname});return{token}}async deleteSession(){const token=getCookie(this.c,this.c.get("core").authorization.cookieName);const device=await new DeviceModel(this.c).getDeviceId();if(!(token&&device.id)){deleteCookie(this.c,this.c.get("core").authorization.cookieName);return}const hashedToken=await this.hashToken(token);await this.c.get("db").delete(core_sessions).where(and(eq(core_sessions.token,hashedToken),eq(core_sessions.deviceId,device.id)));deleteCookie(this.c,this.c.get("core").authorization.cookieName)}async getUser(){const token=getCookie(this.c,this.c.get("core").authorization.cookieName);if(!token)return null;const device=await new DeviceModel(this.c).getDeviceId();if(!device)return null;const hashedToken=await this.hashToken(token);const[session]=await this.c.get("db").select({userId:core_sessions.userId}).from(core_sessions).where(and(eq(core_sessions.token,hashedToken),eq(core_sessions.deviceId,device.id),gt(core_sessions.expiresAt,new Date))).limit(1);if(!session){deleteCookie(this.c,this.c.get("core").authorization.cookieName);return null}const user=await new UserModel().getUserById({id:session.userId,c:this.c});if(!user)return null;return user}}
@@ -1,120 +1 @@
1
- import { and, eq } from "drizzle-orm";
2
- import { deleteCookie, getCookie, setCookie } from "hono/cookie";
3
- import { HTTPException } from "hono/http-exception";
4
- import crypto from "node:crypto";
5
- import { core_users, core_users_sso } from "../../database/users.js";
6
- import { CONFIG } from "../../lib/config.js";
7
- import { removeSpecialCharacters } from "../../lib/special-characters.js";
8
- import { UserModel } from "./user.js";
9
- export const getRedirectUri = (code)=>new URL(`${CONFIG.web.href}login/sso/${code}`).toString();
10
- export class SSOModel {
11
- constructor(c){
12
- this.c = c;
13
- this.plugins = c.get("core").authorization.ssoAdapters;
14
- }
15
- c;
16
- plugins;
17
- signUpUser = async ({ providerId, user, c })=>{
18
- const data = await new UserModel().signUp({
19
- email: user.email,
20
- name: removeSpecialCharacters(user.username, false),
21
- newsletter: false,
22
- hashedPassword: undefined
23
- }, c);
24
- await c.get("db").insert(core_users_sso).values({
25
- userId: data.id,
26
- providerId: providerId,
27
- providerAccountId: user.id
28
- });
29
- return {
30
- userId: data.id
31
- };
32
- };
33
- async callback({ code, providerId, state }) {
34
- await this.verifyState(state);
35
- const provider = this.plugins.find((p)=>p.id === providerId);
36
- if (!provider) {
37
- throw new HTTPException(404);
38
- }
39
- const ssoToken = await provider.fetchToken(code);
40
- const userFromSSO = await provider.fetchUser(ssoToken);
41
- return await this.c.get("db").transaction(async (tx)=>{
42
- const [dataSSOFromDb] = await tx.select({
43
- userId: core_users_sso.userId
44
- }).from(core_users_sso).leftJoin(core_users, eq(core_users.id, core_users_sso.userId)).where(and(eq(core_users_sso.providerId, providerId), eq(core_users_sso.providerAccountId, userFromSSO.id))).limit(1);
45
- if (!dataSSOFromDb) {
46
- const [userWithEmail] = await tx.select({
47
- id: core_users.id,
48
- email: core_users.email
49
- }).from(core_users).where(eq(core_users.email, userFromSSO.email)).limit(1);
50
- if (!userWithEmail) {
51
- const signUpUser = await this.signUpUser({
52
- providerId,
53
- user: userFromSSO,
54
- c: this.c
55
- });
56
- return signUpUser;
57
- }
58
- // If email exists, throw an error
59
- throw new HTTPException(409, {
60
- message: "Email already exists"
61
- });
62
- // await tx.insert(core_users_sso).values({
63
- // providerId: providerId,
64
- // providerAccountId: userFromSSO.id,
65
- // userId: userWithEmail.id,
66
- // });
67
- }
68
- return {
69
- userId: dataSSOFromDb.userId
70
- };
71
- });
72
- }
73
- async encryptState() {
74
- const state = crypto.randomBytes(8).toString("hex");
75
- const encryptedState = await new Promise((resolve, reject)=>{
76
- const salt = crypto.randomBytes(4).toString("hex");
77
- crypto.scrypt(state, salt, 16, (err, derivedKey)=>{
78
- if (err) reject(err);
79
- resolve(`${salt}:${derivedKey.toString("hex")}`);
80
- });
81
- });
82
- setCookie(this.c, `${this.c.get("core").authorization.cookieName}--state-sso`, encryptedState, {
83
- httpOnly: true,
84
- secure: this.c.get("core").authorization.cookieSecure,
85
- path: "/",
86
- domain: CONFIG.web.hostname
87
- });
88
- return state;
89
- }
90
- async getUrl(providerId) {
91
- const provider = this.plugins.find((p)=>p.id === providerId);
92
- if (!provider) {
93
- throw new HTTPException(404);
94
- }
95
- return provider.getUrl({
96
- state: await this.encryptState()
97
- });
98
- }
99
- async verifyState(state) {
100
- const storedState = getCookie(this.c, `${this.c.get("core").authorization.cookieName}--state-sso`);
101
- if (!storedState) {
102
- throw new HTTPException(400, {
103
- message: "Invalid state"
104
- });
105
- }
106
- const isValid = await new Promise((resolve, reject)=>{
107
- const [salt, storedHash] = storedState.split(":");
108
- crypto.scrypt(state, salt, 16, (err, derivedKey)=>{
109
- if (err) reject(err);
110
- resolve(storedHash === derivedKey.toString("hex"));
111
- });
112
- });
113
- if (!isValid) {
114
- throw new HTTPException(400, {
115
- message: "Invalid state"
116
- });
117
- }
118
- deleteCookie(this.c, `${this.c.get("core").authorization.cookieName}--state-sso`);
119
- }
120
- }
1
+ import{and,eq}from"drizzle-orm";import{deleteCookie,getCookie,setCookie}from"hono/cookie";import{HTTPException}from"hono/http-exception";import crypto from"node:crypto";import{core_users,core_users_sso}from"../../database/users.js";import{CONFIG}from"../../lib/config.js";import{removeSpecialCharacters}from"../../lib/special-characters.js";import{UserModel}from"./user.js";export const getRedirectUri=code=>new URL(`${CONFIG.web.href}login/sso/${code}`).toString();export class SSOModel{constructor(c){this.c=c;this.plugins=c.get("core").authorization.ssoAdapters}c;plugins;signUpUser=async({providerId,user,c})=>{const data=await new UserModel().signUp({email:user.email,name:removeSpecialCharacters(user.username,false),newsletter:false,hashedPassword:undefined},c);await c.get("db").insert(core_users_sso).values({userId:data.id,providerId:providerId,providerAccountId:user.id});return{userId:data.id}};async callback({code,providerId,state}){await this.verifyState(state);const provider=this.plugins.find(p=>p.id===providerId);if(!provider){throw new HTTPException(404)}const ssoToken=await provider.fetchToken(code);const userFromSSO=await provider.fetchUser(ssoToken);return await this.c.get("db").transaction(async tx=>{const[dataSSOFromDb]=await tx.select({userId:core_users_sso.userId}).from(core_users_sso).leftJoin(core_users,eq(core_users.id,core_users_sso.userId)).where(and(eq(core_users_sso.providerId,providerId),eq(core_users_sso.providerAccountId,userFromSSO.id))).limit(1);if(!dataSSOFromDb){const[userWithEmail]=await tx.select({id:core_users.id,email:core_users.email}).from(core_users).where(eq(core_users.email,userFromSSO.email)).limit(1);if(!userWithEmail){const signUpUser=await this.signUpUser({providerId,user:userFromSSO,c:this.c});return signUpUser}throw new HTTPException(409,{message:"Email already exists"})}return{userId:dataSSOFromDb.userId}})}async encryptState(){const state=crypto.randomBytes(8).toString("hex");const encryptedState=await new Promise((resolve,reject)=>{const salt=crypto.randomBytes(4).toString("hex");crypto.scrypt(state,salt,16,(err,derivedKey)=>{if(err)reject(err);resolve(`${salt}:${derivedKey.toString("hex")}`)})});setCookie(this.c,`${this.c.get("core").authorization.cookieName}--state-sso`,encryptedState,{httpOnly:true,secure:this.c.get("core").authorization.cookieSecure,path:"/",domain:CONFIG.web.hostname});return state}async getUrl(providerId){const provider=this.plugins.find(p=>p.id===providerId);if(!provider){throw new HTTPException(404)}return provider.getUrl({state:await this.encryptState()})}async verifyState(state){const storedState=getCookie(this.c,`${this.c.get("core").authorization.cookieName}--state-sso`);if(!storedState){throw new HTTPException(400,{message:"Invalid state"})}const isValid=await new Promise((resolve,reject)=>{const[salt,storedHash]=storedState.split(":");crypto.scrypt(state,salt,16,(err,derivedKey)=>{if(err)reject(err);resolve(storedHash===derivedKey.toString("hex"))})});if(!isValid){throw new HTTPException(400,{message:"Invalid state"})}deleteCookie(this.c,`${this.c.get("core").authorization.cookieName}--state-sso`)}}
@@ -1,19 +1 @@
1
- import { eq } from "drizzle-orm";
2
- import { core_users } from "../../../database/users.js";
3
- export const getUserById = async ({ id, c })=>{
4
- const [user] = await c.get("db").select({
5
- id: core_users.id,
6
- email: core_users.email,
7
- name: core_users.name,
8
- nameCode: core_users.nameCode,
9
- createdAt: core_users.createdAt,
10
- newsletter: core_users.newsletter,
11
- avatarColor: core_users.avatarColor,
12
- emailVerified: core_users.emailVerified,
13
- roleId: core_users.roleId,
14
- birthday: core_users.birthday,
15
- language: core_users.language
16
- }).from(core_users).where(eq(core_users.id, id)).limit(1);
17
- if (!user) return null;
18
- return user;
19
- };
1
+ import{eq}from"drizzle-orm";import{core_users}from"../../../database/users.js";export const getUserById=async({id,c})=>{const[user]=await c.get("db").select({id:core_users.id,email:core_users.email,name:core_users.name,nameCode:core_users.nameCode,createdAt:core_users.createdAt,newsletter:core_users.newsletter,avatarColor:core_users.avatarColor,emailVerified:core_users.emailVerified,roleId:core_users.roleId,birthday:core_users.birthday,language:core_users.language}).from(core_users).where(eq(core_users.id,id)).limit(1);if(!user)return null;return user};
@@ -1,22 +1 @@
1
- import { eq } from "drizzle-orm";
2
- import { HTTPException } from "hono/http-exception";
3
- import { core_users } from "../../../database/users.js";
4
- import { PasswordModel } from "../password.js";
5
- export const signInWithPassword = async ({ email, password, c })=>{
6
- const [user] = await c.get("db").select({
7
- id: core_users.id,
8
- email: core_users.email,
9
- password: core_users.password
10
- }).from(core_users).where(eq(core_users.email, email)).limit(1);
11
- if (!user?.password) {
12
- throw new HTTPException(403);
13
- }
14
- const validPassword = await new PasswordModel().verifyPassword(password, user.password);
15
- if (!validPassword) {
16
- throw new HTTPException(403);
17
- }
18
- return {
19
- id: user.id,
20
- email: user.email
21
- };
22
- };
1
+ import{eq}from"drizzle-orm";import{HTTPException}from"hono/http-exception";import{core_users}from"../../../database/users.js";import{PasswordModel}from"../password.js";export const signInWithPassword=async({email,password,c})=>{const[user]=await c.get("db").select({id:core_users.id,email:core_users.email,password:core_users.password}).from(core_users).where(eq(core_users.email,email)).limit(1);if(!user?.password){throw new HTTPException(403)}const validPassword=await new PasswordModel().verifyPassword(password,user.password);if(!validPassword){throw new HTTPException(403)}return{id:user.id,email:user.email}};
@@ -1,73 +1 @@
1
- import { and, count, eq, or } from "drizzle-orm";
2
- import { HTTPException } from "hono/http-exception";
3
- import { generateAvatarColor } from "../../modules/users/avatar-color.js";
4
- import { core_roles } from "../../../database/roles.js";
5
- import { core_users } from "../../../database/users.js";
6
- import { removeSpecialCharacters } from "../../../lib/special-characters.js";
7
- const getDefaultData = async (c)=>{
8
- const [countUsers] = await c.get("db").select({
9
- count: count()
10
- }).from(core_users);
11
- // If no users, return root group
12
- if (countUsers.count === 0) {
13
- const [defaultRole] = await c.get("db").select({
14
- id: core_roles.id
15
- }).from(core_roles).where(and(eq(core_roles.default, false), eq(core_roles.root, true))).limit(1);
16
- if (!defaultRole) {
17
- throw new HTTPException(400, {
18
- message: "Default group not found."
19
- });
20
- }
21
- return {
22
- roleId: defaultRole.id,
23
- emailVerified: true
24
- };
25
- }
26
- const [defaultRole] = await c.get("db").select({
27
- id: core_roles.id
28
- }).from(core_roles).where(and(eq(core_roles.default, true), eq(core_roles.root, false))).limit(1);
29
- if (!defaultRole) {
30
- throw new HTTPException(400, {
31
- message: "Default role not found."
32
- });
33
- }
34
- return {
35
- roleId: defaultRole.id,
36
- emailVerified: !c.get("core").email?.adapter
37
- };
38
- };
39
- export const signUp = async ({ email, name, newsletter, hashedPassword }, c)=>{
40
- const convertToNameSEO = removeSpecialCharacters(name);
41
- const checkIfUserExist = await c.get("db").select({
42
- email: core_users.email,
43
- name_code: core_users.nameCode
44
- }).from(core_users).where(or(eq(core_users.email, email), eq(core_users.nameCode, convertToNameSEO)));
45
- const findEmail = checkIfUserExist.find((user)=>user.email === email);
46
- if (findEmail) {
47
- throw new HTTPException(409, {
48
- message: "Email already exists"
49
- });
50
- }
51
- const findName = checkIfUserExist.find((user)=>user.name_code === convertToNameSEO);
52
- if (findName) {
53
- throw new HTTPException(409, {
54
- message: "Name already exists"
55
- });
56
- }
57
- const { roleId, emailVerified } = await getDefaultData(c);
58
- const [data] = await c.get("db").insert(core_users).values({
59
- email,
60
- name,
61
- nameCode: convertToNameSEO,
62
- // TODO: Handle newsletter only if email is allowed
63
- newsletter,
64
- password: hashedPassword,
65
- avatarColor: generateAvatarColor(name),
66
- roleId,
67
- emailVerified,
68
- ipAddress: c.get("ipAddress")
69
- }).returning();
70
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
71
- const { password: _, ...user } = data;
72
- return user;
73
- };
1
+ import{and,count,eq,or}from"drizzle-orm";import{HTTPException}from"hono/http-exception";import{generateAvatarColor}from"../../modules/users/avatar-color.js";import{core_roles}from"../../../database/roles.js";import{core_users}from"../../../database/users.js";import{removeSpecialCharacters}from"../../../lib/special-characters.js";const getDefaultData=async c=>{const[countUsers]=await c.get("db").select({count:count()}).from(core_users);if(countUsers.count===0){const[defaultRole]=await c.get("db").select({id:core_roles.id}).from(core_roles).where(and(eq(core_roles.default,false),eq(core_roles.root,true))).limit(1);if(!defaultRole){throw new HTTPException(400,{message:"Default group not found."})}return{roleId:defaultRole.id,emailVerified:true}}const[defaultRole]=await c.get("db").select({id:core_roles.id}).from(core_roles).where(and(eq(core_roles.default,true),eq(core_roles.root,false))).limit(1);if(!defaultRole){throw new HTTPException(400,{message:"Default role not found."})}return{roleId:defaultRole.id,emailVerified:!c.get("core").email?.adapter}};export const signUp=async({email,name,newsletter,hashedPassword},c)=>{const convertToNameSEO=removeSpecialCharacters(name);const checkIfUserExist=await c.get("db").select({email:core_users.email,name_code:core_users.nameCode}).from(core_users).where(or(eq(core_users.email,email),eq(core_users.nameCode,convertToNameSEO)));const findEmail=checkIfUserExist.find(user=>user.email===email);if(findEmail){throw new HTTPException(409,{message:"Email already exists"})}const findName=checkIfUserExist.find(user=>user.name_code===convertToNameSEO);if(findName){throw new HTTPException(409,{message:"Name already exists"})}const{roleId,emailVerified}=await getDefaultData(c);const[data]=await c.get("db").insert(core_users).values({email,name,nameCode:convertToNameSEO,newsletter,password:hashedPassword,avatarColor:generateAvatarColor(name),roleId,emailVerified,ipAddress:c.get("ipAddress")}).returning();const{password:_,...user}=data;return user};
@@ -1,8 +1 @@
1
- import { getUserById } from "./user/get-user-by-id.js";
2
- import { signInWithPassword } from "./user/sign-in-with-passwords.js";
3
- import { signUp } from "./user/sign-up.js";
4
- export class UserModel {
5
- getUserById = getUserById;
6
- signInWithPassword = signInWithPassword;
7
- signUp = signUp;
8
- }
1
+ import{getUserById}from"./user/get-user-by-id.js";import{signInWithPassword}from"./user/sign-in-with-passwords.js";import{signUp}from"./user/sign-up.js";export class UserModel{getUserById=getUserById;signInWithPassword=signInWithPassword;signUp=signUp}
@@ -1,19 +1 @@
1
- import { buildModule } from "../../lib/module.js";
2
- import { CONFIG_PLUGIN } from "../../../config.js";
3
- import { advancedAdminModule } from "./advanced/advanced.admin.module.js";
4
- import { debugAdminModule } from "./debug/debug.admin.module.js";
5
- import { sessionAdminRoute } from "./routes/session.route.js";
6
- import { usersAdminModule } from "./users/users.admin.module.js";
7
- export const adminModule = buildModule({
8
- pluginId: CONFIG_PLUGIN.pluginId,
9
- name: "admin",
10
- routes: [
11
- sessionAdminRoute
12
- ],
13
- modules: [
14
- usersAdminModule,
15
- debugAdminModule,
16
- advancedAdminModule
17
- ],
18
- cronJobs: []
19
- });
1
+ import{buildModule}from"../../lib/module.js";import{CONFIG_PLUGIN}from"../../../config.js";import{advancedAdminModule}from"./advanced/advanced.admin.module.js";import{debugAdminModule}from"./debug/debug.admin.module.js";import{sessionAdminRoute}from"./routes/session.route.js";import{usersAdminModule}from"./users/users.admin.module.js";export const adminModule=buildModule({pluginId:CONFIG_PLUGIN.pluginId,name:"admin",routes:[sessionAdminRoute],modules:[usersAdminModule,debugAdminModule,advancedAdminModule],cronJobs:[]});
@@ -1,11 +1 @@
1
- import { buildModule } from "../../../lib/module.js";
2
- import { CONFIG_PLUGIN } from "../../../../config.js";
3
- import { cronAdminModule } from "./cron/cron.admin.module.js";
4
- export const advancedAdminModule = buildModule({
5
- pluginId: CONFIG_PLUGIN.pluginId,
6
- name: "advanced",
7
- routes: [],
8
- modules: [
9
- cronAdminModule
10
- ]
11
- });
1
+ import{buildModule}from"../../../lib/module.js";import{CONFIG_PLUGIN}from"../../../../config.js";import{cronAdminModule}from"./cron/cron.admin.module.js";export const advancedAdminModule=buildModule({pluginId:CONFIG_PLUGIN.pluginId,name:"advanced",routes:[],modules:[cronAdminModule]});
@@ -1,12 +1 @@
1
- import { buildModule } from "../../../../lib/module.js";
2
- import { CONFIG_PLUGIN } from "../../../../../config.js";
3
- import { getCronsRoute } from "./routes/get.route.js";
4
- import { runCronRoute } from "./routes/run.route.js";
5
- export const cronAdminModule = buildModule({
6
- pluginId: CONFIG_PLUGIN.pluginId,
7
- name: "cron",
8
- routes: [
9
- getCronsRoute,
10
- runCronRoute
11
- ]
12
- });
1
+ import{buildModule}from"../../../../lib/module.js";import{CONFIG_PLUGIN}from"../../../../../config.js";import{getCronsRoute}from"./routes/get.route.js";import{runCronRoute}from"./routes/run.route.js";export const cronAdminModule=buildModule({pluginId:CONFIG_PLUGIN.pluginId,name:"cron",routes:[getCronsRoute,runCronRoute]});