Add Session Id (#2263)

* adding sessionId to UserContext

* add session id

* add session id to settings pane and fix npm run compile

* Add conditional for Portal

* set default session id on userContext init

* fix tests

---------

Co-authored-by: Asier Isayas <aisayas@microsoft.com>
This commit is contained in:
asier-isayas
2025-11-26 13:07:18 -05:00
committed by GitHub
parent 784dadce30
commit a33429fd85
11 changed files with 148 additions and 9 deletions

88
package-lock.json generated
View File

@@ -116,6 +116,7 @@
"tinykeys": "2.1.0", "tinykeys": "2.1.0",
"underscore": "1.12.1", "underscore": "1.12.1",
"utility-types": "3.10.0", "utility-types": "3.10.0",
"uuid": "9.0.0",
"zustand": "3.5.0" "zustand": "3.5.0"
}, },
"devDependencies": { "devDependencies": {
@@ -626,6 +627,14 @@
} }
} }
}, },
"node_modules/@azure/ms-rest-js/node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/@azure/ms-rest-js/node_modules/xml2js": { "node_modules/@azure/ms-rest-js/node_modules/xml2js": {
"version": "0.5.0", "version": "0.5.0",
"license": "MIT", "license": "MIT",
@@ -685,6 +694,14 @@
"node": ">=0.8.0" "node": ">=0.8.0"
} }
}, },
"node_modules/@azure/msal-node/node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/@babel/code-frame": { "node_modules/@babel/code-frame": {
"version": "7.24.7", "version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz",
@@ -7595,6 +7612,14 @@
"uuid": "^8.0.0" "uuid": "^8.0.0"
} }
}, },
"node_modules/@nteract/commutable/node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/@nteract/connected-components": { "node_modules/@nteract/connected-components": {
"version": "6.8.2", "version": "6.8.2",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
@@ -9125,6 +9150,14 @@
"uuid": "^8.0.0" "uuid": "^8.0.0"
} }
}, },
"node_modules/@nteract/fixtures/node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/@nteract/iron-icons": { "node_modules/@nteract/iron-icons": {
"version": "1.0.0", "version": "1.0.0",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
@@ -9282,6 +9315,14 @@
"uuid": "^8.0.0" "uuid": "^8.0.0"
} }
}, },
"node_modules/@nteract/messaging/node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/@nteract/monaco-editor": { "node_modules/@nteract/monaco-editor": {
"version": "3.2.2", "version": "3.2.2",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
@@ -9397,6 +9438,14 @@
"version": "0.18.1", "version": "0.18.1",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@nteract/monaco-editor/node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/@nteract/mythic-configuration": { "node_modules/@nteract/mythic-configuration": {
"version": "1.0.12", "version": "1.0.12",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
@@ -9665,6 +9714,14 @@
"uuid": "^8.0.0" "uuid": "^8.0.0"
} }
}, },
"node_modules/@nteract/reducers/node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/@nteract/selectors": { "node_modules/@nteract/selectors": {
"version": "3.2.0", "version": "3.2.0",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
@@ -9888,6 +9945,14 @@
"uuid": "^8.0.0" "uuid": "^8.0.0"
} }
}, },
"node_modules/@nteract/types/node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/@octokit/auth-token": { "node_modules/@octokit/auth-token": {
"version": "4.0.0", "version": "4.0.0",
"license": "MIT", "license": "MIT",
@@ -26419,6 +26484,15 @@
"xmlbuilder": "^15.1.0" "xmlbuilder": "^15.1.0"
} }
}, },
"node_modules/jest-trx-results-processor/node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"dev": true,
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/jest-util": { "node_modules/jest-util": {
"version": "24.9.0", "version": "24.9.0",
"license": "MIT", "license": "MIT",
@@ -33753,6 +33827,15 @@
"websocket-driver": "^0.7.4" "websocket-driver": "^0.7.4"
} }
}, },
"node_modules/sockjs/node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"dev": true,
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/source-map": { "node_modules/source-map": {
"version": "0.5.7", "version": "0.5.7",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
@@ -35619,8 +35702,9 @@
} }
}, },
"node_modules/uuid": { "node_modules/uuid": {
"version": "8.3.2", "version": "9.0.0",
"license": "MIT", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
"integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
"bin": { "bin": {
"uuid": "dist/bin/uuid" "uuid": "dist/bin/uuid"
} }

View File

@@ -46,8 +46,8 @@
"@types/mkdirp": "1.0.1", "@types/mkdirp": "1.0.1",
"@types/node-fetch": "2.5.7", "@types/node-fetch": "2.5.7",
"@xmldom/xmldom": "0.7.13", "@xmldom/xmldom": "0.7.13",
"@xterm/xterm": "5.5.0",
"@xterm/addon-fit": "0.10.0", "@xterm/addon-fit": "0.10.0",
"@xterm/xterm": "5.5.0",
"allotment": "1.20.2", "allotment": "1.20.2",
"applicationinsights": "1.8.0", "applicationinsights": "1.8.0",
"bootstrap": "3.4.1", "bootstrap": "3.4.1",
@@ -111,6 +111,7 @@
"tinykeys": "2.1.0", "tinykeys": "2.1.0",
"underscore": "1.12.1", "underscore": "1.12.1",
"utility-types": "3.10.0", "utility-types": "3.10.0",
"uuid": "9.0.0",
"zustand": "3.5.0" "zustand": "3.5.0"
}, },
"devDependencies": { "devDependencies": {
@@ -248,4 +249,4 @@
"printWidth": 120, "printWidth": 120,
"endOfLine": "auto" "endOfLine": "auto"
} }
} }

