@open-mercato/core 0.4.2-canary-36ab8921da → 0.4.2-canary-07dbc98202
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/dist/generated/entities/notification/index.js +57 -0
- package/dist/generated/entities/notification/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +63 -59
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +2 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/api_docs/frontend/docs/api/page.js +3 -2
- package/dist/modules/api_docs/frontend/docs/api/page.js.map +2 -2
- package/dist/modules/auth/api/admin/nav.js +4 -3
- package/dist/modules/auth/api/admin/nav.js.map +2 -2
- package/dist/modules/auth/api/profile/route.js +155 -0
- package/dist/modules/auth/api/profile/route.js.map +7 -0
- package/dist/modules/auth/api/reset/confirm.js +25 -2
- package/dist/modules/auth/api/reset/confirm.js.map +2 -2
- package/dist/modules/auth/api/reset.js +23 -0
- package/dist/modules/auth/api/reset.js.map +2 -2
- package/dist/modules/auth/api/sidebar/preferences/route.js +14 -9
- package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
- package/dist/modules/auth/backend/auth/profile/page.js +99 -0
- package/dist/modules/auth/backend/auth/profile/page.js.map +7 -0
- package/dist/modules/auth/backend/auth/profile/page.meta.js +12 -0
- package/dist/modules/auth/backend/auth/profile/page.meta.js.map +7 -0
- package/dist/modules/auth/commands/users.js +55 -0
- package/dist/modules/auth/commands/users.js.map +2 -2
- package/dist/modules/auth/lib/setup-app.js +1 -0
- package/dist/modules/auth/lib/setup-app.js.map +2 -2
- package/dist/modules/auth/notifications.js +112 -0
- package/dist/modules/auth/notifications.js.map +7 -0
- package/dist/modules/auth/services/authService.js +3 -3
- package/dist/modules/auth/services/authService.js.map +2 -2
- package/dist/modules/business_rules/notifications.js +28 -0
- package/dist/modules/business_rules/notifications.js.map +7 -0
- package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js +37 -0
- package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js.map +7 -0
- package/dist/modules/catalog/notifications.js +28 -0
- package/dist/modules/catalog/notifications.js.map +7 -0
- package/dist/modules/catalog/subscribers/low-stock-notification.js +38 -0
- package/dist/modules/catalog/subscribers/low-stock-notification.js.map +7 -0
- package/dist/modules/configs/cli.js +6 -0
- package/dist/modules/configs/cli.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +31 -0
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/notifications.js +48 -0
- package/dist/modules/customers/notifications.js.map +7 -0
- package/dist/modules/notifications/acl.js +11 -0
- package/dist/modules/notifications/acl.js.map +7 -0
- package/dist/modules/notifications/api/[id]/action/route.js +74 -0
- package/dist/modules/notifications/api/[id]/action/route.js.map +7 -0
- package/dist/modules/notifications/api/[id]/dismiss/route.js +15 -0
- package/dist/modules/notifications/api/[id]/dismiss/route.js.map +7 -0
- package/dist/modules/notifications/api/[id]/read/route.js +15 -0
- package/dist/modules/notifications/api/[id]/read/route.js.map +7 -0
- package/dist/modules/notifications/api/[id]/restore/route.js +53 -0
- package/dist/modules/notifications/api/[id]/restore/route.js.map +7 -0
- package/dist/modules/notifications/api/batch/route.js +17 -0
- package/dist/modules/notifications/api/batch/route.js.map +7 -0
- package/dist/modules/notifications/api/feature/route.js +17 -0
- package/dist/modules/notifications/api/feature/route.js.map +7 -0
- package/dist/modules/notifications/api/mark-all-read/route.js +35 -0
- package/dist/modules/notifications/api/mark-all-read/route.js.map +7 -0
- package/dist/modules/notifications/api/openapi.js +76 -0
- package/dist/modules/notifications/api/openapi.js.map +7 -0
- package/dist/modules/notifications/api/role/route.js +17 -0
- package/dist/modules/notifications/api/role/route.js.map +7 -0
- package/dist/modules/notifications/api/route.js +85 -0
- package/dist/modules/notifications/api/route.js.map +7 -0
- package/dist/modules/notifications/api/settings/route.js +155 -0
- package/dist/modules/notifications/api/settings/route.js.map +7 -0
- package/dist/modules/notifications/api/unread-count/route.js +38 -0
- package/dist/modules/notifications/api/unread-count/route.js.map +7 -0
- package/dist/modules/notifications/backend/config/notifications/page.js +10 -0
- package/dist/modules/notifications/backend/config/notifications/page.js.map +7 -0
- package/dist/modules/notifications/backend/config/notifications/page.meta.js +24 -0
- package/dist/modules/notifications/backend/config/notifications/page.meta.js.map +7 -0
- package/dist/modules/notifications/cli.js +16 -0
- package/dist/modules/notifications/cli.js.map +7 -0
- package/dist/modules/notifications/data/entities.js +112 -0
- package/dist/modules/notifications/data/entities.js.map +7 -0
- package/dist/modules/notifications/data/validators.js +94 -0
- package/dist/modules/notifications/data/validators.js.map +7 -0
- package/dist/modules/notifications/di.js +13 -0
- package/dist/modules/notifications/di.js.map +7 -0
- package/dist/modules/notifications/emails/NotificationEmail.js +58 -0
- package/dist/modules/notifications/emails/NotificationEmail.js.map +7 -0
- package/dist/modules/notifications/frontend/NotificationInboxPageClient.js +44 -0
- package/dist/modules/notifications/frontend/NotificationInboxPageClient.js.map +7 -0
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js +219 -0
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js.map +7 -0
- package/dist/modules/notifications/index.js +14 -0
- package/dist/modules/notifications/index.js.map +7 -0
- package/dist/modules/notifications/lib/deliveryConfig.js +105 -0
- package/dist/modules/notifications/lib/deliveryConfig.js.map +7 -0
- package/dist/modules/notifications/lib/events.js +12 -0
- package/dist/modules/notifications/lib/events.js.map +7 -0
- package/dist/modules/notifications/lib/notificationBuilder.js +66 -0
- package/dist/modules/notifications/lib/notificationBuilder.js.map +7 -0
- package/dist/modules/notifications/lib/notificationFactory.js +54 -0
- package/dist/modules/notifications/lib/notificationFactory.js.map +7 -0
- package/dist/modules/notifications/lib/notificationMapper.js +34 -0
- package/dist/modules/notifications/lib/notificationMapper.js.map +7 -0
- package/dist/modules/notifications/lib/notificationRecipients.js +35 -0
- package/dist/modules/notifications/lib/notificationRecipients.js.map +7 -0
- package/dist/modules/notifications/lib/notificationService.js +279 -0
- package/dist/modules/notifications/lib/notificationService.js.map +7 -0
- package/dist/modules/notifications/lib/routeHelpers.js +101 -0
- package/dist/modules/notifications/lib/routeHelpers.js.map +7 -0
- package/dist/modules/notifications/lib/safeHref.js +24 -0
- package/dist/modules/notifications/lib/safeHref.js.map +7 -0
- package/dist/modules/notifications/migrations/Migration20260123000001.js +70 -0
- package/dist/modules/notifications/migrations/Migration20260123000001.js.map +7 -0
- package/dist/modules/notifications/migrations/Migration20260126150000.js +37 -0
- package/dist/modules/notifications/migrations/Migration20260126150000.js.map +7 -0
- package/dist/modules/notifications/subscribers/deliver-notification.js +139 -0
- package/dist/modules/notifications/subscribers/deliver-notification.js.map +7 -0
- package/dist/modules/notifications/workers/create-notification.worker.js +70 -0
- package/dist/modules/notifications/workers/create-notification.worker.js.map +7 -0
- package/dist/modules/sales/commands/documents.js +53 -0
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/payments.js +26 -0
- package/dist/modules/sales/commands/payments.js.map +2 -2
- package/dist/modules/sales/notifications.client.js +51 -0
- package/dist/modules/sales/notifications.client.js.map +7 -0
- package/dist/modules/sales/notifications.js +88 -0
- package/dist/modules/sales/notifications.js.map +7 -0
- package/dist/modules/sales/subscribers/quote-expiring-notification.js +38 -0
- package/dist/modules/sales/subscribers/quote-expiring-notification.js.map +7 -0
- package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +137 -0
- package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +7 -0
- package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js +137 -0
- package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js.map +7 -0
- package/dist/modules/sales/widgets/notifications/index.js +7 -0
- package/dist/modules/sales/widgets/notifications/index.js.map +7 -0
- package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js +60 -0
- package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js.map +7 -0
- package/dist/modules/staff/commands/leave-requests.js +79 -0
- package/dist/modules/staff/commands/leave-requests.js.map +2 -2
- package/dist/modules/staff/notifications.js +75 -0
- package/dist/modules/staff/notifications.js.map +7 -0
- package/dist/modules/workflows/notifications.js +28 -0
- package/dist/modules/workflows/notifications.js.map +7 -0
- package/dist/modules/workflows/subscribers/task-assigned-notification.js +38 -0
- package/dist/modules/workflows/subscribers/task-assigned-notification.js.map +7 -0
- package/generated/entities/notification/index.ts +27 -0
- package/generated/entities.ids.generated.ts +63 -59
- package/generated/entity-fields-registry.ts +2 -0
- package/package.json +2 -2
- package/src/modules/api_docs/frontend/docs/api/page.tsx +3 -2
- package/src/modules/auth/api/admin/nav.ts +10 -6
- package/src/modules/auth/api/profile/route.ts +160 -0
- package/src/modules/auth/api/reset/confirm.ts +25 -2
- package/src/modules/auth/api/reset.ts +23 -0
- package/src/modules/auth/api/sidebar/preferences/route.ts +21 -12
- package/src/modules/auth/backend/auth/profile/page.meta.ts +8 -0
- package/src/modules/auth/backend/auth/profile/page.tsx +127 -0
- package/src/modules/auth/commands/users.ts +68 -0
- package/src/modules/auth/i18n/de.json +29 -1
- package/src/modules/auth/i18n/en.json +29 -1
- package/src/modules/auth/i18n/es.json +29 -1
- package/src/modules/auth/i18n/pl.json +29 -1
- package/src/modules/auth/lib/setup-app.ts +1 -0
- package/src/modules/auth/notifications.ts +109 -0
- package/src/modules/auth/services/authService.ts +4 -4
- package/src/modules/business_rules/i18n/en.json +3 -1
- package/src/modules/business_rules/notifications.ts +25 -0
- package/src/modules/business_rules/subscribers/rule-execution-failed-notification.ts +50 -0
- package/src/modules/catalog/i18n/en.json +3 -1
- package/src/modules/catalog/notifications.ts +25 -0
- package/src/modules/catalog/subscribers/low-stock-notification.ts +52 -0
- package/src/modules/configs/cli.ts +6 -0
- package/src/modules/customers/commands/deals.ts +39 -0
- package/src/modules/customers/i18n/en.json +5 -1
- package/src/modules/customers/notifications.ts +44 -0
- package/src/modules/notifications/acl.ts +7 -0
- package/src/modules/notifications/api/[id]/action/route.ts +75 -0
- package/src/modules/notifications/api/[id]/dismiss/route.ts +12 -0
- package/src/modules/notifications/api/[id]/read/route.ts +12 -0
- package/src/modules/notifications/api/[id]/restore/route.ts +53 -0
- package/src/modules/notifications/api/batch/route.ts +14 -0
- package/src/modules/notifications/api/feature/route.ts +14 -0
- package/src/modules/notifications/api/mark-all-read/route.ts +34 -0
- package/src/modules/notifications/api/openapi.ts +76 -0
- package/src/modules/notifications/api/role/route.ts +14 -0
- package/src/modules/notifications/api/route.ts +92 -0
- package/src/modules/notifications/api/settings/route.ts +157 -0
- package/src/modules/notifications/api/unread-count/route.ts +38 -0
- package/src/modules/notifications/backend/config/notifications/page.meta.ts +22 -0
- package/src/modules/notifications/backend/config/notifications/page.tsx +12 -0
- package/src/modules/notifications/cli.ts +18 -0
- package/src/modules/notifications/data/entities.ts +99 -0
- package/src/modules/notifications/data/validators.ts +110 -0
- package/src/modules/notifications/di.ts +11 -0
- package/src/modules/notifications/emails/NotificationEmail.tsx +98 -0
- package/src/modules/notifications/frontend/NotificationInboxPageClient.tsx +42 -0
- package/src/modules/notifications/frontend/NotificationSettingsPageClient.tsx +231 -0
- package/src/modules/notifications/i18n/de.json +50 -0
- package/src/modules/notifications/i18n/en.json +50 -0
- package/src/modules/notifications/i18n/es.json +50 -0
- package/src/modules/notifications/i18n/pl.json +50 -0
- package/src/modules/notifications/index.ts +12 -0
- package/src/modules/notifications/lib/deliveryConfig.ts +145 -0
- package/src/modules/notifications/lib/events.ts +48 -0
- package/src/modules/notifications/lib/notificationBuilder.ts +121 -0
- package/src/modules/notifications/lib/notificationFactory.ts +76 -0
- package/src/modules/notifications/lib/notificationMapper.ts +33 -0
- package/src/modules/notifications/lib/notificationRecipients.ts +83 -0
- package/src/modules/notifications/lib/notificationService.ts +414 -0
- package/src/modules/notifications/lib/routeHelpers.ts +151 -0
- package/src/modules/notifications/lib/safeHref.ts +29 -0
- package/src/modules/notifications/migrations/.snapshot-open-mercato.json +300 -0
- package/src/modules/notifications/migrations/Migration20260123000001.ts +73 -0
- package/src/modules/notifications/migrations/Migration20260126150000.ts +39 -0
- package/src/modules/notifications/subscribers/deliver-notification.ts +175 -0
- package/src/modules/notifications/workers/create-notification.worker.ts +122 -0
- package/src/modules/sales/commands/documents.ts +65 -0
- package/src/modules/sales/commands/payments.ts +33 -0
- package/src/modules/sales/i18n/de.json +20 -0
- package/src/modules/sales/i18n/en.json +25 -1
- package/src/modules/sales/i18n/es.json +20 -0
- package/src/modules/sales/i18n/pl.json +20 -0
- package/src/modules/sales/notifications.client.ts +65 -0
- package/src/modules/sales/notifications.ts +82 -0
- package/src/modules/sales/subscribers/quote-expiring-notification.ts +53 -0
- package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +156 -0
- package/src/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.tsx +156 -0
- package/src/modules/sales/widgets/notifications/index.ts +2 -0
- package/src/modules/sales/widgets/notifications/useSalesDocumentTotals.ts +81 -0
- package/src/modules/staff/commands/leave-requests.ts +94 -0
- package/src/modules/staff/i18n/de.json +4 -0
- package/src/modules/staff/i18n/en.json +9 -1
- package/src/modules/staff/i18n/es.json +4 -0
- package/src/modules/staff/i18n/pl.json +4 -0
- package/src/modules/staff/notifications.ts +71 -0
- package/src/modules/workflows/i18n/en.json +3 -1
- package/src/modules/workflows/notifications.ts +25 -0
- package/src/modules/workflows/subscribers/task-assigned-notification.ts +53 -0
|
@@ -21,7 +21,8 @@ export const M = {
|
|
|
21
21
|
"currencies": "currencies",
|
|
22
22
|
"planner": "planner",
|
|
23
23
|
"resources": "resources",
|
|
24
|
-
"staff": "staff"
|
|
24
|
+
"staff": "staff",
|
|
25
|
+
"notifications": "notifications"
|
|
25
26
|
} as const
|
|
26
27
|
export const E = {
|
|
27
28
|
"dashboards": {
|
|
@@ -30,34 +31,34 @@ export const E = {
|
|
|
30
31
|
"dashboard_user_widgets": "dashboards:dashboard_user_widgets"
|
|
31
32
|
},
|
|
32
33
|
"auth": {
|
|
33
|
-
"
|
|
34
|
+
"password_reset": "auth:password_reset",
|
|
34
35
|
"role": "auth:role",
|
|
35
|
-
"
|
|
36
|
+
"role_acl": "auth:role_acl",
|
|
36
37
|
"role_sidebar_preference": "auth:role_sidebar_preference",
|
|
37
|
-
"user_role": "auth:user_role",
|
|
38
38
|
"session": "auth:session",
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
39
|
+
"user": "auth:user",
|
|
40
|
+
"user_acl": "auth:user_acl",
|
|
41
|
+
"user_role": "auth:user_role",
|
|
42
|
+
"user_sidebar_preference": "auth:user_sidebar_preference"
|
|
42
43
|
},
|
|
43
44
|
"directory": {
|
|
44
|
-
"
|
|
45
|
-
"
|
|
45
|
+
"organization": "directory:organization",
|
|
46
|
+
"tenant": "directory:tenant"
|
|
46
47
|
},
|
|
47
48
|
"customers": {
|
|
48
|
-
"
|
|
49
|
-
"
|
|
49
|
+
"customer_activity": "customers:customer_activity",
|
|
50
|
+
"customer_address": "customers:customer_address",
|
|
51
|
+
"customer_comment": "customers:customer_comment",
|
|
50
52
|
"customer_company_profile": "customers:customer_company_profile",
|
|
51
53
|
"customer_deal": "customers:customer_deal",
|
|
52
|
-
"customer_deal_person_link": "customers:customer_deal_person_link",
|
|
53
54
|
"customer_deal_company_link": "customers:customer_deal_company_link",
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
55
|
+
"customer_deal_person_link": "customers:customer_deal_person_link",
|
|
56
|
+
"customer_dictionary_entry": "customers:customer_dictionary_entry",
|
|
57
|
+
"customer_entity": "customers:customer_entity",
|
|
58
|
+
"customer_person_profile": "customers:customer_person_profile",
|
|
57
59
|
"customer_settings": "customers:customer_settings",
|
|
58
60
|
"customer_tag": "customers:customer_tag",
|
|
59
61
|
"customer_tag_assignment": "customers:customer_tag_assignment",
|
|
60
|
-
"customer_dictionary_entry": "customers:customer_dictionary_entry",
|
|
61
62
|
"customer_todo_link": "customers:customer_todo_link"
|
|
62
63
|
},
|
|
63
64
|
"perspectives": {
|
|
@@ -65,10 +66,10 @@ export const E = {
|
|
|
65
66
|
"role_perspective": "perspectives:role_perspective"
|
|
66
67
|
},
|
|
67
68
|
"entities": {
|
|
68
|
-
"custom_field_def": "entities:custom_field_def",
|
|
69
|
-
"custom_field_entity_config": "entities:custom_field_entity_config",
|
|
70
69
|
"custom_entity": "entities:custom_entity",
|
|
71
70
|
"custom_entity_storage": "entities:custom_entity_storage",
|
|
71
|
+
"custom_field_def": "entities:custom_field_def",
|
|
72
|
+
"custom_field_entity_config": "entities:custom_field_entity_config",
|
|
72
73
|
"custom_field_value": "entities:custom_field_value",
|
|
73
74
|
"encryption_map": "entities:encryption_map"
|
|
74
75
|
},
|
|
@@ -77,60 +78,60 @@ export const E = {
|
|
|
77
78
|
"upgrade_action_run": "configs:upgrade_action_run"
|
|
78
79
|
},
|
|
79
80
|
"query_index": {
|
|
80
|
-
"entity_index_row": "query_index:entity_index_row",
|
|
81
|
-
"entity_index_job": "query_index:entity_index_job",
|
|
82
81
|
"entity_index_coverage": "query_index:entity_index_coverage",
|
|
82
|
+
"entity_index_job": "query_index:entity_index_job",
|
|
83
|
+
"entity_index_row": "query_index:entity_index_row",
|
|
83
84
|
"indexer_error_log": "query_index:indexer_error_log",
|
|
84
85
|
"indexer_status_log": "query_index:indexer_status_log",
|
|
85
86
|
"search_token": "query_index:search_token"
|
|
86
87
|
},
|
|
87
88
|
"audit_logs": {
|
|
88
|
-
"
|
|
89
|
-
"
|
|
89
|
+
"access_log": "audit_logs:access_log",
|
|
90
|
+
"action_log": "audit_logs:action_log"
|
|
90
91
|
},
|
|
91
92
|
"attachments": {
|
|
92
|
-
"
|
|
93
|
-
"
|
|
93
|
+
"attachment": "attachments:attachment",
|
|
94
|
+
"attachment_partition": "attachments:attachment_partition"
|
|
94
95
|
},
|
|
95
96
|
"catalog": {
|
|
97
|
+
"catalog_offer": "catalog:catalog_offer",
|
|
96
98
|
"catalog_option_schema_template": "catalog:catalog_option_schema_template",
|
|
99
|
+
"catalog_price_kind": "catalog:catalog_price_kind",
|
|
97
100
|
"catalog_product": "catalog:catalog_product",
|
|
98
101
|
"catalog_product_category": "catalog:catalog_product_category",
|
|
99
102
|
"catalog_product_category_assignment": "catalog:catalog_product_category_assignment",
|
|
103
|
+
"catalog_product_price": "catalog:catalog_product_price",
|
|
100
104
|
"catalog_product_tag": "catalog:catalog_product_tag",
|
|
101
105
|
"catalog_product_tag_assignment": "catalog:catalog_product_tag_assignment",
|
|
102
|
-
"catalog_offer": "catalog:catalog_offer",
|
|
103
106
|
"catalog_product_variant": "catalog:catalog_product_variant",
|
|
104
|
-
"catalog_product_variant_relation": "catalog:catalog_product_variant_relation"
|
|
105
|
-
"catalog_price_kind": "catalog:catalog_price_kind",
|
|
106
|
-
"catalog_product_price": "catalog:catalog_product_price"
|
|
107
|
+
"catalog_product_variant_relation": "catalog:catalog_product_variant_relation"
|
|
107
108
|
},
|
|
108
109
|
"sales": {
|
|
109
110
|
"sales_channel": "sales:sales_channel",
|
|
110
|
-
"
|
|
111
|
+
"sales_credit_memo": "sales:sales_credit_memo",
|
|
112
|
+
"sales_credit_memo_line": "sales:sales_credit_memo_line",
|
|
111
113
|
"sales_delivery_window": "sales:sales_delivery_window",
|
|
112
|
-
"
|
|
113
|
-
"
|
|
114
|
+
"sales_document_address": "sales:sales_document_address",
|
|
115
|
+
"sales_document_sequence": "sales:sales_document_sequence",
|
|
116
|
+
"sales_document_tag": "sales:sales_document_tag",
|
|
117
|
+
"sales_document_tag_assignment": "sales:sales_document_tag_assignment",
|
|
118
|
+
"sales_invoice": "sales:sales_invoice",
|
|
119
|
+
"sales_invoice_line": "sales:sales_invoice_line",
|
|
120
|
+
"sales_note": "sales:sales_note",
|
|
114
121
|
"sales_order": "sales:sales_order",
|
|
115
|
-
"sales_order_line": "sales:sales_order_line",
|
|
116
122
|
"sales_order_adjustment": "sales:sales_order_adjustment",
|
|
117
|
-
"
|
|
118
|
-
"
|
|
123
|
+
"sales_order_line": "sales:sales_order_line",
|
|
124
|
+
"sales_payment": "sales:sales_payment",
|
|
125
|
+
"sales_payment_allocation": "sales:sales_payment_allocation",
|
|
126
|
+
"sales_payment_method": "sales:sales_payment_method",
|
|
119
127
|
"sales_quote": "sales:sales_quote",
|
|
120
|
-
"sales_quote_line": "sales:sales_quote_line",
|
|
121
128
|
"sales_quote_adjustment": "sales:sales_quote_adjustment",
|
|
129
|
+
"sales_quote_line": "sales:sales_quote_line",
|
|
130
|
+
"sales_settings": "sales:sales_settings",
|
|
122
131
|
"sales_shipment": "sales:sales_shipment",
|
|
123
132
|
"sales_shipment_item": "sales:sales_shipment_item",
|
|
124
|
-
"
|
|
125
|
-
"
|
|
126
|
-
"sales_credit_memo": "sales:sales_credit_memo",
|
|
127
|
-
"sales_credit_memo_line": "sales:sales_credit_memo_line",
|
|
128
|
-
"sales_payment": "sales:sales_payment",
|
|
129
|
-
"sales_payment_allocation": "sales:sales_payment_allocation",
|
|
130
|
-
"sales_note": "sales:sales_note",
|
|
131
|
-
"sales_document_address": "sales:sales_document_address",
|
|
132
|
-
"sales_document_tag": "sales:sales_document_tag",
|
|
133
|
-
"sales_document_tag_assignment": "sales:sales_document_tag_assignment"
|
|
133
|
+
"sales_shipping_method": "sales:sales_shipping_method",
|
|
134
|
+
"sales_tax_rate": "sales:sales_tax_rate"
|
|
134
135
|
},
|
|
135
136
|
"api_keys": {
|
|
136
137
|
"api_key": "api_keys:api_key"
|
|
@@ -150,38 +151,41 @@ export const E = {
|
|
|
150
151
|
"feature_toggle_override": "feature_toggles:feature_toggle_override"
|
|
151
152
|
},
|
|
152
153
|
"workflows": {
|
|
153
|
-
"workflow_definition": "workflows:workflow_definition",
|
|
154
|
-
"workflow_instance": "workflows:workflow_instance",
|
|
155
154
|
"step_instance": "workflows:step_instance",
|
|
156
155
|
"user_task": "workflows:user_task",
|
|
157
|
-
"
|
|
156
|
+
"workflow_definition": "workflows:workflow_definition",
|
|
157
|
+
"workflow_event": "workflows:workflow_event",
|
|
158
|
+
"workflow_instance": "workflows:workflow_instance"
|
|
158
159
|
},
|
|
159
160
|
"currencies": {
|
|
160
161
|
"currency": "currencies:currency",
|
|
161
|
-
"
|
|
162
|
-
"
|
|
162
|
+
"currency_fetch_config": "currencies:currency_fetch_config",
|
|
163
|
+
"exchange_rate": "currencies:exchange_rate"
|
|
163
164
|
},
|
|
164
165
|
"planner": {
|
|
165
|
-
"
|
|
166
|
-
"
|
|
166
|
+
"planner_availability_rule": "planner:planner_availability_rule",
|
|
167
|
+
"planner_availability_rule_set": "planner:planner_availability_rule_set"
|
|
167
168
|
},
|
|
168
169
|
"resources": {
|
|
169
|
-
"resources_resource_type": "resources:resources_resource_type",
|
|
170
170
|
"resources_resource": "resources:resources_resource",
|
|
171
|
-
"resources_resource_comment": "resources:resources_resource_comment",
|
|
172
171
|
"resources_resource_activity": "resources:resources_resource_activity",
|
|
172
|
+
"resources_resource_comment": "resources:resources_resource_comment",
|
|
173
173
|
"resources_resource_tag": "resources:resources_resource_tag",
|
|
174
|
-
"resources_resource_tag_assignment": "resources:resources_resource_tag_assignment"
|
|
174
|
+
"resources_resource_tag_assignment": "resources:resources_resource_tag_assignment",
|
|
175
|
+
"resources_resource_type": "resources:resources_resource_type"
|
|
175
176
|
},
|
|
176
177
|
"staff": {
|
|
178
|
+
"staff_leave_request": "staff:staff_leave_request",
|
|
177
179
|
"staff_team": "staff:staff_team",
|
|
178
|
-
"staff_team_role": "staff:staff_team_role",
|
|
179
180
|
"staff_team_member": "staff:staff_team_member",
|
|
180
|
-
"staff_leave_request": "staff:staff_leave_request",
|
|
181
|
-
"staff_team_member_comment": "staff:staff_team_member_comment",
|
|
182
181
|
"staff_team_member_activity": "staff:staff_team_member_activity",
|
|
182
|
+
"staff_team_member_address": "staff:staff_team_member_address",
|
|
183
|
+
"staff_team_member_comment": "staff:staff_team_member_comment",
|
|
183
184
|
"staff_team_member_job_history": "staff:staff_team_member_job_history",
|
|
184
|
-
"
|
|
185
|
+
"staff_team_role": "staff:staff_team_role"
|
|
186
|
+
},
|
|
187
|
+
"notifications": {
|
|
188
|
+
"notification": "notifications:notification"
|
|
185
189
|
}
|
|
186
190
|
} as const
|
|
187
191
|
export type KnownModuleId = keyof typeof M
|
|
@@ -53,6 +53,7 @@ import * as feature_toggle_override from './entities/feature_toggle_override/ind
|
|
|
53
53
|
import * as indexer_error_log from './entities/indexer_error_log/index'
|
|
54
54
|
import * as indexer_status_log from './entities/indexer_status_log/index'
|
|
55
55
|
import * as module_config from './entities/module_config/index'
|
|
56
|
+
import * as notification from './entities/notification/index'
|
|
56
57
|
import * as organization from './entities/organization/index'
|
|
57
58
|
import * as password_reset from './entities/password_reset/index'
|
|
58
59
|
import * as perspective from './entities/perspective/index'
|
|
@@ -172,6 +173,7 @@ export const entityFieldsRegistry: Record<string, Record<string, string>> = {
|
|
|
172
173
|
indexer_error_log,
|
|
173
174
|
indexer_status_log,
|
|
174
175
|
module_config,
|
|
176
|
+
notification,
|
|
175
177
|
organization,
|
|
176
178
|
password_reset,
|
|
177
179
|
perspective,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/core",
|
|
3
|
-
"version": "0.4.2-canary-
|
|
3
|
+
"version": "0.4.2-canary-07dbc98202",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -207,7 +207,7 @@
|
|
|
207
207
|
}
|
|
208
208
|
},
|
|
209
209
|
"dependencies": {
|
|
210
|
-
"@open-mercato/shared": "0.4.2-canary-
|
|
210
|
+
"@open-mercato/shared": "0.4.2-canary-07dbc98202",
|
|
211
211
|
"@xyflow/react": "^12.6.0",
|
|
212
212
|
"date-fns": "^4.1.0",
|
|
213
213
|
"date-fns-tz": "^3.2.0"
|
|
@@ -2,6 +2,7 @@ import ApiDocsExplorer from './Explorer'
|
|
|
2
2
|
import { getModules } from '@open-mercato/shared/lib/i18n/server'
|
|
3
3
|
import { buildOpenApiDocument } from '@open-mercato/shared/lib/openapi'
|
|
4
4
|
import { resolveApiDocsBaseUrl } from '@open-mercato/core/modules/api_docs/lib/resources'
|
|
5
|
+
import { APP_VERSION } from '@open-mercato/shared/lib/version'
|
|
5
6
|
|
|
6
7
|
type ExplorerOperation = {
|
|
7
8
|
id: string
|
|
@@ -54,7 +55,7 @@ export default async function ApiDocsViewerPage() {
|
|
|
54
55
|
const modules = getModules()
|
|
55
56
|
const doc = buildOpenApiDocument(modules, {
|
|
56
57
|
title: 'Open Mercato API',
|
|
57
|
-
version:
|
|
58
|
+
version: APP_VERSION,
|
|
58
59
|
description: 'Auto-generated OpenAPI definition for all enabled modules.',
|
|
59
60
|
servers: [{ url: baseUrl, description: 'Default environment' }],
|
|
60
61
|
baseUrlForExamples: baseUrl,
|
|
@@ -67,7 +68,7 @@ export default async function ApiDocsViewerPage() {
|
|
|
67
68
|
return (
|
|
68
69
|
<ApiDocsExplorer
|
|
69
70
|
title={doc.info?.title ?? 'Open Mercato API'}
|
|
70
|
-
version={doc.info?.version ??
|
|
71
|
+
version={doc.info?.version ?? APP_VERSION}
|
|
71
72
|
description={doc.info?.description}
|
|
72
73
|
operations={operations}
|
|
73
74
|
tagOrder={tagOrder}
|
|
@@ -297,12 +297,16 @@ export async function GET(req: Request) {
|
|
|
297
297
|
const groupsWithRole = rolePreference ? applySidebarPreference(groups, rolePreference) : groups
|
|
298
298
|
const baseForUser = adoptSidebarDefaults(groupsWithRole)
|
|
299
299
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
300
|
+
// For API key auth, use userId (the actual user) if available; otherwise skip user preferences
|
|
301
|
+
const effectiveUserId = auth.isApiKey ? auth.userId : auth.sub
|
|
302
|
+
const preference = effectiveUserId
|
|
303
|
+
? await loadSidebarPreference(em, {
|
|
304
|
+
userId: effectiveUserId,
|
|
305
|
+
tenantId: auth.tenantId ?? null,
|
|
306
|
+
organizationId: auth.orgId ?? null,
|
|
307
|
+
locale,
|
|
308
|
+
})
|
|
309
|
+
: null
|
|
306
310
|
|
|
307
311
|
const withPreference = applySidebarPreference(baseForUser, preference)
|
|
308
312
|
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
import { z } from 'zod'
|
|
3
|
+
import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
|
|
4
|
+
import type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
|
|
5
|
+
import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
6
|
+
import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
|
|
7
|
+
import { signJwt } from '@open-mercato/shared/lib/auth/jwt'
|
|
8
|
+
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
9
|
+
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
10
|
+
import { AuthService } from '@open-mercato/core/modules/auth/services/authService'
|
|
11
|
+
import { User } from '@open-mercato/core/modules/auth/data/entities'
|
|
12
|
+
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
13
|
+
import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
14
|
+
|
|
15
|
+
const profileResponseSchema = z.object({
|
|
16
|
+
email: z.string().email(),
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
const updateSchema = z.object({
|
|
20
|
+
email: z.string().email().optional(),
|
|
21
|
+
password: z.string().min(6).optional(),
|
|
22
|
+
}).refine((data) => Boolean(data.email || data.password), {
|
|
23
|
+
message: 'Provide an email or password.',
|
|
24
|
+
path: ['email'],
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const profileUpdateResponseSchema = z.object({
|
|
28
|
+
ok: z.literal(true),
|
|
29
|
+
email: z.string().email(),
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
export const metadata = {
|
|
33
|
+
GET: { requireAuth: true },
|
|
34
|
+
PUT: { requireAuth: true },
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function buildCommandContext(container: Awaited<ReturnType<typeof createRequestContainer>>, auth: NonNullable<Awaited<ReturnType<typeof getAuthFromRequest>>>, req: Request): CommandRuntimeContext {
|
|
38
|
+
return {
|
|
39
|
+
container,
|
|
40
|
+
auth,
|
|
41
|
+
organizationScope: null,
|
|
42
|
+
selectedOrganizationId: auth.orgId ?? null,
|
|
43
|
+
organizationIds: auth.orgId ? [auth.orgId] : null,
|
|
44
|
+
request: req,
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function GET(req: Request) {
|
|
49
|
+
const { translate } = await resolveTranslations()
|
|
50
|
+
const auth = await getAuthFromRequest(req)
|
|
51
|
+
if (!auth?.sub) {
|
|
52
|
+
return NextResponse.json({ error: translate('api.errors.unauthorized', 'Unauthorized') }, { status: 401 })
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const container = await createRequestContainer()
|
|
56
|
+
const em = (container.resolve('em') as EntityManager)
|
|
57
|
+
const user = await findOneWithDecryption(
|
|
58
|
+
em,
|
|
59
|
+
User,
|
|
60
|
+
{ id: auth.sub, deletedAt: null },
|
|
61
|
+
undefined,
|
|
62
|
+
{ tenantId: auth.tenantId ?? null, organizationId: auth.orgId ?? null },
|
|
63
|
+
)
|
|
64
|
+
if (!user) {
|
|
65
|
+
return NextResponse.json({ error: translate('auth.users.form.errors.notFound', 'User not found') }, { status: 404 })
|
|
66
|
+
}
|
|
67
|
+
return NextResponse.json({ email: String(user.email) })
|
|
68
|
+
} catch (err) {
|
|
69
|
+
console.error('auth.profile.load failed', err)
|
|
70
|
+
return NextResponse.json({ error: translate('auth.profile.form.errors.load', 'Failed to load profile.') }, { status: 400 })
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export async function PUT(req: Request) {
|
|
75
|
+
const { translate } = await resolveTranslations()
|
|
76
|
+
const auth = await getAuthFromRequest(req)
|
|
77
|
+
if (!auth?.sub) {
|
|
78
|
+
return NextResponse.json({ error: translate('api.errors.unauthorized', 'Unauthorized') }, { status: 401 })
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
const body = await req.json().catch(() => ({}))
|
|
82
|
+
const parsed = updateSchema.safeParse(body)
|
|
83
|
+
if (!parsed.success) {
|
|
84
|
+
return NextResponse.json(
|
|
85
|
+
{
|
|
86
|
+
error: translate('auth.profile.form.errors.invalid', 'Invalid profile update.'),
|
|
87
|
+
issues: parsed.error.issues,
|
|
88
|
+
},
|
|
89
|
+
{ status: 400 },
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
const container = await createRequestContainer()
|
|
93
|
+
const commandBus = (container.resolve('commandBus') as CommandBus)
|
|
94
|
+
const ctx = buildCommandContext(container, auth, req)
|
|
95
|
+
const { result } = await commandBus.execute<{ id: string; email?: string; password?: string }, User>(
|
|
96
|
+
'auth.users.update',
|
|
97
|
+
{
|
|
98
|
+
input: {
|
|
99
|
+
id: auth.sub,
|
|
100
|
+
email: parsed.data.email,
|
|
101
|
+
password: parsed.data.password,
|
|
102
|
+
},
|
|
103
|
+
ctx,
|
|
104
|
+
},
|
|
105
|
+
)
|
|
106
|
+
const authService = container.resolve('authService') as AuthService
|
|
107
|
+
const roles = await authService.getUserRoles(result, result.tenantId ? String(result.tenantId) : null)
|
|
108
|
+
const jwt = signJwt({
|
|
109
|
+
sub: String(result.id),
|
|
110
|
+
tenantId: result.tenantId ? String(result.tenantId) : null,
|
|
111
|
+
orgId: result.organizationId ? String(result.organizationId) : null,
|
|
112
|
+
email: result.email,
|
|
113
|
+
roles,
|
|
114
|
+
})
|
|
115
|
+
const res = NextResponse.json({ ok: true, email: String(result.email) })
|
|
116
|
+
res.cookies.set('auth_token', jwt, {
|
|
117
|
+
httpOnly: true,
|
|
118
|
+
path: '/',
|
|
119
|
+
sameSite: 'lax',
|
|
120
|
+
secure: process.env.NODE_ENV === 'production',
|
|
121
|
+
maxAge: 60 * 60 * 8,
|
|
122
|
+
})
|
|
123
|
+
return res
|
|
124
|
+
} catch (err) {
|
|
125
|
+
if (err instanceof CrudHttpError) {
|
|
126
|
+
return NextResponse.json(err.body, { status: err.status })
|
|
127
|
+
}
|
|
128
|
+
console.error('auth.profile.update failed', err)
|
|
129
|
+
return NextResponse.json({ error: translate('auth.profile.form.errors.save', 'Failed to update profile.') }, { status: 400 })
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export const openApi: OpenApiRouteDoc = {
|
|
134
|
+
tag: 'Authentication & Accounts',
|
|
135
|
+
summary: 'Profile settings',
|
|
136
|
+
methods: {
|
|
137
|
+
GET: {
|
|
138
|
+
summary: 'Get current profile',
|
|
139
|
+
description: 'Returns the email address for the signed-in user.',
|
|
140
|
+
responses: [
|
|
141
|
+
{ status: 200, description: 'Profile payload', schema: profileResponseSchema },
|
|
142
|
+
{ status: 401, description: 'Unauthorized', schema: z.object({ error: z.string() }) },
|
|
143
|
+
{ status: 404, description: 'User not found', schema: z.object({ error: z.string() }) },
|
|
144
|
+
],
|
|
145
|
+
},
|
|
146
|
+
PUT: {
|
|
147
|
+
summary: 'Update current profile',
|
|
148
|
+
description: 'Updates the email address or password for the signed-in user.',
|
|
149
|
+
requestBody: {
|
|
150
|
+
contentType: 'application/json',
|
|
151
|
+
schema: updateSchema,
|
|
152
|
+
},
|
|
153
|
+
responses: [
|
|
154
|
+
{ status: 200, description: 'Profile updated', schema: profileUpdateResponseSchema },
|
|
155
|
+
{ status: 400, description: 'Invalid payload', schema: z.object({ error: z.string() }) },
|
|
156
|
+
{ status: 401, description: 'Unauthorized', schema: z.object({ error: z.string() }) },
|
|
157
|
+
],
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
}
|
|
@@ -3,6 +3,9 @@ import { NextResponse } from 'next/server'
|
|
|
3
3
|
import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
|
|
4
4
|
import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
5
5
|
import { AuthService } from '@open-mercato/core/modules/auth/services/authService'
|
|
6
|
+
import { buildNotificationFromType } from '@open-mercato/core/modules/notifications/lib/notificationBuilder'
|
|
7
|
+
import { resolveNotificationService } from '@open-mercato/core/modules/notifications/lib/notificationService'
|
|
8
|
+
import notificationTypes from '@open-mercato/core/modules/auth/notifications'
|
|
6
9
|
import { z } from 'zod'
|
|
7
10
|
|
|
8
11
|
// validation via confirmPasswordResetSchema
|
|
@@ -15,8 +18,28 @@ export async function POST(req: Request) {
|
|
|
15
18
|
if (!parsed.success) return NextResponse.json({ ok: false, error: 'Invalid request' }, { status: 400 })
|
|
16
19
|
const c = await createRequestContainer()
|
|
17
20
|
const auth = c.resolve<AuthService>('authService')
|
|
18
|
-
const
|
|
19
|
-
if (!
|
|
21
|
+
const user = await auth.confirmPasswordReset(parsed.data.token, parsed.data.password)
|
|
22
|
+
if (!user) return NextResponse.json({ ok: false, error: 'Invalid or expired token' }, { status: 400 })
|
|
23
|
+
try {
|
|
24
|
+
const tenantId = user.tenantId ? String(user.tenantId) : null
|
|
25
|
+
if (tenantId) {
|
|
26
|
+
const notificationService = resolveNotificationService(c)
|
|
27
|
+
const typeDef = notificationTypes.find((type) => type.type === 'auth.password_reset.completed')
|
|
28
|
+
if (typeDef) {
|
|
29
|
+
const notificationInput = buildNotificationFromType(typeDef, {
|
|
30
|
+
recipientUserId: String(user.id),
|
|
31
|
+
sourceEntityType: 'auth:user',
|
|
32
|
+
sourceEntityId: String(user.id),
|
|
33
|
+
})
|
|
34
|
+
await notificationService.create(notificationInput, {
|
|
35
|
+
tenantId,
|
|
36
|
+
organizationId: user.organizationId ? String(user.organizationId) : null,
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
} catch (err) {
|
|
41
|
+
console.error('[auth.reset.confirm] Failed to create notification:', err)
|
|
42
|
+
}
|
|
20
43
|
return NextResponse.json({ ok: true, redirect: '/login' })
|
|
21
44
|
}
|
|
22
45
|
|
|
@@ -6,6 +6,9 @@ import { AuthService } from '@open-mercato/core/modules/auth/services/authServic
|
|
|
6
6
|
import { sendEmail } from '@open-mercato/shared/lib/email/send'
|
|
7
7
|
import ResetPasswordEmail from '@open-mercato/core/modules/auth/emails/ResetPasswordEmail'
|
|
8
8
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
9
|
+
import { buildNotificationFromType } from '@open-mercato/core/modules/notifications/lib/notificationBuilder'
|
|
10
|
+
import { resolveNotificationService } from '@open-mercato/core/modules/notifications/lib/notificationService'
|
|
11
|
+
import notificationTypes from '@open-mercato/core/modules/auth/notifications'
|
|
9
12
|
import { z } from 'zod'
|
|
10
13
|
|
|
11
14
|
// validation via requestPasswordResetSchema
|
|
@@ -35,6 +38,26 @@ export async function POST(req: Request) {
|
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
await sendEmail({ to: user.email, subject, react: ResetPasswordEmail({ resetUrl, copy }) })
|
|
41
|
+
try {
|
|
42
|
+
const tenantId = user.tenantId ? String(user.tenantId) : null
|
|
43
|
+
if (tenantId) {
|
|
44
|
+
const notificationService = resolveNotificationService(c)
|
|
45
|
+
const typeDef = notificationTypes.find((type) => type.type === 'auth.password_reset.requested')
|
|
46
|
+
if (typeDef) {
|
|
47
|
+
const notificationInput = buildNotificationFromType(typeDef, {
|
|
48
|
+
recipientUserId: String(user.id),
|
|
49
|
+
sourceEntityType: 'auth:user',
|
|
50
|
+
sourceEntityId: String(user.id),
|
|
51
|
+
})
|
|
52
|
+
await notificationService.create(notificationInput, {
|
|
53
|
+
tenantId,
|
|
54
|
+
organizationId: user.organizationId ? String(user.organizationId) : null,
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
} catch (err) {
|
|
59
|
+
console.error('[auth.reset] Failed to create notification:', err)
|
|
60
|
+
}
|
|
38
61
|
return NextResponse.json({ ok: true })
|
|
39
62
|
}
|
|
40
63
|
|
|
@@ -64,12 +64,16 @@ export async function GET(req: Request) {
|
|
|
64
64
|
{ tenantId: auth.tenantId ?? null, organizationId: auth.orgId ?? null },
|
|
65
65
|
) ?? false
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
67
|
+
// For API key auth, use userId (the actual user) if available
|
|
68
|
+
const effectiveUserId = auth.isApiKey ? auth.userId : auth.sub
|
|
69
|
+
const settings = effectiveUserId
|
|
70
|
+
? await loadSidebarPreference(em, {
|
|
71
|
+
userId: effectiveUserId,
|
|
72
|
+
tenantId: auth.tenantId ?? null,
|
|
73
|
+
organizationId: auth.orgId ?? null,
|
|
74
|
+
locale,
|
|
75
|
+
})
|
|
76
|
+
: null
|
|
73
77
|
|
|
74
78
|
let rolesPayload: Array<{ id: string; name: string; hasPreference: boolean }> = []
|
|
75
79
|
if (canApplyToRoles) {
|
|
@@ -92,11 +96,11 @@ export async function GET(req: Request) {
|
|
|
92
96
|
return NextResponse.json({
|
|
93
97
|
locale,
|
|
94
98
|
settings: {
|
|
95
|
-
version: settings
|
|
96
|
-
groupOrder: settings
|
|
97
|
-
groupLabels: settings
|
|
98
|
-
itemLabels: settings
|
|
99
|
-
hiddenItems: settings
|
|
99
|
+
version: settings?.version ?? SIDEBAR_PREFERENCES_VERSION,
|
|
100
|
+
groupOrder: settings?.groupOrder ?? [],
|
|
101
|
+
groupLabels: settings?.groupLabels ?? {},
|
|
102
|
+
itemLabels: settings?.itemLabels ?? {},
|
|
103
|
+
hiddenItems: settings?.hiddenItems ?? [],
|
|
100
104
|
},
|
|
101
105
|
canApplyToRoles,
|
|
102
106
|
roles: rolesPayload,
|
|
@@ -106,6 +110,11 @@ export async function GET(req: Request) {
|
|
|
106
110
|
export async function PUT(req: Request) {
|
|
107
111
|
const auth = await getAuthFromRequest(req)
|
|
108
112
|
if (!auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
113
|
+
// For API key auth, use userId (the actual user) if available
|
|
114
|
+
const effectiveUserId = auth.isApiKey ? auth.userId : auth.sub
|
|
115
|
+
if (!effectiveUserId) {
|
|
116
|
+
return NextResponse.json({ error: 'Cannot save preferences: no user associated with this API key' }, { status: 403 })
|
|
117
|
+
}
|
|
109
118
|
|
|
110
119
|
let parsedBody: unknown
|
|
111
120
|
try {
|
|
@@ -182,7 +191,7 @@ export async function PUT(req: Request) {
|
|
|
182
191
|
}
|
|
183
192
|
|
|
184
193
|
const settings = await saveSidebarPreference(em, {
|
|
185
|
-
userId:
|
|
194
|
+
userId: effectiveUserId,
|
|
186
195
|
tenantId: auth.tenantId ?? null,
|
|
187
196
|
organizationId: auth.orgId ?? null,
|
|
188
197
|
locale,
|