Skip to content

Commit

Permalink
Merge pull request #421 from Philip-Carneiro/KXI-52687
Browse files Browse the repository at this point in the history
[KXI-52687] add tests and auth data
  • Loading branch information
Philip-Carneiro-KX authored Sep 6, 2024
2 parents 0a2e240 + 0abeb0a commit 52cf42d
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 5 deletions.
19 changes: 18 additions & 1 deletion src/commands/serverCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,24 @@ export async function openMeta(node: MetaObjectPayloadNode | InsightsMetaNode) {

export async function exportConnections(connLabel?: string) {
const connMngService = new ConnectionManagementService();
const doc = connMngService.exportConnection(connLabel);

const exportAuth = await window.showQuickPick(["Yes", "No"], {
placeHolder: "Do you want to export username and password?",
});

if (!exportAuth) {
kdbOutputLog(
"[EXPORT CONNECTIONS] Export operation was cancelled by the user",
"INFO",
);
return;
}

const includeAuth = exportAuth === "Yes";
if (includeAuth) {
await connMngService.retrieveUserPass();
}
const doc = await connMngService.exportConnection(connLabel, includeAuth);
if (doc && doc !== "") {
const formattedDoc = JSON.stringify(JSON.parse(doc), null, 2);
const uri = await window.showSaveDialog({
Expand Down
2 changes: 2 additions & 0 deletions src/extensionVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { LocalConnection } from "./classes/localConnection";
import { InsightsConnection } from "./classes/insightsConnection";
import { DataSourceFiles } from "./models/dataSource";
import { ConnectionLabel, LabelColors, Labels } from "./models/labels";
import { kdbAuthMap } from "./models/connectionsModels";

// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace ext {
Expand Down Expand Up @@ -80,6 +81,7 @@ export namespace ext {
export const kdbDataSourceRootNodes: string[] = [];
export const kdbQueryHistoryNodes: string[] = [];
export const kdbQueryHistoryList: QueryHistory[] = [];
export const kdbAuthMap: kdbAuthMap[] = [];
export const kdbrootNodes: string[] = [];
export const kdbinsightsNodes: string[] = [];
export const kdbNodesWithoutAuth: string[] = [];
Expand Down
7 changes: 7 additions & 0 deletions src/models/connectionsModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ export interface Server {
[name: string]: ServerDetails;
}

export interface kdbAuthMap {
[name: string]: {
username: string;
password: string;
};
}

export interface InsightDetails {
alias: string;
server: string;
Expand Down
45 changes: 42 additions & 3 deletions src/services/connectionManagerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { retrieveConnLabelsNames } from "../utils/connLabel";
import {
ExportedConnections,
Insights,
kdbAuthMap,
Server,
} from "../models/connectionsModels";

Expand Down Expand Up @@ -407,7 +408,27 @@ export class ConnectionManagementService {
return connection.returnMetaObject(metaType);
}

public exportConnection(connLabel?: string): string {
public async retrieveUserPass() {
for (const connection of ext.connectionsList) {
if (connection instanceof KdbNode) {
const authCredentials = await ext.secretSettings.getAuthData(
connection.children[0],
);
if (authCredentials) {
const [username, password] = authCredentials.split(":");
const authMap: kdbAuthMap = {
[connection.children[0]]: {
username,
password,
},
};
ext.kdbAuthMap.push(authMap);
}
}
}
}

public exportConnection(connLabel?: string, includeAuth?: boolean): string {
const exportedContent: ExportedConnections = {
connections: {
Insights: [],
Expand All @@ -420,21 +441,39 @@ export class ConnectionManagementService {
return "";
}
if (connection instanceof KdbNode) {
connection.details.auth = false;
exportedContent.connections.KDB.push(connection.details);
} else {
exportedContent.connections.Insights.push(connection.details);
}
} else {
ext.connectionsList.forEach((connection) => {
if (connection instanceof KdbNode) {
connection.details.auth = false;
exportedContent.connections.KDB.push(connection.details);
} else {
exportedContent.connections.Insights.push(connection.details);
}
});
}

if (exportedContent.connections.KDB.length > 0) {
for (const kdbConn of exportedContent.connections.KDB) {
if (!includeAuth) {
kdbConn.auth = false;
kdbConn.username = undefined;
kdbConn.password = undefined;
} else {
const auth = ext.kdbAuthMap.find((auth) => {
return Object.keys(auth)[0] === kdbConn.serverAlias;
});
if (auth) {
kdbConn.auth = true;
kdbConn.username = auth[kdbConn.serverAlias].username;
kdbConn.password = auth[kdbConn.serverAlias].password;
}
}
}
}
ext.kdbAuthMap.length = 0;
return exportedContent.connections.Insights.length === 0 &&
exportedContent.connections.KDB.length === 0
? ""
Expand Down
10 changes: 10 additions & 0 deletions test/suite/commands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1911,6 +1911,9 @@ describe("serverCommand", () => {
const exportConnectionStub = sandbox
.stub(ConnectionManagementService.prototype, "exportConnection")
.returns("");
const showQuickPickStub = sandbox
.stub(vscode.window, "showQuickPick")
.resolves({ label: "No" });

await serverCommand.exportConnections();

Expand All @@ -1920,7 +1923,9 @@ describe("serverCommand", () => {
"[EXPORT CONNECTIONS] No connections found to be exported",
"ERROR",
);

exportConnectionStub.restore();
showQuickPickStub.restore();
});

it("should log info when save operation is cancelled by the user", async () => {
Expand All @@ -1930,6 +1935,9 @@ describe("serverCommand", () => {
const showSaveDialogStub = sandbox
.stub(vscode.window, "showSaveDialog")
.resolves(undefined);
const showQuickPickStub = sandbox
.stub(vscode.window, "showQuickPick")
.resolves({ label: "Yes" });

await serverCommand.exportConnections();

Expand All @@ -1939,8 +1947,10 @@ describe("serverCommand", () => {
"[EXPORT CONNECTIONS] Save operation was cancelled by the user",
"INFO",
);

exportConnectionStub.restore();
showSaveDialogStub.restore();
showQuickPickStub.restore();
});
});
});
Expand Down
139 changes: 138 additions & 1 deletion test/suite/services.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import assert from "node:assert";
import sinon from "sinon";
import {
ExtensionContext,
MarkdownString,
TreeItemCollapsibleState,
Uri,
WebviewPanel,
Expand Down Expand Up @@ -66,8 +67,10 @@ import { ConnectionLabel, Labels } from "../../src/models/labels";
import {
Insights,
Server,
ServerDetails,
ServerType,
} from "../../src/models/connectionsModels";
import AuthSettings from "../../src/utils/secretStorage";

// eslint-disable-next-line @typescript-eslint/no-var-requires
const codeFlow = require("../../src/services/kdbInsights/codeFlowLogin");
Expand Down Expand Up @@ -1397,16 +1400,79 @@ describe("connectionManagerService", () => {
});
});

describe("ConnectionManagementService", () => {
describe("retrieveUserPass", () => {
let connectionManagerService: ConnectionManagementService;
let connectionsListStub: sinon.SinonStub;
let getAuthDataStub: sinon.SinonStub;
let kdbAuthMapStub: sinon.SinonStub;
let contextStub: sinon.SinonStub;
ext.context = {} as ExtensionContext;

beforeEach(() => {
contextStub = sinon.stub(ext, "context").value({
globalStorageUri: {
fsPath: "/temp/",
},
});
AuthSettings.init(ext.context);
ext.secretSettings = AuthSettings.instance;
connectionManagerService = new ConnectionManagementService();
connectionsListStub = sinon.stub(ext, "connectionsList").value([]);
getAuthDataStub = sinon.stub(ext.secretSettings, "getAuthData");
kdbAuthMapStub = sinon.stub(ext, "kdbAuthMap").value([]);
});

afterEach(() => {
sinon.restore();
ext.connectionsList.length = 0;
});

it("should retrieve and store auth data for KdbNode connections", async () => {
ext.connectionsList.push(kdbNode);
getAuthDataStub.withArgs(kdbNode.children[0]).resolves("user1:pass1");

await connectionManagerService.retrieveUserPass();

assert.strictEqual(ext.kdbAuthMap.length, 1);
assert.deepEqual(ext.kdbAuthMap[0], {
child1: {
username: "user1",
password: "pass1",
},
});
});

it("should not store auth data if getAuthData returns null", async () => {
connectionsListStub.value([kdbNode]);
getAuthDataStub.withArgs("server1").resolves(null);

await connectionManagerService.retrieveUserPass();

assert.strictEqual(ext.kdbAuthMap.length, 0);
});

it("should not store auth data for non-KdbNode connections", async () => {
const nonKdbNode = { children: ["server1"] };
connectionsListStub.value([nonKdbNode]);

await connectionManagerService.retrieveUserPass();

assert.strictEqual(ext.kdbAuthMap.length, 0);
});
});

describe("exportConnection", () => {
let retrieveConnectionStub: sinon.SinonStub;
let connectionsListStub: sinon.SinonStub;
let kdbAuthMapStub: sinon.SinonStub;

beforeEach(() => {
retrieveConnectionStub = sinon.stub(
connectionManagerService,
"retrieveConnection",
);
connectionsListStub = sinon.stub(ext, "connectionsList").value([]);
kdbAuthMapStub = sinon.stub(ext, "kdbAuthMap").value([]);
});

afterEach(() => {
Expand Down Expand Up @@ -1475,6 +1541,77 @@ describe("connectionManagerService", () => {

assert.strictEqual(result, JSON.stringify(expectedOutput, null, 2));
});

it("should set auth to false and clear username and password if includeAuth is false", () => {
connectionsListStub.value([kdbNode]);

const result = connectionManagerService.exportConnection(
undefined,
false,
);

const expectedOutput = {
connections: {
Insights: [],
KDB: [kdbNode.details],
},
};

assert.strictEqual(result, JSON.stringify(expectedOutput, null, 2));
});

it("should set auth to true and populate username and password if includeAuth is true and auth is found", () => {
const authData = {
server1: {
username: "user1",
password: "pass1",
},
};
connectionsListStub.value([kdbNode]);
kdbAuthMapStub.value([authData]);

const result = connectionManagerService.exportConnection(undefined, true);

const expectedOutput = {
connections: {
Insights: [],
KDB: [kdbNode.details],
},
};

assert.strictEqual(result, JSON.stringify(expectedOutput, null, 2));
});

it("should not change auth, username, and password if includeAuth is true and auth is not found", () => {
connectionsListStub.value([kdbNode]);
kdbAuthMapStub.value([]);

const result = connectionManagerService.exportConnection(undefined, true);

const expectedOutput = {
connections: {
Insights: [],
KDB: [kdbNode.details],
},
};

assert.strictEqual(result, JSON.stringify(expectedOutput, null, 2));
});

it("should clear kdbAuthMap after processing", () => {
const authData = {
server1: {
username: "user1",
password: "pass1",
},
};
connectionsListStub.value([kdbNode]);
kdbAuthMapStub.value([authData]);

connectionManagerService.exportConnection(undefined, true);

assert.strictEqual(ext.kdbAuthMap.length, 0);
});
});
});

Expand Down

0 comments on commit 52cf42d

Please sign in to comment.