View File

@@ -297,6 +297,7 @@ export class HttpHeaders {
public static migrateOfferToManualThroughput: string = "x-ms-cosmos-migrate-offer-to-manual-throughput"; public static migrateOfferToManualThroughput: string = "x-ms-cosmos-migrate-offer-to-manual-throughput";
public static migrateOfferToAutopilot: string = "x-ms-cosmos-migrate-offer-to-autopilot"; public static migrateOfferToAutopilot: string = "x-ms-cosmos-migrate-offer-to-autopilot";
public static xAPIKey: string = "X-API-Key"; public static xAPIKey: string = "X-API-Key";
public static sessionId: string = "x-ms-client-session-id";
} }
export class ContentType { export class ContentType {

View File

@@ -17,6 +17,7 @@ const defaultHeaders = {
[HttpHeaders.apiType]: ApiType.MongoDB.toString(), [HttpHeaders.apiType]: ApiType.MongoDB.toString(),
[CosmosSDKConstants.HttpHeaders.MaxEntityCount]: "100", [CosmosSDKConstants.HttpHeaders.MaxEntityCount]: "100",
[CosmosSDKConstants.HttpHeaders.Version]: "2017-11-15", [CosmosSDKConstants.HttpHeaders.Version]: "2017-11-15",
[HttpHeaders.sessionId]: userContext.sessionId,
}; };
function authHeaders() { function authHeaders() {

View File

@@ -446,6 +446,7 @@ export interface DataExplorerInputsFrame {
feedbackPolicies?: any; feedbackPolicies?: any;
aadToken?: string; aadToken?: string;
containerCopyEnabled?: boolean; containerCopyEnabled?: boolean;
sessionId?: string;
} }
export interface SelfServeFrameInputs { export interface SelfServeFrameInputs {

View File

@@ -5,6 +5,12 @@ import { updateUserContext } from "../../../UserContext";
import { SettingsPane } from "./SettingsPane"; import { SettingsPane } from "./SettingsPane";
describe("Settings Pane", () => { describe("Settings Pane", () => {
beforeEach(() => {
updateUserContext({
sessionId: "1234-5678",
});
});
it("should render Default properly", () => { it("should render Default properly", () => {
const wrapper = shallow(<SettingsPane explorer={null} />); const wrapper = shallow(<SettingsPane explorer={null} />);
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();

View File

@@ -212,6 +212,7 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
const styles = useStyles(); const styles = useStyles();
const explorerVersion = configContext.gitSha; const explorerVersion = configContext.gitSha;
const sessionId: string = userContext.sessionId;
const isEmulator = configContext.platform === Platform.Emulator; const isEmulator = configContext.platform === Platform.Emulator;
const shouldShowQueryPageOptions = userContext.apiType === "SQL"; const shouldShowQueryPageOptions = userContext.apiType === "SQL";
const showRetrySettings = const showRetrySettings =
@@ -1227,6 +1228,12 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
<div>{explorerVersion}</div> <div>{explorerVersion}</div>
</div> </div>
</div> </div>
<div className="settingsSection">
<div className="settingsSectionPart">
<div className="settingsSectionLabel">Session ID</div>
<div>{sessionId}</div>
</div>
</div>
</div> </div>
</RightPaneForm> </RightPaneForm>
); );

View File

@@ -649,6 +649,22 @@ exports[`Settings Pane should render Default properly 1`] = `
<div /> <div />
</div> </div>
</div> </div>
<div
className="settingsSection"
>
<div
className="settingsSectionPart"
>
<div
className="settingsSectionLabel"
>
Session ID
</div>
<div>
1234-5678
</div>
</div>
</div>
</div> </div>
</RightPaneForm> </RightPaneForm>
`; `;
@@ -958,6 +974,22 @@ exports[`Settings Pane should render Gremlin properly 1`] = `
<div /> <div />
</div> </div>
</div> </div>
<div
className="settingsSection"
>
<div
className="settingsSectionPart"
>
<div
className="settingsSectionLabel"
>
Session ID
</div>
<div>
1234-5678
</div>
</div>
</div>
</div> </div>
</RightPaneForm> </RightPaneForm>
`; `;

View File

@@ -286,7 +286,7 @@ export class CassandraAPIDataClient extends TableDataClient {
query, query,
paginationToken, paginationToken,
}), }),
beforeSend: this.setAuthorizationHeader as any, beforeSend: this.setCommonHeaders as any,
cache: false, cache: false,
}); });
shouldNotify && shouldNotify &&
@@ -440,7 +440,7 @@ export class CassandraAPIDataClient extends TableDataClient {
keyspaceId: collection.databaseId, keyspaceId: collection.databaseId,
tableId: collection.id(), tableId: collection.id(),
}), }),
beforeSend: this.setAuthorizationHeader as any, beforeSend: this.setCommonHeaders as any,
cache: false, cache: false,
}) })
.then( .then(
@@ -482,7 +482,7 @@ export class CassandraAPIDataClient extends TableDataClient {
keyspaceId: collection.databaseId, keyspaceId: collection.databaseId,
tableId: collection.id(), tableId: collection.id(),
}), }),
beforeSend: this.setAuthorizationHeader as any, beforeSend: this.setCommonHeaders as any,
cache: false, cache: false,
}) })
.then( .then(
@@ -518,7 +518,7 @@ export class CassandraAPIDataClient extends TableDataClient {
resourceId: resourceId, resourceId: resourceId,
query: query, query: query,
}), }),
beforeSend: this.setAuthorizationHeader as any, beforeSend: this.setCommonHeaders as any,
cache: false, cache: false,
}).then( }).then(
(data: any) => { (data: any) => {
@@ -547,7 +547,7 @@ export class CassandraAPIDataClient extends TableDataClient {
return cassandraEndpoint; return cassandraEndpoint;
} }
private setAuthorizationHeader: (xhr: XMLHttpRequest) => boolean = (xhr: XMLHttpRequest): boolean => { private setCommonHeaders: (xhr: XMLHttpRequest) => boolean = (xhr: XMLHttpRequest): boolean => {
const authorizationHeaderMetadata: ViewModels.AuthorizationTokenHeaderMetadata = getAuthorizationHeader(); const authorizationHeaderMetadata: ViewModels.AuthorizationTokenHeaderMetadata = getAuthorizationHeader();
xhr.setRequestHeader(authorizationHeaderMetadata.header, authorizationHeaderMetadata.token); xhr.setRequestHeader(authorizationHeaderMetadata.header, authorizationHeaderMetadata.token);
@@ -555,6 +555,7 @@ export class CassandraAPIDataClient extends TableDataClient {
xhr.setRequestHeader(Constants.HttpHeaders.entraIdToken, userContext.aadToken); xhr.setRequestHeader(Constants.HttpHeaders.entraIdToken, userContext.aadToken);
} }
xhr.setRequestHeader(Constants.HttpHeaders.sessionId, userContext.sessionId);
return true; return true;
}; };

View File

@@ -4,6 +4,7 @@ import { Action } from "Shared/Telemetry/TelemetryConstants";
import { traceOpen } from "Shared/Telemetry/TelemetryProcessor"; import { traceOpen } from "Shared/Telemetry/TelemetryProcessor";
import { useCarousel } from "hooks/useCarousel"; import { useCarousel } from "hooks/useCarousel";
import { usePostgres } from "hooks/usePostgres"; import { usePostgres } from "hooks/usePostgres";
import { v4 as uuidv4 } from "uuid";
import { AuthType } from "./AuthType"; import { AuthType } from "./AuthType";
import { DatabaseAccount } from "./Contracts/DataModels"; import { DatabaseAccount } from "./Contracts/DataModels";
import { SubscriptionType } from "./Contracts/SubscriptionType"; import { SubscriptionType } from "./Contracts/SubscriptionType";
@@ -118,6 +119,7 @@ export interface UserContext {
readonly dataPlaneRbacEnabled?: boolean; readonly dataPlaneRbacEnabled?: boolean;
readonly refreshCosmosClient?: boolean; readonly refreshCosmosClient?: boolean;
throughputBucketsEnabled?: boolean; throughputBucketsEnabled?: boolean;
readonly sessionId: string;
} }
export type ApiType = "SQL" | "Mongo" | "Gremlin" | "Tables" | "Cassandra" | "Postgres" | "VCoreMongo"; export type ApiType = "SQL" | "Mongo" | "Gremlin" | "Tables" | "Cassandra" | "Postgres" | "VCoreMongo";
@@ -135,6 +137,7 @@ const userContext: UserContext = {
features, features,
subscriptionType: CollectionCreation.DefaultSubscriptionType, subscriptionType: CollectionCreation.DefaultSubscriptionType,
collectionCreationDefaults: CollectionCreationDefaults, collectionCreationDefaults: CollectionCreationDefaults,
sessionId: uuidv4(), // Default sessionId - will be overwritten if provided by host
}; };
export function isAccountNewerThanThresholdInMs(createdAt: string, threshold: number) { export function isAccountNewerThanThresholdInMs(createdAt: string, threshold: number) {

View File

@@ -85,6 +85,7 @@ export function useKnockoutExplorer(platform: Platform): Explorer {
userContext.features.phoenixNotebooks = true; userContext.features.phoenixNotebooks = true;
userContext.features.phoenixFeatures = true; userContext.features.phoenixFeatures = true;
} }
let explorer: Explorer; let explorer: Explorer;
if (platform === Platform.Hosted) { if (platform === Platform.Hosted) {
explorer = await configureHosted(); explorer = await configureHosted();
@@ -927,6 +928,7 @@ function updateContextsFromPortalMessage(inputs: DataExplorerInputsFrame) {
collectionCreationDefaults: inputs.defaultCollectionThroughput, collectionCreationDefaults: inputs.defaultCollectionThroughput,
isTryCosmosDBSubscription: inputs.isTryCosmosDBSubscription, isTryCosmosDBSubscription: inputs.isTryCosmosDBSubscription,
feedbackPolicies: inputs.feedbackPolicies, feedbackPolicies: inputs.feedbackPolicies,
...(inputs.sessionId && { sessionId: inputs.sessionId }), // Remove conditional once Portal sends sessionId
}); });
if (inputs.isPostgresAccount) { if (inputs.isPostgresAccount) {