mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-09-16 06:42:02 +02:00
Import Digest, NTLM, OAuth 1.0, and folder-level auth from Postman collections (#667)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
a822cc93d4
commit
31d55440c1
@@ -16,6 +16,20 @@ const POSTMAN_2_1_0_SCHEMA = "https://schema.getpostman.com/json/collection/v2.1
|
||||
const POSTMAN_2_0_0_SCHEMA = "https://schema.getpostman.com/json/collection/v2.0.0/collection.json";
|
||||
const VALID_SCHEMAS = [POSTMAN_2_0_0_SCHEMA, POSTMAN_2_1_0_SCHEMA];
|
||||
|
||||
// Both products happen to spell these the same way, but the names are written
|
||||
// out so anything Yaak's oauth1 plugin can't offer as a select option lands on
|
||||
// the default instead of being passed straight through.
|
||||
const OAUTH1_SIGNATURE_METHODS: Record<string, string> = {
|
||||
"HMAC-SHA1": "HMAC-SHA1",
|
||||
"HMAC-SHA256": "HMAC-SHA256",
|
||||
"HMAC-SHA512": "HMAC-SHA512",
|
||||
"RSA-SHA1": "RSA-SHA1",
|
||||
"RSA-SHA256": "RSA-SHA256",
|
||||
"RSA-SHA512": "RSA-SHA512",
|
||||
PLAINTEXT: "PLAINTEXT",
|
||||
};
|
||||
const DEFAULT_OAUTH1_SIGNATURE_METHOD = "HMAC-SHA1";
|
||||
|
||||
type AtLeast<T, K extends keyof T> = Partial<T> & Pick<T, K>;
|
||||
|
||||
interface ExportResources {
|
||||
@@ -98,6 +112,7 @@ export function convertPostman(contents: string): ImportPluginResponse | undefin
|
||||
id: generateId("folder"),
|
||||
name: v.name,
|
||||
folderId,
|
||||
...importAuth(v.auth),
|
||||
};
|
||||
trackSourceKey(folder.id, v, "item");
|
||||
exportResources.folders.push(folder);
|
||||
@@ -222,8 +237,6 @@ function convertUrl(rawUrl: unknown): Pick<HttpRequest, "url" | "urlParameters">
|
||||
v += `#${url.hash}`;
|
||||
}
|
||||
|
||||
// TODO: Implement url.variables (path variables)
|
||||
|
||||
return { url: v, urlParameters: params };
|
||||
}
|
||||
|
||||
@@ -274,6 +287,31 @@ function importAuth(rawAuth: unknown): Pick<HttpRequest, "authentication" | "aut
|
||||
};
|
||||
}
|
||||
|
||||
if ("digest" in auth && authType === "digest") {
|
||||
const d = pmArrayToObj(auth.digest);
|
||||
return {
|
||||
authenticationType: "digest",
|
||||
authentication: {
|
||||
username: d.username != null ? String(d.username) : undefined,
|
||||
password: d.password != null ? String(d.password) : undefined,
|
||||
realm: d.realm != null ? String(d.realm) : undefined,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if ("ntlm" in auth && authType === "ntlm") {
|
||||
const n = pmArrayToObj(auth.ntlm);
|
||||
return {
|
||||
authenticationType: "windows",
|
||||
authentication: {
|
||||
username: n.username != null ? String(n.username) : undefined,
|
||||
password: n.password != null ? String(n.password) : undefined,
|
||||
domain: n.domain != null ? String(n.domain) : undefined,
|
||||
workstation: n.workstation != null ? String(n.workstation) : undefined,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if ("awsv4" in auth && authType === "awsv4") {
|
||||
const a = pmArrayToObj(auth.awsv4);
|
||||
return {
|
||||
@@ -317,6 +355,32 @@ function importAuth(rawAuth: unknown): Pick<HttpRequest, "authentication" | "aut
|
||||
};
|
||||
}
|
||||
|
||||
if ("oauth1" in auth && authType === "oauth1") {
|
||||
const o = pmArrayToObj(auth.oauth1);
|
||||
const signatureMethod =
|
||||
o.signatureMethod != null
|
||||
? String(o.signatureMethod).toUpperCase()
|
||||
: DEFAULT_OAUTH1_SIGNATURE_METHOD;
|
||||
return {
|
||||
authenticationType: "oauth1",
|
||||
authentication: {
|
||||
signatureMethod:
|
||||
OAUTH1_SIGNATURE_METHODS[signatureMethod] ?? DEFAULT_OAUTH1_SIGNATURE_METHOD,
|
||||
consumerKey: o.consumerKey != null ? String(o.consumerKey) : undefined,
|
||||
consumerSecret: o.consumerSecret != null ? String(o.consumerSecret) : undefined,
|
||||
tokenKey: o.token != null ? String(o.token) : undefined,
|
||||
tokenSecret: o.tokenSecret != null ? String(o.tokenSecret) : undefined,
|
||||
privateKey: o.privateKey != null ? String(o.privateKey) : undefined,
|
||||
callback: o.callback != null ? String(o.callback) : undefined,
|
||||
verifier: o.verifier != null ? String(o.verifier) : undefined,
|
||||
timestamp: o.timestamp != null ? String(o.timestamp) : undefined,
|
||||
nonce: o.nonce != null ? String(o.nonce) : undefined,
|
||||
version: o.version != null ? String(o.version) : undefined,
|
||||
realm: o.realm != null ? String(o.realm) : undefined,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if ("oauth2" in auth && authType === "oauth2") {
|
||||
const o = pmArrayToObj(auth.oauth2);
|
||||
|
||||
|
||||
@@ -738,6 +738,254 @@
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "Digest",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "digest",
|
||||
"digest": [
|
||||
{
|
||||
"key": "algorithm",
|
||||
"value": "MD5",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "username",
|
||||
"value": "digest-user",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "password",
|
||||
"value": "digest-pass",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "realm",
|
||||
"value": "testrealm@yaak.app",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "nonce",
|
||||
"value": "dcd98b7102dd2f0e8b11d0f600bfb0c093",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "nonceCount",
|
||||
"value": "00000001",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "clientNonce",
|
||||
"value": "0a4f113b",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "opaque",
|
||||
"value": "5ccc069c403ebaf9f0171e9517f40e41",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "qop",
|
||||
"value": "auth",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "disableRetryRequest",
|
||||
"value": true,
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
},
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "https://yaak.app/x/echo",
|
||||
"protocol": "https",
|
||||
"host": ["yaak", "app"],
|
||||
"path": ["x", "echo"]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "NTLM",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "ntlm",
|
||||
"ntlm": [
|
||||
{
|
||||
"key": "username",
|
||||
"value": "ntlm-user",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "password",
|
||||
"value": "ntlm-pass",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "domain",
|
||||
"value": "CORP",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "workstation",
|
||||
"value": "WORKSTATION-01",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "disableRetryRequest",
|
||||
"value": true,
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
},
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "https://yaak.app/x/echo",
|
||||
"protocol": "https",
|
||||
"host": ["yaak", "app"],
|
||||
"path": ["x", "echo"]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "OAuth 1",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "oauth1",
|
||||
"oauth1": [
|
||||
{
|
||||
"key": "consumerKey",
|
||||
"value": "consumer-key",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "consumerSecret",
|
||||
"value": "consumer-secret",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "token",
|
||||
"value": "access-token",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "tokenSecret",
|
||||
"value": "token-secret",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "signatureMethod",
|
||||
"value": "HMAC-SHA256",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "timestamp",
|
||||
"value": "1700000000",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "nonce",
|
||||
"value": "9e6dfada256c",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "version",
|
||||
"value": "1.0",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "realm",
|
||||
"value": "yaak.app",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "callback",
|
||||
"value": "https://yaak.app/x/callback",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "verifier",
|
||||
"value": "verifier-123",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "addParamsToHeader",
|
||||
"value": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"key": "addEmptyParamsToSign",
|
||||
"value": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"key": "includeBodyHash",
|
||||
"value": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
},
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "https://yaak.app/x/echo",
|
||||
"protocol": "https",
|
||||
"host": ["yaak", "app"],
|
||||
"path": ["x", "echo"]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "Folder With Auth",
|
||||
"item": [
|
||||
{
|
||||
"name": "Folder Child Inherit",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "https://yaak.app/x/echo",
|
||||
"protocol": "https",
|
||||
"host": ["yaak", "app"],
|
||||
"path": ["x", "echo"]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "Folder Child No Auth",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "noauth"
|
||||
},
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "https://yaak.app/x/echo",
|
||||
"protocol": "https",
|
||||
"host": ["yaak", "app"],
|
||||
"path": ["x", "echo"]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
}
|
||||
],
|
||||
"auth": {
|
||||
"type": "bearer",
|
||||
"bearer": [
|
||||
{
|
||||
"key": "token",
|
||||
"value": "folder-token",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"auth": {
|
||||
|
||||
+115
-1
@@ -297,9 +297,123 @@
|
||||
"headerPrefix": "Bearer",
|
||||
"location": "header"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "http_request",
|
||||
"id": "GENERATE_ID::HTTP_REQUEST_10",
|
||||
"workspaceId": "GENERATE_ID::WORKSPACE_0",
|
||||
"folderId": null,
|
||||
"name": "Digest",
|
||||
"method": "GET",
|
||||
"url": "https://yaak.app/x/echo",
|
||||
"urlParameters": [],
|
||||
"body": {},
|
||||
"bodyType": null,
|
||||
"sortPriority": 10,
|
||||
"headers": [],
|
||||
"authenticationType": "digest",
|
||||
"authentication": {
|
||||
"username": "digest-user",
|
||||
"password": "digest-pass",
|
||||
"realm": "testrealm@yaak.app"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "http_request",
|
||||
"id": "GENERATE_ID::HTTP_REQUEST_11",
|
||||
"workspaceId": "GENERATE_ID::WORKSPACE_0",
|
||||
"folderId": null,
|
||||
"name": "NTLM",
|
||||
"method": "GET",
|
||||
"url": "https://yaak.app/x/echo",
|
||||
"urlParameters": [],
|
||||
"body": {},
|
||||
"bodyType": null,
|
||||
"sortPriority": 11,
|
||||
"headers": [],
|
||||
"authenticationType": "windows",
|
||||
"authentication": {
|
||||
"username": "ntlm-user",
|
||||
"password": "ntlm-pass",
|
||||
"domain": "CORP",
|
||||
"workstation": "WORKSTATION-01"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "http_request",
|
||||
"id": "GENERATE_ID::HTTP_REQUEST_12",
|
||||
"workspaceId": "GENERATE_ID::WORKSPACE_0",
|
||||
"folderId": null,
|
||||
"name": "OAuth 1",
|
||||
"method": "GET",
|
||||
"url": "https://yaak.app/x/echo",
|
||||
"urlParameters": [],
|
||||
"body": {},
|
||||
"bodyType": null,
|
||||
"sortPriority": 12,
|
||||
"headers": [],
|
||||
"authenticationType": "oauth1",
|
||||
"authentication": {
|
||||
"signatureMethod": "HMAC-SHA256",
|
||||
"consumerKey": "consumer-key",
|
||||
"consumerSecret": "consumer-secret",
|
||||
"tokenKey": "access-token",
|
||||
"tokenSecret": "token-secret",
|
||||
"callback": "https://yaak.app/x/callback",
|
||||
"verifier": "verifier-123",
|
||||
"timestamp": "1700000000",
|
||||
"nonce": "9e6dfada256c",
|
||||
"version": "1.0",
|
||||
"realm": "yaak.app"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "http_request",
|
||||
"id": "GENERATE_ID::HTTP_REQUEST_13",
|
||||
"workspaceId": "GENERATE_ID::WORKSPACE_0",
|
||||
"folderId": "GENERATE_ID::FOLDER_0",
|
||||
"name": "Folder Child Inherit",
|
||||
"method": "GET",
|
||||
"url": "https://yaak.app/x/echo",
|
||||
"urlParameters": [],
|
||||
"body": {},
|
||||
"bodyType": null,
|
||||
"sortPriority": 14,
|
||||
"headers": [],
|
||||
"authenticationType": null,
|
||||
"authentication": {}
|
||||
},
|
||||
{
|
||||
"model": "http_request",
|
||||
"id": "GENERATE_ID::HTTP_REQUEST_14",
|
||||
"workspaceId": "GENERATE_ID::WORKSPACE_0",
|
||||
"folderId": "GENERATE_ID::FOLDER_0",
|
||||
"name": "Folder Child No Auth",
|
||||
"method": "GET",
|
||||
"url": "https://yaak.app/x/echo",
|
||||
"urlParameters": [],
|
||||
"body": {},
|
||||
"bodyType": null,
|
||||
"sortPriority": 15,
|
||||
"headers": [],
|
||||
"authenticationType": "none",
|
||||
"authentication": {}
|
||||
}
|
||||
],
|
||||
"folders": []
|
||||
"folders": [
|
||||
{
|
||||
"model": "folder",
|
||||
"sortPriority": 13,
|
||||
"workspaceId": "GENERATE_ID::WORKSPACE_0",
|
||||
"id": "GENERATE_ID::FOLDER_0",
|
||||
"name": "Folder With Auth",
|
||||
"folderId": null,
|
||||
"authenticationType": "bearer",
|
||||
"authentication": {
|
||||
"token": "folder-token"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"sourceKeys": {
|
||||
"GENERATE_ID::WORKSPACE_0": "collection:9e6dfada-256c-49ea-a38f-7d1b05b7ca2d"
|
||||
|
||||
+13
-9
@@ -23,9 +23,9 @@
|
||||
"httpRequests": [
|
||||
{
|
||||
"model": "http_request",
|
||||
"id": "GENERATE_ID::HTTP_REQUEST_10",
|
||||
"id": "GENERATE_ID::HTTP_REQUEST_15",
|
||||
"workspaceId": "GENERATE_ID::WORKSPACE_1",
|
||||
"folderId": "GENERATE_ID::FOLDER_1",
|
||||
"folderId": "GENERATE_ID::FOLDER_2",
|
||||
"name": "Request 1",
|
||||
"method": "GET",
|
||||
"url": "",
|
||||
@@ -39,9 +39,9 @@
|
||||
},
|
||||
{
|
||||
"model": "http_request",
|
||||
"id": "GENERATE_ID::HTTP_REQUEST_11",
|
||||
"id": "GENERATE_ID::HTTP_REQUEST_16",
|
||||
"workspaceId": "GENERATE_ID::WORKSPACE_1",
|
||||
"folderId": "GENERATE_ID::FOLDER_0",
|
||||
"folderId": "GENERATE_ID::FOLDER_1",
|
||||
"name": "Request 2",
|
||||
"method": "GET",
|
||||
"url": "",
|
||||
@@ -55,7 +55,7 @@
|
||||
},
|
||||
{
|
||||
"model": "http_request",
|
||||
"id": "GENERATE_ID::HTTP_REQUEST_12",
|
||||
"id": "GENERATE_ID::HTTP_REQUEST_17",
|
||||
"workspaceId": "GENERATE_ID::WORKSPACE_1",
|
||||
"folderId": null,
|
||||
"name": "Request 3",
|
||||
@@ -75,17 +75,21 @@
|
||||
"model": "folder",
|
||||
"sortPriority": 0,
|
||||
"workspaceId": "GENERATE_ID::WORKSPACE_1",
|
||||
"id": "GENERATE_ID::FOLDER_0",
|
||||
"id": "GENERATE_ID::FOLDER_1",
|
||||
"name": "Top Folder",
|
||||
"folderId": null
|
||||
"folderId": null,
|
||||
"authenticationType": null,
|
||||
"authentication": {}
|
||||
},
|
||||
{
|
||||
"model": "folder",
|
||||
"sortPriority": 1,
|
||||
"workspaceId": "GENERATE_ID::WORKSPACE_1",
|
||||
"id": "GENERATE_ID::FOLDER_1",
|
||||
"id": "GENERATE_ID::FOLDER_2",
|
||||
"name": "Nested Folder",
|
||||
"folderId": "GENERATE_ID::FOLDER_0"
|
||||
"folderId": "GENERATE_ID::FOLDER_1",
|
||||
"authenticationType": null,
|
||||
"authentication": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"httpRequests": [
|
||||
{
|
||||
"model": "http_request",
|
||||
"id": "GENERATE_ID::HTTP_REQUEST_13",
|
||||
"id": "GENERATE_ID::HTTP_REQUEST_18",
|
||||
"workspaceId": "GENERATE_ID::WORKSPACE_2",
|
||||
"folderId": null,
|
||||
"name": "Form URL",
|
||||
|
||||
@@ -123,6 +123,37 @@ describe("importer-postman", () => {
|
||||
expect(keyOf(before, before?.resources.workspaces[0]?.id)).toBe("collection:collection-id");
|
||||
});
|
||||
|
||||
test("Falls back to the default OAuth 1 signature method for unrecognized ones", () => {
|
||||
const result = convertPostman(
|
||||
JSON.stringify({
|
||||
info: {
|
||||
name: "OAuth 1 Signature",
|
||||
schema: "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
|
||||
},
|
||||
item: [
|
||||
{
|
||||
name: "Request",
|
||||
request: {
|
||||
method: "GET",
|
||||
url: "https://yaak.app",
|
||||
auth: {
|
||||
type: "oauth1",
|
||||
oauth1: [{ key: "signatureMethod", value: "HMAC-SHA384" }],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result?.resources.httpRequests).toEqual([
|
||||
expect.objectContaining({
|
||||
authenticationType: "oauth1",
|
||||
authentication: { signatureMethod: "HMAC-SHA1" },
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
test("Omits keys for items the collection never identified", () => {
|
||||
const result = convertPostman(
|
||||
JSON.stringify({
|
||||
|
||||
Reference in New Issue
Block a user