@kumori/aurora-backend-handler 1.0.88 → 1.0.90
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/api/account-api-service.ts +3 -0
- package/api/environment-api-service.ts +10 -5
- package/api/resources-api-service.ts +16 -8
- package/api/service-api-service.ts +3 -0
- package/api/tenant-api-service.ts +14 -0
- package/api/user-api-service.ts +2 -0
- package/helpers/account-helper.ts +149 -91
- package/helpers/environment-helper.ts +1 -0
- package/package.json +2 -2
- package/websocket-manager.ts +3 -1
|
@@ -642,6 +642,7 @@ export const createAccount = async (account: Account, security: Security) => {
|
|
|
642
642
|
account: account.name,
|
|
643
643
|
tenant: account.tenant,
|
|
644
644
|
},
|
|
645
|
+
userError: true,
|
|
645
646
|
};
|
|
646
647
|
eventHelper.notification.publish.creation(accountErrorNotification);
|
|
647
648
|
throw error;
|
|
@@ -758,6 +759,7 @@ export const deleteAccount = async (account: Account, security: Security) => {
|
|
|
758
759
|
account: account.name,
|
|
759
760
|
tenant: account.tenant,
|
|
760
761
|
},
|
|
762
|
+
userError: true,
|
|
761
763
|
};
|
|
762
764
|
eventHelper.notification.publish.creation(accountErrorNotification);
|
|
763
765
|
throw error;
|
|
@@ -818,6 +820,7 @@ export const clearAccount = async (account: Account, security: Security) => {
|
|
|
818
820
|
account: account.name,
|
|
819
821
|
tenant: account.tenant,
|
|
820
822
|
},
|
|
823
|
+
userError: true,
|
|
821
824
|
};
|
|
822
825
|
eventHelper.notification.publish.creation(accountErrorNotification);
|
|
823
826
|
throw error;
|
|
@@ -143,7 +143,8 @@ export const createEnvironment = async (
|
|
|
143
143
|
environment: env.name,
|
|
144
144
|
account: env.account,
|
|
145
145
|
tenant: env.tenant
|
|
146
|
-
}
|
|
146
|
+
},
|
|
147
|
+
userError: true,
|
|
147
148
|
};
|
|
148
149
|
eventHelper.notification.publish.creation(envErrorNotification);
|
|
149
150
|
throw error;
|
|
@@ -232,7 +233,8 @@ export const deleteEnvironment = async (
|
|
|
232
233
|
environment: env.name,
|
|
233
234
|
account: env.account,
|
|
234
235
|
tenant: env.tenant
|
|
235
|
-
}
|
|
236
|
+
},
|
|
237
|
+
userError: true,
|
|
236
238
|
};
|
|
237
239
|
eventHelper.notification.publish.creation(envErrorNotification);
|
|
238
240
|
throw error;
|
|
@@ -319,7 +321,8 @@ export const clearEnvironment = async (
|
|
|
319
321
|
environment: env.name,
|
|
320
322
|
account: env.account,
|
|
321
323
|
tenant: env.tenant
|
|
322
|
-
}
|
|
324
|
+
},
|
|
325
|
+
userError: true,
|
|
323
326
|
};
|
|
324
327
|
eventHelper.notification.publish.creation(envErrorNotification);
|
|
325
328
|
throw error;
|
|
@@ -456,7 +459,8 @@ export const updateEnvironment = async (
|
|
|
456
459
|
environment: env.name,
|
|
457
460
|
account: env.account,
|
|
458
461
|
tenant: env.tenant
|
|
459
|
-
}
|
|
462
|
+
},
|
|
463
|
+
userError: true
|
|
460
464
|
};
|
|
461
465
|
eventHelper.notification.publish.creation(envErrorNotification);
|
|
462
466
|
throw error;
|
|
@@ -534,7 +538,8 @@ export const scaleEnvironment = async (
|
|
|
534
538
|
environment: env.name,
|
|
535
539
|
account: env.account,
|
|
536
540
|
tenant: env.tenant
|
|
537
|
-
}
|
|
541
|
+
},
|
|
542
|
+
userError: true
|
|
538
543
|
};
|
|
539
544
|
eventHelper.notification.publish.creation(envErrorNotification);
|
|
540
545
|
throw error;
|
|
@@ -98,7 +98,8 @@ export const createDomain = async (
|
|
|
98
98
|
data: {
|
|
99
99
|
resource: domain.name,
|
|
100
100
|
tenant: tenant
|
|
101
|
-
}
|
|
101
|
+
},
|
|
102
|
+
userError: true,
|
|
102
103
|
};
|
|
103
104
|
eventHelper.notification.publish.creation(resourceErrorNotification);
|
|
104
105
|
throw error;
|
|
@@ -177,7 +178,8 @@ export const createPort = async (
|
|
|
177
178
|
data: {
|
|
178
179
|
resource: port.name,
|
|
179
180
|
tenant: tenant
|
|
180
|
-
}
|
|
181
|
+
},
|
|
182
|
+
userError: true,
|
|
181
183
|
};
|
|
182
184
|
eventHelper.notification.publish.creation(resourceErrorNotification);
|
|
183
185
|
throw error;
|
|
@@ -256,7 +258,8 @@ export const createCA = async (
|
|
|
256
258
|
data: {
|
|
257
259
|
resource: ca.name,
|
|
258
260
|
tenant: tenant
|
|
259
|
-
}
|
|
261
|
+
},
|
|
262
|
+
userError: true,
|
|
260
263
|
};
|
|
261
264
|
eventHelper.notification.publish.creation(resourceErrorNotification);
|
|
262
265
|
throw error;
|
|
@@ -348,7 +351,8 @@ export const createCertificate = async (
|
|
|
348
351
|
data: {
|
|
349
352
|
resource: certificate.name,
|
|
350
353
|
tenant: tenant
|
|
351
|
-
}
|
|
354
|
+
},
|
|
355
|
+
userError: true,
|
|
352
356
|
};
|
|
353
357
|
eventHelper.notification.publish.creation(resourceErrorNotification);
|
|
354
358
|
throw error;
|
|
@@ -427,7 +431,8 @@ export const createSecret = async (
|
|
|
427
431
|
data: {
|
|
428
432
|
resource: secret.name,
|
|
429
433
|
tenant: tenant
|
|
430
|
-
}
|
|
434
|
+
},
|
|
435
|
+
userError: true,
|
|
431
436
|
};
|
|
432
437
|
eventHelper.notification.publish.creation(resourceErrorNotification);
|
|
433
438
|
throw error;
|
|
@@ -526,7 +531,8 @@ export const createVolume = async (
|
|
|
526
531
|
data: {
|
|
527
532
|
resource: volume.name,
|
|
528
533
|
tenant: tenant
|
|
529
|
-
}
|
|
534
|
+
},
|
|
535
|
+
userError: true,
|
|
530
536
|
};
|
|
531
537
|
eventHelper.notification.publish.creation(resourceErrorNotification);
|
|
532
538
|
throw error;
|
|
@@ -632,7 +638,8 @@ const deleteResourceBase = async (
|
|
|
632
638
|
resource: resource.name,
|
|
633
639
|
type: resource.type,
|
|
634
640
|
tenant: tenant
|
|
635
|
-
}
|
|
641
|
+
},
|
|
642
|
+
userError: true,
|
|
636
643
|
};
|
|
637
644
|
eventHelper.notification.publish.creation(resourceErrorNotification);
|
|
638
645
|
throw error;
|
|
@@ -726,7 +733,8 @@ const updateResourceBase = async (
|
|
|
726
733
|
resource: resource.name,
|
|
727
734
|
type: resource.type,
|
|
728
735
|
tenant: tenant
|
|
729
|
-
}
|
|
736
|
+
},
|
|
737
|
+
userError: true,
|
|
730
738
|
};
|
|
731
739
|
eventHelper.notification.publish.creation(resourceErrorNotification);
|
|
732
740
|
throw error;
|
|
@@ -636,6 +636,7 @@ export const updateService = async (
|
|
|
636
636
|
service: data.name,
|
|
637
637
|
tenant: data.tenant,
|
|
638
638
|
},
|
|
639
|
+
userError: true,
|
|
639
640
|
};
|
|
640
641
|
eventHelper.notification.publish.creation(notification);
|
|
641
642
|
eventHelper.service.publish.updateError(data);
|
|
@@ -692,6 +693,7 @@ export const unlinkServices = async (service: Service, token: string) => {
|
|
|
692
693
|
service: service.name,
|
|
693
694
|
tenant: service.tenant,
|
|
694
695
|
},
|
|
696
|
+
userError: true,
|
|
695
697
|
};
|
|
696
698
|
eventHelper.notification.publish.creation(notification);
|
|
697
699
|
}
|
|
@@ -753,6 +755,7 @@ export const updateServiceLinks = async (link: Link, token: string) => {
|
|
|
753
755
|
service: link.origin,
|
|
754
756
|
tenant: link.tenant,
|
|
755
757
|
},
|
|
758
|
+
userError: true,
|
|
756
759
|
};
|
|
757
760
|
eventHelper.notification.publish.creation(notification);
|
|
758
761
|
}
|
|
@@ -109,6 +109,7 @@ export const createTenant = async (tenant: Tenant, security: Security) => {
|
|
|
109
109
|
data: {
|
|
110
110
|
tenant: tenant.name,
|
|
111
111
|
},
|
|
112
|
+
userError: true,
|
|
112
113
|
};
|
|
113
114
|
eventHelper.notification.publish.creation(tenantCreationErrorNotification);
|
|
114
115
|
throw error;
|
|
@@ -176,6 +177,7 @@ export const deleteTenant = async (tenant: Tenant, security: string) => {
|
|
|
176
177
|
data: {
|
|
177
178
|
tenant: tenant.name,
|
|
178
179
|
},
|
|
180
|
+
userError: true,
|
|
179
181
|
};
|
|
180
182
|
eventHelper.notification.publish.creation(tenantDeletionErrorNotification);
|
|
181
183
|
throw err;
|
|
@@ -265,6 +267,7 @@ export const updateTenant = async (tenant: Tenant, security: string) => {
|
|
|
265
267
|
data: {
|
|
266
268
|
tenant: tenant.name,
|
|
267
269
|
},
|
|
270
|
+
userError: true,
|
|
268
271
|
};
|
|
269
272
|
eventHelper.notification.publish.creation(tenantUpdateErrorNotification);
|
|
270
273
|
throw err;
|
|
@@ -364,6 +367,7 @@ export const createTenantHTTP = async (tenant: Tenant) => {
|
|
|
364
367
|
data: {
|
|
365
368
|
tenant: tenant.name,
|
|
366
369
|
},
|
|
370
|
+
userError: true,
|
|
367
371
|
};
|
|
368
372
|
|
|
369
373
|
eventHelper.notification.publish.creation(tenantCreationErrorNotification);
|
|
@@ -423,6 +427,7 @@ export const deleteTenantHTTP = async (tenant: Tenant) => {
|
|
|
423
427
|
data: {
|
|
424
428
|
tenant: tenant.name,
|
|
425
429
|
},
|
|
430
|
+
userError: true,
|
|
426
431
|
};
|
|
427
432
|
eventHelper.notification.publish.creation(tenantDeletionErrorNotification);
|
|
428
433
|
}
|
|
@@ -514,6 +519,7 @@ export const updateTenantHTTP = async (tenant: Tenant) => {
|
|
|
514
519
|
data: {
|
|
515
520
|
tenant: tenant.name,
|
|
516
521
|
},
|
|
522
|
+
userError: true,
|
|
517
523
|
};
|
|
518
524
|
eventHelper.notification.publish.creation(tenantUpdateErrorNotification);
|
|
519
525
|
}
|
|
@@ -602,6 +608,7 @@ export const createRegistry = async (
|
|
|
602
608
|
data: {
|
|
603
609
|
tenant: tenant.name,
|
|
604
610
|
},
|
|
611
|
+
userError: true,
|
|
605
612
|
};
|
|
606
613
|
eventHelper.notification.publish.creation(
|
|
607
614
|
dregistryCreationErrorNotification
|
|
@@ -703,6 +710,7 @@ export const updateRegistry = async (
|
|
|
703
710
|
data: {
|
|
704
711
|
tenant: tenant.name,
|
|
705
712
|
},
|
|
713
|
+
userError: true,
|
|
706
714
|
};
|
|
707
715
|
eventHelper.notification.publish.creation(dregistryUpdateErrorNotification);
|
|
708
716
|
throw error;
|
|
@@ -785,6 +793,7 @@ export const deleteRegistry = async (
|
|
|
785
793
|
data: {
|
|
786
794
|
tenant: tenant.name,
|
|
787
795
|
},
|
|
796
|
+
userError: true,
|
|
788
797
|
};
|
|
789
798
|
eventHelper.notification.publish.creation(
|
|
790
799
|
dregistryDeletionErrorNotification
|
|
@@ -872,6 +881,7 @@ export const inviteUser = async (
|
|
|
872
881
|
role,
|
|
873
882
|
tenantRole,
|
|
874
883
|
},
|
|
884
|
+
userError: true,
|
|
875
885
|
};
|
|
876
886
|
eventHelper.notification.publish.creation(tenantInviteErrorNotification);
|
|
877
887
|
throw error;
|
|
@@ -948,6 +958,7 @@ export const removeUser = async (
|
|
|
948
958
|
tenant: tenant,
|
|
949
959
|
user: userId,
|
|
950
960
|
},
|
|
961
|
+
userError: true,
|
|
951
962
|
};
|
|
952
963
|
eventHelper.notification.publish.creation(
|
|
953
964
|
tenantUserRemovedErrorNotification
|
|
@@ -1031,6 +1042,7 @@ export const updateUserRole = async (
|
|
|
1031
1042
|
user: userId,
|
|
1032
1043
|
role: role,
|
|
1033
1044
|
},
|
|
1045
|
+
userError: true,
|
|
1034
1046
|
};
|
|
1035
1047
|
eventHelper.notification.publish.creation(
|
|
1036
1048
|
tenantUserUpdatedErrorNotification
|
|
@@ -1099,6 +1111,7 @@ export const acceptInvite = async (tenant: string, security: string) => {
|
|
|
1099
1111
|
data: {
|
|
1100
1112
|
tenant: tenant,
|
|
1101
1113
|
},
|
|
1114
|
+
userError: true,
|
|
1102
1115
|
};
|
|
1103
1116
|
eventHelper.notification.publish.creation(
|
|
1104
1117
|
tenantInviteAcceptedErrorNotification
|
|
@@ -1167,6 +1180,7 @@ export const rejectInvite = async (tenant: string, security: string) => {
|
|
|
1167
1180
|
data: {
|
|
1168
1181
|
tenant: tenant,
|
|
1169
1182
|
},
|
|
1183
|
+
userError: true,
|
|
1170
1184
|
};
|
|
1171
1185
|
eventHelper.notification.publish.creation(
|
|
1172
1186
|
tenantInviteRejectedErrorNotification
|
package/api/user-api-service.ts
CHANGED
|
@@ -1091,6 +1091,7 @@ export const updateUser = async (user: User) => {
|
|
|
1091
1091
|
message: (error as any).error.content,
|
|
1092
1092
|
},
|
|
1093
1093
|
data: { user: user.name },
|
|
1094
|
+
userError: true,
|
|
1094
1095
|
});
|
|
1095
1096
|
throw error;
|
|
1096
1097
|
}
|
|
@@ -1129,6 +1130,7 @@ export const deleteUSer = async (user: User, security: string) => {
|
|
|
1129
1130
|
message: (error as any).error.content,
|
|
1130
1131
|
},
|
|
1131
1132
|
data: { user: user.name },
|
|
1133
|
+
userError: true,
|
|
1132
1134
|
});
|
|
1133
1135
|
throw error;
|
|
1134
1136
|
}
|
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
import { Account, Notification } from "@kumori/aurora-interfaces";
|
|
2
|
+
const CREDENTIAL_ERROR_CODES = new Set([
|
|
3
|
+
"_error_retrieving_credentials_",
|
|
4
|
+
"_invalid_account_credentials_",
|
|
5
|
+
"_unsupported_region_",
|
|
6
|
+
]);
|
|
2
7
|
|
|
8
|
+
/**
|
|
9
|
+
* All statuses that mean the account has reached a final error state.
|
|
10
|
+
* Pollers and status-strategy consumers should treat these as terminal.
|
|
11
|
+
*/
|
|
12
|
+
export const ACCOUNT_ERROR_STATUSES = new Set([
|
|
13
|
+
"error",
|
|
14
|
+
"invalid_credentials",
|
|
15
|
+
"failed",
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Map a raw backend error code to the normalized account status
|
|
20
|
+
* we write to accountsMap / the Account object.
|
|
21
|
+
*/
|
|
22
|
+
export const resolveErrorStatus = (
|
|
23
|
+
code: string,
|
|
24
|
+
): "invalid_credentials" | "error" =>
|
|
25
|
+
CREDENTIAL_ERROR_CODES.has(code) ? "invalid_credentials" : "error";
|
|
3
26
|
|
|
4
27
|
interface HandleAccountEventParams {
|
|
5
28
|
entityId: string;
|
|
@@ -39,10 +62,10 @@ interface HandleAccountOperationErrorResult {
|
|
|
39
62
|
eventType: "creationError" | "updateError" | "deletionError";
|
|
40
63
|
}
|
|
41
64
|
/**
|
|
42
|
-
* Extract cloud provider credentials from event data
|
|
65
|
+
* Extract cloud provider credentials from event data.
|
|
43
66
|
*/
|
|
44
67
|
const extractCloudProviderCredentials = (
|
|
45
|
-
eventData: any
|
|
68
|
+
eventData: any,
|
|
46
69
|
): { providerType: string; credentials: any } => {
|
|
47
70
|
let providerType = "";
|
|
48
71
|
let credentials = {};
|
|
@@ -52,18 +75,24 @@ const extractCloudProviderCredentials = (
|
|
|
52
75
|
credentials = {
|
|
53
76
|
region: eventData.spec.credentials.openstack?.region_name || "",
|
|
54
77
|
interface: eventData.spec.credentials.openstack?.interface || "",
|
|
55
|
-
apiVersion:
|
|
78
|
+
apiVersion:
|
|
79
|
+
eventData.spec.credentials.openstack?.identity_api_version || "",
|
|
56
80
|
authType: eventData.spec.credentials.openstack?.auth_type || "",
|
|
57
81
|
authUrl: eventData.spec.credentials.openstack?.auth?.auth_url || "",
|
|
58
|
-
credentialId:
|
|
59
|
-
|
|
82
|
+
credentialId:
|
|
83
|
+
eventData.spec.credentials.openstack?.auth?.application_credential_id ||
|
|
84
|
+
"",
|
|
85
|
+
credentialSecret:
|
|
86
|
+
eventData.spec.credentials.openstack?.auth
|
|
87
|
+
?.application_credential_secret || "",
|
|
60
88
|
};
|
|
61
89
|
} else if (eventData.spec.credentials.aws) {
|
|
62
90
|
providerType = "aws";
|
|
63
91
|
credentials = {
|
|
64
92
|
region: eventData.spec.credentials.aws?.region || "",
|
|
65
93
|
credentialId: eventData.spec.credentials.aws?.aws_access_key_id || "",
|
|
66
|
-
credentialSecret:
|
|
94
|
+
credentialSecret:
|
|
95
|
+
eventData.spec.credentials.aws?.aws_secret_access_key || "",
|
|
67
96
|
};
|
|
68
97
|
} else if (eventData.spec.credentials.azure) {
|
|
69
98
|
providerType = "azure";
|
|
@@ -87,28 +116,72 @@ const extractCloudProviderCredentials = (
|
|
|
87
116
|
};
|
|
88
117
|
|
|
89
118
|
/**
|
|
90
|
-
* Determine account status from event
|
|
119
|
+
* Determine the canonical account status from a WebSocket event.
|
|
120
|
+
*
|
|
121
|
+
* Priority order:
|
|
122
|
+
* 1. Soft-deleted accounts → 'deleting'
|
|
123
|
+
* 2. validCredentials status reported by the backend (covers both
|
|
124
|
+
* success and the async credential-validation path)
|
|
125
|
+
* 3. Keep the existing status so we never regress a terminal state
|
|
126
|
+
* (e.g. don't overwrite 'invalid_credentials' with 'pending')
|
|
127
|
+
* 4. Default to 'pending' for brand-new accounts
|
|
91
128
|
*/
|
|
92
129
|
const determineAccountStatus = (
|
|
93
130
|
eventData: any,
|
|
94
|
-
existingAccount: Account | undefined
|
|
131
|
+
existingAccount: Account | undefined,
|
|
95
132
|
): string => {
|
|
96
133
|
if (eventData.meta?.deleted) {
|
|
97
134
|
return "deleting";
|
|
98
135
|
}
|
|
99
|
-
|
|
100
|
-
|
|
136
|
+
const rawStatus: string | undefined =
|
|
137
|
+
eventData.status?.validCredentials?.status;
|
|
138
|
+
if (rawStatus) {
|
|
139
|
+
if (CREDENTIAL_ERROR_CODES.has(rawStatus)) {
|
|
140
|
+
return "invalid_credentials";
|
|
141
|
+
}
|
|
142
|
+
return rawStatus;
|
|
101
143
|
}
|
|
102
|
-
if (existingAccount?.status) {
|
|
144
|
+
if (existingAccount?.status && existingAccount.status !== "pending") {
|
|
103
145
|
return existingAccount.status;
|
|
104
146
|
}
|
|
105
147
|
return "pending";
|
|
106
148
|
};
|
|
107
149
|
|
|
150
|
+
/**
|
|
151
|
+
* Translates account error notifications → account.status on accountsMap
|
|
152
|
+
* so that waitForAccountStatus only needs to poll account.status, not notifications.
|
|
153
|
+
*
|
|
154
|
+
* Called from the websocket-manager's `user` event case immediately after
|
|
155
|
+
* handleUserEvent so the status is always written in the same event-loop tick.
|
|
156
|
+
*/
|
|
157
|
+
export const syncAccountStatusFromNotifications = (
|
|
158
|
+
notifications: any[] = [],
|
|
159
|
+
accountsMap: Map<string, Account>,
|
|
160
|
+
): void => {
|
|
161
|
+
for (const notification of notifications) {
|
|
162
|
+
if (notification.type !== "error") continue;
|
|
163
|
+
if (
|
|
164
|
+
notification.subtype !== "account-creation-error" &&
|
|
165
|
+
notification.subtype !== "account-update-error"
|
|
166
|
+
)
|
|
167
|
+
continue;
|
|
168
|
+
|
|
169
|
+
const accountName: string = notification.data?.account;
|
|
170
|
+
if (!accountName) continue;
|
|
171
|
+
|
|
172
|
+
const account = accountsMap.get(accountName);
|
|
173
|
+
if (!account || ACCOUNT_ERROR_STATUSES.has(account.status)) continue;
|
|
174
|
+
|
|
175
|
+
const code: string = notification.info_content?.code ?? "";
|
|
176
|
+
accountsMap.set(accountName, {
|
|
177
|
+
...account,
|
|
178
|
+
status: resolveErrorStatus(code),
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
};
|
|
108
182
|
|
|
109
183
|
/**
|
|
110
|
-
* Handles the "account" event from WebSocket messages
|
|
111
|
-
* Processes account data updates and cloud provider credentials
|
|
184
|
+
* Handles the "account" kind event from WebSocket messages.
|
|
112
185
|
*/
|
|
113
186
|
export const handleAccountEvent = ({
|
|
114
187
|
entityId,
|
|
@@ -117,11 +190,13 @@ export const handleAccountEvent = ({
|
|
|
117
190
|
accountsMap,
|
|
118
191
|
}: HandleAccountEventParams): HandleAccountEventResult => {
|
|
119
192
|
const accountTenantId = parentParts.tenant;
|
|
120
|
-
const { providerType, credentials } =
|
|
193
|
+
const { providerType, credentials } =
|
|
194
|
+
extractCloudProviderCredentials(eventData);
|
|
121
195
|
const accountLabels: Record<string, string> = eventData.meta.labels;
|
|
122
196
|
const hasCredentials = "__axebow::managedCredentials" in accountLabels;
|
|
123
197
|
const existingAccount = accountsMap.get(entityId);
|
|
124
198
|
const accountStatus = determineAccountStatus(eventData, existingAccount);
|
|
199
|
+
|
|
125
200
|
const newAccount: Account = {
|
|
126
201
|
id: entityId,
|
|
127
202
|
name: entityId,
|
|
@@ -196,9 +271,8 @@ export const handleAccountEvent = ({
|
|
|
196
271
|
};
|
|
197
272
|
};
|
|
198
273
|
|
|
199
|
-
|
|
200
274
|
/**
|
|
201
|
-
* Handles successful account operations (CREATE, UPDATE, DELETE)
|
|
275
|
+
* Handles successful account operations (CREATE, UPDATE, DELETE).
|
|
202
276
|
*/
|
|
203
277
|
export const handleAccountOperationSuccess = ({
|
|
204
278
|
action,
|
|
@@ -206,57 +280,37 @@ export const handleAccountOperationSuccess = ({
|
|
|
206
280
|
originalData,
|
|
207
281
|
}: HandleAccountOperationSuccessParams): HandleAccountOperationSuccessResult => {
|
|
208
282
|
if (action === "DELETE") {
|
|
209
|
-
const accountNotification: Notification = {
|
|
210
|
-
type: "success",
|
|
211
|
-
subtype: "account-deleted",
|
|
212
|
-
date: Date.now().toString(),
|
|
213
|
-
status: "unread",
|
|
214
|
-
callToAction: false,
|
|
215
|
-
data: {
|
|
216
|
-
account: originalData.name,
|
|
217
|
-
tenant: originalData.tenant,
|
|
218
|
-
},
|
|
219
|
-
};
|
|
220
|
-
|
|
221
283
|
return {
|
|
222
284
|
updatedAccount: null,
|
|
223
285
|
shouldDelete: true,
|
|
224
|
-
notification:
|
|
286
|
+
notification: {
|
|
287
|
+
type: "success",
|
|
288
|
+
subtype: "account-deleted",
|
|
289
|
+
date: Date.now().toString(),
|
|
290
|
+
status: "unread",
|
|
291
|
+
callToAction: false,
|
|
292
|
+
data: { account: originalData.name, tenant: originalData.tenant },
|
|
293
|
+
},
|
|
225
294
|
eventType: "deleted",
|
|
226
295
|
};
|
|
227
296
|
}
|
|
228
297
|
|
|
229
298
|
if (originalData) {
|
|
230
|
-
const updatedAccount = { ...originalData, status: "active" };
|
|
231
|
-
|
|
232
|
-
let subtype: string;
|
|
233
|
-
let eventType: "created" | "updated" | null = null;
|
|
234
|
-
|
|
235
|
-
if (action === "CREATE") {
|
|
236
|
-
subtype = "account-created";
|
|
237
|
-
eventType = "created";
|
|
238
|
-
} else {
|
|
239
|
-
subtype = "account-updated";
|
|
240
|
-
eventType = "updated";
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
const accountNotification: Notification = {
|
|
244
|
-
type: "success",
|
|
245
|
-
subtype,
|
|
246
|
-
date: Date.now().toString(),
|
|
247
|
-
status: "unread",
|
|
248
|
-
callToAction: false,
|
|
249
|
-
data: {
|
|
250
|
-
account: updatedAccount.name,
|
|
251
|
-
tenant: updatedAccount.tenant,
|
|
252
|
-
},
|
|
253
|
-
};
|
|
299
|
+
const updatedAccount: Account = { ...originalData, status: "active" };
|
|
300
|
+
const isCreate = action === "CREATE";
|
|
254
301
|
|
|
255
302
|
return {
|
|
256
303
|
updatedAccount,
|
|
257
304
|
shouldDelete: false,
|
|
258
|
-
notification:
|
|
259
|
-
|
|
305
|
+
notification: {
|
|
306
|
+
type: "success",
|
|
307
|
+
subtype: isCreate ? "account-created" : "account-updated",
|
|
308
|
+
date: Date.now().toString(),
|
|
309
|
+
status: "unread",
|
|
310
|
+
callToAction: false,
|
|
311
|
+
data: { account: updatedAccount.name, tenant: updatedAccount.tenant },
|
|
312
|
+
},
|
|
313
|
+
eventType: isCreate ? "created" : "updated",
|
|
260
314
|
};
|
|
261
315
|
}
|
|
262
316
|
|
|
@@ -275,9 +329,12 @@ export const handleAccountOperationSuccess = ({
|
|
|
275
329
|
};
|
|
276
330
|
};
|
|
277
331
|
|
|
278
|
-
|
|
279
332
|
/**
|
|
280
|
-
* Handles failed account operations (CREATE, UPDATE, DELETE)
|
|
333
|
+
* Handles failed account operations (CREATE, UPDATE, DELETE).
|
|
334
|
+
*
|
|
335
|
+
* For CREATE failures the account is removed from the map (shouldDelete = true).
|
|
336
|
+
* For UPDATE failures the existing account is kept but stamped with the
|
|
337
|
+
* resolved error status so waitForAccountStatus can terminate cleanly.
|
|
281
338
|
*/
|
|
282
339
|
export const handleAccountOperationError = ({
|
|
283
340
|
action,
|
|
@@ -285,52 +342,53 @@ export const handleAccountOperationError = ({
|
|
|
285
342
|
originalData,
|
|
286
343
|
error,
|
|
287
344
|
}: HandleAccountOperationErrorParams): HandleAccountOperationErrorResult => {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
let shouldDelete = false;
|
|
345
|
+
const isCreate = action === "CREATE";
|
|
346
|
+
const isUpdate = action === "UPDATE";
|
|
291
347
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
348
|
+
const subtype = isCreate
|
|
349
|
+
? "account-creation-error"
|
|
350
|
+
: isUpdate
|
|
351
|
+
? "account-update-error"
|
|
352
|
+
: "account-deletion-error";
|
|
353
|
+
|
|
354
|
+
const eventType: "creationError" | "updateError" | "deletionError" = isCreate
|
|
355
|
+
? "creationError"
|
|
356
|
+
: isUpdate
|
|
357
|
+
? "updateError"
|
|
358
|
+
: "deletionError";
|
|
359
|
+
const errorCode: string = error?.error?.code ?? error?.code ?? "";
|
|
360
|
+
const errorStatus = resolveErrorStatus(errorCode);
|
|
303
361
|
|
|
304
|
-
const
|
|
362
|
+
const notification: Notification = {
|
|
305
363
|
type: "error",
|
|
306
364
|
subtype,
|
|
307
365
|
date: Date.now().toString(),
|
|
308
366
|
status: "unread",
|
|
309
367
|
info_content: {
|
|
310
|
-
code:
|
|
311
|
-
message:
|
|
312
|
-
|
|
368
|
+
code: errorCode || "UNKNOWN_ERROR",
|
|
369
|
+
message:
|
|
370
|
+
error?.error?.content ?? error?.error?.message ?? "Unknown error",
|
|
371
|
+
timestamp: error?.error?.timestamp ?? Date.now().toString(),
|
|
313
372
|
},
|
|
314
373
|
callToAction: false,
|
|
315
374
|
data: {
|
|
316
|
-
account:
|
|
317
|
-
|
|
375
|
+
account:
|
|
376
|
+
entityName || originalData?.name || originalData?.account || "unknown",
|
|
377
|
+
tenant: originalData?.tenant ?? "unknown",
|
|
318
378
|
},
|
|
379
|
+
userError: true,
|
|
319
380
|
};
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
status: "error",
|
|
381
|
+
if (isCreate) {
|
|
382
|
+
return {
|
|
383
|
+
updatedAccount: null,
|
|
384
|
+
shouldDelete: true,
|
|
385
|
+
notification,
|
|
386
|
+
eventType,
|
|
327
387
|
};
|
|
328
388
|
}
|
|
389
|
+
const updatedAccount: Account | null = originalData
|
|
390
|
+
? { ...originalData, status: errorStatus }
|
|
391
|
+
: null;
|
|
329
392
|
|
|
330
|
-
return {
|
|
331
|
-
|
|
332
|
-
shouldDelete,
|
|
333
|
-
notification: accountErrorNotification,
|
|
334
|
-
eventType,
|
|
335
|
-
};
|
|
336
|
-
};
|
|
393
|
+
return { updatedAccount, shouldDelete: false, notification, eventType };
|
|
394
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kumori/aurora-backend-handler",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.90",
|
|
4
4
|
"description": "backend handler",
|
|
5
5
|
"main": "backend-handler.ts",
|
|
6
6
|
"scripts": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"glob": "^11.0.0"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@kumori/aurora-interfaces": "^1.0.
|
|
14
|
+
"@kumori/aurora-interfaces": "^1.0.11",
|
|
15
15
|
"@kumori/kumori-dsl-generator": "^1.0.4",
|
|
16
16
|
"@kumori/kumori-module-generator": "^1.1.6",
|
|
17
17
|
"ts-node": "^10.9.2",
|
package/websocket-manager.ts
CHANGED
|
@@ -53,6 +53,7 @@ import {
|
|
|
53
53
|
handleAccountEvent,
|
|
54
54
|
handleAccountOperationError,
|
|
55
55
|
handleAccountOperationSuccess,
|
|
56
|
+
syncAccountStatusFromNotifications,
|
|
56
57
|
} from "./helpers/account-helper";
|
|
57
58
|
import {
|
|
58
59
|
handleCAEvent,
|
|
@@ -191,7 +192,6 @@ const REPORTING_ITERATIONS = 5;
|
|
|
191
192
|
const REPORTING_INTERVAL = 1000;
|
|
192
193
|
let hasLoadedReportingOnce = false;
|
|
193
194
|
let recentlyUpdatedServices = new Map<string, Service>();
|
|
194
|
-
|
|
195
195
|
/**
|
|
196
196
|
* Helper function to safely stringify error objects
|
|
197
197
|
*/
|
|
@@ -644,6 +644,7 @@ const handleEvent = async (message: WSMessage) => {
|
|
|
644
644
|
userEventResult.deletedTenantKeys.forEach((key) => {
|
|
645
645
|
tenantsMap.delete(key);
|
|
646
646
|
});
|
|
647
|
+
syncAccountStatusFromNotifications(userData.notifications, accountsMap);
|
|
647
648
|
break;
|
|
648
649
|
case "environment":
|
|
649
650
|
const envEventResult = handleEnvironmentEvent({
|
|
@@ -1453,6 +1454,7 @@ const handleOperationError = (operation: PendingOperation, error: any) => {
|
|
|
1453
1454
|
} else if (accErrorResult.updatedAccount) {
|
|
1454
1455
|
accountsMap.set(entityName, accErrorResult.updatedAccount);
|
|
1455
1456
|
}
|
|
1457
|
+
|
|
1456
1458
|
if (accErrorResult.eventType === "creationError") {
|
|
1457
1459
|
eventHelper.account.publish.creationError(originalData);
|
|
1458
1460
|
} else if (accErrorResult.eventType === "updateError") {
|