@kumori/aurora-backend-handler 1.1.83 → 1.1.85

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.
@@ -1,10 +1,11 @@
1
- import { ClusterToken, Token, UserData } from "@kumori/aurora-interfaces";
1
+ import { ClusterToken, errors, Notification, Token, UserData } from "@kumori/aurora-interfaces";
2
2
 
3
3
 
4
4
  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
 
@@ -107,4 +124,56 @@ export const handleTokenOperationSuccess = ({
107
124
  return {
108
125
  token: tokenWithData,
109
126
  };
127
+ };
128
+ interface HandleTokenDeletionParams {
129
+ tokenId: string;
130
+ tokenMap: Map<string, Token>;
131
+ userData: UserData;
132
+ deletedTokenIds: Set<string>;
133
+ }
134
+
135
+ interface HandleTokenDeletionResult {
136
+ removed: boolean;
137
+ updatedUserTokens: Token[];
138
+ notification: Notification | null;
139
+ }
140
+
141
+ export const handleTokenDeletion = ({
142
+ tokenId,
143
+ tokenMap,
144
+ userData,
145
+ deletedTokenIds,
146
+ }: HandleTokenDeletionParams): HandleTokenDeletionResult => {
147
+ deletedTokenIds.add(tokenId);
148
+ const tokenIndex = userData.tokens.findIndex((t) => t.name === tokenId);
149
+ if (tokenIndex === -1) {
150
+ return {
151
+ removed: false,
152
+ updatedUserTokens: userData.tokens,
153
+ notification: null,
154
+ };
155
+ }
156
+
157
+ const deletedToken = userData.tokens[tokenIndex];
158
+ const updatedUserTokens = [...userData.tokens];
159
+ updatedUserTokens.splice(tokenIndex, 1);
160
+ tokenMap.delete(tokenId);
161
+
162
+ const notification: Notification = {
163
+ type: "success",
164
+ subtype: errors.user.tokenDeleted.subtype,
165
+ date: Date.now().toString(),
166
+ status: "unread",
167
+ callToAction: false,
168
+ data: {
169
+ tokenName: deletedToken.name,
170
+ tenant: deletedToken.tenant,
171
+ },
172
+ };
173
+
174
+ return {
175
+ removed: true,
176
+ updatedUserTokens,
177
+ notification,
178
+ };
110
179
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kumori/aurora-backend-handler",
3
- "version": "1.1.83",
3
+ "version": "1.1.85",
4
4
  "description": "backend handler",
5
5
  "main": "backend-handler.ts",
6
6
  "scripts": {
@@ -70,6 +70,7 @@ import {
70
70
  } from "./helpers/plan-helper";
71
71
  import { handleRegistryEvent } from "./helpers/registry-helper";
72
72
  import {
73
+ handleTokenDeletion,
73
74
  handleTokenEvent,
74
75
  handleTokenOperationSuccess,
75
76
  } from "./helpers/token-helper";
@@ -173,6 +174,7 @@ let accountsMap = new Map<string, Account>();
173
174
  let revisionsMap = new Map<string, Revision>();
174
175
  let roleMap = new Map<string, Role[]>();
175
176
  let tokenMap = new Map<string, Token>();
177
+ let deletedTokenIds = new Set<string>();
176
178
  let platformInfo: Platform | null = null;
177
179
  let isPlatformInfoLoading = false;
178
180
  let isPlatformInfoLoaded = false;
@@ -638,7 +640,11 @@ const rebuildHierarchy = () => {
638
640
  notificationsEnabled: preservedUserData.notificationsEnabled,
639
641
  organizations: Array.from(organizationsMap.values()),
640
642
  clusterTokens: Array.from(clusterTokensMap.values()),
641
- tokens: tokenMap.size > 0 ? (preservedUserData.tokens || []).filter(t => tokenMap.has(t.name)) : (preservedUserData.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)),
642
648
  tenants: Array.from(tenantsMap.values()),
643
649
  axebowPlan: preservedUserData.axebowPlan,
644
650
  companyName: preservedUserData.companyName,
@@ -1128,6 +1134,7 @@ const handleEvent = async (message: WSMessage) => {
1128
1134
  eventData,
1129
1135
  tokenMap,
1130
1136
  userData,
1137
+ deletedTokenIds,
1131
1138
  });
1132
1139
 
1133
1140
  if (tokenResult.isUserToken) {
@@ -1513,12 +1520,17 @@ const handleOperationSuccess = (operation: PendingOperation, response: any) => {
1513
1520
  if (action === "DELETE") {
1514
1521
  const deletedTokenId = entityName.split("/").pop();
1515
1522
  if (deletedTokenId) {
1516
- tokenMap.delete(deletedTokenId);
1517
- const tokenIndex = userData.tokens.findIndex(
1518
- (t) => t.name === deletedTokenId,
1519
- );
1520
- if (tokenIndex !== -1) {
1521
- userData.tokens.splice(tokenIndex, 1);
1523
+ const tokenDeletionResult = handleTokenDeletion({
1524
+ tokenId: deletedTokenId,
1525
+ tokenMap,
1526
+ userData,
1527
+ deletedTokenIds,
1528
+ });
1529
+ if (tokenDeletionResult.removed) {
1530
+ userData.tokens = tokenDeletionResult.updatedUserTokens;
1531
+ eventHelper.notification.publish.creation(
1532
+ tokenDeletionResult.notification!,
1533
+ );
1522
1534
  }
1523
1535
  }
1524
1536
  } else {
@@ -1907,24 +1919,17 @@ const handleDeleteEvent = async (message: WSMessage) => {
1907
1919
  }
1908
1920
  }
1909
1921
  if (keyParts.token && keyParts.user) {
1910
- const tokenId = keyParts.token;
1911
- const tokenIndex = userData.tokens.findIndex((t) => t.name === tokenId);
1912
- if (tokenIndex !== -1) {
1913
- const deletedToken = userData.tokens[tokenIndex];
1914
- userData.tokens.splice(tokenIndex, 1);
1915
- tokenMap.delete(tokenId);
1916
- const tokenNotification: Notification = {
1917
- type: "success",
1918
- subtype: errors.user.tokenDeleted.subtype,
1919
- date: Date.now().toString(),
1920
- status: "unread",
1921
- callToAction: false,
1922
- data: {
1923
- tokenName: deletedToken.name,
1924
- tenant: deletedToken.tenant,
1925
- },
1926
- };
1927
- eventHelper.notification.publish.creation(tokenNotification);
1922
+ const tokenDeletionResult = handleTokenDeletion({
1923
+ tokenId: keyParts.token,
1924
+ tokenMap,
1925
+ userData,
1926
+ deletedTokenIds,
1927
+ });
1928
+ if (tokenDeletionResult.removed) {
1929
+ userData.tokens = tokenDeletionResult.updatedUserTokens;
1930
+ eventHelper.notification.publish.creation(
1931
+ tokenDeletionResult.notification!,
1932
+ );
1928
1933
  }
1929
1934
  }
1930
1935
  rebuildHierarchy();
@@ -2059,7 +2064,8 @@ export const updateUserComplete = (updatedUserData: UserData): User => {
2059
2064
  );
2060
2065
  const mergedTokens = [...(updatedUserData.tokens || []), ...localOnlyTokens]
2061
2066
  .filter((t, index, arr) => arr.findIndex(x => x.name === t.name) === index)
2062
- .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));
2063
2069
 
2064
2070
  userData = {
2065
2071
  id: updatedUserData.id || userData.id,