@beechcms/api 0.4.0-preview.9 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/dashboard/BeechLogo.svg +18 -18
- package/assets/dashboard/BeechLogoLIght.svg +48 -48
- package/assets/dashboard/assets/index-CH13idU1.js +554 -0
- package/assets/dashboard/assets/index-CewtCjom.css +1 -0
- package/assets/dashboard/beechLogoDark.svg +48 -48
- package/assets/dashboard/index.html +18 -18
- package/assets/dashboard/sol.svg +3 -3
- package/assets/dashboard/undraw_enter_nwx3.svg +36 -36
- package/migrations/0000_v040_base.sql +213 -213
- package/package.json +2 -2
- package/src/auth/bcrypt-hash-provider.ts +20 -0
- package/src/auth/constants.ts +10 -10
- package/src/auth/generate-refresh-token.test.ts +19 -0
- package/src/auth/hash-provider.test.ts +46 -0
- package/src/auth/in-memory-hash-provider.ts +13 -0
- package/src/auth/jose-token-service.ts +55 -0
- package/src/auth/login.test.ts +92 -0
- package/src/auth/login.ts +74 -91
- package/src/auth/refresh.ts +5 -127
- package/src/auth/static-token-service.ts +18 -0
- package/src/auth/token-service.test.ts +82 -0
- package/src/factory.ts +339 -303
- package/src/features/content/constants.ts +10 -0
- package/src/features/content/handlers/create.ts +157 -0
- package/src/features/content/handlers/delete.ts +80 -0
- package/src/features/content/handlers/facets.ts +45 -0
- package/src/features/content/handlers/get.ts +116 -0
- package/src/features/content/handlers/list.ts +88 -0
- package/src/features/content/handlers/update.ts +211 -0
- package/src/features/content/index.ts +20 -0
- package/src/features/draft/draft.handler.ts +283 -198
- package/src/features/draft/index.ts +1 -1
- package/src/features/email/email.provider.ts +38 -38
- package/src/features/email/email.service.ts +80 -80
- package/src/features/email/email.types.ts +98 -98
- package/src/features/email/index.ts +28 -28
- package/src/features/email/providers/resend.ts +63 -63
- package/src/features/email/templates/password-changed.ts +59 -59
- package/src/features/email/templates/password-reset.ts +64 -64
- package/src/features/email/templates/shell.ts +92 -93
- package/src/features/notifications/index.ts +1 -1
- package/src/features/notifications/notifications.handler.ts +101 -88
- package/src/features/password-reset/index.ts +15 -15
- package/src/features/password-reset/request.ts +82 -88
- package/src/features/password-reset/reset.ts +92 -110
- package/src/features/rotate-field/index.ts +1 -1
- package/src/features/rotate-field/rotate-field.handler.ts +128 -82
- package/src/features/rotate-field/rotate-field.schema.ts +13 -9
- package/src/features/schema/schema.handler.ts +16 -16
- package/src/features/settings/settings.handler.ts +301 -249
- package/src/features/setup/index.ts +91 -59
- package/src/features/stats/index.ts +1 -1
- package/src/features/stats/stats.handler.ts +430 -395
- package/src/index.ts +24 -11
- package/src/media-utils.ts +78 -78
- package/src/middleware/auth-providers.middleware.ts +32 -0
- package/src/middleware/observability.middleware.ts +52 -0
- package/src/middleware/rate-limit.middleware.ts +41 -0
- package/src/middleware/repository.middleware.ts +60 -0
- package/src/middleware/storage.middleware.ts +21 -0
- package/src/middleware.ts +47 -67
- package/src/public/access-policy.ts +23 -23
- package/src/public/api-key-middleware.ts +53 -53
- package/src/public/index.ts +12 -12
- package/src/public/problem-details.ts +48 -42
- package/src/public/public-add.ts +156 -183
- package/src/public/public-edit.ts +159 -183
- package/src/public/public-errors.ts +15 -15
- package/src/public/public-read.ts +216 -217
- package/src/public/public-routes.ts +84 -31
- package/src/public/query-builder.test.ts +220 -0
- package/src/public/query-builder.ts +152 -241
- package/src/public/rate-limit-middleware.ts +30 -42
- package/src/public/response-builder.ts +26 -26
- package/src/public/sanitize.ts +65 -65
- package/src/public/slug-utils.ts +14 -14
- package/src/rate-limit/cloudflare-rate-limiter.test.ts +26 -0
- package/src/rate-limit/cloudflare-rate-limiter.ts +11 -0
- package/src/rate-limit/in-memory-rate-limiter.test.ts +33 -0
- package/src/rate-limit/in-memory-rate-limiter.ts +13 -0
- package/src/rate-limit/no-op-rate-limiter.test.ts +18 -0
- package/src/rate-limit/no-op-rate-limiter.ts +7 -0
- package/src/search-utils.test.ts +207 -0
- package/src/search-utils.ts +209 -192
- package/src/search.ts +61 -72
- package/src/shared/apply-policies.test.ts +77 -0
- package/src/shared/apply-policies.ts +63 -63
- package/src/shared/background-notification-service.test.ts +58 -0
- package/src/shared/background-notification-service.ts +48 -0
- package/src/shared/base.repository.d1.ts +28 -0
- package/src/shared/content-utils.test.ts +161 -0
- package/src/shared/content-utils.ts +82 -108
- package/src/shared/content.repository.d1.test.ts +312 -0
- package/src/shared/content.repository.d1.ts +382 -0
- package/src/shared/d1-activity-log.repository.test.ts +136 -0
- package/src/shared/d1-activity-log.repository.ts +101 -0
- package/src/shared/d1-activity-logger.test.ts +82 -0
- package/src/shared/d1-activity-logger.ts +63 -0
- package/src/shared/d1-analytics.repository.test.ts +74 -0
- package/src/shared/d1-analytics.repository.ts +81 -0
- package/src/shared/d1-content-scan.repository.ts +29 -0
- package/src/shared/d1-notification.repository.test.ts +124 -0
- package/src/shared/d1-notification.repository.ts +114 -0
- package/src/shared/d1-password-reset-token.repository.test.ts +77 -0
- package/src/shared/d1-password-reset-token.repository.ts +52 -0
- package/src/shared/d1-search.repository.test.ts +83 -0
- package/src/shared/d1-search.repository.ts +84 -0
- package/src/shared/d1-session.repository.test.ts +121 -0
- package/src/shared/d1-session.repository.ts +98 -0
- package/src/shared/d1-user.repository.test.ts +147 -0
- package/src/shared/d1-user.repository.ts +109 -0
- package/src/shared/d1-widget.repository.test.ts +217 -0
- package/src/shared/d1-widget.repository.ts +337 -0
- package/src/shared/fixed-clock.ts +21 -0
- package/src/shared/fts-sync.ts +4 -4
- package/src/shared/idempotency.repository.d1.test.ts +79 -0
- package/src/shared/idempotency.repository.d1.ts +56 -0
- package/src/shared/in-memory-activity-logger.ts +15 -0
- package/src/shared/in-memory-notification-service.ts +15 -0
- package/src/shared/media.repository.d1.test.ts +103 -0
- package/src/shared/media.repository.d1.ts +64 -0
- package/src/shared/query-utils.ts +137 -137
- package/src/shared/request-utils.ts +22 -0
- package/src/shared/sequential-id-generator.ts +22 -0
- package/src/shared/storage/factory.ts +40 -0
- package/src/shared/storage/r2-binding-bucket.ts +81 -0
- package/src/shared/storage/s3-bucket.ts +163 -0
- package/src/shared/storage-utils.ts +36 -36
- package/src/shared/system-stats.repository.d1.test.ts +54 -0
- package/src/shared/system-stats.repository.d1.ts +44 -0
- package/src/types.ts +63 -36
- package/src/upload.ts +186 -335
- package/src/widget.ts +208 -349
- package/assets/dashboard/assets/index-CC-jbp6g.js +0 -554
- package/assets/dashboard/assets/index-CQODXprH.css +0 -1
- package/src/content.ts +0 -502
- package/src/features/draft/draft.test.ts +0 -315
- package/src/features/rotate-field/rotate-field.test.ts +0 -297
- package/src/shared/activity-logger.ts +0 -79
- package/src/shared/notification-service.ts +0 -56
|
@@ -1,59 +1,91 @@
|
|
|
1
|
-
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
-
import { Hono } from 'hono'
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
1
|
+
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
+
import { Hono } from 'hono'
|
|
3
|
+
import type { Env, Variables } from '../../types'
|
|
4
|
+
import { publicProblem } from '../../public/problem-details'
|
|
5
|
+
|
|
6
|
+
const setupApp = new Hono<{ Bindings: Env; Variables: Variables }>()
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* GET /auth/setup
|
|
10
|
+
* Checks if the application needs an initial setup (i.e., if no users exist).
|
|
11
|
+
*/
|
|
12
|
+
setupApp.get('/auth/setup', async (context) => {
|
|
13
|
+
const userCount = await context.get('userRepository').countAll()
|
|
14
|
+
return context.json({ needsSetup: userCount === 0 })
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* POST /auth/setup
|
|
19
|
+
* Creates the first administrator account. This endpoint is disabled once at least one user exists.
|
|
20
|
+
*/
|
|
21
|
+
setupApp.post('/auth/setup', async (context) => {
|
|
22
|
+
const userCount = await context.get('userRepository').countAll()
|
|
23
|
+
|
|
24
|
+
if (userCount > 0) {
|
|
25
|
+
return publicProblem(context, {
|
|
26
|
+
type: 'setup-already-done',
|
|
27
|
+
title: 'Setup already completed',
|
|
28
|
+
status: 403,
|
|
29
|
+
detail: 'An administrator account already exists. Initial setup can only be performed once.'
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let payload: unknown
|
|
34
|
+
try {
|
|
35
|
+
payload = await context.req.json()
|
|
36
|
+
} catch {
|
|
37
|
+
return publicProblem(context, {
|
|
38
|
+
type: 'bad-request',
|
|
39
|
+
title: 'Invalid JSON body',
|
|
40
|
+
status: 400,
|
|
41
|
+
detail: 'The request body could not be parsed as valid JSON.'
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!payload || typeof payload !== 'object') {
|
|
46
|
+
return publicProblem(context, {
|
|
47
|
+
type: 'bad-request',
|
|
48
|
+
title: 'Invalid request',
|
|
49
|
+
status: 400,
|
|
50
|
+
detail: 'The request payload is missing or invalid.'
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const { email, password, name } = payload as Record<string, unknown>
|
|
55
|
+
|
|
56
|
+
if (typeof email !== 'string' || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.trim())) {
|
|
57
|
+
return publicProblem(context, {
|
|
58
|
+
type: 'validation-error',
|
|
59
|
+
title: 'Valid email required',
|
|
60
|
+
status: 422,
|
|
61
|
+
detail: 'A valid email address is required for the administrator account.'
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (typeof password !== 'string' || password.length < 8 || password.length > 128) {
|
|
66
|
+
return publicProblem(context, {
|
|
67
|
+
type: 'validation-error',
|
|
68
|
+
title: 'Invalid password',
|
|
69
|
+
status: 422,
|
|
70
|
+
detail: 'Password must be between 8 and 128 characters long.'
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const passwordHash = await context.get('hashProvider').hash(password)
|
|
75
|
+
const normalizedEmail = email.trim().toLowerCase()
|
|
76
|
+
const normalizedName = typeof name === 'string' ? name.trim() : null
|
|
77
|
+
|
|
78
|
+
await context.get('userRepository').create({
|
|
79
|
+
id: context.get('idGenerator').uuid(),
|
|
80
|
+
email: normalizedEmail,
|
|
81
|
+
passwordHash,
|
|
82
|
+
role: 'admin',
|
|
83
|
+
name: normalizedName,
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
return context.json({ success: true }, 201)
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
export { setupApp }
|
|
90
|
+
|
|
91
|
+
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { statsApp } from './stats.handler'
|
|
1
|
+
export { statsApp } from './stats.handler'
|