@aphexcms/cms-core 2.0.9 → 2.0.11
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 +21 -0
- package/dist/api/api-keys.d.ts +8 -7
- package/dist/api/api-keys.d.ts.map +1 -1
- package/dist/api/assets.d.ts +7 -22
- package/dist/api/assets.d.ts.map +1 -1
- package/dist/api/assets.js +1 -10
- package/dist/api/documents.d.ts +17 -16
- package/dist/api/documents.d.ts.map +1 -1
- package/dist/api/documents.js +2 -2
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +1 -0
- package/dist/api/organizations.d.ts +15 -35
- package/dist/api/organizations.d.ts.map +1 -1
- package/dist/api/roles.d.ts +22 -0
- package/dist/api/roles.d.ts.map +1 -0
- package/dist/api/roles.js +26 -0
- package/dist/api/schemas/api-keys.d.ts +62 -0
- package/dist/api/schemas/api-keys.d.ts.map +1 -0
- package/dist/api/schemas/api-keys.js +28 -0
- package/dist/api/schemas/assets.d.ts +174 -0
- package/dist/api/schemas/assets.d.ts.map +1 -0
- package/dist/api/schemas/assets.js +99 -0
- package/dist/api/schemas/documents.d.ts +325 -0
- package/dist/api/schemas/documents.d.ts.map +1 -0
- package/dist/api/schemas/documents.js +161 -0
- package/dist/api/schemas/organizations.d.ts +41 -0
- package/dist/api/schemas/organizations.d.ts.map +1 -0
- package/dist/api/schemas/organizations.js +56 -0
- package/dist/api/schemas/roles.d.ts +77 -0
- package/dist/api/schemas/roles.d.ts.map +1 -0
- package/dist/api/schemas/roles.js +42 -0
- package/dist/api/schemas/user.d.ts +10 -0
- package/dist/api/schemas/user.d.ts.map +1 -0
- package/dist/api/schemas/user.js +11 -0
- package/dist/api/user.d.ts +4 -6
- package/dist/api/user.d.ts.map +1 -1
- package/dist/app-augment.d.ts +32 -0
- package/dist/app-augment.d.ts.map +1 -0
- package/dist/app-augment.js +18 -0
- package/dist/auth/auth-hooks.d.ts +2 -1
- package/dist/auth/auth-hooks.d.ts.map +1 -1
- package/dist/auth/auth-hooks.js +22 -2
- package/dist/auth/provider.d.ts +5 -0
- package/dist/auth/provider.d.ts.map +1 -1
- package/dist/cli/index.js +0 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +7 -0
- package/dist/components/AdminApp.svelte +306 -142
- package/dist/components/AdminApp.svelte.d.ts +8 -0
- package/dist/components/AdminApp.svelte.d.ts.map +1 -1
- package/dist/components/admin/DocumentEditor.svelte +653 -365
- package/dist/components/admin/DocumentEditor.svelte.d.ts +2 -0
- package/dist/components/admin/DocumentEditor.svelte.d.ts.map +1 -1
- package/dist/components/admin/DocumentVersionPanel.svelte +57 -44
- package/dist/components/admin/DocumentVersionPanel.svelte.d.ts.map +1 -1
- package/dist/components/admin/MediaBrowser.svelte +70 -30
- package/dist/components/admin/MediaBrowser.svelte.d.ts.map +1 -1
- package/dist/components/admin/ObjectModal.svelte +70 -95
- package/dist/components/admin/ObjectModal.svelte.d.ts +1 -2
- package/dist/components/admin/ObjectModal.svelte.d.ts.map +1 -1
- package/dist/components/admin/PermissionsDebug.svelte +119 -0
- package/dist/components/admin/PermissionsDebug.svelte.d.ts +4 -0
- package/dist/components/admin/PermissionsDebug.svelte.d.ts.map +1 -0
- package/dist/components/admin/SchemaField.svelte +3 -1
- package/dist/components/admin/SchemaField.svelte.d.ts.map +1 -1
- package/dist/components/admin/confirm-dialog/ConfirmDialogHost.svelte +35 -0
- package/dist/components/admin/confirm-dialog/ConfirmDialogHost.svelte.d.ts +19 -0
- package/dist/components/admin/confirm-dialog/ConfirmDialogHost.svelte.d.ts.map +1 -0
- package/dist/components/admin/confirm-dialog/confirm-dialog.svelte.d.ts +16 -0
- package/dist/components/admin/confirm-dialog/confirm-dialog.svelte.d.ts.map +1 -0
- package/dist/components/admin/confirm-dialog/confirm-dialog.svelte.js +29 -0
- package/dist/components/admin/fields/ArrayField.svelte +104 -108
- package/dist/components/admin/fields/ArrayField.svelte.d.ts.map +1 -1
- package/dist/components/admin/fields/FileField.svelte +22 -17
- package/dist/components/admin/fields/FileField.svelte.d.ts.map +1 -1
- package/dist/components/admin/fields/ImageField.svelte +21 -15
- package/dist/components/admin/fields/ImageField.svelte.d.ts.map +1 -1
- package/dist/components/admin/fields/ReferenceField.svelte +142 -112
- package/dist/components/admin/fields/ReferenceField.svelte.d.ts.map +1 -1
- package/dist/components/admin/fields/TextareaField.svelte +4 -3
- package/dist/components/admin/fields/TextareaField.svelte.d.ts +2 -2
- package/dist/components/admin/fields/TextareaField.svelte.d.ts.map +1 -1
- package/dist/components/layout/Sidebar.svelte +21 -11
- package/dist/components/layout/Sidebar.svelte.d.ts.map +1 -1
- package/dist/components/layout/sidebar/NavMain.svelte +1 -0
- package/dist/db/interfaces/document.d.ts.map +1 -1
- package/dist/db/interfaces/index.d.ts +3 -1
- package/dist/db/interfaces/index.d.ts.map +1 -1
- package/dist/db/interfaces/organization.d.ts +1 -1
- package/dist/db/interfaces/organization.d.ts.map +1 -1
- package/dist/db/interfaces/role.d.ts +25 -0
- package/dist/db/interfaces/role.d.ts.map +1 -0
- package/dist/db/interfaces/role.js +1 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +5 -0
- package/dist/field-access.d.ts +30 -0
- package/dist/field-access.d.ts.map +1 -0
- package/dist/field-access.js +79 -0
- package/dist/hooks.d.ts +2 -0
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +23 -13
- package/dist/lib/api/api-keys.d.ts +8 -7
- package/dist/lib/api/api-keys.d.ts.map +1 -1
- package/dist/lib/api/api-keys.js.map +1 -1
- package/dist/lib/api/assets.d.ts +7 -22
- package/dist/lib/api/assets.d.ts.map +1 -1
- package/dist/lib/api/assets.js +1 -10
- package/dist/lib/api/assets.js.map +1 -1
- package/dist/lib/api/documents.d.ts +17 -16
- package/dist/lib/api/documents.d.ts.map +1 -1
- package/dist/lib/api/documents.js +2 -2
- package/dist/lib/api/documents.js.map +1 -1
- package/dist/lib/api/index.d.ts +1 -0
- package/dist/lib/api/index.d.ts.map +1 -1
- package/dist/lib/api/index.js +1 -0
- package/dist/lib/api/index.js.map +1 -1
- package/dist/lib/api/organizations.d.ts +15 -35
- package/dist/lib/api/organizations.d.ts.map +1 -1
- package/dist/lib/api/organizations.js.map +1 -1
- package/dist/lib/api/roles.d.ts +22 -0
- package/dist/lib/api/roles.d.ts.map +1 -0
- package/dist/lib/api/roles.js +27 -0
- package/dist/lib/api/roles.js.map +1 -0
- package/dist/lib/api/schemas/api-keys.d.ts +62 -0
- package/dist/lib/api/schemas/api-keys.d.ts.map +1 -0
- package/dist/lib/api/schemas/api-keys.js +29 -0
- package/dist/lib/api/schemas/api-keys.js.map +1 -0
- package/dist/lib/api/schemas/assets.d.ts +174 -0
- package/dist/lib/api/schemas/assets.d.ts.map +1 -0
- package/dist/lib/api/schemas/assets.js +100 -0
- package/dist/lib/api/schemas/assets.js.map +1 -0
- package/dist/lib/api/schemas/documents.d.ts +325 -0
- package/dist/lib/api/schemas/documents.d.ts.map +1 -0
- package/dist/lib/api/schemas/documents.js +162 -0
- package/dist/lib/api/schemas/documents.js.map +1 -0
- package/dist/lib/api/schemas/organizations.d.ts +41 -0
- package/dist/lib/api/schemas/organizations.d.ts.map +1 -0
- package/dist/lib/api/schemas/organizations.js +57 -0
- package/dist/lib/api/schemas/organizations.js.map +1 -0
- package/dist/lib/api/schemas/roles.d.ts +77 -0
- package/dist/lib/api/schemas/roles.d.ts.map +1 -0
- package/dist/lib/api/schemas/roles.js +43 -0
- package/dist/lib/api/schemas/roles.js.map +1 -0
- package/dist/lib/api/schemas/user.d.ts +10 -0
- package/dist/lib/api/schemas/user.d.ts.map +1 -0
- package/dist/lib/api/schemas/user.js +12 -0
- package/dist/lib/api/schemas/user.js.map +1 -0
- package/dist/lib/api/user.d.ts +4 -6
- package/dist/lib/api/user.d.ts.map +1 -1
- package/dist/lib/api/user.js.map +1 -1
- package/dist/lib/app-augment.d.ts +32 -0
- package/dist/lib/app-augment.d.ts.map +1 -0
- package/dist/lib/app-augment.js +19 -0
- package/dist/lib/app-augment.js.map +1 -0
- package/dist/lib/auth/auth-hooks.d.ts +2 -1
- package/dist/lib/auth/auth-hooks.d.ts.map +1 -1
- package/dist/lib/auth/auth-hooks.js +22 -2
- package/dist/lib/auth/auth-hooks.js.map +1 -1
- package/dist/lib/auth/provider.d.ts +5 -0
- package/dist/lib/auth/provider.d.ts.map +1 -1
- package/dist/lib/client/index.d.ts +4 -0
- package/dist/lib/client/index.d.ts.map +1 -1
- package/dist/lib/client/index.js +7 -0
- package/dist/lib/client/index.js.map +1 -1
- package/dist/lib/components/admin/confirm-dialog/confirm-dialog.svelte.d.ts +16 -0
- package/dist/lib/components/admin/confirm-dialog/confirm-dialog.svelte.d.ts.map +1 -0
- package/dist/lib/components/admin/confirm-dialog/confirm-dialog.svelte.js +30 -0
- package/dist/lib/components/admin/confirm-dialog/confirm-dialog.svelte.js.map +1 -0
- package/dist/lib/db/interfaces/document.d.ts.map +1 -1
- package/dist/lib/db/interfaces/index.d.ts +3 -1
- package/dist/lib/db/interfaces/index.d.ts.map +1 -1
- package/dist/lib/db/interfaces/organization.d.ts +1 -1
- package/dist/lib/db/interfaces/organization.d.ts.map +1 -1
- package/dist/lib/db/interfaces/role.d.ts +25 -0
- package/dist/lib/db/interfaces/role.d.ts.map +1 -0
- package/dist/lib/db/interfaces/role.js +2 -0
- package/dist/lib/db/interfaces/role.js.map +1 -0
- package/dist/lib/engine.d.ts.map +1 -1
- package/dist/lib/engine.js +5 -0
- package/dist/lib/engine.js.map +1 -1
- package/dist/lib/field-access.d.ts +30 -0
- package/dist/lib/field-access.d.ts.map +1 -0
- package/dist/lib/field-access.js +80 -0
- package/dist/lib/field-access.js.map +1 -0
- package/dist/lib/hooks.d.ts +2 -0
- package/dist/lib/hooks.d.ts.map +1 -1
- package/dist/lib/hooks.js +23 -13
- package/dist/lib/hooks.js.map +1 -1
- package/dist/lib/local-api/collection-api.d.ts +2 -0
- package/dist/lib/local-api/collection-api.d.ts.map +1 -1
- package/dist/lib/local-api/collection-api.js +98 -30
- package/dist/lib/local-api/collection-api.js.map +1 -1
- package/dist/lib/local-api/index.d.ts.map +1 -1
- package/dist/lib/local-api/index.js.map +1 -1
- package/dist/lib/local-api/permissions.d.ts +26 -26
- package/dist/lib/local-api/permissions.d.ts.map +1 -1
- package/dist/lib/local-api/permissions.js +122 -80
- package/dist/lib/local-api/permissions.js.map +1 -1
- package/dist/lib/permissions-context.svelte.d.ts +44 -0
- package/dist/lib/permissions-context.svelte.d.ts.map +1 -0
- package/dist/lib/permissions-context.svelte.js +80 -0
- package/dist/lib/permissions-context.svelte.js.map +1 -0
- package/dist/lib/routes/assets-bulk.d.ts.map +1 -1
- package/dist/lib/routes/assets-bulk.js +10 -3
- package/dist/lib/routes/assets-bulk.js.map +1 -1
- package/dist/lib/routes/assets-by-id.d.ts.map +1 -1
- package/dist/lib/routes/assets-by-id.js +11 -1
- package/dist/lib/routes/assets-by-id.js.map +1 -1
- package/dist/lib/routes/assets-references-counts.d.ts.map +1 -1
- package/dist/lib/routes/assets-references-counts.js +12 -2
- package/dist/lib/routes/assets-references-counts.js.map +1 -1
- package/dist/lib/routes/assets.d.ts.map +1 -1
- package/dist/lib/routes/assets.js +14 -13
- package/dist/lib/routes/assets.js.map +1 -1
- package/dist/lib/routes/document-versions.d.ts.map +1 -1
- package/dist/lib/routes/document-versions.js +16 -2
- package/dist/lib/routes/document-versions.js.map +1 -1
- package/dist/lib/routes/documents-by-id.d.ts.map +1 -1
- package/dist/lib/routes/documents-by-id.js +15 -3
- package/dist/lib/routes/documents-by-id.js.map +1 -1
- package/dist/lib/routes/documents-query.d.ts.map +1 -1
- package/dist/lib/routes/documents-query.js +13 -10
- package/dist/lib/routes/documents-query.js.map +1 -1
- package/dist/lib/routes/documents.d.ts.map +1 -1
- package/dist/lib/routes/documents.js +29 -26
- package/dist/lib/routes/documents.js.map +1 -1
- package/dist/lib/routes/organizations-by-id.d.ts.map +1 -1
- package/dist/lib/routes/organizations-by-id.js +17 -4
- package/dist/lib/routes/organizations-by-id.js.map +1 -1
- package/dist/lib/routes/organizations-invitations.d.ts.map +1 -1
- package/dist/lib/routes/organizations-invitations.js +48 -18
- package/dist/lib/routes/organizations-invitations.js.map +1 -1
- package/dist/lib/routes/organizations-members.d.ts.map +1 -1
- package/dist/lib/routes/organizations-members.js +24 -18
- package/dist/lib/routes/organizations-members.js.map +1 -1
- package/dist/lib/routes/organizations-switch.d.ts.map +1 -1
- package/dist/lib/routes/organizations-switch.js +7 -3
- package/dist/lib/routes/organizations-switch.js.map +1 -1
- package/dist/lib/routes/organizations.d.ts.map +1 -1
- package/dist/lib/routes/organizations.js +11 -5
- package/dist/lib/routes/organizations.js.map +1 -1
- package/dist/lib/routes/roles-by-name.d.ts +4 -0
- package/dist/lib/routes/roles-by-name.d.ts.map +1 -0
- package/dist/lib/routes/roles-by-name.js +112 -0
- package/dist/lib/routes/roles-by-name.js.map +1 -0
- package/dist/lib/routes/roles.d.ts +4 -0
- package/dist/lib/routes/roles.d.ts.map +1 -0
- package/dist/lib/routes/roles.js +91 -0
- package/dist/lib/routes/roles.js.map +1 -0
- package/dist/lib/routes/user-preferences.d.ts.map +1 -1
- package/dist/lib/routes/user-preferences.js +7 -13
- package/dist/lib/routes/user-preferences.js.map +1 -1
- package/dist/lib/routes-exports.d.ts +2 -0
- package/dist/lib/routes-exports.d.ts.map +1 -1
- package/dist/lib/routes-exports.js +3 -0
- package/dist/lib/routes-exports.js.map +1 -1
- package/dist/lib/save-state-context.svelte.d.ts +8 -0
- package/dist/lib/save-state-context.svelte.d.ts.map +1 -0
- package/dist/lib/save-state-context.svelte.js +9 -0
- package/dist/lib/save-state-context.svelte.js.map +1 -0
- package/dist/lib/schema-utils/validator.d.ts.map +1 -1
- package/dist/lib/schema-utils/validator.js +14 -0
- package/dist/lib/schema-utils/validator.js.map +1 -1
- package/dist/lib/server/index.d.ts +1 -0
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/index.js +1 -0
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/services/index.d.ts +1 -0
- package/dist/lib/services/index.d.ts.map +1 -1
- package/dist/lib/services/index.js +1 -0
- package/dist/lib/services/index.js.map +1 -1
- package/dist/lib/services/roles-service.d.ts +35 -0
- package/dist/lib/services/roles-service.d.ts.map +1 -0
- package/dist/lib/services/roles-service.js +91 -0
- package/dist/lib/services/roles-service.js.map +1 -0
- package/dist/lib/services/version-service.d.ts.map +1 -1
- package/dist/lib/services/version-service.js.map +1 -1
- package/dist/lib/types/auth.d.ts +43 -9
- package/dist/lib/types/auth.d.ts.map +1 -1
- package/dist/lib/types/auth.js +31 -26
- package/dist/lib/types/auth.js.map +1 -1
- package/dist/lib/types/capabilities.d.ts +104 -0
- package/dist/lib/types/capabilities.d.ts.map +1 -0
- package/dist/lib/types/capabilities.js +217 -0
- package/dist/lib/types/capabilities.js.map +1 -0
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/lib/types/index.d.ts.map +1 -1
- package/dist/lib/types/index.js +1 -0
- package/dist/lib/types/index.js.map +1 -1
- package/dist/lib/types/organization.d.ts +13 -4
- package/dist/lib/types/organization.d.ts.map +1 -1
- package/dist/lib/types/schemas.d.ts +71 -0
- package/dist/lib/types/schemas.d.ts.map +1 -1
- package/dist/lib/types/sidebar.d.ts +1 -1
- package/dist/lib/types/sidebar.d.ts.map +1 -1
- package/dist/lib/utils/mime-detect.d.ts.map +1 -1
- package/dist/lib/utils/mime-detect.js +28 -6
- package/dist/lib/utils/mime-detect.js.map +1 -1
- package/dist/local-api/collection-api.d.ts +2 -0
- package/dist/local-api/collection-api.d.ts.map +1 -1
- package/dist/local-api/collection-api.js +98 -30
- package/dist/local-api/index.d.ts.map +1 -1
- package/dist/local-api/permissions.d.ts +26 -26
- package/dist/local-api/permissions.d.ts.map +1 -1
- package/dist/local-api/permissions.js +122 -80
- package/dist/permissions-context.svelte.d.ts +44 -0
- package/dist/permissions-context.svelte.d.ts.map +1 -0
- package/dist/permissions-context.svelte.js +79 -0
- package/dist/plugins/README.md +20 -20
- package/dist/routes/assets-bulk.d.ts.map +1 -1
- package/dist/routes/assets-bulk.js +10 -3
- package/dist/routes/assets-by-id.d.ts.map +1 -1
- package/dist/routes/assets-by-id.js +11 -1
- package/dist/routes/assets-references-counts.d.ts.map +1 -1
- package/dist/routes/assets-references-counts.js +12 -2
- package/dist/routes/assets.d.ts.map +1 -1
- package/dist/routes/assets.js +14 -13
- package/dist/routes/document-versions.d.ts.map +1 -1
- package/dist/routes/document-versions.js +16 -2
- package/dist/routes/documents-by-id.d.ts.map +1 -1
- package/dist/routes/documents-by-id.js +15 -3
- package/dist/routes/documents-query.d.ts.map +1 -1
- package/dist/routes/documents-query.js +13 -10
- package/dist/routes/documents.d.ts.map +1 -1
- package/dist/routes/documents.js +29 -26
- package/dist/routes/organizations-by-id.d.ts.map +1 -1
- package/dist/routes/organizations-by-id.js +17 -4
- package/dist/routes/organizations-invitations.d.ts.map +1 -1
- package/dist/routes/organizations-invitations.js +48 -18
- package/dist/routes/organizations-members.d.ts.map +1 -1
- package/dist/routes/organizations-members.js +24 -18
- package/dist/routes/organizations-switch.d.ts.map +1 -1
- package/dist/routes/organizations-switch.js +7 -3
- package/dist/routes/organizations.d.ts.map +1 -1
- package/dist/routes/organizations.js +11 -5
- package/dist/routes/roles-by-name.d.ts +4 -0
- package/dist/routes/roles-by-name.d.ts.map +1 -0
- package/dist/routes/roles-by-name.js +111 -0
- package/dist/routes/roles.d.ts +4 -0
- package/dist/routes/roles.d.ts.map +1 -0
- package/dist/routes/roles.js +90 -0
- package/dist/routes/user-preferences.d.ts.map +1 -1
- package/dist/routes/user-preferences.js +7 -13
- package/dist/routes-exports.d.ts +2 -0
- package/dist/routes-exports.d.ts.map +1 -1
- package/dist/routes-exports.js +3 -0
- package/dist/save-state-context.svelte.d.ts +8 -0
- package/dist/save-state-context.svelte.d.ts.map +1 -0
- package/dist/save-state-context.svelte.js +8 -0
- package/dist/schema-utils/validator.d.ts.map +1 -1
- package/dist/schema-utils/validator.js +14 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +1 -0
- package/dist/services/roles-service.d.ts +35 -0
- package/dist/services/roles-service.d.ts.map +1 -0
- package/dist/services/roles-service.js +90 -0
- package/dist/services/version-service.d.ts.map +1 -1
- package/dist/types/auth.d.ts +43 -9
- package/dist/types/auth.d.ts.map +1 -1
- package/dist/types/auth.js +31 -26
- package/dist/types/capabilities.d.ts +104 -0
- package/dist/types/capabilities.d.ts.map +1 -0
- package/dist/types/capabilities.js +216 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/organization.d.ts +13 -4
- package/dist/types/organization.d.ts.map +1 -1
- package/dist/types/schemas.d.ts +71 -0
- package/dist/types/schemas.d.ts.map +1 -1
- package/dist/types/sidebar.d.ts +1 -1
- package/dist/types/sidebar.d.ts.map +1 -1
- package/dist/utils/mime-detect.d.ts.map +1 -1
- package/dist/utils/mime-detect.js +28 -6
- package/package.json +142 -138
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// Aphex CMS Organization Invitations API Handlers
|
|
2
2
|
import { json } from '@sveltejs/kit';
|
|
3
3
|
import { cmsLogger } from '../utils/logger.js';
|
|
4
|
+
import { inviteMemberRequest, cancelInvitationRequest } from '../api/schemas/organizations.js';
|
|
5
|
+
import { hasCapability } from '../types/capabilities.js';
|
|
4
6
|
// POST /api/organizations/invitations - Create/send an invitation
|
|
5
7
|
export const POST = async ({ request, locals }) => {
|
|
6
8
|
try {
|
|
@@ -13,31 +15,57 @@ export const POST = async ({ request, locals }) => {
|
|
|
13
15
|
message: 'Session authentication required'
|
|
14
16
|
}, { status: 401 });
|
|
15
17
|
}
|
|
16
|
-
|
|
17
|
-
if (auth.organizationRole !== 'owner' && auth.organizationRole !== 'admin') {
|
|
18
|
+
if (!hasCapability(auth, 'member.invite')) {
|
|
18
19
|
return json({
|
|
19
20
|
success: false,
|
|
20
21
|
error: 'Forbidden',
|
|
21
|
-
message: '
|
|
22
|
+
message: 'You do not have permission to invite members'
|
|
22
23
|
}, { status: 403 });
|
|
23
24
|
}
|
|
24
|
-
const
|
|
25
|
-
|
|
25
|
+
const rawBody = await request.json();
|
|
26
|
+
const parsed = inviteMemberRequest.safeParse(rawBody);
|
|
27
|
+
if (!parsed.success) {
|
|
26
28
|
return json({
|
|
27
29
|
success: false,
|
|
28
|
-
error: '
|
|
29
|
-
message: 'email and role are required'
|
|
30
|
+
error: 'Invalid request body',
|
|
31
|
+
message: 'email and role are required',
|
|
32
|
+
issues: parsed.error.issues
|
|
30
33
|
}, { status: 400 });
|
|
31
34
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
const body = parsed.data;
|
|
36
|
+
// Verify the role exists in this organization. Defends against
|
|
37
|
+
// clients sending a role name that was deleted between page load
|
|
38
|
+
// and submit, or against typos slipping past the format regex.
|
|
39
|
+
const roleRow = await databaseAdapter.findRoleByName(auth.organizationId, body.role);
|
|
40
|
+
if (!roleRow) {
|
|
35
41
|
return json({
|
|
36
42
|
success: false,
|
|
37
|
-
error: '
|
|
38
|
-
message:
|
|
43
|
+
error: 'Unknown role',
|
|
44
|
+
message: `No role named "${body.role}" in this organization`
|
|
39
45
|
}, { status: 400 });
|
|
40
46
|
}
|
|
47
|
+
// Reject self-invitation
|
|
48
|
+
if (body.email.toLowerCase() === auth.user.email.toLowerCase()) {
|
|
49
|
+
return json({
|
|
50
|
+
success: false,
|
|
51
|
+
error: 'Invalid invitation',
|
|
52
|
+
message: 'You cannot invite yourself'
|
|
53
|
+
}, { status: 400 });
|
|
54
|
+
}
|
|
55
|
+
// Reject if the invitee is already a member of the organization
|
|
56
|
+
if (locals.aphexCMS.auth) {
|
|
57
|
+
const existingUser = await locals.aphexCMS.auth.getUserByEmail(body.email);
|
|
58
|
+
if (existingUser) {
|
|
59
|
+
const existingMembership = await databaseAdapter.findUserMembership(existingUser.id, auth.organizationId);
|
|
60
|
+
if (existingMembership) {
|
|
61
|
+
return json({
|
|
62
|
+
success: false,
|
|
63
|
+
error: 'Already a member',
|
|
64
|
+
message: 'This user is already a member of the organization'
|
|
65
|
+
}, { status: 400 });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
41
69
|
// Check if there's already a pending invitation for this email
|
|
42
70
|
const existingInvitations = await databaseAdapter.findOrganizationInvitations(auth.organizationId);
|
|
43
71
|
const pendingInvitation = existingInvitations.find((inv) => inv.email.toLowerCase() === body.email.toLowerCase() && inv.acceptedAt === null);
|
|
@@ -86,22 +114,24 @@ export const DELETE = async ({ request, locals }) => {
|
|
|
86
114
|
message: 'Session authentication required'
|
|
87
115
|
}, { status: 401 });
|
|
88
116
|
}
|
|
89
|
-
|
|
90
|
-
if (auth.organizationRole !== 'owner' && auth.organizationRole !== 'admin') {
|
|
117
|
+
if (!hasCapability(auth, 'member.invite')) {
|
|
91
118
|
return json({
|
|
92
119
|
success: false,
|
|
93
120
|
error: 'Forbidden',
|
|
94
|
-
message: '
|
|
121
|
+
message: 'You do not have permission to cancel invitations'
|
|
95
122
|
}, { status: 403 });
|
|
96
123
|
}
|
|
97
|
-
const
|
|
98
|
-
|
|
124
|
+
const rawBody = await request.json();
|
|
125
|
+
const parsed = cancelInvitationRequest.safeParse(rawBody);
|
|
126
|
+
if (!parsed.success) {
|
|
99
127
|
return json({
|
|
100
128
|
success: false,
|
|
101
129
|
error: 'Missing required field',
|
|
102
|
-
message: 'invitationId is required'
|
|
130
|
+
message: 'invitationId is required',
|
|
131
|
+
issues: parsed.error.issues
|
|
103
132
|
}, { status: 400 });
|
|
104
133
|
}
|
|
134
|
+
const body = parsed.data;
|
|
105
135
|
// Delete the invitation
|
|
106
136
|
const deleted = await databaseAdapter.deleteInvitation(body.invitationId);
|
|
107
137
|
if (!deleted) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"organizations-members.d.ts","sourceRoot":"","sources":["../../src/lib/routes/organizations-members.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"organizations-members.d.ts","sourceRoot":"","sources":["../../src/lib/routes/organizations-members.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAMpD,eAAO,MAAM,GAAG,EAAE,cAkCjB,CAAC;AAGF,eAAO,MAAM,MAAM,EAAE,cAoIpB,CAAC;AAGF,eAAO,MAAM,KAAK,EAAE,cA6HnB,CAAC"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// Aphex CMS Organization Members API Handlers
|
|
2
2
|
import { json } from '@sveltejs/kit';
|
|
3
3
|
import { cmsLogger } from '../utils/logger.js';
|
|
4
|
+
import { removeMemberRequest, updateMemberRoleRequest } from '../api/schemas/organizations.js';
|
|
5
|
+
import { hasCapability } from '../types/capabilities.js';
|
|
4
6
|
// GET /api/organizations/members - List organization members
|
|
5
7
|
export const GET = async ({ locals }) => {
|
|
6
8
|
try {
|
|
@@ -41,22 +43,24 @@ export const DELETE = async ({ request, locals }) => {
|
|
|
41
43
|
message: 'Session authentication required'
|
|
42
44
|
}, { status: 401 });
|
|
43
45
|
}
|
|
44
|
-
|
|
45
|
-
if (auth.organizationRole !== 'owner' && auth.organizationRole !== 'admin') {
|
|
46
|
+
if (!hasCapability(auth, 'member.remove')) {
|
|
46
47
|
return json({
|
|
47
48
|
success: false,
|
|
48
49
|
error: 'Forbidden',
|
|
49
|
-
message: '
|
|
50
|
+
message: 'You do not have permission to remove members'
|
|
50
51
|
}, { status: 403 });
|
|
51
52
|
}
|
|
52
|
-
const
|
|
53
|
-
|
|
53
|
+
const rawBody = await request.json();
|
|
54
|
+
const parsed = removeMemberRequest.safeParse(rawBody);
|
|
55
|
+
if (!parsed.success) {
|
|
54
56
|
return json({
|
|
55
57
|
success: false,
|
|
56
58
|
error: 'Missing required field',
|
|
57
|
-
message: 'userId is required'
|
|
59
|
+
message: 'userId is required',
|
|
60
|
+
issues: parsed.error.issues
|
|
58
61
|
}, { status: 400 });
|
|
59
62
|
}
|
|
63
|
+
const body = parsed.data;
|
|
60
64
|
// Prevent removing yourself
|
|
61
65
|
if (body.userId === auth.user.id) {
|
|
62
66
|
return json({
|
|
@@ -133,29 +137,31 @@ export const PATCH = async ({ request, locals }) => {
|
|
|
133
137
|
message: 'Session authentication required'
|
|
134
138
|
}, { status: 401 });
|
|
135
139
|
}
|
|
136
|
-
|
|
137
|
-
if (auth.organizationRole !== 'owner' && auth.organizationRole !== 'admin') {
|
|
140
|
+
if (!hasCapability(auth, 'member.changeRole')) {
|
|
138
141
|
return json({
|
|
139
142
|
success: false,
|
|
140
143
|
error: 'Forbidden',
|
|
141
|
-
message: '
|
|
144
|
+
message: 'You do not have permission to change member roles'
|
|
142
145
|
}, { status: 403 });
|
|
143
146
|
}
|
|
144
|
-
const
|
|
145
|
-
|
|
147
|
+
const rawBody = await request.json();
|
|
148
|
+
const parsed = updateMemberRoleRequest.safeParse(rawBody);
|
|
149
|
+
if (!parsed.success) {
|
|
146
150
|
return json({
|
|
147
151
|
success: false,
|
|
148
|
-
error: '
|
|
149
|
-
message: 'userId and role are required'
|
|
152
|
+
error: 'Invalid request body',
|
|
153
|
+
message: 'userId and role are required',
|
|
154
|
+
issues: parsed.error.issues
|
|
150
155
|
}, { status: 400 });
|
|
151
156
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
157
|
+
const body = parsed.data;
|
|
158
|
+
// Verify the target role exists in this organization.
|
|
159
|
+
const roleRow = await databaseAdapter.findRoleByName(auth.organizationId, body.role);
|
|
160
|
+
if (!roleRow) {
|
|
155
161
|
return json({
|
|
156
162
|
success: false,
|
|
157
|
-
error: '
|
|
158
|
-
message:
|
|
163
|
+
error: 'Unknown role',
|
|
164
|
+
message: `No role named "${body.role}" in this organization`
|
|
159
165
|
}, { status: 400 });
|
|
160
166
|
}
|
|
161
167
|
// Prevent changing your own role
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"organizations-switch.d.ts","sourceRoot":"","sources":["../../src/lib/routes/organizations-switch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"organizations-switch.d.ts","sourceRoot":"","sources":["../../src/lib/routes/organizations-switch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,eAAO,MAAM,IAAI,EAAE,cAsElB,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Aphex CMS Organization Switch API Handler
|
|
2
2
|
import { json } from '@sveltejs/kit';
|
|
3
3
|
import { cmsLogger } from '../utils/logger.js';
|
|
4
|
+
import { switchOrganizationRequest } from '../api/schemas/organizations.js';
|
|
4
5
|
// POST /api/organizations/switch - Switch active organization
|
|
5
6
|
export const POST = async ({ request, locals }) => {
|
|
6
7
|
try {
|
|
@@ -13,14 +14,17 @@ export const POST = async ({ request, locals }) => {
|
|
|
13
14
|
message: 'Session authentication required'
|
|
14
15
|
}, { status: 401 });
|
|
15
16
|
}
|
|
16
|
-
const
|
|
17
|
-
|
|
17
|
+
const rawBody = await request.json();
|
|
18
|
+
const parsed = switchOrganizationRequest.safeParse(rawBody);
|
|
19
|
+
if (!parsed.success) {
|
|
18
20
|
return json({
|
|
19
21
|
success: false,
|
|
20
22
|
error: 'Missing required field',
|
|
21
|
-
message: 'organizationId is required'
|
|
23
|
+
message: 'organizationId is required',
|
|
24
|
+
issues: parsed.error.issues
|
|
22
25
|
}, { status: 400 });
|
|
23
26
|
}
|
|
27
|
+
const body = parsed.data;
|
|
24
28
|
// Verify user is a member of the target organization
|
|
25
29
|
const membership = await databaseAdapter.findUserMembership(auth.user.id, body.organizationId);
|
|
26
30
|
if (!membership) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"organizations.d.ts","sourceRoot":"","sources":["../../src/lib/routes/organizations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"organizations.d.ts","sourceRoot":"","sources":["../../src/lib/routes/organizations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,eAAO,MAAM,GAAG,EAAE,cA6CjB,CAAC;AAGF,eAAO,MAAM,IAAI,EAAE,cAkGlB,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Aphex CMS Organization API Handlers
|
|
2
2
|
import { json } from '@sveltejs/kit';
|
|
3
3
|
import { cmsLogger } from '../utils/logger.js';
|
|
4
|
+
import { createOrganizationRequest } from '../api/schemas/organizations.js';
|
|
4
5
|
// GET /api/organizations - List user's organizations
|
|
5
6
|
export const GET = async ({ locals }) => {
|
|
6
7
|
try {
|
|
@@ -59,15 +60,17 @@ export const POST = async ({ request, locals }) => {
|
|
|
59
60
|
message: 'Only super admins can create organizations'
|
|
60
61
|
}, { status: 403 });
|
|
61
62
|
}
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
if (!
|
|
63
|
+
const rawBody = await request.json();
|
|
64
|
+
const parsed = createOrganizationRequest.safeParse(rawBody);
|
|
65
|
+
if (!parsed.success) {
|
|
65
66
|
return json({
|
|
66
67
|
success: false,
|
|
67
|
-
error: '
|
|
68
|
-
message: 'Organization name and slug are required'
|
|
68
|
+
error: 'Invalid request body',
|
|
69
|
+
message: 'Organization name and slug are required',
|
|
70
|
+
issues: parsed.error.issues
|
|
69
71
|
}, { status: 400 });
|
|
70
72
|
}
|
|
73
|
+
const body = parsed.data;
|
|
71
74
|
// Check if slug is already taken
|
|
72
75
|
const existingOrg = await databaseAdapter.findOrganizationBySlug(body.slug);
|
|
73
76
|
if (existingOrg) {
|
|
@@ -86,6 +89,9 @@ export const POST = async ({ request, locals }) => {
|
|
|
86
89
|
parentOrganizationId: auth.organizationId, // Current active org becomes parent
|
|
87
90
|
createdBy: auth.user.id
|
|
88
91
|
});
|
|
92
|
+
// Seed the four built-in roles for this org before assigning membership.
|
|
93
|
+
// The member row references the role by name, so the rows must exist.
|
|
94
|
+
await databaseAdapter.seedBuiltinRoles(newOrganization.id);
|
|
89
95
|
// Add the creator as owner
|
|
90
96
|
await databaseAdapter.addMember({
|
|
91
97
|
organizationId: newOrganization.id,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roles-by-name.d.ts","sourceRoot":"","sources":["../../src/lib/routes/roles-by-name.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAgBpD,eAAO,MAAM,KAAK,EAAE,cA4DnB,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,cAoEpB,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// Aphex CMS Roles API Handlers (by-name)
|
|
2
|
+
//
|
|
3
|
+
// PATCH /api/roles/[name] — edit description / capabilities
|
|
4
|
+
// DELETE /api/roles/[name] — delete a custom role (built-ins cannot be deleted)
|
|
5
|
+
import { json } from '@sveltejs/kit';
|
|
6
|
+
import { cmsLogger } from '../utils/logger.js';
|
|
7
|
+
import { hasCapability, BUILTIN_ROLE_NAMES } from '../types/capabilities.js';
|
|
8
|
+
import { updateRoleRequest } from '../api/schemas/roles.js';
|
|
9
|
+
function unauthorized() {
|
|
10
|
+
return json({ success: false, error: 'Unauthorized', message: 'Session authentication required' }, { status: 401 });
|
|
11
|
+
}
|
|
12
|
+
function forbidden(message) {
|
|
13
|
+
return json({ success: false, error: 'Forbidden', message }, { status: 403 });
|
|
14
|
+
}
|
|
15
|
+
export const PATCH = async ({ params, request, locals }) => {
|
|
16
|
+
try {
|
|
17
|
+
const { databaseAdapter, rolesService } = locals.aphexCMS;
|
|
18
|
+
const auth = locals.auth;
|
|
19
|
+
if (!auth || auth.type !== 'session')
|
|
20
|
+
return unauthorized();
|
|
21
|
+
if (!hasCapability(auth, 'role.manage')) {
|
|
22
|
+
return forbidden('You do not have permission to manage roles');
|
|
23
|
+
}
|
|
24
|
+
const name = params.name;
|
|
25
|
+
if (!name) {
|
|
26
|
+
return json({ success: false, error: 'Invalid request', message: 'Role name is required' }, { status: 400 });
|
|
27
|
+
}
|
|
28
|
+
const rawBody = await request.json();
|
|
29
|
+
const parsed = updateRoleRequest.safeParse(rawBody);
|
|
30
|
+
if (!parsed.success) {
|
|
31
|
+
return json({
|
|
32
|
+
success: false,
|
|
33
|
+
error: 'Invalid request body',
|
|
34
|
+
issues: parsed.error.issues
|
|
35
|
+
}, { status: 400 });
|
|
36
|
+
}
|
|
37
|
+
const body = parsed.data;
|
|
38
|
+
const updated = await databaseAdapter.updateRole(auth.organizationId, name, body);
|
|
39
|
+
if (!updated) {
|
|
40
|
+
return json({
|
|
41
|
+
success: false,
|
|
42
|
+
error: 'Not found',
|
|
43
|
+
message: `No role named "${name}" in this organization`
|
|
44
|
+
}, { status: 404 });
|
|
45
|
+
}
|
|
46
|
+
// Bust the capability cache so open sessions pick up the change on
|
|
47
|
+
// their next request instead of waiting for TTL.
|
|
48
|
+
await rolesService.invalidate(auth.organizationId, name);
|
|
49
|
+
return json({ success: true, data: updated });
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
cmsLogger.error('Failed to update role:', error);
|
|
53
|
+
return json({
|
|
54
|
+
success: false,
|
|
55
|
+
error: 'Failed to update role',
|
|
56
|
+
message: error instanceof Error ? error.message : 'Unknown error'
|
|
57
|
+
}, { status: 500 });
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
export const DELETE = async ({ params, locals }) => {
|
|
61
|
+
try {
|
|
62
|
+
const { databaseAdapter, rolesService } = locals.aphexCMS;
|
|
63
|
+
const auth = locals.auth;
|
|
64
|
+
if (!auth || auth.type !== 'session')
|
|
65
|
+
return unauthorized();
|
|
66
|
+
if (!hasCapability(auth, 'role.manage')) {
|
|
67
|
+
return forbidden('You do not have permission to manage roles');
|
|
68
|
+
}
|
|
69
|
+
const name = params.name;
|
|
70
|
+
if (!name) {
|
|
71
|
+
return json({ success: false, error: 'Invalid request', message: 'Role name is required' }, { status: 400 });
|
|
72
|
+
}
|
|
73
|
+
// Built-ins are part of the org's guaranteed floor — deleting one
|
|
74
|
+
// would let a seed run re-create it with stale capabilities. Force the
|
|
75
|
+
// user to edit instead.
|
|
76
|
+
if (BUILTIN_ROLE_NAMES.includes(name)) {
|
|
77
|
+
return forbidden(`"${name}" is a built-in role and cannot be deleted.`);
|
|
78
|
+
}
|
|
79
|
+
// Block deletion while the role is assigned to any member or invitation.
|
|
80
|
+
// Avoids silently orphaning memberships to an unknown role name.
|
|
81
|
+
const members = await databaseAdapter.findOrganizationMembers(auth.organizationId);
|
|
82
|
+
const inUseByMember = members.some((m) => m.role === name);
|
|
83
|
+
const invitations = await databaseAdapter.findOrganizationInvitations(auth.organizationId);
|
|
84
|
+
const inUseByInvitation = invitations.some((i) => i.role === name && !i.acceptedAt);
|
|
85
|
+
if (inUseByMember || inUseByInvitation) {
|
|
86
|
+
return json({
|
|
87
|
+
success: false,
|
|
88
|
+
error: 'Role in use',
|
|
89
|
+
message: `Cannot delete "${name}": reassign affected members or invitations first.`
|
|
90
|
+
}, { status: 409 });
|
|
91
|
+
}
|
|
92
|
+
const deleted = await databaseAdapter.deleteRole(auth.organizationId, name);
|
|
93
|
+
if (!deleted) {
|
|
94
|
+
return json({
|
|
95
|
+
success: false,
|
|
96
|
+
error: 'Not found',
|
|
97
|
+
message: `No role named "${name}" in this organization`
|
|
98
|
+
}, { status: 404 });
|
|
99
|
+
}
|
|
100
|
+
await rolesService.invalidate(auth.organizationId, name);
|
|
101
|
+
return json({ success: true, message: 'Role deleted' });
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
cmsLogger.error('Failed to delete role:', error);
|
|
105
|
+
return json({
|
|
106
|
+
success: false,
|
|
107
|
+
error: 'Failed to delete role',
|
|
108
|
+
message: error instanceof Error ? error.message : 'Unknown error'
|
|
109
|
+
}, { status: 500 });
|
|
110
|
+
}
|
|
111
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roles.d.ts","sourceRoot":"","sources":["../../src/lib/routes/roles.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAgBpD,eAAO,MAAM,GAAG,EAAE,cAoBjB,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,cA0ElB,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// Aphex CMS Roles API Handlers
|
|
2
|
+
//
|
|
3
|
+
// GET /api/roles — list roles for the active org
|
|
4
|
+
// POST /api/roles — create a custom role (requires role.manage)
|
|
5
|
+
import { json } from '@sveltejs/kit';
|
|
6
|
+
import { cmsLogger } from '../utils/logger.js';
|
|
7
|
+
import { hasCapability, BUILTIN_ROLE_NAMES } from '../types/capabilities.js';
|
|
8
|
+
import { createRoleRequest } from '../api/schemas/roles.js';
|
|
9
|
+
function unauthorized() {
|
|
10
|
+
return json({ success: false, error: 'Unauthorized', message: 'Session authentication required' }, { status: 401 });
|
|
11
|
+
}
|
|
12
|
+
function forbidden(message) {
|
|
13
|
+
return json({ success: false, error: 'Forbidden', message }, { status: 403 });
|
|
14
|
+
}
|
|
15
|
+
export const GET = async ({ locals }) => {
|
|
16
|
+
try {
|
|
17
|
+
const { rolesService } = locals.aphexCMS;
|
|
18
|
+
const auth = locals.auth;
|
|
19
|
+
if (!auth || auth.type !== 'session')
|
|
20
|
+
return unauthorized();
|
|
21
|
+
const roles = await rolesService.listRoles(auth.organizationId);
|
|
22
|
+
return json({ success: true, data: roles });
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
cmsLogger.error('Failed to list roles:', error);
|
|
26
|
+
return json({
|
|
27
|
+
success: false,
|
|
28
|
+
error: 'Failed to list roles',
|
|
29
|
+
message: error instanceof Error ? error.message : 'Unknown error'
|
|
30
|
+
}, { status: 500 });
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
export const POST = async ({ request, locals }) => {
|
|
34
|
+
try {
|
|
35
|
+
const { databaseAdapter, rolesService } = locals.aphexCMS;
|
|
36
|
+
const auth = locals.auth;
|
|
37
|
+
if (!auth || auth.type !== 'session')
|
|
38
|
+
return unauthorized();
|
|
39
|
+
if (!hasCapability(auth, 'role.manage')) {
|
|
40
|
+
return forbidden('You do not have permission to manage roles');
|
|
41
|
+
}
|
|
42
|
+
const rawBody = await request.json();
|
|
43
|
+
const parsed = createRoleRequest.safeParse(rawBody);
|
|
44
|
+
if (!parsed.success) {
|
|
45
|
+
return json({
|
|
46
|
+
success: false,
|
|
47
|
+
error: 'Invalid request body',
|
|
48
|
+
message: 'name and capabilities are required',
|
|
49
|
+
issues: parsed.error.issues
|
|
50
|
+
}, { status: 400 });
|
|
51
|
+
}
|
|
52
|
+
const body = parsed.data;
|
|
53
|
+
// Reject collisions with reserved built-in names — built-ins are seeded
|
|
54
|
+
// on every org; a matching custom row would never be reachable.
|
|
55
|
+
if (BUILTIN_ROLE_NAMES.includes(body.name)) {
|
|
56
|
+
return json({
|
|
57
|
+
success: false,
|
|
58
|
+
error: 'Reserved name',
|
|
59
|
+
message: `"${body.name}" is a built-in role name. Edit the existing role instead.`
|
|
60
|
+
}, { status: 409 });
|
|
61
|
+
}
|
|
62
|
+
const existing = await databaseAdapter.findRoleByName(auth.organizationId, body.name);
|
|
63
|
+
if (existing) {
|
|
64
|
+
return json({
|
|
65
|
+
success: false,
|
|
66
|
+
error: 'Conflict',
|
|
67
|
+
message: `A role named "${body.name}" already exists in this organization.`
|
|
68
|
+
}, { status: 409 });
|
|
69
|
+
}
|
|
70
|
+
const role = await databaseAdapter.createRole({
|
|
71
|
+
organizationId: auth.organizationId,
|
|
72
|
+
name: body.name,
|
|
73
|
+
description: body.description ?? null,
|
|
74
|
+
capabilities: body.capabilities,
|
|
75
|
+
isBuiltIn: false
|
|
76
|
+
});
|
|
77
|
+
// New role can't be in use yet, but invalidate the prefix just in case
|
|
78
|
+
// a prior lookup populated the cache with an empty fallback entry.
|
|
79
|
+
await rolesService.invalidate(auth.organizationId, body.name);
|
|
80
|
+
return json({ success: true, data: role }, { status: 201 });
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
cmsLogger.error('Failed to create role:', error);
|
|
84
|
+
return json({
|
|
85
|
+
success: false,
|
|
86
|
+
error: 'Failed to create role',
|
|
87
|
+
message: error instanceof Error ? error.message : 'Unknown error'
|
|
88
|
+
}, { status: 500 });
|
|
89
|
+
}
|
|
90
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-preferences.d.ts","sourceRoot":"","sources":["../../src/lib/routes/user-preferences.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,eAAO,MAAM,GAAG,EAAE,cAiCjB,CAAC;AAGF,eAAO,MAAM,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"user-preferences.d.ts","sourceRoot":"","sources":["../../src/lib/routes/user-preferences.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,eAAO,MAAM,GAAG,EAAE,cAiCjB,CAAC;AAGF,eAAO,MAAM,KAAK,EAAE,cAoDnB,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Aphex CMS User Preferences API Handler
|
|
2
2
|
import { json } from '@sveltejs/kit';
|
|
3
3
|
import { cmsLogger } from '../utils/logger.js';
|
|
4
|
+
import { updateUserPreferencesRequest } from '../api/schemas/user.js';
|
|
4
5
|
// GET /api/user/preferences - Get user preferences
|
|
5
6
|
export const GET = async ({ locals }) => {
|
|
6
7
|
try {
|
|
@@ -40,24 +41,17 @@ export const PATCH = async ({ request, locals }) => {
|
|
|
40
41
|
message: 'Session authentication required'
|
|
41
42
|
}, { status: 401 });
|
|
42
43
|
}
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
if (
|
|
44
|
+
const rawBody = await request.json();
|
|
45
|
+
const parsed = updateUserPreferencesRequest.safeParse(rawBody);
|
|
46
|
+
if (!parsed.success) {
|
|
46
47
|
return json({
|
|
47
48
|
success: false,
|
|
48
49
|
error: 'Invalid request body',
|
|
49
|
-
message: '
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
// Validate individual preference types
|
|
53
|
-
if (body.includeChildOrganizations !== undefined &&
|
|
54
|
-
typeof body.includeChildOrganizations !== 'boolean') {
|
|
55
|
-
return json({
|
|
56
|
-
success: false,
|
|
57
|
-
error: 'Invalid preference value',
|
|
58
|
-
message: 'includeChildOrganizations must be a boolean'
|
|
50
|
+
message: 'Invalid preference values',
|
|
51
|
+
issues: parsed.error.issues
|
|
59
52
|
}, { status: 400 });
|
|
60
53
|
}
|
|
54
|
+
const body = parsed.data;
|
|
61
55
|
// Update preferences
|
|
62
56
|
await databaseAdapter.updateUserPreferences(auth.user.id, body);
|
|
63
57
|
// Get updated profile
|
package/dist/routes-exports.d.ts
CHANGED
|
@@ -15,4 +15,6 @@ export { GET as getOrganizationById, PATCH as updateOrganization, DELETE as dele
|
|
|
15
15
|
export { POST as switchOrganization } from './routes/organizations-switch.js';
|
|
16
16
|
export { GET as getOrganizationMembers, DELETE as removeMember, PATCH as updateMemberRole } from './routes/organizations-members.js';
|
|
17
17
|
export { POST as inviteMember, DELETE as cancelInvitation } from './routes/organizations-invitations.js';
|
|
18
|
+
export { GET as getRoles, POST as createRole } from './routes/roles.js';
|
|
19
|
+
export { PATCH as updateRole, DELETE as deleteRole } from './routes/roles-by-name.js';
|
|
18
20
|
//# sourceMappingURL=routes-exports.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes-exports.d.ts","sourceRoot":"","sources":["../src/lib/routes-exports.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,GAAG,IAAI,YAAY,EAAE,IAAI,IAAI,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EACN,GAAG,IAAI,eAAe,EACtB,GAAG,IAAI,cAAc,EACrB,MAAM,IAAI,cAAc,EACxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,IAAI,IAAI,eAAe,EAAE,MAAM,IAAI,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAClG,OAAO,EACN,GAAG,IAAI,mBAAmB,EAC1B,UAAU,IAAI,kBAAkB,EAChC,cAAc,IAAI,sBAAsB,EACxC,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EAAE,GAAG,IAAI,SAAS,EAAE,IAAI,IAAI,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EACN,GAAG,IAAI,YAAY,EACnB,KAAK,IAAI,WAAW,EACpB,MAAM,IAAI,WAAW,EACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,GAAG,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,MAAM,IAAI,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,GAAG,IAAI,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,IAAI,IAAI,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAGpF,OAAO,EAAE,GAAG,IAAI,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,GAAG,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,EAAE,GAAG,IAAI,gBAAgB,EAAE,IAAI,IAAI,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC7F,OAAO,EACN,GAAG,IAAI,mBAAmB,EAC1B,KAAK,IAAI,kBAAkB,EAC3B,MAAM,IAAI,kBAAkB,EAC5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,IAAI,IAAI,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EACN,GAAG,IAAI,sBAAsB,EAC7B,MAAM,IAAI,YAAY,EACtB,KAAK,IAAI,gBAAgB,EACzB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACN,IAAI,IAAI,YAAY,EACpB,MAAM,IAAI,gBAAgB,EAC1B,MAAM,oCAAoC,CAAC"}
|
|
1
|
+
{"version":3,"file":"routes-exports.d.ts","sourceRoot":"","sources":["../src/lib/routes-exports.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,GAAG,IAAI,YAAY,EAAE,IAAI,IAAI,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EACN,GAAG,IAAI,eAAe,EACtB,GAAG,IAAI,cAAc,EACrB,MAAM,IAAI,cAAc,EACxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,IAAI,IAAI,eAAe,EAAE,MAAM,IAAI,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAClG,OAAO,EACN,GAAG,IAAI,mBAAmB,EAC1B,UAAU,IAAI,kBAAkB,EAChC,cAAc,IAAI,sBAAsB,EACxC,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EAAE,GAAG,IAAI,SAAS,EAAE,IAAI,IAAI,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EACN,GAAG,IAAI,YAAY,EACnB,KAAK,IAAI,WAAW,EACpB,MAAM,IAAI,WAAW,EACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,GAAG,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,MAAM,IAAI,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,GAAG,IAAI,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,IAAI,IAAI,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAGpF,OAAO,EAAE,GAAG,IAAI,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,GAAG,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,EAAE,GAAG,IAAI,gBAAgB,EAAE,IAAI,IAAI,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC7F,OAAO,EACN,GAAG,IAAI,mBAAmB,EAC1B,KAAK,IAAI,kBAAkB,EAC3B,MAAM,IAAI,kBAAkB,EAC5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,IAAI,IAAI,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EACN,GAAG,IAAI,sBAAsB,EAC7B,MAAM,IAAI,YAAY,EACtB,KAAK,IAAI,gBAAgB,EACzB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACN,IAAI,IAAI,YAAY,EACpB,MAAM,IAAI,gBAAgB,EAC1B,MAAM,oCAAoC,CAAC;AAG5C,OAAO,EAAE,GAAG,IAAI,QAAQ,EAAE,IAAI,IAAI,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,EAAE,KAAK,IAAI,UAAU,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/routes-exports.js
CHANGED
|
@@ -21,3 +21,6 @@ export { GET as getOrganizationById, PATCH as updateOrganization, DELETE as dele
|
|
|
21
21
|
export { POST as switchOrganization } from './routes/organizations-switch.js';
|
|
22
22
|
export { GET as getOrganizationMembers, DELETE as removeMember, PATCH as updateMemberRole } from './routes/organizations-members.js';
|
|
23
23
|
export { POST as inviteMember, DELETE as cancelInvitation } from './routes/organizations-invitations.js';
|
|
24
|
+
// Role management routes
|
|
25
|
+
export { GET as getRoles, POST as createRole } from './routes/roles.js';
|
|
26
|
+
export { PATCH as updateRole, DELETE as deleteRole } from './routes/roles-by-name.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface SaveState {
|
|
2
|
+
readonly saving: boolean;
|
|
3
|
+
readonly hasUnsavedChanges: boolean;
|
|
4
|
+
readonly savedAgoText: string | null;
|
|
5
|
+
}
|
|
6
|
+
export declare function setSaveStateContext(state: SaveState): void;
|
|
7
|
+
export declare function getSaveStateContext(): SaveState | null;
|
|
8
|
+
//# sourceMappingURL=save-state-context.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save-state-context.svelte.d.ts","sourceRoot":"","sources":["../src/lib/save-state-context.svelte.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACzB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,QAEnD;AAED,wBAAgB,mBAAmB,IAAI,SAAS,GAAG,IAAI,CAEtD"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { getContext, setContext } from 'svelte';
|
|
2
|
+
const SAVE_STATE_KEY = Symbol('aphex-save-state');
|
|
3
|
+
export function setSaveStateContext(state) {
|
|
4
|
+
setContext(SAVE_STATE_KEY, state);
|
|
5
|
+
}
|
|
6
|
+
export function getSaveStateContext() {
|
|
7
|
+
return getContext(SAVE_STATE_KEY) ?? null;
|
|
8
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/lib/schema-utils/validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAS,MAAM,kBAAkB,CAAC;AAmB1D;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/lib/schema-utils/validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAS,MAAM,kBAAkB,CAAC;AAmB1D;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,CAqNpE"}
|
|
@@ -103,6 +103,20 @@ export function validateSchemaReferences(schemas) {
|
|
|
103
103
|
validateField(field, schema.name);
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
|
+
// Validate field.group references against schema.groups
|
|
107
|
+
if (schema.fields) {
|
|
108
|
+
const groupNames = new Set((schema.groups ?? []).map((g) => g.name));
|
|
109
|
+
for (const field of schema.fields) {
|
|
110
|
+
if (!field.group)
|
|
111
|
+
continue;
|
|
112
|
+
const refs = Array.isArray(field.group) ? field.group : [field.group];
|
|
113
|
+
for (const ref of refs) {
|
|
114
|
+
if (!groupNames.has(ref)) {
|
|
115
|
+
errors.push(`Schema "${schema.name}" field "${field.name}" references unknown group "${ref}". Declare it in schema.groups.`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
106
120
|
// Validate preview config references
|
|
107
121
|
if (schema.preview?.select) {
|
|
108
122
|
const fieldNames = new Set(schema.fields?.map((f) => f.name) || []);
|
package/dist/server/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export * from '../storage/interfaces/index.js';
|
|
|
12
12
|
export * from '../storage/providers/storage.js';
|
|
13
13
|
export * from '../services/index.js';
|
|
14
14
|
export { AssetService } from '../services/asset-service.js';
|
|
15
|
+
export { RolesService } from '../services/roles-service.js';
|
|
15
16
|
export * from '../routes-exports.js';
|
|
16
17
|
export * from '../schema-utils/index.js';
|
|
17
18
|
export { createHashForPublishing } from '../utils/content-hash.js';
|