convex-cms 0.0.1 → 0.0.3
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/LICENSE +190 -0
- package/README.md +99 -0
- package/admin-dist/nitro.json +15 -0
- package/admin-dist/public/assets/CmsEmptyState-CRswfTzk.js +5 -0
- package/admin-dist/public/assets/CmsPageHeader-CirpXndm.js +1 -0
- package/admin-dist/public/assets/CmsStatusBadge-CbEUpQu-.js +1 -0
- package/admin-dist/public/assets/CmsToolbar-BI2nZOXp.js +1 -0
- package/admin-dist/public/assets/ContentEntryEditor-CBeCyK_m.js +4 -0
- package/admin-dist/public/assets/ErrorState-BIVaWmom.js +1 -0
- package/admin-dist/public/assets/TaxonomyFilter-ChaY6Y_x.js +1 -0
- package/admin-dist/public/assets/_contentTypeId-DQ8k_Rvw.js +1 -0
- package/admin-dist/public/assets/_entryId-CKU_glsK.js +1 -0
- package/admin-dist/public/assets/alert-BXjTqrwQ.js +1 -0
- package/admin-dist/public/assets/badge-hvUOzpVZ.js +1 -0
- package/admin-dist/public/assets/circle-check-big-CF_pR17r.js +1 -0
- package/admin-dist/public/assets/command-DU82cJlt.js +1 -0
- package/admin-dist/public/assets/content-_LXl3pp7.js +1 -0
- package/admin-dist/public/assets/content-types-KjxaXGxY.js +2 -0
- package/admin-dist/public/assets/globals-CS6BZ0zp.css +1 -0
- package/admin-dist/public/assets/index-DNGIZHL-.js +1 -0
- package/admin-dist/public/assets/label-KNtpL71g.js +1 -0
- package/admin-dist/public/assets/link-2-Bw2aI4V4.js +1 -0
- package/admin-dist/public/assets/list-sYepHjt_.js +1 -0
- package/admin-dist/public/assets/main-CKj5yfEi.js +97 -0
- package/admin-dist/public/assets/media-Bkrkffm7.js +1 -0
- package/admin-dist/public/assets/new._contentTypeId-C3LstjNs.js +1 -0
- package/admin-dist/public/assets/plus-DUn8v_Xf.js +1 -0
- package/admin-dist/public/assets/rotate-ccw-DJEoHcRI.js +1 -0
- package/admin-dist/public/assets/scroll-area-DfIlT0in.js +1 -0
- package/admin-dist/public/assets/search-MuAUDJKR.js +1 -0
- package/admin-dist/public/assets/select-BD29IXCI.js +1 -0
- package/admin-dist/public/assets/settings-DmMyn_6A.js +1 -0
- package/admin-dist/public/assets/switch-h3Rrnl5i.js +1 -0
- package/admin-dist/public/assets/tabs-imc8h-Dp.js +1 -0
- package/admin-dist/public/assets/taxonomies-dAsrT65H.js +1 -0
- package/admin-dist/public/assets/textarea-BTy7nwzR.js +1 -0
- package/admin-dist/public/assets/trash-SAWKZZHv.js +1 -0
- package/admin-dist/public/assets/triangle-alert-E52Vfeuh.js +1 -0
- package/admin-dist/public/assets/useBreadcrumbLabel-BECBMCzM.js +1 -0
- package/admin-dist/public/assets/usePermissions-Basjs9BT.js +1 -0
- package/admin-dist/public/favicon.ico +0 -0
- package/admin-dist/server/_chunks/_libs/@date-fns/tz.mjs +217 -0
- package/admin-dist/server/_chunks/_libs/@floating-ui/core.mjs +719 -0
- package/admin-dist/server/_chunks/_libs/@floating-ui/dom.mjs +622 -0
- package/admin-dist/server/_chunks/_libs/@floating-ui/react-dom.mjs +292 -0
- package/admin-dist/server/_chunks/_libs/@floating-ui/utils.mjs +320 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/number.mjs +6 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/primitive.mjs +11 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-arrow.mjs +23 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-avatar.mjs +119 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-checkbox.mjs +270 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-collection.mjs +69 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-compose-refs.mjs +39 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-context.mjs +137 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-dialog.mjs +325 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-direction.mjs +9 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-dismissable-layer.mjs +210 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-dropdown-menu.mjs +253 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-focus-guards.mjs +29 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-focus-scope.mjs +206 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-id.mjs +14 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-label.mjs +23 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-menu.mjs +812 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-popover.mjs +300 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-popper.mjs +286 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-portal.mjs +16 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-presence.mjs +128 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-primitive.mjs +141 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-roving-focus.mjs +224 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-scroll-area.mjs +721 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-select.mjs +1163 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-separator.mjs +28 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-slot.mjs +601 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-switch.mjs +152 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-tabs.mjs +189 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-callback-ref.mjs +11 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-controllable-state.mjs +69 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-effect-event.mjs +1 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-escape-keydown.mjs +17 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-is-hydrated.mjs +15 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-layout-effect.mjs +6 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-previous.mjs +14 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-size.mjs +39 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-visually-hidden.mjs +33 -0
- package/admin-dist/server/_chunks/_libs/@tanstack/history.mjs +409 -0
- package/admin-dist/server/_chunks/_libs/@tanstack/react-router.mjs +1711 -0
- package/admin-dist/server/_chunks/_libs/@tanstack/react-store.mjs +56 -0
- package/admin-dist/server/_chunks/_libs/@tanstack/router-core.mjs +4829 -0
- package/admin-dist/server/_chunks/_libs/@tanstack/store.mjs +134 -0
- package/admin-dist/server/_chunks/_libs/react-dom.mjs +10781 -0
- package/admin-dist/server/_chunks/_libs/react.mjs +513 -0
- package/admin-dist/server/_libs/aria-hidden.mjs +122 -0
- package/admin-dist/server/_libs/class-variance-authority.mjs +44 -0
- package/admin-dist/server/_libs/clsx.mjs +16 -0
- package/admin-dist/server/_libs/cmdk.mjs +315 -0
- package/admin-dist/server/_libs/convex.mjs +4841 -0
- package/admin-dist/server/_libs/cookie-es.mjs +58 -0
- package/admin-dist/server/_libs/croner.mjs +1 -0
- package/admin-dist/server/_libs/crossws.mjs +1 -0
- package/admin-dist/server/_libs/date-fns.mjs +1716 -0
- package/admin-dist/server/_libs/detect-node-es.mjs +1 -0
- package/admin-dist/server/_libs/get-nonce.mjs +9 -0
- package/admin-dist/server/_libs/h3-v2.mjs +277 -0
- package/admin-dist/server/_libs/h3.mjs +401 -0
- package/admin-dist/server/_libs/hookable.mjs +1 -0
- package/admin-dist/server/_libs/isbot.mjs +20 -0
- package/admin-dist/server/_libs/lucide-react.mjs +850 -0
- package/admin-dist/server/_libs/ohash.mjs +1 -0
- package/admin-dist/server/_libs/react-day-picker.mjs +2201 -0
- package/admin-dist/server/_libs/react-remove-scroll-bar.mjs +82 -0
- package/admin-dist/server/_libs/react-remove-scroll.mjs +328 -0
- package/admin-dist/server/_libs/react-style-singleton.mjs +69 -0
- package/admin-dist/server/_libs/rou3.mjs +8 -0
- package/admin-dist/server/_libs/seroval-plugins.mjs +58 -0
- package/admin-dist/server/_libs/seroval.mjs +1765 -0
- package/admin-dist/server/_libs/srvx.mjs +719 -0
- package/admin-dist/server/_libs/tailwind-merge.mjs +3010 -0
- package/admin-dist/server/_libs/tiny-invariant.mjs +12 -0
- package/admin-dist/server/_libs/tiny-warning.mjs +5 -0
- package/admin-dist/server/_libs/tslib.mjs +39 -0
- package/admin-dist/server/_libs/ufo.mjs +54 -0
- package/admin-dist/server/_libs/unctx.mjs +1 -0
- package/admin-dist/server/_libs/unstorage.mjs +1 -0
- package/admin-dist/server/_libs/use-callback-ref.mjs +66 -0
- package/admin-dist/server/_libs/use-sidecar.mjs +106 -0
- package/admin-dist/server/_libs/use-sync-external-store.mjs +139 -0
- package/admin-dist/server/_libs/zod.mjs +4223 -0
- package/admin-dist/server/_ssr/CmsEmptyState-DU7-7-mV.mjs +290 -0
- package/admin-dist/server/_ssr/CmsPageHeader-CseW0AHm.mjs +24 -0
- package/admin-dist/server/_ssr/CmsStatusBadge-B_pi4KCp.mjs +127 -0
- package/admin-dist/server/_ssr/CmsToolbar-X75ex6ek.mjs +49 -0
- package/admin-dist/server/_ssr/ContentEntryEditor-CepusRsA.mjs +3720 -0
- package/admin-dist/server/_ssr/ErrorState-cI-bKLez.mjs +89 -0
- package/admin-dist/server/_ssr/TaxonomyFilter-Bwrq0-cz.mjs +188 -0
- package/admin-dist/server/_ssr/_contentTypeId-BqYKEcLr.mjs +379 -0
- package/admin-dist/server/_ssr/_entryId-CRfnqeDf.mjs +161 -0
- package/admin-dist/server/_ssr/_tanstack-start-manifest_v-BwDlABVk.mjs +4 -0
- package/admin-dist/server/_ssr/alert-CVt45UUP.mjs +92 -0
- package/admin-dist/server/_ssr/badge-6BsP37vG.mjs +125 -0
- package/admin-dist/server/_ssr/command-fy8epIKf.mjs +128 -0
- package/admin-dist/server/_ssr/config.server-D7JHDcDv.mjs +117 -0
- package/admin-dist/server/_ssr/content-B5RhL7uW.mjs +532 -0
- package/admin-dist/server/_ssr/content-types-BIOqCQYN.mjs +1166 -0
- package/admin-dist/server/_ssr/index-DHSHDPt1.mjs +193 -0
- package/admin-dist/server/_ssr/index.mjs +1275 -0
- package/admin-dist/server/_ssr/label-C8Dko1j7.mjs +22 -0
- package/admin-dist/server/_ssr/media-CSx3XttC.mjs +1832 -0
- package/admin-dist/server/_ssr/new._contentTypeId-DzanEZQM.mjs +144 -0
- package/admin-dist/server/_ssr/router-DDWcF-kt.mjs +1556 -0
- package/admin-dist/server/_ssr/scroll-area-bjPYwhXN.mjs +59 -0
- package/admin-dist/server/_ssr/select-BUhDDf4T.mjs +142 -0
- package/admin-dist/server/_ssr/settings-DAsxnw2q.mjs +348 -0
- package/admin-dist/server/_ssr/start-HYkvq4Ni.mjs +4 -0
- package/admin-dist/server/_ssr/switch-BgyRtQ1Z.mjs +31 -0
- package/admin-dist/server/_ssr/tabs-DzMdRB1A.mjs +628 -0
- package/admin-dist/server/_ssr/taxonomies-C8j8g5Q5.mjs +915 -0
- package/admin-dist/server/_ssr/textarea-9jNeYJSc.mjs +18 -0
- package/admin-dist/server/_ssr/trash-DYMxwhZB.mjs +291 -0
- package/admin-dist/server/_ssr/useBreadcrumbLabel-FNSAr2Ha.mjs +16 -0
- package/admin-dist/server/_ssr/usePermissions-BJGGahrJ.mjs +68 -0
- package/admin-dist/server/favicon.ico +0 -0
- package/admin-dist/server/index.mjs +627 -0
- package/dist/cli/index.js +0 -0
- package/dist/client/admin-config.d.ts +0 -1
- package/dist/client/admin-config.d.ts.map +1 -1
- package/dist/client/admin-config.js +0 -1
- package/dist/client/admin-config.js.map +1 -1
- package/dist/client/adminApi.d.ts.map +1 -1
- package/dist/client/agentTools.d.ts +1237 -135
- package/dist/client/agentTools.d.ts.map +1 -1
- package/dist/client/agentTools.js +33 -9
- package/dist/client/agentTools.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/component.d.ts +9 -0
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/mediaAssets.d.ts +35 -0
- package/dist/component/mediaAssets.d.ts.map +1 -1
- package/dist/component/mediaAssets.js +81 -0
- package/dist/component/mediaAssets.js.map +1 -1
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +2 -1
- package/dist/test.js.map +1 -1
- package/package.json +24 -9
- package/dist/component/auditLog.d.ts +0 -410
- package/dist/component/auditLog.d.ts.map +0 -1
- package/dist/component/auditLog.js +0 -607
- package/dist/component/auditLog.js.map +0 -1
- package/dist/component/types.d.ts +0 -4
- package/dist/component/types.d.ts.map +0 -1
- package/dist/component/types.js +0 -2
- package/dist/component/types.js.map +0 -1
- package/src/cli/commands/admin.ts +0 -104
- package/src/cli/index.ts +0 -21
- package/src/cli/utils/detectConvexUrl.ts +0 -54
- package/src/cli/utils/openBrowser.ts +0 -16
- package/src/client/admin-config.ts +0 -138
- package/src/client/adminApi.ts +0 -942
- package/src/client/agentTools.ts +0 -1311
- package/src/client/argTypes.ts +0 -316
- package/src/client/field-types.ts +0 -187
- package/src/client/index.ts +0 -1301
- package/src/client/queryBuilder.ts +0 -1100
- package/src/client/schema/codegen.ts +0 -500
- package/src/client/schema/defineContentType.ts +0 -501
- package/src/client/schema/index.ts +0 -169
- package/src/client/schema/schemaDrift.ts +0 -574
- package/src/client/schema/typedClient.ts +0 -688
- package/src/client/schema/types.ts +0 -666
- package/src/client/types.ts +0 -723
- package/src/client/workflows.ts +0 -141
- package/src/client/wrapper.ts +0 -4304
- package/src/component/_generated/api.ts +0 -140
- package/src/component/_generated/component.ts +0 -5029
- package/src/component/_generated/dataModel.ts +0 -60
- package/src/component/_generated/server.ts +0 -156
- package/src/component/authorization.ts +0 -647
- package/src/component/authorizationHooks.ts +0 -668
- package/src/component/bulkOperations.ts +0 -687
- package/src/component/contentEntries.ts +0 -1976
- package/src/component/contentEntryMutations.ts +0 -1223
- package/src/component/contentEntryValidation.ts +0 -707
- package/src/component/contentLock.ts +0 -550
- package/src/component/contentTypeMigration.ts +0 -1064
- package/src/component/contentTypeMutations.ts +0 -969
- package/src/component/contentTypes.ts +0 -346
- package/src/component/convex.config.ts +0 -44
- package/src/component/documentTypes.ts +0 -240
- package/src/component/eventEmitter.ts +0 -485
- package/src/component/exportImport.ts +0 -1169
- package/src/component/index.ts +0 -491
- package/src/component/lib/deepReferenceResolver.ts +0 -999
- package/src/component/lib/errors.ts +0 -816
- package/src/component/lib/index.ts +0 -145
- package/src/component/lib/mediaReferenceResolver.ts +0 -495
- package/src/component/lib/metadataExtractor.ts +0 -792
- package/src/component/lib/mutationAuth.ts +0 -199
- package/src/component/lib/queries.ts +0 -79
- package/src/component/lib/ragContentChunker.ts +0 -1371
- package/src/component/lib/referenceResolver.ts +0 -430
- package/src/component/lib/slugGenerator.ts +0 -262
- package/src/component/lib/slugUniqueness.ts +0 -333
- package/src/component/lib/softDelete.ts +0 -44
- package/src/component/localeFallbackChain.ts +0 -673
- package/src/component/localeFields.ts +0 -896
- package/src/component/mediaAssetMutations.ts +0 -725
- package/src/component/mediaAssets.ts +0 -932
- package/src/component/mediaFolderMutations.ts +0 -1046
- package/src/component/mediaUploadMutations.ts +0 -224
- package/src/component/mediaVariantMutations.ts +0 -900
- package/src/component/mediaVariants.ts +0 -793
- package/src/component/ragContentIndexer.ts +0 -1067
- package/src/component/rateLimitHooks.ts +0 -572
- package/src/component/roles.ts +0 -1360
- package/src/component/scheduledPublish.ts +0 -358
- package/src/component/schema.ts +0 -617
- package/src/component/taxonomies.ts +0 -949
- package/src/component/taxonomyMutations.ts +0 -1210
- package/src/component/trash.ts +0 -724
- package/src/component/userContext.ts +0 -898
- package/src/component/validation.ts +0 -1388
- package/src/component/validators.ts +0 -949
- package/src/component/versionMutations.ts +0 -392
- package/src/component/webhookTrigger.ts +0 -1922
- package/src/react/index.ts +0 -898
- package/src/test.ts +0 -1580
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mutation-Level Authorization Helper
|
|
3
|
-
*
|
|
4
|
-
* Provides defense-in-depth authorization for component mutations.
|
|
5
|
-
* When auth context is provided, mutations verify the role has permission.
|
|
6
|
-
*
|
|
7
|
-
* This complements the client wrapper's authorization:
|
|
8
|
-
* - Client wrapper: Primary authorization layer (runs hooks, RBAC)
|
|
9
|
-
* - Mutation auth: Secondary validation layer (pure RBAC check)
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```typescript
|
|
13
|
-
* import { requireMutationAuth } from "./lib/mutationAuth.js";
|
|
14
|
-
*
|
|
15
|
-
* export const createEntry = mutation({
|
|
16
|
-
* args: {
|
|
17
|
-
* ...createContentEntryArgs.fields,
|
|
18
|
-
* _auth: v.optional(mutationAuthContext),
|
|
19
|
-
* },
|
|
20
|
-
* handler: async (ctx, args) => {
|
|
21
|
-
* requireMutationAuth(args._auth, "contentEntries", "create");
|
|
22
|
-
* // ... mutation logic
|
|
23
|
-
* },
|
|
24
|
-
* });
|
|
25
|
-
* ```
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
import type { MutationAuthContext } from "../validators.js";
|
|
29
|
-
import { hasPermission, type Resource, type Action, type RoleDefinition } from "../roles.js";
|
|
30
|
-
import { permissionDenied } from "./errors.js";
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Options for mutation authorization check.
|
|
34
|
-
*/
|
|
35
|
-
export interface MutationAuthOptions {
|
|
36
|
-
/**
|
|
37
|
-
* Custom role definitions to include in permission checks.
|
|
38
|
-
* These are in addition to the default roles (admin, editor, author, viewer).
|
|
39
|
-
*/
|
|
40
|
-
customRoles?: Record<string, RoleDefinition>;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Verify the auth context has permission for the requested operation.
|
|
45
|
-
*
|
|
46
|
-
* This function:
|
|
47
|
-
* 1. If `_auth` is undefined, does nothing (backwards compatible)
|
|
48
|
-
* 2. If `_auth` is provided, checks the role has permission
|
|
49
|
-
* 3. Throws CMSError with PERMISSION_DENIED if check fails
|
|
50
|
-
*
|
|
51
|
-
* For ownership-scoped permissions (e.g., author editing their own content):
|
|
52
|
-
* - If the role only has "own" scope, verifies resourceOwnerId matches userId
|
|
53
|
-
* - If the role has "all" scope, ownership is not checked
|
|
54
|
-
*
|
|
55
|
-
* @param auth - The auth context from mutation args (may be undefined)
|
|
56
|
-
* @param resource - The resource being accessed (e.g., "contentEntries")
|
|
57
|
-
* @param action - The action being performed (e.g., "create", "update")
|
|
58
|
-
* @param options - Optional configuration including custom roles
|
|
59
|
-
* @throws CMSError with code PERMISSION_DENIED if authorization fails
|
|
60
|
-
*
|
|
61
|
-
* @example
|
|
62
|
-
* ```typescript
|
|
63
|
-
* // Basic usage - check if role can create content entries
|
|
64
|
-
* requireMutationAuth(args._auth, "contentEntries", "create");
|
|
65
|
-
*
|
|
66
|
-
* // For update/delete - include resource owner for "own" scope check
|
|
67
|
-
* const entry = await ctx.db.get(args.id);
|
|
68
|
-
* requireMutationAuth(
|
|
69
|
-
* { ...args._auth, resourceOwnerId: entry.createdBy },
|
|
70
|
-
* "contentEntries",
|
|
71
|
-
* "update"
|
|
72
|
-
* );
|
|
73
|
-
* ```
|
|
74
|
-
*/
|
|
75
|
-
export function requireMutationAuth(
|
|
76
|
-
auth: MutationAuthContext | undefined,
|
|
77
|
-
resource: Resource,
|
|
78
|
-
action: Action,
|
|
79
|
-
options?: MutationAuthOptions
|
|
80
|
-
): void {
|
|
81
|
-
// If no auth context provided, skip authorization (backwards compatible)
|
|
82
|
-
// Security note: Caller is responsible for ensuring authorization was done elsewhere
|
|
83
|
-
if (!auth) {
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const { userId, role, resourceOwnerId } = auth;
|
|
88
|
-
|
|
89
|
-
// No role means no permissions
|
|
90
|
-
if (!role) {
|
|
91
|
-
throw permissionDenied(action, resource);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Check if role has "all" scope permission
|
|
95
|
-
const hasAllScope = hasPermission(
|
|
96
|
-
role,
|
|
97
|
-
{ resource, action, scope: "all" },
|
|
98
|
-
options?.customRoles
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
if (hasAllScope) {
|
|
102
|
-
return; // Authorized with "all" scope
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Check if role has "own" scope permission
|
|
106
|
-
const hasOwnScope = hasPermission(
|
|
107
|
-
role,
|
|
108
|
-
{ resource, action, scope: "own" },
|
|
109
|
-
options?.customRoles
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
if (hasOwnScope) {
|
|
113
|
-
// "own" scope requires ownership verification
|
|
114
|
-
if (resourceOwnerId && resourceOwnerId === userId) {
|
|
115
|
-
return; // Authorized - user owns the resource
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// For create operations, ownership is always satisfied (user will own it)
|
|
119
|
-
if (action === "create") {
|
|
120
|
-
return; // Authorized - creating own resource
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Ownership check failed
|
|
124
|
-
throw permissionDenied(
|
|
125
|
-
`${action} other users'`,
|
|
126
|
-
resource
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// No permission found
|
|
131
|
-
throw permissionDenied(action, resource);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Check if auth context has permission without throwing.
|
|
136
|
-
*
|
|
137
|
-
* Useful for conditional logic based on permissions.
|
|
138
|
-
*
|
|
139
|
-
* @param auth - The auth context from mutation args
|
|
140
|
-
* @param resource - The resource being accessed
|
|
141
|
-
* @param action - The action being performed
|
|
142
|
-
* @param options - Optional configuration including custom roles
|
|
143
|
-
* @returns true if authorized, false otherwise
|
|
144
|
-
*/
|
|
145
|
-
export function hasMutationAuth(
|
|
146
|
-
auth: MutationAuthContext | undefined,
|
|
147
|
-
resource: Resource,
|
|
148
|
-
action: Action,
|
|
149
|
-
options?: MutationAuthOptions
|
|
150
|
-
): boolean {
|
|
151
|
-
if (!auth) {
|
|
152
|
-
return true; // No auth = no restriction (backwards compatible)
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const { userId, role, resourceOwnerId } = auth;
|
|
156
|
-
|
|
157
|
-
if (!role) {
|
|
158
|
-
return false;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// Check "all" scope first
|
|
162
|
-
if (hasPermission(role, { resource, action, scope: "all" }, options?.customRoles)) {
|
|
163
|
-
return true;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// Check "own" scope
|
|
167
|
-
if (hasPermission(role, { resource, action, scope: "own" }, options?.customRoles)) {
|
|
168
|
-
// For "own" scope, verify ownership or it's a create action
|
|
169
|
-
if (action === "create") {
|
|
170
|
-
return true;
|
|
171
|
-
}
|
|
172
|
-
if (resourceOwnerId && resourceOwnerId === userId) {
|
|
173
|
-
return true;
|
|
174
|
-
}
|
|
175
|
-
return false;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
return false;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Augment auth context with resource owner information.
|
|
183
|
-
*
|
|
184
|
-
* Use this when you have an auth context and need to add ownership info
|
|
185
|
-
* for permission checks on existing resources.
|
|
186
|
-
*
|
|
187
|
-
* @param auth - The original auth context
|
|
188
|
-
* @param resourceOwnerId - The owner of the resource being accessed
|
|
189
|
-
* @returns Auth context with resourceOwnerId set
|
|
190
|
-
*/
|
|
191
|
-
export function withResourceOwner(
|
|
192
|
-
auth: MutationAuthContext | undefined,
|
|
193
|
-
resourceOwnerId: string | undefined
|
|
194
|
-
): MutationAuthContext | undefined {
|
|
195
|
-
if (!auth) {
|
|
196
|
-
return undefined;
|
|
197
|
-
}
|
|
198
|
-
return { ...auth, resourceOwnerId };
|
|
199
|
-
}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Common query helpers for the CMS component.
|
|
3
|
-
*
|
|
4
|
-
* Provides reusable query patterns for looking up documents by name,
|
|
5
|
-
* ID, or other common patterns with soft-delete awareness.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { QueryCtx } from "../_generated/server.js";
|
|
9
|
-
import type { Id, Doc, TableNames } from "../_generated/dataModel.js";
|
|
10
|
-
import { isDeleted } from "./softDelete.js";
|
|
11
|
-
|
|
12
|
-
export interface GetByIdOptions {
|
|
13
|
-
includeDeleted?: boolean;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export async function getContentTypeByName(
|
|
17
|
-
ctx: QueryCtx,
|
|
18
|
-
name: string,
|
|
19
|
-
options: GetByIdOptions = {}
|
|
20
|
-
): Promise<Doc<"contentTypes"> | null> {
|
|
21
|
-
const contentType = await ctx.db
|
|
22
|
-
.query("contentTypes")
|
|
23
|
-
.withIndex("by_name", (q) => q.eq("name", name))
|
|
24
|
-
.first();
|
|
25
|
-
|
|
26
|
-
if (!contentType) return null;
|
|
27
|
-
if (!options.includeDeleted && isDeleted(contentType)) return null;
|
|
28
|
-
return contentType;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export async function getTaxonomyByName(
|
|
32
|
-
ctx: QueryCtx,
|
|
33
|
-
name: string,
|
|
34
|
-
options: GetByIdOptions = {}
|
|
35
|
-
): Promise<Doc<"taxonomies"> | null> {
|
|
36
|
-
const taxonomy = await ctx.db
|
|
37
|
-
.query("taxonomies")
|
|
38
|
-
.withIndex("by_name", (q) => q.eq("name", name))
|
|
39
|
-
.first();
|
|
40
|
-
|
|
41
|
-
if (!taxonomy) return null;
|
|
42
|
-
if (!options.includeDeleted && isDeleted(taxonomy)) return null;
|
|
43
|
-
return taxonomy;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export async function contentTypeExists(
|
|
47
|
-
ctx: QueryCtx,
|
|
48
|
-
name: string,
|
|
49
|
-
options: GetByIdOptions = {}
|
|
50
|
-
): Promise<boolean> {
|
|
51
|
-
const contentType = await getContentTypeByName(ctx, name, options);
|
|
52
|
-
return contentType !== null;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export async function taxonomyExists(
|
|
56
|
-
ctx: QueryCtx,
|
|
57
|
-
name: string,
|
|
58
|
-
options: GetByIdOptions = {}
|
|
59
|
-
): Promise<boolean> {
|
|
60
|
-
const taxonomy = await getTaxonomyByName(ctx, name, options);
|
|
61
|
-
return taxonomy !== null;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export async function getActiveById<T extends TableNames>(
|
|
65
|
-
ctx: QueryCtx,
|
|
66
|
-
id: Id<T>,
|
|
67
|
-
options: GetByIdOptions = {}
|
|
68
|
-
): Promise<Doc<T> | null> {
|
|
69
|
-
const doc = await ctx.db.get(id);
|
|
70
|
-
if (!doc) return null;
|
|
71
|
-
if (
|
|
72
|
-
!options.includeDeleted &&
|
|
73
|
-
"deletedAt" in doc &&
|
|
74
|
-
(doc as { deletedAt?: number }).deletedAt !== undefined
|
|
75
|
-
) {
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
return doc;
|
|
79
|
-
}
|