diff --git a/packages/plugin-runtime/src/PluginInstance.ts b/packages/plugin-runtime/src/PluginInstance.ts index 25f07132..fdb2b06b 100644 --- a/packages/plugin-runtime/src/PluginInstance.ts +++ b/packages/plugin-runtime/src/PluginInstance.ts @@ -241,12 +241,10 @@ export class PluginInstance { } if (payload.type === 'get_http_authentication_summary_request' && this.#mod?.authentication) { - const { name, shortLabel, label } = this.#mod.authentication; + const replyPayload: InternalEventPayload = { type: 'get_http_authentication_summary_response', - name, - label, - shortLabel, + ...this.#mod.authentication, }; this.#sendPayload(windowContext, replyPayload, replyId); diff --git a/plugins/auth-aws/src/index.ts b/plugins/auth-aws/src/index.ts index 323c48f5..efe3f4cf 100644 --- a/plugins/auth-aws/src/index.ts +++ b/plugins/auth-aws/src/index.ts @@ -6,7 +6,7 @@ import { URL } from 'node:url'; export const plugin: PluginDefinition = { authentication: { - name: 'auth-aws-sig-v4', + name: 'awsv4', label: 'AWS Signature', shortLabel: 'AWS v4', args: [ diff --git a/plugins/auth-jwt/src/index.ts b/plugins/auth-jwt/src/index.ts index 9c2dba22..6ae02768 100644 --- a/plugins/auth-jwt/src/index.ts +++ b/plugins/auth-jwt/src/index.ts @@ -46,6 +46,50 @@ export const plugin: PluginDefinition = { name: 'secretBase64', label: 'Secret is base64 encoded', }, + { + type: 'select', + name: 'location', + label: 'Behavior', + defaultValue: 'header', + options: [ + { label: 'Insert Header', value: 'header' }, + { label: 'Append Query Parameter', value: 'query' }, + ], + }, + { + type: 'text', + name: 'name', + label: 'Header Name', + defaultValue: 'Authorization', + optional: true, + dynamic(_ctx, args) { + if (args.values.location === 'query') { + return { + label: 'Parameter Name', + description: 'The name of the query parameter to add to the request', + }; + } else { + return { + label: 'Header Name', + description: 'The name of the header to add to the request', + }; + } + }, + }, + { + type: 'text', + name: 'headerPrefix', + label: 'Header Prefix', + optional: true, + defaultValue: 'Bearer', + dynamic(_ctx, args) { + if (args.values.location === 'query') { + return { + hidden: true, + }; + } + }, + }, { type: 'editor', name: 'payload', @@ -61,8 +105,17 @@ export const plugin: PluginDefinition = { const token = jwt.sign(`${payload}`, secret, { algorithm: algorithm as (typeof algorithms)[number], }); - const value = `Bearer ${token}`; - return { setHeaders: [{ name: 'Authorization', value }] }; + + if (values.location === 'query') { + const paramName = String(values.name || 'token'); + const paramValue = String(values.value || ''); + return { setQueryParameters: [{ name: paramName, value: paramValue }] }; + } else { + const headerPrefix = values.headerPrefix != null ? values.headerPrefix : 'Bearer'; + const headerName = String(values.name || 'Authorization'); + const headerValue = `${headerPrefix} ${token}`.trim(); + return { setHeaders: [{ name: headerName, value: headerValue }] }; + } }, }, }; diff --git a/plugins/importer-postman/src/index.ts b/plugins/importer-postman/src/index.ts index 60f54198..a0300e9b 100644 --- a/plugins/importer-postman/src/index.ts +++ b/plugins/importer-postman/src/index.ts @@ -68,6 +68,7 @@ export function convertPostman(contents: string): ImportPluginResponse | undefin id: generateId('workspace'), name: info.name ? String(info.name) : 'Postman Import', description, + ...globalAuth, }; exportResources.workspaces.push(workspace); @@ -105,8 +106,7 @@ export function convertPostman(contents: string): ImportPluginResponse | undefin } else if (typeof v.name === 'string' && 'request' in v) { const r = toRecord(v.request); const bodyPatch = importBody(r.body); - const requestAuthPath = importAuth(r.auth); - const authPatch = requestAuthPath.authenticationType == null ? globalAuth : requestAuthPath; + const requestAuth = importAuth(r.auth); const headers: HttpRequestHeader[] = toArray<{ key: string; @@ -145,10 +145,9 @@ export function convertPostman(contents: string): ImportPluginResponse | undefin urlParameters, body: bodyPatch.body, bodyType: bodyPatch.bodyType, - authentication: authPatch.authentication, - authenticationType: authPatch.authenticationType, sortPriority: sortPriorityIndex++, headers, + ...requestAuth, }; exportResources.httpRequests.push(request); } else { @@ -223,25 +222,159 @@ function convertUrl(rawUrl: string | unknown): Pick { - const auth = toRecord<{ username?: string; password?: string; token?: string }>(rawAuth); - if ('basic' in auth) { + const auth = toRecord>(rawAuth); + + // Helper: Postman stores auth params as an array of { key, value, ... } + const pmArrayToObj = (v: unknown): Record => { + if (!Array.isArray(v)) return toRecord(v); + const o: Record = {}; + for (const i of v) { + const ii = toRecord(i); + if (typeof ii.key === 'string') { + o[ii.key] = ii.value; + } + } + return o; + }; + + const authType: string | undefined = auth.type ? String(auth.type) : undefined; + + if (authType === 'noauth') { + return { + authenticationType: 'none', + authentication: {}, + }; + } + + if ('basic' in auth && authType === 'basic') { + const b = pmArrayToObj(auth.basic); return { authenticationType: 'basic', authentication: { - username: auth.basic.username || '', - password: auth.basic.password || '', + username: String(b.username ?? ''), + password: String(b.password ?? ''), }, }; - } else if ('bearer' in auth) { + } + + if ('bearer' in auth && authType === 'bearer') { + const b = pmArrayToObj(auth.bearer); + // Postman uses key "token" return { authenticationType: 'bearer', authentication: { - token: auth.bearer.token || '', + token: String(b.token ?? ''), }, }; - } else { - return { authenticationType: null, authentication: {} }; } + + if ('awsv4' in auth && authType === 'awsv4') { + const a = pmArrayToObj(auth.awsv4); + return { + authenticationType: 'awsv4', + authentication: { + accessKeyId: a.accessKeyId != null ? String(a.accessKeyId) : undefined, + secretAccessKey: a.secretKey != null ? String(a.secretKey) : undefined, + sessionToken: a.sessionToken != null ? String(a.sessionToken) : undefined, + region: a.region != null ? String(a.region) : undefined, + service: a.service != null ? String(a.service) : undefined, + }, + }; + } + + if ('apikey' in auth && authType === 'apikey') { + const a = pmArrayToObj(auth.apikey); + return { + authenticationType: 'apikey', + authentication: { + location: a.in === 'query' ? 'query' : 'header', + key: a.value != null ? String(a.value) : undefined, + value: a.key != null ? String(a.key) : undefined, + }, + }; + } + + if ('jwt' in auth && authType === 'jwt') { + const a = pmArrayToObj(auth.jwt); + return { + authenticationType: 'jwt', + authentication: { + algorithm: a.algorithm != null ? String(a.algorithm).toUpperCase() : undefined, + secret: a.secret != null ? String(a.secret) : undefined, + secretBase64: !!a.isSecretBase64Encoded, + payload: a.payload != null ? String(a.payload) : undefined, + headerPrefix: a.headerPrefix != null ? String(a.headerPrefix) : undefined, + location: a.addTokenTo === 'header' ? 'header' : 'query', + }, + }; + } + + if ('oauth2' in auth && authType === 'oauth2') { + const o = pmArrayToObj(auth.oauth2); + + let grantType = o.grant_type ? String(o.grant_type) : 'authorization_code'; + let pkcePatch: Record = {}; + + if (grantType === 'authorization_code_with_pkce') { + grantType = 'authorization_code'; + pkcePatch = + o.grant_type === 'authorization_code_with_pkce' + ? { + usePkce: true, + pkceChallengeMethod: o.challengeAlgorithm ?? undefined, + pkceCodeVerifier: o.code_verifier != null ? String(o.code_verifier) : undefined, + } + : {}; + } else if (grantType === 'password_credentials') { + grantType = 'password'; + } + + const accessTokenUrl = o.accessTokenUrl != null ? String(o.accessTokenUrl) : undefined; + const audience = o.audience != null ? String(o.audience) : undefined; + const authorizationUrl = o.authUrl != null ? String(o.authUrl) : undefined; + const clientId = o.clientId != null ? String(o.clientId) : undefined; + const clientSecret = o.clientSecret != null ? String(o.clientSecret) : undefined; + const credentials = o.client_authentication === 'body' ? 'body' : undefined; + const headerPrefix = o.headerPrefix ?? 'Bearer'; + const password = o.password != null ? String(o.password) : undefined; + const redirectUri = o.redirect_uri != null ? String(o.redirect_uri) : undefined; + const scope = o.scope != null ? String(o.scope) : undefined; + const state = o.state != null ? String(o.state) : undefined; + const username = o.username != null ? String(o.username) : undefined; + + let grantPatch: Record = {}; + if (grantType === 'authorization_code') { + grantPatch = { + clientSecret, + authorizationUrl, + accessTokenUrl, + redirectUri, + state, + ...pkcePatch, + }; + } else if (grantType === 'implicit') { + grantPatch = { authorizationUrl, redirectUri, state }; + } else if (grantType === 'password') { + grantPatch = { clientSecret, accessTokenUrl, username, password }; + } else if (grantType === 'client_credentials') { + grantPatch = { clientSecret, accessTokenUrl }; + } + + const authentication = { + name: 'oauth2', + grantType, + audience, + clientId, + credentials, + headerPrefix, + scope, + ...grantPatch, + } as Record; + + return { authenticationType: 'oauth2', authentication }; + } + + return { authenticationType: null, authentication: {} }; } function importBody(rawBody: unknown): Pick { @@ -376,7 +509,10 @@ function toArray(value: unknown): T[] { /** Recursively render all nested object properties */ function convertTemplateSyntax(obj: T): T { if (typeof obj === 'string') { - return obj.replace(/{{\s*(_\.)?([^}]*)\s*}}/g, (_m, _dot, expr) => '${[' + expr.trim() + ']}') as T; + return obj.replace( + /{{\s*(_\.)?([^}]*)\s*}}/g, + (_m, _dot, expr) => '${[' + expr.trim().replace(/^vault:/, '') + ']}', + ) as T; } else if (Array.isArray(obj) && obj != null) { return obj.map(convertTemplateSyntax) as T; } else if (typeof obj === 'object' && obj != null) { diff --git a/plugins/importer-postman/tests/fixtures/auth.input.json b/plugins/importer-postman/tests/fixtures/auth.input.json new file mode 100644 index 00000000..5561fd14 --- /dev/null +++ b/plugins/importer-postman/tests/fixtures/auth.input.json @@ -0,0 +1,828 @@ +{ + "info": { + "_postman_id": "9e6dfada-256c-49ea-a38f-7d1b05b7ca2d", + "name": "Authentication", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "18798" + }, + "item": [ + { + "name": "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": [] + }, + { + "name": "Inherit", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "https://yaak.app/x/echo", + "protocol": "https", + "host": [ + "yaak", + "app" + ], + "path": [ + "x", + "echo" + ] + } + }, + "response": [] + }, + { + "name": "OAuth 2 Auth Code", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "oauth2", + "oauth2": [ + { + "key": "grant_type", + "value": "authorization_code", + "type": "string" + }, + { + "key": "headerPrefix", + "value": "Bearer", + "type": "string" + }, + { + "key": "client_authentication", + "value": "header", + "type": "string" + }, + { + "key": "challengeAlgorithm", + "value": "S256", + "type": "string" + }, + { + "key": "refreshTokenUrl", + "value": "https://github.com/login/oauth/access_token", + "type": "string" + }, + { + "key": "state", + "value": "state", + "type": "string" + }, + { + "key": "scope", + "value": "scope", + "type": "string" + }, + { + "key": "code_verifier", + "value": "verifier", + "type": "string" + }, + { + "key": "clientSecret", + "value": "clientsecet", + "type": "string" + }, + { + "key": "clientId", + "value": "cliend id", + "type": "string" + }, + { + "key": "authUrl", + "value": "https://github.com/login/oauth/authorize", + "type": "string" + }, + { + "key": "accessTokenUrl", + "value": "https://github.com/login/oauth/access_token", + "type": "string" + }, + { + "key": "useBrowser", + "value": true, + "type": "boolean" + }, + { + "key": "redirect_uri", + "value": "https://callback", + "type": "string" + }, + { + "key": "tokenName", + "value": "name", + "type": "string" + }, + { + "key": "addTokenTo", + "value": "header", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"hello\": \"world\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{vault:hello}}", + "host": [ + "{{vault:hello}}" + ] + } + }, + "response": [] + }, + { + "name": "OAuth 2 Auth Code (PKCE)", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "oauth2", + "oauth2": [ + { + "key": "headerPrefix", + "value": "Bearer", + "type": "string" + }, + { + "key": "client_authentication", + "value": "header", + "type": "string" + }, + { + "key": "challengeAlgorithm", + "value": "S256", + "type": "string" + }, + { + "key": "refreshTokenUrl", + "value": "https://github.com/login/oauth/access_token", + "type": "string" + }, + { + "key": "state", + "value": "state", + "type": "string" + }, + { + "key": "scope", + "value": "scope", + "type": "string" + }, + { + "key": "code_verifier", + "value": "verifier", + "type": "string" + }, + { + "key": "grant_type", + "value": "authorization_code_with_pkce", + "type": "string" + }, + { + "key": "clientSecret", + "value": "clientsecet", + "type": "string" + }, + { + "key": "clientId", + "value": "cliend id", + "type": "string" + }, + { + "key": "authUrl", + "value": "https://github.com/login/oauth/authorize", + "type": "string" + }, + { + "key": "accessTokenUrl", + "value": "https://github.com/login/oauth/access_token", + "type": "string" + }, + { + "key": "useBrowser", + "value": true, + "type": "boolean" + }, + { + "key": "redirect_uri", + "value": "https://callback", + "type": "string" + }, + { + "key": "tokenName", + "value": "name", + "type": "string" + }, + { + "key": "addTokenTo", + "value": "header", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"hello\": \"world\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{vault:hello}}", + "host": [ + "{{vault:hello}}" + ] + } + }, + "response": [] + }, + { + "name": "OAuth 2 Implicit", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "oauth2", + "oauth2": [ + { + "key": "client_authentication", + "value": "header", + "type": "string" + }, + { + "key": "redirect_uri", + "value": "https://yaak.app/x/echo", + "type": "string" + }, + { + "key": "useBrowser", + "value": false, + "type": "boolean" + }, + { + "key": "grant_type", + "value": "implicit", + "type": "string" + }, + { + "key": "headerPrefix", + "value": "Bearer", + "type": "string" + }, + { + "key": "challengeAlgorithm", + "value": "S256", + "type": "string" + }, + { + "key": "refreshTokenUrl", + "value": "https://github.com/login/oauth/access_token", + "type": "string" + }, + { + "key": "state", + "value": "state", + "type": "string" + }, + { + "key": "scope", + "value": "scope", + "type": "string" + }, + { + "key": "code_verifier", + "value": "verifier", + "type": "string" + }, + { + "key": "clientSecret", + "value": "clientsecet", + "type": "string" + }, + { + "key": "clientId", + "value": "cliend id", + "type": "string" + }, + { + "key": "authUrl", + "value": "https://github.com/login/oauth/authorize", + "type": "string" + }, + { + "key": "accessTokenUrl", + "value": "https://github.com/login/oauth/access_token", + "type": "string" + }, + { + "key": "tokenName", + "value": "name", + "type": "string" + }, + { + "key": "addTokenTo", + "value": "header", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"hello\": \"world\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{vault:hello}}", + "host": [ + "{{vault:hello}}" + ] + } + }, + "response": [] + }, + { + "name": "OAuth 2 Password", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "oauth2", + "oauth2": [ + { + "key": "password", + "value": "password", + "type": "string" + }, + { + "key": "username", + "value": "username", + "type": "string" + }, + { + "key": "clientSecret", + "value": "clientsecret", + "type": "string" + }, + { + "key": "clientId", + "value": "clientid", + "type": "string" + }, + { + "key": "grant_type", + "value": "password_credentials", + "type": "string" + }, + { + "key": "client_authentication", + "value": "header", + "type": "string" + }, + { + "key": "redirect_uri", + "value": "https://yaak.app/x/echo", + "type": "string" + }, + { + "key": "useBrowser", + "value": false, + "type": "boolean" + }, + { + "key": "headerPrefix", + "value": "Bearer", + "type": "string" + }, + { + "key": "challengeAlgorithm", + "value": "S256", + "type": "string" + }, + { + "key": "refreshTokenUrl", + "value": "https://github.com/login/oauth/access_token", + "type": "string" + }, + { + "key": "state", + "value": "state", + "type": "string" + }, + { + "key": "scope", + "value": "scope", + "type": "string" + }, + { + "key": "code_verifier", + "value": "verifier", + "type": "string" + }, + { + "key": "authUrl", + "value": "https://github.com/login/oauth/authorize", + "type": "string" + }, + { + "key": "accessTokenUrl", + "value": "https://github.com/login/oauth/access_token", + "type": "string" + }, + { + "key": "tokenName", + "value": "name", + "type": "string" + }, + { + "key": "addTokenTo", + "value": "header", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"hello\": \"world\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{vault:hello}}", + "host": [ + "{{vault:hello}}" + ] + } + }, + "response": [] + }, + { + "name": "OAuth 2 Client Credentials", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "oauth2", + "oauth2": [ + { + "key": "grant_type", + "value": "client_credentials", + "type": "string" + }, + { + "key": "password", + "value": "password", + "type": "string" + }, + { + "key": "username", + "value": "username", + "type": "string" + }, + { + "key": "clientSecret", + "value": "clientsecret", + "type": "string" + }, + { + "key": "clientId", + "value": "clientid", + "type": "string" + }, + { + "key": "client_authentication", + "value": "header", + "type": "string" + }, + { + "key": "redirect_uri", + "value": "https://yaak.app/x/echo", + "type": "string" + }, + { + "key": "useBrowser", + "value": false, + "type": "boolean" + }, + { + "key": "headerPrefix", + "value": "Bearer", + "type": "string" + }, + { + "key": "challengeAlgorithm", + "value": "S256", + "type": "string" + }, + { + "key": "refreshTokenUrl", + "value": "https://github.com/login/oauth/access_token", + "type": "string" + }, + { + "key": "state", + "value": "state", + "type": "string" + }, + { + "key": "scope", + "value": "scope", + "type": "string" + }, + { + "key": "code_verifier", + "value": "verifier", + "type": "string" + }, + { + "key": "authUrl", + "value": "https://github.com/login/oauth/authorize", + "type": "string" + }, + { + "key": "accessTokenUrl", + "value": "https://github.com/login/oauth/access_token", + "type": "string" + }, + { + "key": "tokenName", + "value": "name", + "type": "string" + }, + { + "key": "addTokenTo", + "value": "header", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"hello\": \"world\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{vault:hello}}", + "host": [ + "{{vault:hello}}" + ] + } + }, + "response": [] + }, + { + "name": "AWS V4", + "request": { + "auth": { + "type": "awsv4", + "awsv4": [ + { + "key": "sessionToken", + "value": "session", + "type": "string" + }, + { + "key": "service", + "value": "s3", + "type": "string" + }, + { + "key": "region", + "value": "us-west-1", + "type": "string" + }, + { + "key": "secretKey", + "value": "secret", + "type": "string" + }, + { + "key": "accessKey", + "value": "access", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "https://yaak.app/x/echo", + "protocol": "https", + "host": [ + "yaak", + "app" + ], + "path": [ + "x", + "echo" + ] + } + }, + "response": [] + }, + { + "name": "API Key", + "request": { + "auth": { + "type": "apikey", + "apikey": [ + { + "key": "in", + "value": "query", + "type": "string" + }, + { + "key": "value", + "value": "value", + "type": "string" + }, + { + "key": "key", + "value": "key", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "https://yaak.app/x/echo", + "protocol": "https", + "host": [ + "yaak", + "app" + ], + "path": [ + "x", + "echo" + ] + } + }, + "response": [] + }, + { + "name": "JWT", + "request": { + "auth": { + "type": "jwt", + "jwt": [ + { + "key": "header", + "value": "{\n \"header\": \"foo\"\n}", + "type": "string" + }, + { + "key": "headerPrefix", + "value": "Bearer", + "type": "string" + }, + { + "key": "payload", + "value": "{\n \"my\": \"payload\"\n}", + "type": "string" + }, + { + "key": "isSecretBase64Encoded", + "value": false, + "type": "boolean" + }, + { + "key": "secret", + "value": "mysecret", + "type": "string" + }, + { + "key": "algorithm", + "value": "HS384", + "type": "string" + }, + { + "key": "addTokenTo", + "value": "header", + "type": "string" + }, + { + "key": "queryParamKey", + "value": "token", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "https://yaak.app/x/echo", + "protocol": "https", + "host": [ + "yaak", + "app" + ], + "path": [ + "x", + "echo" + ] + } + }, + "response": [] + } + ], + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "workspace_secret", + "type": "string" + }, + { + "key": "username", + "value": "workspace", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "requests": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "requests": {}, + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "COLLECTION VARIABLE", + "value": "collection variable" + } + ] +} \ No newline at end of file diff --git a/plugins/importer-postman/tests/fixtures/auth.output.json b/plugins/importer-postman/tests/fixtures/auth.output.json new file mode 100644 index 00000000..e4881654 --- /dev/null +++ b/plugins/importer-postman/tests/fixtures/auth.output.json @@ -0,0 +1,303 @@ +{ + "resources": { + "workspaces": [ + { + "model": "workspace", + "id": "GENERATE_ID::WORKSPACE_0", + "name": "Authentication", + "authenticationType": "basic", + "authentication": { + "username": "workspace", + "password": "workspace_secret" + } + } + ], + "environments": [ + { + "model": "environment", + "id": "GENERATE_ID::ENVIRONMENT_0", + "name": "Global Variables", + "workspaceId": "GENERATE_ID::WORKSPACE_0", + "parentModel": "workspace", + "parentId": null, + "variables": [ + { + "name": "COLLECTION VARIABLE", + "value": "collection variable" + } + ] + } + ], + "httpRequests": [ + { + "model": "http_request", + "id": "GENERATE_ID::HTTP_REQUEST_0", + "workspaceId": "GENERATE_ID::WORKSPACE_0", + "folderId": null, + "name": "No Auth", + "method": "GET", + "url": "https://yaak.app/x/echo", + "urlParameters": [], + "body": {}, + "bodyType": null, + "sortPriority": 0, + "headers": [], + "authenticationType": "none", + "authentication": {} + }, + { + "model": "http_request", + "id": "GENERATE_ID::HTTP_REQUEST_1", + "workspaceId": "GENERATE_ID::WORKSPACE_0", + "folderId": null, + "name": "Inherit", + "method": "GET", + "url": "https://yaak.app/x/echo", + "urlParameters": [], + "body": {}, + "bodyType": null, + "sortPriority": 1, + "headers": [], + "authenticationType": null, + "authentication": {} + }, + { + "model": "http_request", + "id": "GENERATE_ID::HTTP_REQUEST_2", + "workspaceId": "GENERATE_ID::WORKSPACE_0", + "folderId": null, + "name": "OAuth 2 Auth Code", + "method": "GET", + "url": "${[hello]}", + "urlParameters": [], + "body": { + "text": "{\n \"hello\": \"world\"\n}" + }, + "bodyType": "application/json", + "sortPriority": 2, + "headers": [ + { + "name": "Content-Type", + "value": "application/json", + "enabled": true + } + ], + "authenticationType": "oauth2", + "authentication": { + "name": "oauth2", + "grantType": "authorization_code", + "clientId": "cliend id", + "headerPrefix": "Bearer", + "scope": "scope", + "clientSecret": "clientsecet", + "authorizationUrl": "https://github.com/login/oauth/authorize", + "accessTokenUrl": "https://github.com/login/oauth/access_token", + "redirectUri": "https://callback", + "state": "state" + } + }, + { + "model": "http_request", + "id": "GENERATE_ID::HTTP_REQUEST_3", + "workspaceId": "GENERATE_ID::WORKSPACE_0", + "folderId": null, + "name": "OAuth 2 Auth Code (PKCE)", + "method": "GET", + "url": "${[hello]}", + "urlParameters": [], + "body": { + "text": "{\n \"hello\": \"world\"\n}" + }, + "bodyType": "application/json", + "sortPriority": 3, + "headers": [ + { + "name": "Content-Type", + "value": "application/json", + "enabled": true + } + ], + "authenticationType": "oauth2", + "authentication": { + "name": "oauth2", + "grantType": "authorization_code", + "clientId": "cliend id", + "headerPrefix": "Bearer", + "scope": "scope", + "clientSecret": "clientsecet", + "authorizationUrl": "https://github.com/login/oauth/authorize", + "accessTokenUrl": "https://github.com/login/oauth/access_token", + "redirectUri": "https://callback", + "state": "state", + "usePkce": true, + "pkceChallengeMethod": "S256", + "pkceCodeVerifier": "verifier" + } + }, + { + "model": "http_request", + "id": "GENERATE_ID::HTTP_REQUEST_4", + "workspaceId": "GENERATE_ID::WORKSPACE_0", + "folderId": null, + "name": "OAuth 2 Implicit", + "method": "GET", + "url": "${[hello]}", + "urlParameters": [], + "body": { + "text": "{\n \"hello\": \"world\"\n}" + }, + "bodyType": "application/json", + "sortPriority": 4, + "headers": [ + { + "name": "Content-Type", + "value": "application/json", + "enabled": true + } + ], + "authenticationType": "oauth2", + "authentication": { + "name": "oauth2", + "grantType": "implicit", + "clientId": "cliend id", + "headerPrefix": "Bearer", + "scope": "scope", + "authorizationUrl": "https://github.com/login/oauth/authorize", + "redirectUri": "https://yaak.app/x/echo", + "state": "state" + } + }, + { + "model": "http_request", + "id": "GENERATE_ID::HTTP_REQUEST_5", + "workspaceId": "GENERATE_ID::WORKSPACE_0", + "folderId": null, + "name": "OAuth 2 Password", + "method": "GET", + "url": "${[hello]}", + "urlParameters": [], + "body": { + "text": "{\n \"hello\": \"world\"\n}" + }, + "bodyType": "application/json", + "sortPriority": 5, + "headers": [ + { + "name": "Content-Type", + "value": "application/json", + "enabled": true + } + ], + "authenticationType": "oauth2", + "authentication": { + "name": "oauth2", + "grantType": "password", + "clientId": "clientid", + "headerPrefix": "Bearer", + "scope": "scope", + "clientSecret": "clientsecret", + "accessTokenUrl": "https://github.com/login/oauth/access_token", + "username": "username", + "password": "password" + } + }, + { + "model": "http_request", + "id": "GENERATE_ID::HTTP_REQUEST_6", + "workspaceId": "GENERATE_ID::WORKSPACE_0", + "folderId": null, + "name": "OAuth 2 Client Credentials", + "method": "GET", + "url": "${[hello]}", + "urlParameters": [], + "body": { + "text": "{\n \"hello\": \"world\"\n}" + }, + "bodyType": "application/json", + "sortPriority": 6, + "headers": [ + { + "name": "Content-Type", + "value": "application/json", + "enabled": true + } + ], + "authenticationType": "oauth2", + "authentication": { + "name": "oauth2", + "grantType": "client_credentials", + "clientId": "clientid", + "headerPrefix": "Bearer", + "scope": "scope", + "clientSecret": "clientsecret", + "accessTokenUrl": "https://github.com/login/oauth/access_token" + } + }, + { + "model": "http_request", + "id": "GENERATE_ID::HTTP_REQUEST_7", + "workspaceId": "GENERATE_ID::WORKSPACE_0", + "folderId": null, + "name": "AWS V4", + "method": "GET", + "url": "https://yaak.app/x/echo", + "urlParameters": [], + "body": {}, + "bodyType": null, + "sortPriority": 7, + "headers": [], + "authenticationType": "awsv4", + "authentication": { + "secretAccessKey": "secret", + "sessionToken": "session", + "region": "us-west-1", + "service": "s3" + } + }, + { + "model": "http_request", + "id": "GENERATE_ID::HTTP_REQUEST_8", + "workspaceId": "GENERATE_ID::WORKSPACE_0", + "folderId": null, + "name": "API Key", + "method": "GET", + "url": "https://yaak.app/x/echo", + "urlParameters": [], + "body": {}, + "bodyType": null, + "sortPriority": 8, + "headers": [], + "authenticationType": "apikey", + "authentication": { + "location": "query", + "key": "value", + "value": "key" + } + }, + { + "model": "http_request", + "id": "GENERATE_ID::HTTP_REQUEST_9", + "workspaceId": "GENERATE_ID::WORKSPACE_0", + "folderId": null, + "name": "JWT", + "method": "GET", + "url": "https://yaak.app/x/echo", + "urlParameters": [], + "body": {}, + "bodyType": null, + "sortPriority": 9, + "headers": [], + "authenticationType": "jwt", + "authentication": { + "algorithm": "HS384", + "secret": "mysecret", + "secretBase64": false, + "payload": "{\n \"my\": \"payload\"\n}", + "headerPrefix": "Bearer", + "location": "header" + } + } + ], + "folders": [] + } +} diff --git a/plugins/importer-postman/tests/fixtures/nested.output.json b/plugins/importer-postman/tests/fixtures/nested.output.json index b44cab1b..4c444711 100644 --- a/plugins/importer-postman/tests/fixtures/nested.output.json +++ b/plugins/importer-postman/tests/fixtures/nested.output.json @@ -3,86 +3,88 @@ "workspaces": [ { "model": "workspace", - "id": "GENERATE_ID::WORKSPACE_0", - "name": "New Collection" + "id": "GENERATE_ID::WORKSPACE_1", + "name": "New Collection", + "authenticationType": null, + "authentication": {} } ], "environments": [ { - "id": "GENERATE_ID::ENVIRONMENT_0", "model": "environment", + "id": "GENERATE_ID::ENVIRONMENT_1", "name": "Global Variables", - "variables": [], - "workspaceId": "GENERATE_ID::WORKSPACE_0", + "workspaceId": "GENERATE_ID::WORKSPACE_1", + "parentModel": "workspace", "parentId": null, - "parentModel": "workspace" + "variables": [] } ], "httpRequests": [ { "model": "http_request", - "id": "GENERATE_ID::HTTP_REQUEST_0", - "workspaceId": "GENERATE_ID::WORKSPACE_0", + "id": "GENERATE_ID::HTTP_REQUEST_10", + "workspaceId": "GENERATE_ID::WORKSPACE_1", "folderId": "GENERATE_ID::FOLDER_1", "name": "Request 1", "method": "GET", "url": "", - "sortPriority": 2, "urlParameters": [], "body": {}, "bodyType": null, - "authentication": {}, + "sortPriority": 2, + "headers": [], "authenticationType": null, - "headers": [] + "authentication": {} }, { "model": "http_request", - "id": "GENERATE_ID::HTTP_REQUEST_1", - "workspaceId": "GENERATE_ID::WORKSPACE_0", + "id": "GENERATE_ID::HTTP_REQUEST_11", + "workspaceId": "GENERATE_ID::WORKSPACE_1", "folderId": "GENERATE_ID::FOLDER_0", "name": "Request 2", "method": "GET", - "sortPriority": 3, "url": "", "urlParameters": [], "body": {}, "bodyType": null, - "authentication": {}, + "sortPriority": 3, + "headers": [], "authenticationType": null, - "headers": [] + "authentication": {} }, { "model": "http_request", - "id": "GENERATE_ID::HTTP_REQUEST_2", - "workspaceId": "GENERATE_ID::WORKSPACE_0", + "id": "GENERATE_ID::HTTP_REQUEST_12", + "workspaceId": "GENERATE_ID::WORKSPACE_1", "folderId": null, - "sortPriority": 4, "name": "Request 3", "method": "GET", "url": "", "urlParameters": [], "body": {}, "bodyType": null, - "authentication": {}, + "sortPriority": 4, + "headers": [], "authenticationType": null, - "headers": [] + "authentication": {} } ], "folders": [ { "model": "folder", - "workspaceId": "GENERATE_ID::WORKSPACE_0", + "sortPriority": 0, + "workspaceId": "GENERATE_ID::WORKSPACE_1", "id": "GENERATE_ID::FOLDER_0", "name": "Top Folder", - "sortPriority": 0, "folderId": null }, { "model": "folder", - "workspaceId": "GENERATE_ID::WORKSPACE_0", + "sortPriority": 1, + "workspaceId": "GENERATE_ID::WORKSPACE_1", "id": "GENERATE_ID::FOLDER_1", "name": "Nested Folder", - "sortPriority": 1, "folderId": "GENERATE_ID::FOLDER_0" } ] diff --git a/plugins/importer-postman/tests/fixtures/params.input.json b/plugins/importer-postman/tests/fixtures/params.input.json index f2969d24..b647a992 100644 --- a/plugins/importer-postman/tests/fixtures/params.input.json +++ b/plugins/importer-postman/tests/fixtures/params.input.json @@ -14,7 +14,7 @@ "bearer": [ { "key": "token", - "value": "baeare", + "value": "my-token", "type": "string" } ] diff --git a/plugins/importer-postman/tests/fixtures/params.output.json b/plugins/importer-postman/tests/fixtures/params.output.json index 34acac0a..417d20a3 100644 --- a/plugins/importer-postman/tests/fixtures/params.output.json +++ b/plugins/importer-postman/tests/fixtures/params.output.json @@ -3,18 +3,23 @@ "workspaces": [ { "model": "workspace", - "id": "GENERATE_ID::WORKSPACE_1", - "name": "New Collection" + "id": "GENERATE_ID::WORKSPACE_2", + "name": "New Collection", + "authenticationType": "basic", + "authentication": { + "username": "globaluser", + "password": "globalpass" + } } ], "environments": [ { - "id": "GENERATE_ID::ENVIRONMENT_1", - "workspaceId": "GENERATE_ID::WORKSPACE_1", "model": "environment", + "id": "GENERATE_ID::ENVIRONMENT_2", "name": "Global Variables", - "parentId": null, + "workspaceId": "GENERATE_ID::WORKSPACE_2", "parentModel": "workspace", + "parentId": null, "variables": [ { "name": "COLLECTION VARIABLE", @@ -26,11 +31,10 @@ "httpRequests": [ { "model": "http_request", - "id": "GENERATE_ID::HTTP_REQUEST_3", - "workspaceId": "GENERATE_ID::WORKSPACE_1", + "id": "GENERATE_ID::HTTP_REQUEST_13", + "workspaceId": "GENERATE_ID::WORKSPACE_2", "folderId": null, "name": "Form URL", - "sortPriority": 0, "method": "POST", "url": "example.com/:foo/:bar", "urlParameters": [ @@ -71,10 +75,7 @@ ] }, "bodyType": "multipart/form-data", - "authentication": { - "token": "" - }, - "authenticationType": "bearer", + "sortPriority": 0, "headers": [ { "name": "X-foo", @@ -91,7 +92,11 @@ "value": "multipart/form-data", "enabled": true } - ] + ], + "authenticationType": "bearer", + "authentication": { + "token": "my-token" + } } ], "folders": [] diff --git a/plugins/importer-postman/tests/index.test.ts b/plugins/importer-postman/tests/index.test.ts index 3311605a..0d88c875 100644 --- a/plugins/importer-postman/tests/index.test.ts +++ b/plugins/importer-postman/tests/index.test.ts @@ -17,7 +17,9 @@ describe('importer-postman', () => { const expected = fs.readFileSync(path.join(p, fixture.replace('.input', '.output')), 'utf-8'); const result = convertPostman(contents); // console.log(JSON.stringify(result, null, 2)) - expect(result).toEqual(JSON.parse(expected)); + expect(JSON.stringify(result, null, 2)).toEqual( + JSON.stringify(JSON.parse(expected), null, 2), + ); }); } }); diff --git a/src-tauri/yaak-models/migrations/20251029062024_aws-auth-name.sql b/src-tauri/yaak-models/migrations/20251029062024_aws-auth-name.sql new file mode 100644 index 00000000..7f2b092b --- /dev/null +++ b/src-tauri/yaak-models/migrations/20251029062024_aws-auth-name.sql @@ -0,0 +1,11 @@ +UPDATE http_requests +SET authentication_type = 'awsv4' +WHERE authentication_type = 'auth-aws-sig-v4'; + +UPDATE folders +SET authentication_type = 'awsv4' +WHERE authentication_type = 'auth-aws-sig-v4'; + +UPDATE workspaces +SET authentication_type = 'awsv4' +WHERE authentication_type = 'auth-aws-sig-v4'; diff --git a/src-tauri/yaak-models/src/migrate.rs b/src-tauri/yaak-models/src/migrate.rs index b1cf50ac..4186b5f5 100644 --- a/src-tauri/yaak-models/src/migrate.rs +++ b/src-tauri/yaak-models/src/migrate.rs @@ -1,7 +1,7 @@ use crate::error::Error::MigrationError; use crate::error::Result; use include_dir::{Dir, DirEntry, include_dir}; -use log::info; +use log::{debug, info}; use r2d2::Pool; use r2d2_sqlite::SqliteConnectionManager; use rusqlite::{OptionalExtension, TransactionBehavior, params}; @@ -86,6 +86,7 @@ fn run_migration(migration_path: &DirEntry, tx: &mut rusqlite::Transaction) -> R .optional()?; if row.is_some() { + debug!("Skipping already run migration {description}"); return Ok(false); // Migration was already run }