@kumori/aurora-backend-handler 1.1.84 → 1.1.86
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/tenant-api-service.ts +51 -189
- package/helpers/token-helper.ts +20 -0
- package/package.json +1 -1
- package/websocket-manager.ts +11 -2
|
@@ -16,6 +16,35 @@ interface DregistryBody {
|
|
|
16
16
|
docker_password: string;
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Extracts a user-facing code/content pair from a failed request.
|
|
22
|
+
* Errors coming back from the WS layer are usually nested under `.error`
|
|
23
|
+
* (e.g. `{ error: { code, content } }`), but some server-side rejections
|
|
24
|
+
* (e.g. plan/limits validation) return the fields flat on the error object
|
|
25
|
+
* itself (`{ code, content }`). Without this fallback those errors were
|
|
26
|
+
* silently reported as "Unknown error" instead of surfacing the real code.
|
|
27
|
+
*/
|
|
28
|
+
const extractWsErrorInfo = (
|
|
29
|
+
err: unknown
|
|
30
|
+
): { code: string; content: string } => {
|
|
31
|
+
const candidate =
|
|
32
|
+
err && typeof err === "object" && "error" in err
|
|
33
|
+
? (err as any).error
|
|
34
|
+
: err;
|
|
35
|
+
|
|
36
|
+
const code =
|
|
37
|
+
candidate && typeof candidate === "object" && typeof candidate.code === "string"
|
|
38
|
+
? candidate.code
|
|
39
|
+
: "Unknown error";
|
|
40
|
+
const content =
|
|
41
|
+
candidate && typeof candidate === "object" && typeof candidate.content === "string"
|
|
42
|
+
? candidate.content
|
|
43
|
+
: "Unknown error";
|
|
44
|
+
|
|
45
|
+
return { code, content };
|
|
46
|
+
};
|
|
47
|
+
|
|
19
48
|
/**
|
|
20
49
|
* Function to create a tenant using the global WebSocket connection
|
|
21
50
|
* @param tenant Tenant object with the data of the tenant
|
|
@@ -79,23 +108,8 @@ export const createTenant = async (tenant: Tenant, security: Security) => {
|
|
|
79
108
|
tenant: tenant.name,
|
|
80
109
|
webSocketStatus: getWebSocketStatus(),
|
|
81
110
|
});
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (
|
|
86
|
-
typeof error === "object" &&
|
|
87
|
-
error !== null &&
|
|
88
|
-
"error" in error &&
|
|
89
|
-
typeof (error as any).error === "object" &&
|
|
90
|
-
(error as any).error !== null
|
|
91
|
-
) {
|
|
92
|
-
if ("code" in (error as any).error) {
|
|
93
|
-
contentMessage = (error as any).error.code;
|
|
94
|
-
}
|
|
95
|
-
if ("content" in (error as any).error) {
|
|
96
|
-
errorContent = (error as any).error.content;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
111
|
+
const { code: contentMessage, content: errorContent } =
|
|
112
|
+
extractWsErrorInfo(error);
|
|
99
113
|
const tenantCreationErrorNotification: Notification = {
|
|
100
114
|
type: "error",
|
|
101
115
|
subtype: errors.tenant.creationError.subtype,
|
|
@@ -146,24 +160,8 @@ export const deleteTenant = async (tenant: Tenant, security: string) => {
|
|
|
146
160
|
return response;
|
|
147
161
|
} catch (err) {
|
|
148
162
|
console.error("Error in tenant deletion WebSocket request:", err);
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
let errorContent = "Unknown error";
|
|
152
|
-
|
|
153
|
-
if (
|
|
154
|
-
typeof err === "object" &&
|
|
155
|
-
err !== null &&
|
|
156
|
-
"error" in err &&
|
|
157
|
-
typeof (err as any).error === "object" &&
|
|
158
|
-
(err as any).error !== null
|
|
159
|
-
) {
|
|
160
|
-
if ("code" in (err as any).error) {
|
|
161
|
-
contentMessage = (err as any).error.code;
|
|
162
|
-
}
|
|
163
|
-
if ("content" in (err as any).error) {
|
|
164
|
-
errorContent = (err as any).error.content;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
163
|
+
const { code: contentMessage, content: errorContent } =
|
|
164
|
+
extractWsErrorInfo(err);
|
|
167
165
|
const tenantDeletionErrorNotification: Notification = {
|
|
168
166
|
type: "error",
|
|
169
167
|
subtype: errors.tenant.deletionError.subtype,
|
|
@@ -244,24 +242,8 @@ export const updateTenant = async (tenant: Tenant, security: string) => {
|
|
|
244
242
|
return response;
|
|
245
243
|
} catch (err) {
|
|
246
244
|
console.error("Error in tenant update WebSocket request:", err);
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
let errorContent = "Unknown error";
|
|
250
|
-
|
|
251
|
-
if (
|
|
252
|
-
typeof err === "object" &&
|
|
253
|
-
err !== null &&
|
|
254
|
-
"error" in err &&
|
|
255
|
-
typeof (err as any).error === "object" &&
|
|
256
|
-
(err as any).error !== null
|
|
257
|
-
) {
|
|
258
|
-
if ("code" in (err as any).error) {
|
|
259
|
-
contentMessage = (err as any).error.code;
|
|
260
|
-
}
|
|
261
|
-
if ("content" in (err as any).error) {
|
|
262
|
-
errorContent = (err as any).error.content;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
245
|
+
const { code: contentMessage, content: errorContent } =
|
|
246
|
+
extractWsErrorInfo(err);
|
|
265
247
|
const tenantUpdateErrorNotification: Notification = {
|
|
266
248
|
type: "error",
|
|
267
249
|
subtype: errors.tenant.updateError.subtype,
|
|
@@ -586,23 +568,8 @@ export const createRegistry = async (
|
|
|
586
568
|
webSocketStatus: getWebSocketStatus(),
|
|
587
569
|
});
|
|
588
570
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
if (
|
|
593
|
-
typeof error === "object" &&
|
|
594
|
-
error !== null &&
|
|
595
|
-
"error" in error &&
|
|
596
|
-
typeof (error as any).error === "object" &&
|
|
597
|
-
(error as any).error !== null
|
|
598
|
-
) {
|
|
599
|
-
if ("code" in (error as any).error) {
|
|
600
|
-
contentMessage = (error as any).error.code;
|
|
601
|
-
}
|
|
602
|
-
if ("content" in (error as any).error) {
|
|
603
|
-
errorContent = (error as any).error.content;
|
|
604
|
-
}
|
|
605
|
-
}
|
|
571
|
+
const { code: contentMessage, content: errorContent } =
|
|
572
|
+
extractWsErrorInfo(error);
|
|
606
573
|
|
|
607
574
|
const dregistryCreationErrorNotification: Notification = {
|
|
608
575
|
type: "error",
|
|
@@ -689,23 +656,8 @@ export const updateRegistry = async (
|
|
|
689
656
|
webSocketStatus: getWebSocketStatus(),
|
|
690
657
|
});
|
|
691
658
|
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
if (
|
|
696
|
-
typeof error === "object" &&
|
|
697
|
-
error !== null &&
|
|
698
|
-
"error" in error &&
|
|
699
|
-
typeof (error as any).error === "object" &&
|
|
700
|
-
(error as any).error !== null
|
|
701
|
-
) {
|
|
702
|
-
if ("code" in (error as any).error) {
|
|
703
|
-
contentMessage = (error as any).error.code;
|
|
704
|
-
}
|
|
705
|
-
if ("content" in (error as any).error) {
|
|
706
|
-
errorContent = (error as any).error.content;
|
|
707
|
-
}
|
|
708
|
-
}
|
|
659
|
+
const { code: contentMessage, content: errorContent } =
|
|
660
|
+
extractWsErrorInfo(error);
|
|
709
661
|
|
|
710
662
|
const dregistryUpdateErrorNotification: Notification = {
|
|
711
663
|
type: "error",
|
|
@@ -773,23 +725,8 @@ export const deleteRegistry = async (
|
|
|
773
725
|
webSocketStatus: getWebSocketStatus(),
|
|
774
726
|
});
|
|
775
727
|
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
if (
|
|
780
|
-
typeof error === "object" &&
|
|
781
|
-
error !== null &&
|
|
782
|
-
"error" in error &&
|
|
783
|
-
typeof (error as any).error === "object" &&
|
|
784
|
-
(error as any).error !== null
|
|
785
|
-
) {
|
|
786
|
-
if ("code" in (error as any).error) {
|
|
787
|
-
contentMessage = (error as any).error.code;
|
|
788
|
-
}
|
|
789
|
-
if ("content" in (error as any).error) {
|
|
790
|
-
errorContent = (error as any).error.content;
|
|
791
|
-
}
|
|
792
|
-
}
|
|
728
|
+
const { code: contentMessage, content: errorContent } =
|
|
729
|
+
extractWsErrorInfo(error);
|
|
793
730
|
|
|
794
731
|
const dregistryDeletionErrorNotification: Notification = {
|
|
795
732
|
type: "error",
|
|
@@ -859,23 +796,8 @@ export const inviteUser = async (
|
|
|
859
796
|
role: role,
|
|
860
797
|
webSocketStatus: getWebSocketStatus(),
|
|
861
798
|
});
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
if (
|
|
866
|
-
typeof error === "object" &&
|
|
867
|
-
error !== null &&
|
|
868
|
-
"error" in error &&
|
|
869
|
-
typeof (error as any).error === "object" &&
|
|
870
|
-
(error as any).error !== null
|
|
871
|
-
) {
|
|
872
|
-
if ("code" in (error as any).error) {
|
|
873
|
-
contentMessage = (error as any).error.code;
|
|
874
|
-
}
|
|
875
|
-
if ("content" in (error as any).error) {
|
|
876
|
-
errorContent = (error as any).error.content;
|
|
877
|
-
}
|
|
878
|
-
}
|
|
799
|
+
const { code: contentMessage, content: errorContent } =
|
|
800
|
+
extractWsErrorInfo(error);
|
|
879
801
|
const tenantInviteErrorNotification: Notification = {
|
|
880
802
|
type: "error",
|
|
881
803
|
subtype: errors.tenant.userInviteError.subtype,
|
|
@@ -938,23 +860,8 @@ export const removeUser = async (
|
|
|
938
860
|
userId: userId,
|
|
939
861
|
webSocketStatus: getWebSocketStatus(),
|
|
940
862
|
});
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
if (
|
|
945
|
-
typeof error === "object" &&
|
|
946
|
-
error !== null &&
|
|
947
|
-
"error" in error &&
|
|
948
|
-
typeof (error as any).error === "object" &&
|
|
949
|
-
(error as any).error !== null
|
|
950
|
-
) {
|
|
951
|
-
if ("code" in (error as any).error) {
|
|
952
|
-
contentMessage = (error as any).error.code;
|
|
953
|
-
}
|
|
954
|
-
if ("content" in (error as any).error) {
|
|
955
|
-
errorContent = (error as any).error.content;
|
|
956
|
-
}
|
|
957
|
-
}
|
|
863
|
+
const { code: contentMessage, content: errorContent } =
|
|
864
|
+
extractWsErrorInfo(error);
|
|
958
865
|
const tenantUserRemovedErrorNotification: Notification = {
|
|
959
866
|
type: "error",
|
|
960
867
|
subtype: errors.tenant.userRemovedError.subtype,
|
|
@@ -1021,23 +928,8 @@ export const updateUserRole = async (
|
|
|
1021
928
|
role: role,
|
|
1022
929
|
webSocketStatus: getWebSocketStatus(),
|
|
1023
930
|
});
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
if (
|
|
1028
|
-
typeof error === "object" &&
|
|
1029
|
-
error !== null &&
|
|
1030
|
-
"error" in error &&
|
|
1031
|
-
typeof (error as any).error === "object" &&
|
|
1032
|
-
(error as any).error !== null
|
|
1033
|
-
) {
|
|
1034
|
-
if ("code" in (error as any).error) {
|
|
1035
|
-
contentMessage = (error as any).error.code;
|
|
1036
|
-
}
|
|
1037
|
-
if ("content" in (error as any).error) {
|
|
1038
|
-
errorContent = (error as any).error.content;
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
931
|
+
const { code: contentMessage, content: errorContent } =
|
|
932
|
+
extractWsErrorInfo(error);
|
|
1041
933
|
const tenantUserUpdatedErrorNotification: Notification = {
|
|
1042
934
|
type: "error",
|
|
1043
935
|
subtype: errors.tenant.roleUpdateError.subtype,
|
|
@@ -1092,23 +984,8 @@ export const acceptInvite = async (tenant: string, security: string) => {
|
|
|
1092
984
|
tenant: tenant,
|
|
1093
985
|
webSocketStatus: getWebSocketStatus(),
|
|
1094
986
|
});
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
if (
|
|
1099
|
-
typeof error === "object" &&
|
|
1100
|
-
error !== null &&
|
|
1101
|
-
"error" in error &&
|
|
1102
|
-
typeof (error as any).error === "object" &&
|
|
1103
|
-
(error as any).error !== null
|
|
1104
|
-
) {
|
|
1105
|
-
if ("code" in (error as any).error) {
|
|
1106
|
-
contentMessage = (error as any).error.code;
|
|
1107
|
-
}
|
|
1108
|
-
if ("content" in (error as any).error) {
|
|
1109
|
-
errorContent = (error as any).error.content;
|
|
1110
|
-
}
|
|
1111
|
-
}
|
|
987
|
+
const { code: contentMessage, content: errorContent } =
|
|
988
|
+
extractWsErrorInfo(error);
|
|
1112
989
|
const tenantInviteAcceptedErrorNotification: Notification = {
|
|
1113
990
|
type: "error",
|
|
1114
991
|
subtype: errors.tenant.inviteAcceptError.subtype,
|
|
@@ -1177,23 +1054,8 @@ export const rejectInvite = async (tenant: string, security: string, leave: bool
|
|
|
1177
1054
|
tenant: tenant,
|
|
1178
1055
|
webSocketStatus: getWebSocketStatus(),
|
|
1179
1056
|
});
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
if (
|
|
1184
|
-
typeof error === "object" &&
|
|
1185
|
-
error !== null &&
|
|
1186
|
-
"error" in error &&
|
|
1187
|
-
typeof (error as any).error === "object" &&
|
|
1188
|
-
(error as any).error !== null
|
|
1189
|
-
) {
|
|
1190
|
-
if ("code" in (error as any).error) {
|
|
1191
|
-
contentMessage = (error as any).error.code;
|
|
1192
|
-
}
|
|
1193
|
-
if ("content" in (error as any).error) {
|
|
1194
|
-
errorContent = (error as any).error.content;
|
|
1195
|
-
}
|
|
1196
|
-
}
|
|
1057
|
+
const { code: contentMessage, content: errorContent } =
|
|
1058
|
+
extractWsErrorInfo(error);
|
|
1197
1059
|
const tenantInviteRejectedErrorNotification: Notification = {
|
|
1198
1060
|
type: "error",
|
|
1199
1061
|
subtype: errors.tenant.inviteRejectError.subtype,
|
package/helpers/token-helper.ts
CHANGED
|
@@ -5,6 +5,7 @@ interface HandleTokenEventParams {
|
|
|
5
5
|
eventData: any;
|
|
6
6
|
tokenMap: Map<string, Token>;
|
|
7
7
|
userData: UserData;
|
|
8
|
+
deletedTokenIds: Set<string>;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
interface HandleTokenEventResult {
|
|
@@ -24,10 +25,26 @@ export const handleTokenEvent = ({
|
|
|
24
25
|
eventData,
|
|
25
26
|
tokenMap,
|
|
26
27
|
userData,
|
|
28
|
+
deletedTokenIds,
|
|
27
29
|
}: HandleTokenEventParams): HandleTokenEventResult => {
|
|
28
30
|
const tokenParentKind = eventData.id.parent?.kind;
|
|
29
31
|
const tokenId = eventData.id.name;
|
|
30
32
|
|
|
33
|
+
if (tokenParentKind === "user" && deletedTokenIds.has(tokenId)) {
|
|
34
|
+
// A tombstoned token (already explicitly deleted by the user) must
|
|
35
|
+
// never be resurrected by a stale/out-of-order "token" event -
|
|
36
|
+
// e.g. one reflecting backend state that hasn't caught up with the
|
|
37
|
+
// deletion yet.
|
|
38
|
+
return {
|
|
39
|
+
isUserToken: false,
|
|
40
|
+
isClusterToken: false,
|
|
41
|
+
userToken: null,
|
|
42
|
+
clusterToken: null,
|
|
43
|
+
updatedUserTokens: userData.tokens,
|
|
44
|
+
tokenId,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
31
48
|
if (tokenParentKind === "user") {
|
|
32
49
|
const tokenInMap = tokenMap.get(tokenId);
|
|
33
50
|
|
|
@@ -112,6 +129,7 @@ interface HandleTokenDeletionParams {
|
|
|
112
129
|
tokenId: string;
|
|
113
130
|
tokenMap: Map<string, Token>;
|
|
114
131
|
userData: UserData;
|
|
132
|
+
deletedTokenIds: Set<string>;
|
|
115
133
|
}
|
|
116
134
|
|
|
117
135
|
interface HandleTokenDeletionResult {
|
|
@@ -124,7 +142,9 @@ export const handleTokenDeletion = ({
|
|
|
124
142
|
tokenId,
|
|
125
143
|
tokenMap,
|
|
126
144
|
userData,
|
|
145
|
+
deletedTokenIds,
|
|
127
146
|
}: HandleTokenDeletionParams): HandleTokenDeletionResult => {
|
|
147
|
+
deletedTokenIds.add(tokenId);
|
|
128
148
|
const tokenIndex = userData.tokens.findIndex((t) => t.name === tokenId);
|
|
129
149
|
if (tokenIndex === -1) {
|
|
130
150
|
return {
|
package/package.json
CHANGED
package/websocket-manager.ts
CHANGED
|
@@ -174,6 +174,7 @@ let accountsMap = new Map<string, Account>();
|
|
|
174
174
|
let revisionsMap = new Map<string, Revision>();
|
|
175
175
|
let roleMap = new Map<string, Role[]>();
|
|
176
176
|
let tokenMap = new Map<string, Token>();
|
|
177
|
+
let deletedTokenIds = new Set<string>();
|
|
177
178
|
let platformInfo: Platform | null = null;
|
|
178
179
|
let isPlatformInfoLoading = false;
|
|
179
180
|
let isPlatformInfoLoaded = false;
|
|
@@ -639,7 +640,11 @@ const rebuildHierarchy = () => {
|
|
|
639
640
|
notificationsEnabled: preservedUserData.notificationsEnabled,
|
|
640
641
|
organizations: Array.from(organizationsMap.values()),
|
|
641
642
|
clusterTokens: Array.from(clusterTokensMap.values()),
|
|
642
|
-
tokens:
|
|
643
|
+
tokens: (
|
|
644
|
+
tokenMap.size > 0
|
|
645
|
+
? (preservedUserData.tokens || []).filter(t => tokenMap.has(t.name))
|
|
646
|
+
: (preservedUserData.tokens || [])
|
|
647
|
+
).filter(t => !deletedTokenIds.has(t.name)),
|
|
643
648
|
tenants: Array.from(tenantsMap.values()),
|
|
644
649
|
axebowPlan: preservedUserData.axebowPlan,
|
|
645
650
|
companyName: preservedUserData.companyName,
|
|
@@ -1129,6 +1134,7 @@ const handleEvent = async (message: WSMessage) => {
|
|
|
1129
1134
|
eventData,
|
|
1130
1135
|
tokenMap,
|
|
1131
1136
|
userData,
|
|
1137
|
+
deletedTokenIds,
|
|
1132
1138
|
});
|
|
1133
1139
|
|
|
1134
1140
|
if (tokenResult.isUserToken) {
|
|
@@ -1518,6 +1524,7 @@ const handleOperationSuccess = (operation: PendingOperation, response: any) => {
|
|
|
1518
1524
|
tokenId: deletedTokenId,
|
|
1519
1525
|
tokenMap,
|
|
1520
1526
|
userData,
|
|
1527
|
+
deletedTokenIds,
|
|
1521
1528
|
});
|
|
1522
1529
|
if (tokenDeletionResult.removed) {
|
|
1523
1530
|
userData.tokens = tokenDeletionResult.updatedUserTokens;
|
|
@@ -1916,6 +1923,7 @@ const handleDeleteEvent = async (message: WSMessage) => {
|
|
|
1916
1923
|
tokenId: keyParts.token,
|
|
1917
1924
|
tokenMap,
|
|
1918
1925
|
userData,
|
|
1926
|
+
deletedTokenIds,
|
|
1919
1927
|
});
|
|
1920
1928
|
if (tokenDeletionResult.removed) {
|
|
1921
1929
|
userData.tokens = tokenDeletionResult.updatedUserTokens;
|
|
@@ -2056,7 +2064,8 @@ export const updateUserComplete = (updatedUserData: UserData): User => {
|
|
|
2056
2064
|
);
|
|
2057
2065
|
const mergedTokens = [...(updatedUserData.tokens || []), ...localOnlyTokens]
|
|
2058
2066
|
.filter((t, index, arr) => arr.findIndex(x => x.name === t.name) === index)
|
|
2059
|
-
.filter(t => tokenMap.size === 0 || tokenMap.has(t.name))
|
|
2067
|
+
.filter(t => tokenMap.size === 0 || tokenMap.has(t.name))
|
|
2068
|
+
.filter(t => !deletedTokenIds.has(t.name));
|
|
2060
2069
|
|
|
2061
2070
|
userData = {
|
|
2062
2071
|
id: updatedUserData.id || userData.id,
|