openapi-explorer 2.1.647 → 2.1.650
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.
- package/dist/browser/openapi-explorer.min.js +2 -2
- package/dist/es/components/api-request.js +12 -1
- package/dist/es/styles/input-styles.js +1 -1
- package/dist/es/templates/security-scheme-template.js +60 -19
- package/dist/es/utils/spec-parser.js +2 -14
- package/dist/lib/components/api-request.js +12 -1
- package/dist/lib/styles/input-styles.js +1 -1
- package/dist/lib/templates/security-scheme-template.js +60 -19
- package/dist/lib/utils/spec-parser.js +2 -14
- package/package.json +1 -1
@@ -496,7 +496,9 @@ export default class ApiRequest extends LitElement {
|
|
496
496
|
const requestBodyContainerEl = requestPanelEl.querySelector('.request-body-container');
|
497
497
|
let pathUrl = `${this.serverUrl.replace(/\/$/, '')}${this.path.replaceAll(' ', '')}`; // Generate URL using Path Params
|
498
498
|
|
499
|
+
const pathParameterMap = {};
|
499
500
|
pathParamEls.map(el => {
|
501
|
+
pathParameterMap[el.dataset.pname] = el.value;
|
500
502
|
pathUrl = pathUrl.replace(`{${el.dataset.pname}}`, encodeURIComponent(el.value) || '-');
|
501
503
|
}); // Handle relative serverUrls
|
502
504
|
|
@@ -511,15 +513,18 @@ export default class ApiRequest extends LitElement {
|
|
511
513
|
headers: new Headers()
|
512
514
|
}; // Query Params
|
513
515
|
|
516
|
+
const queryParameterMap = {};
|
514
517
|
queryParamEls.forEach(el => {
|
515
518
|
if (!el.dataset.array || el.dataset.array === 'false') {
|
516
519
|
if (el.value !== '') {
|
520
|
+
queryParameterMap[el.dataset.pname] = el.value;
|
517
521
|
fetchUrl.searchParams.append(el.dataset.pname, el.value);
|
518
522
|
}
|
519
523
|
} else {
|
520
524
|
const paramSerializeStyle = el.dataset.paramSerializeStyle;
|
521
525
|
const paramSerializeExplode = el.dataset.paramSerializeExplode;
|
522
526
|
const values = Array.isArray(el.value) ? el.value.filter(v => v !== '') : [];
|
527
|
+
queryParameterMap[el.dataset.pname] = values;
|
523
528
|
|
524
529
|
if (values.length > 0) {
|
525
530
|
if (paramSerializeStyle === 'spaceDelimited') {
|
@@ -727,6 +732,8 @@ export default class ApiRequest extends LitElement {
|
|
727
732
|
return {
|
728
733
|
fetchOptions,
|
729
734
|
fetchUrl,
|
735
|
+
path: pathParameterMap,
|
736
|
+
query: queryParameterMap,
|
730
737
|
curlParts: {
|
731
738
|
data: curlData,
|
732
739
|
form: curlForm
|
@@ -752,7 +759,9 @@ export default class ApiRequest extends LitElement {
|
|
752
759
|
const tryBtnEl = this.querySelectorAll('.btn-execute')[0];
|
753
760
|
const {
|
754
761
|
fetchOptions,
|
755
|
-
fetchUrl
|
762
|
+
fetchUrl,
|
763
|
+
path,
|
764
|
+
query
|
756
765
|
} = this.recomputeFetchOptions();
|
757
766
|
this.responseIsBlob = false;
|
758
767
|
this.respContentDisposition = '';
|
@@ -766,6 +775,8 @@ export default class ApiRequest extends LitElement {
|
|
766
775
|
const fetchRequest = {
|
767
776
|
explorerLocation: this.elementId,
|
768
777
|
url: fetchUrl.toString(),
|
778
|
+
path,
|
779
|
+
query,
|
769
780
|
options: fetchOptions,
|
770
781
|
...fetchOptions
|
771
782
|
};
|
@@ -1,4 +1,4 @@
|
|
1
1
|
import { css } from 'lit';
|
2
2
|
/* eslint-disable max-len */
|
3
3
|
|
4
|
-
export default css`.m-btn{border-radius:var(--border-radius);font-weight:600;display:inline-block;padding:6px 16px;font-size:var(--font-size-small);outline:0;line-height:1;text-align:center;white-space:nowrap;border:2px solid var(--primary-color);background-color:transparent;transition:background-color .2s;user-select:none;cursor:pointer;box-shadow:0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24)}.m-btn.primary{background-color:var(--primary-color);color:var(--primary-btn-text-color)}.m-btn.outline-primary{color:var(--primary-color);background-color:var(--bg);border:1px solid var(--bg)}.m-btn.outline-primary:hover{border:1px solid var(--bg)}.m-btn.thin-border{border-width:1px}.m-btn.large{padding:8px 14px}.m-btn.small{padding:5px 12px}.m-btn.tiny{padding:5px 6px}.m-btn.circle{border-radius:50%}.m-btn:hover{background-color:var(--primary-color);color:var(--primary-btn-text-color)}.m-btn.nav{border:2px solid var(--secondary-color)}.m-btn.nav:hover{background-color:var(--secondary-color)}.m-btn:disabled{background-color:var(--bg3);color:var(--fg3);border-color:var(--fg3);cursor:progress;opacity:.4}button,input,select,textarea{color:var(--fg);outline:0;background-color:var(--input-bg);border:1px solid var(--border-color);border-radius:var(--border-radius)}button{font-family:var(--font-regular)}input[type=file],input[type=password],input[type=text],select,textarea{font-family:var(--font-regular);font-weight:400;font-size:var(--font-size-small);transition:border .2s;padding:6px 5px}select{font-family:var(--font-regular);padding-right:30px;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2212%22%20height%3D%2212%22%3E%3Cpath%20d%3D%22M10.3%203.3L6%207.6%201.7%203.3A1%201%200%2000.3%204.7l5%205a1%201%200%20001.4%200l5-5a1%201%200%2010-1.4-1.4z%22%20fill%3D%22%23777777%22%2F%3E%3C%2Fsvg%3E");background-position:calc(100% - 5px) center;background-repeat:no-repeat;background-size:10px;-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer}select:hover{border-color:var(--primary-color)}input[type=password]::placeholder,input[type=text]::placeholder,textarea::placeholder{color:var(--placeholder-color);opacity:1}input[type=password]:active,input[type=password]:focus,input[type=text]:active,input[type=text]:focus,select:focus,textarea:active,textarea:focus{border:1px solid var(--primary-color)}input[type=file]{font-family:var(--font-regular);padding:2px;cursor:pointer;border:1px solid var(--primary-color);min-height:calc(var(--font-size-small) + 18px)}input[type=file]::-webkit-file-upload-button{font-family:var(--font-regular);font-size:var(--font-size-small);outline:0;cursor:pointer;padding:3px 8px;border:1px solid var(--primary-color);background-color:var(--primary-color);color:var(--primary-btn-text-color);border-radius:var(--border-radius);-webkit-appearance:none}pre,textarea{scrollbar-width:thin;scrollbar-color:var(--border-color) var(--input-bg)}pre::-webkit-scrollbar,textarea::-webkit-scrollbar{width:8px;height:8px}pre::-webkit-scrollbar-track,textarea::-webkit-scrollbar-track{background:var(--input-bg)}pre::-webkit-scrollbar-thumb,textarea::-webkit-scrollbar-thumb{border-radius:2px;background-color:var(--border-color)}.link{font-size:var(--font-size-small);text-decoration:underline;color:var(--blue);font-family:var(--font-mono);margin-bottom:2px}input[type=checkbox]:focus{outline:0}input[type=checkbox]{appearance:none;display:inline-block;background-color:var(--light-bg);border-radius:9px;cursor:pointer;height:18px;position:relative;transition:border .15s,padding .25s;min-width:36px;width:36px;vertical-align:top}input[type=checkbox]:after{position:absolute;background-color:var(--bg);border-radius:8px;content:'';top:0;left:0;right:16px;display:block;height:16px;transition:left .25s .1s,right .15s .175s}input[type=checkbox]:checked{box-shadow:inset 0 0 0 13px var(--primary-color);border-color:var(--primary-color)}input[type=checkbox]:checked:after{border:1px solid var(--primary-color);left:16px;right:1px;transition:border .25s,left .15s .25s,right .25s .175s}
|
4
|
+
export default css`.m-btn{border-radius:var(--border-radius);font-weight:600;display:inline-block;padding:6px 16px;font-size:var(--font-size-small);outline:0;line-height:1;text-align:center;white-space:nowrap;border:2px solid var(--primary-color);background-color:transparent;transition:background-color .2s;user-select:none;cursor:pointer;box-shadow:0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24)}.m-btn.primary{background-color:var(--primary-color);color:var(--primary-btn-text-color)}.m-btn.outline-primary{color:var(--primary-color);background-color:var(--bg);border:1px solid var(--bg)}.m-btn.outline-primary:hover{border:1px solid var(--bg)}.m-btn.thin-border{border-width:1px}.m-btn.large{padding:8px 14px}.m-btn.small{padding:5px 12px}.m-btn.tiny{padding:5px 6px}.m-btn.circle{border-radius:50%}.m-btn:hover{background-color:var(--primary-color);color:var(--primary-btn-text-color)}.m-btn.nav{border:2px solid var(--secondary-color)}.m-btn.nav:hover{background-color:var(--secondary-color)}.m-btn:disabled{background-color:var(--bg3);color:var(--fg3);border-color:var(--fg3);cursor:progress;opacity:.4}button,input,select,textarea{color:var(--fg);outline:0;background-color:var(--input-bg);border:1px solid var(--border-color);border-radius:var(--border-radius)}button{font-family:var(--font-regular)}input[type=file],input[type=password],input[type=text],select,textarea{font-family:var(--font-regular);font-weight:400;font-size:var(--font-size-small);transition:border .2s;padding:6px 5px}select{font-family:var(--font-regular);padding-right:30px;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2212%22%20height%3D%2212%22%3E%3Cpath%20d%3D%22M10.3%203.3L6%207.6%201.7%203.3A1%201%200%2000.3%204.7l5%205a1%201%200%20001.4%200l5-5a1%201%200%2010-1.4-1.4z%22%20fill%3D%22%23777777%22%2F%3E%3C%2Fsvg%3E");background-position:calc(100% - 5px) center;background-repeat:no-repeat;background-size:10px;-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer}select:hover{border-color:var(--primary-color)}input[type=password]::placeholder,input[type=text]::placeholder,textarea::placeholder{color:var(--placeholder-color);opacity:1}input[type=password]:active,input[type=password]:focus,input[type=text]:active,input[type=text]:focus,select:focus,textarea:active,textarea:focus{border:1px solid var(--primary-color)}input[type=file]{font-family:var(--font-regular);padding:2px;cursor:pointer;border:1px solid var(--primary-color);min-height:calc(var(--font-size-small) + 18px)}input[type=file]::-webkit-file-upload-button{font-family:var(--font-regular);font-size:var(--font-size-small);outline:0;cursor:pointer;padding:3px 8px;border:1px solid var(--primary-color);background-color:var(--primary-color);color:var(--primary-btn-text-color);border-radius:var(--border-radius);-webkit-appearance:none}pre,textarea{scrollbar-width:thin;scrollbar-color:var(--border-color) var(--input-bg)}pre::-webkit-scrollbar,textarea::-webkit-scrollbar{width:8px;height:8px}pre::-webkit-scrollbar-track,textarea::-webkit-scrollbar-track{background:var(--input-bg)}pre::-webkit-scrollbar-thumb,textarea::-webkit-scrollbar-thumb{border-radius:2px;background-color:var(--border-color)}.link{font-size:var(--font-size-small);text-decoration:underline;color:var(--blue);font-family:var(--font-mono);margin-bottom:2px}input[type=checkbox]:focus{outline:0}input[type=checkbox]{appearance:none;display:inline-block;background-color:var(--light-bg);border-radius:9px;cursor:pointer;height:18px;position:relative;transition:border .15s,padding .25s;min-width:36px;width:36px;vertical-align:top}input[type=checkbox]:after{position:absolute;background-color:var(--bg);border-radius:8px;content:'';top:0;left:0;right:16px;display:block;height:16px;transition:left .25s .1s,right .15s .175s}input[type=checkbox]:checked{box-shadow:inset 0 0 0 13px var(--primary-color);border-color:var(--primary-color)}input[type=checkbox]:checked:after{border:1px solid var(--primary-color);left:16px;right:1px;transition:border .25s,left .15s .25s,right .25s .175s}.oauth-client-input{display:flex;align-items:center;flex-grow:1;width:300px;max-width:300px;margin-top:1rem}input.oauth-client-secret{flex-grow:1;max-width:300px}`;
|
@@ -204,9 +204,9 @@ export async function checkForAuthToken(redirectToApiLocation) {
|
|
204
204
|
|
205
205
|
async function onInvokeOAuthFlow(apiKeyId, flowType, authUrl, tokenUrl, e) {
|
206
206
|
const authFlowDivEl = e.target.closest('.oauth-flow');
|
207
|
-
const clientId = authFlowDivEl.querySelector('
|
208
|
-
const clientSecret = authFlowDivEl.querySelector('
|
209
|
-
const sendClientSecretIn = authFlowDivEl.querySelector('
|
207
|
+
const clientId = authFlowDivEl.querySelector('#oauth-client-id') ? authFlowDivEl.querySelector('#oauth-client-id').value.trim() : '';
|
208
|
+
const clientSecret = authFlowDivEl.querySelector('#oauth-client-secret') ? authFlowDivEl.querySelector('#oauth-client-secret').value.trim() : '';
|
209
|
+
const sendClientSecretIn = authFlowDivEl.querySelector('#oauth-send-client-secret-in') ? authFlowDivEl.querySelector('#oauth-send-client-secret-in').value.trim() : 'header';
|
210
210
|
const checkedScopeEls = [...authFlowDivEl.querySelectorAll('input[type="checkbox"]:checked')];
|
211
211
|
const securityObj = this.resolvedSpec.securitySchemes.find(v => v.apiKeyId === apiKeyId);
|
212
212
|
let grantType = '';
|
@@ -294,9 +294,45 @@ function oAuthFlowTemplate(flowName, securityObj, authFlow) {
|
|
294
294
|
flowNameDisplay = flowName;
|
295
295
|
}
|
296
296
|
|
297
|
-
return html` <div class="oauth-flow" style="padding:10px 0;margin-bottom:10px"> <div class="tiny-title upper" style="margin-bottom:5px">${flowNameDisplay}</div> ${authorizationUrl ? html`<div><span style="width:75px;display:inline-block">Auth URL</span> <span class="mono-font"> ${authorizationUrl} </span></div>` : ''} ${tokenUrl ? html`<div><span style="width:75px;display:inline-block">Token URL</span> <span class="mono-font">${tokenUrl}</span></div>` : ''} ${refreshUrl ? html`<div><span style="width:75px;display:inline-block">Refresh URL</span> <span class="mono-font">${refreshUrl}</span></div>` : ''} ${flowName === 'authorizationCode' || flowName === 'clientCredentials' || flowName === 'implicit' ? html` ${authFlow.scopes ? html` <span> Scopes </span> <div class="oauth-scopes" part="section-auth-scopes" style="width:100%;display:flex;flex-direction:column;flex-wrap:wrap;margin:0 0 .125rem 0"> ${Object.entries(authFlow.scopes).map((scopeAndDescr, index) => html` <div class="m-checkbox" style="display:inline-flex;align-items:center"> <input type="checkbox" checked="checked" part="checkbox checkbox-auth-scope" id="${flowName}${index}" value="${scopeAndDescr[0]}"> <label for="${flowName}${index}" style="margin-left:5px"> <span class="mono-font">${scopeAndDescr[0]}</span> ${scopeAndDescr[0] !== scopeAndDescr[1] ? ` - ${scopeAndDescr[1] || ''}` : ''} </label> </div> `)} </div> ` : ''} <div style="display:flex"> <input type="text" part="textbox textbox-auth-client-id" value="${securityObj.clientId || ''}" placeholder="Client ID" spellcheck="false" class="oauth-client-
|
297
|
+
return html` <div class="oauth-flow" style="padding:10px 0;margin-bottom:10px"> <div class="tiny-title upper" style="margin-bottom:5px">${flowNameDisplay}</div> ${authorizationUrl ? html`<div><span style="width:75px;display:inline-block">Auth URL</span> <span class="mono-font"> ${authorizationUrl} </span></div>` : ''} ${tokenUrl ? html`<div><span style="width:75px;display:inline-block">Token URL</span> <span class="mono-font">${tokenUrl}</span></div>` : ''} ${refreshUrl ? html`<div><span style="width:75px;display:inline-block">Refresh URL</span> <span class="mono-font">${refreshUrl}</span></div>` : ''} ${flowName === 'authorizationCode' || flowName === 'clientCredentials' || flowName === 'implicit' ? html` ${authFlow.scopes ? html` <span> Scopes </span> <div class="oauth-scopes" part="section-auth-scopes" style="width:100%;display:flex;flex-direction:column;flex-wrap:wrap;margin:0 0 .125rem 0"> ${Object.entries(authFlow.scopes).map((scopeAndDescr, index) => html` <div class="m-checkbox" style="display:inline-flex;align-items:center"> <input type="checkbox" checked="checked" part="checkbox checkbox-auth-scope" id="${flowName}${index}" value="${scopeAndDescr[0]}"> <label for="${flowName}${index}" style="margin-left:5px"> <span class="mono-font">${scopeAndDescr[0]}</span> ${scopeAndDescr[0] !== scopeAndDescr[1] ? ` - ${scopeAndDescr[1] || ''}` : ''} </label> </div> `)} </div> ` : ''} <div style="display:flex"> <div> <input id="oauth-client-id" type="text" part="textbox textbox-auth-client-id" value="${securityObj.clientId || ''}" placeholder="Client ID" spellcheck="false" class="oauth-client-input"> ${flowName === 'clientCredentials' ? html` <input id="oauth-client-secret" type="password" part="textbox textbox-auth-client-secret" value="" placeholder="Client Secret" spellcheck="false" class="oauth-client-input"> <select id="oauth-send-client-secret-in" aria-label="oauth client secret location" style="margin-right:5px" class="oauth-client-input"> <option value="header" selected="selected"> Authorization Header </option> <option value="request-body"> Request Body </option> </select> ` : html`<div style="width:5px"></div>`} </div> ${flowName === 'authorizationCode' || flowName === 'clientCredentials' || flowName === 'implicit' ? html` <div class="oauth-client-input" style="margin-left:1rem"> <button class="m-btn thin-border" part="btn btn-outline" @click="${e => {
|
298
298
|
onInvokeOAuthFlow.call(this, apiKeyId, flowName, authorizationUrl, tokenUrl, e);
|
299
|
-
}}">GET TOKEN</button>` : ''} </div> <div class="oauth-resp-display red-text small-font-size"></div> ` : ''} </div> `;
|
299
|
+
}}">GET TOKEN</button> </div>` : ''} </div> <div class="oauth-resp-display red-text small-font-size"></div> ` : ''} </div> `;
|
300
|
+
}
|
301
|
+
|
302
|
+
function renderSecurityScheme(v) {
|
303
|
+
if (!v.type) {
|
304
|
+
return '';
|
305
|
+
}
|
306
|
+
|
307
|
+
if (v.type.toLowerCase() === 'apikey' || v.type.toLowerCase() === 'http' && v.scheme && v.scheme.toLowerCase() === 'bearer') {
|
308
|
+
var _v$bearerFormat, _v$bearerFormat2;
|
309
|
+
|
310
|
+
return html` <div style="padding-top:1rem"> ${v.type.toLowerCase() === 'apikey' ? html`Send <code>${v.name || 'API key'}</code> in <code>${v.in || 'the request'}</code> with the given value:` : html`Send <code>Authorization</code> in <code>header</code> containing the word <code>Bearer</code> followed by a space and then the ${(_v$bearerFormat = v.bearerFormat) !== null && _v$bearerFormat !== void 0 ? _v$bearerFormat : 'Token String'}.`} </div> <form style="height:50px;margin-top:1rem;padding:10px 0;margin-bottom:10px"> ${v.in === 'cookie' ? html` <div style="display:block"> <input type="text" value="${getCookieValue(v.apiKeyId)}" disabled="disabled" class="api-key-input" placeholder="IygRVGf54B59e0GAkKmigGfuiVlp/uhFfk2ifA+jMMJzau2F1jPldc09gPTfnMw13BFBxqUZIFDm55DPfwkb0A==" spellcheck="false" style="resize:horizontal;width:100%"> <br> <small> <strong>Cookies</strong> are set and configured by the remote service, therefore it is not possible to configure them from the browser. </small> </div>` : !v.finalKeyValue ? html` <input type="text" value="${v.value}" placeholder="${(_v$bearerFormat2 = v.bearerFormat) !== null && _v$bearerFormat2 !== void 0 ? _v$bearerFormat2 : 'api-token'}" spellcheck="false" class="api-key-input fs-exclude" data-hj-suppress data-sl="mask"> <button type="submit" class="m-btn thin-border" style="margin-left:5px" part="btn btn-outline" @click="${e => {
|
311
|
+
onApiKeyChange.call(this, v.apiKeyId, e);
|
312
|
+
}}"> ${getI18nText('authentication.set')} </button>` : html`<span class="blue-text" style="margin-right:1rem">Key Applied</span> <button class="m-btn thin-border small" part="btn btn-outline" @click="${() => {
|
313
|
+
v.finalKeyValue = '';
|
314
|
+
this.requestUpdate();
|
315
|
+
}}">REMOVE</button>`} </form>`;
|
316
|
+
}
|
317
|
+
|
318
|
+
if (v.type.toLowerCase() === 'http' && v.scheme && v.scheme.toLowerCase() === 'basic') {
|
319
|
+
if (v.finalKeyValue) {
|
320
|
+
return html` <div style="padding-top:1rem">${getI18nText('authentication.http-basic-desc')}</div> <div style="height:50px;margin-top:1rem;padding:10px 0;margin-bottom:10px"> <span class="blue-text" style="margin-right:1rem">Key Applied</span> <button class="m-btn thin-border small" part="btn btn-outline" @click="${() => {
|
321
|
+
v.finalKeyValue = '';
|
322
|
+
this.requestUpdate();
|
323
|
+
}}">REMOVE</button> </div>`;
|
324
|
+
}
|
325
|
+
|
326
|
+
return html` <div style="padding-top:1rem">${getI18nText('authentication.http-basic-desc')}</div> <div style="height:50px;margin-top:1rem;padding:10px 0;margin-bottom:10px"> <form style="display:flex"> <input type="text" value="${v.user}" placeholder="${getI18nText('authentication.username')}" spellcheck="false" class="api-key-user" style="width:100px"> <input class="api-key-password fs-exclude" data-hj-suppress data-sl="mask" type="password" value="${v.password}" placeholder="${getI18nText('authentication.password')}" spellcheck="false" style="width:100px;margin:0 5px"> <button type="submit" class="m-btn thin-border" @click="${e => {
|
327
|
+
onApiKeyChange.call(this, v.apiKeyId, e);
|
328
|
+
}}" part="btn btn-outline"> ${v.finalKeyValue ? 'UPDATE' : getI18nText('authentication.set')} </button> </form> </div>`;
|
329
|
+
}
|
330
|
+
|
331
|
+
if (v.type.toLowerCase() === 'oauth2' && Object.keys(v.flows).length) {
|
332
|
+
return html`${Object.keys(v.flows).map(f => oAuthFlowTemplate.call(this, f, v, v.flows[f]))}`;
|
333
|
+
}
|
334
|
+
|
335
|
+
return '';
|
300
336
|
}
|
301
337
|
|
302
338
|
export default function securitySchemeTemplate() {
|
@@ -307,20 +343,9 @@ export default function securitySchemeTemplate() {
|
|
307
343
|
}
|
308
344
|
|
309
345
|
const providedApiKeys = schemes.filter(v => v.finalKeyValue);
|
310
|
-
return html` <section id="auth" part="section-auth" class="observe-me ${this.renderStyle === 'focused' ? 'section-gap--focused-mode' : 'section-gap'}"> <slot name="authentication"> <div class="section-padding"> <slot name="authentication-header"> <div class="sub-title regular-font">${getI18nText('headers.authentication')}</div> </slot> <div class="small-font-size" style="display:flex;align-items:center;min-height:
|
346
|
+
return html` <section id="auth" part="section-auth" class="observe-me ${this.renderStyle === 'focused' ? 'section-gap--focused-mode' : 'section-gap'}"> <slot name="authentication"> <div class="section-padding"> <slot name="authentication-header"> <div class="sub-title regular-font">${getI18nText('headers.authentication')}</div> </slot> <div class="small-font-size" style="display:flex;align-items:center;min-height:40px"> ${providedApiKeys.length > 0 ? html` <div class="blue-text"> ${providedApiKeys.length} API key applied </div> <div style="flex:1"></div> <button class="m-btn thin-border" part="btn btn-outline" @click="${() => {
|
311
347
|
onClearAllApiKeys.call(this);
|
312
|
-
}}">CLEAR ALL API KEYS</button>` : html`<div class="red-text">${getI18nText('authentication.no-api-key-applied')}</div>`} </div> ${schemes.length > 0 ? html` <table role="presentation" class="m-table" style="width:100%"> ${schemes.map(v => {
|
313
|
-
var _v$bearerFormat, _v$bearerFormat2;
|
314
|
-
|
315
|
-
return html` <tr> <td colspan="1" style="max-width:500px;overflow-wrap:break-word"> <div style="min-height:24px"> <span style="font-weight:700">${v.typeDisplay}</span> ${v.finalKeyValue ? html` <span class="blue-text"> ${v.finalKeyValue ? 'Key Applied' : ''} </span> <button class="m-btn thin-border small" part="btn btn-outline" @click="${() => {
|
316
|
-
v.finalKeyValue = '';
|
317
|
-
this.requestUpdate();
|
318
|
-
}}">REMOVE</button> ` : ''} </div> ${v.description ? html` <div class="m-markdown"> ${unsafeHTML(marked(v.description || ''))} </div>` : ''} </td> <td colspan="3"> ${v.type && (v.type.toLowerCase() === 'apikey' || v.type.toLowerCase() === 'http' && v.scheme && v.scheme.toLowerCase() === 'bearer') ? html` ${v.type.toLowerCase() === 'apikey' ? html`Send <code>${v.name}</code> in <code>${v.in}</code> with the given value:` : html`Send <code>Authorization</code> in <code>header</code> containing the word <code>Bearer</code> followed by a space and then the ${(_v$bearerFormat = v.bearerFormat) !== null && _v$bearerFormat !== void 0 ? _v$bearerFormat : 'Token String'}.`} <form style="display:flex"> ${v.in === 'cookie' ? html` <div style="display:block"> <input type="text" value="${getCookieValue(v.apiKeyId)}" disabled="disabled" class="api-key-input" placeholder="IygRVGf54B59e0GAkKmigGfuiVlp/uhFfk2ifA+jMMJzau2F1jPldc09gPTfnMw13BFBxqUZIFDm55DPfwkb0A==" spellcheck="false" style="resize:horizontal;width:100%"> <br> <small> <strong>Cookies</strong> are set and configured by the remote service, therefore it is not possible to configure them from the browser. </small> </div>` : html` <input type="text" value="${v.value}" placeholder="${(_v$bearerFormat2 = v.bearerFormat) !== null && _v$bearerFormat2 !== void 0 ? _v$bearerFormat2 : 'api-token'}" spellcheck="false" class="api-key-input fs-exclude" data-hj-suppress data-sl="mask"> <button type="submit" class="m-btn thin-border" style="margin-left:5px" part="btn btn-outline" @click="${e => {
|
319
|
-
onApiKeyChange.call(this, v.apiKeyId, e);
|
320
|
-
}}"> ${v.finalKeyValue ? 'UPDATE' : 'SET'} </button>`} </form>` : ''} ${v.type && v.type.toLowerCase() === 'http' && v.scheme && v.scheme.toLowerCase() === 'basic' ? html` ${getI18nText('authentication.http-basic-desc')} <form style="display:flex"> <input type="text" value="${v.user}" placeholder="${getI18nText('authentication.username')}" spellcheck="false" class="api-key-user" style="width:100px"> <input class="api-key-password fs-exclude" data-hj-suppress data-sl="mask" type="password" value="${v.password}" placeholder="${getI18nText('authentication.password')}" spellcheck="false" style="width:100px;margin:0 5px"> <button type="submit" class="m-btn thin-border" @click="${e => {
|
321
|
-
onApiKeyChange.call(this, v.apiKeyId, e);
|
322
|
-
}}" part="btn btn-outline"> ${v.finalKeyValue ? 'UPDATE' : getI18nText('authentication.set')} </button> </form>` : ''} </td> </tr> ${v.type.toLowerCase() === 'oauth2' ? html` <tr> <td colspan="2" style="border:none;padding-left:48px"> ${Object.keys(v.flows).map(f => oAuthFlowTemplate.call(this, f, v, v.flows[f]))} </td> </tr> ` : ''} `;
|
323
|
-
})} </table>` : ''} <slot name="authentication-footer"></slot> </div> </slot> </section> `;
|
348
|
+
}}">CLEAR ALL API KEYS</button>` : html`<div class="red-text">${getI18nText('authentication.no-api-key-applied')}</div>`} </div> ${schemes.length > 0 ? html` <table role="presentation" class="m-table" style="width:100%"> ${schemes.map(v => html` <tr> <td colspan="1" style="max-width:500px;overflow-wrap:break-word"> <div style="min-height:24px;display:flex;flex-direction:column;justify-content:center;align-items:center"> <div style="display:flex;justify-content:center"> <span style="font-weight:700">${getTypeDisplayHeader(v)}</span> </div> </div> ${v.description ? html` <div class="m-markdown"> ${unsafeHTML(marked(v.description || ''))} </div>` : ''} </td> <td colspan="3">${renderSecurityScheme.call(this, v)}</td> </tr>`)} </table>` : ''} <slot name="authentication-footer"></slot> </div> </slot> </section> `;
|
324
349
|
}
|
325
350
|
|
326
351
|
function getOauthScopeTemplate(rawScopes) {
|
@@ -333,6 +358,22 @@ function getOauthScopeTemplate(rawScopes) {
|
|
333
358
|
return html` <div> <b>Required scopes:</b> <br> <div style="margin-left:8px"> ${scopes.map(scope => html`<span>${scope}</span> `)} </div> </div>`;
|
334
359
|
}
|
335
360
|
|
361
|
+
function getTypeDisplayHeader(securityScheme) {
|
362
|
+
if (securityScheme.type === 'apiKey') {
|
363
|
+
return `API Key (${securityScheme.name})`;
|
364
|
+
}
|
365
|
+
|
366
|
+
if (securityScheme.type === 'oauth2') {
|
367
|
+
return 'OAuth2.0';
|
368
|
+
}
|
369
|
+
|
370
|
+
if (securityScheme.type === 'http') {
|
371
|
+
return securityScheme.scheme === 'basic' ? getI18nText('authentication.http-basic') : 'HTTP Bearer';
|
372
|
+
}
|
373
|
+
|
374
|
+
return securityScheme.type;
|
375
|
+
}
|
376
|
+
|
336
377
|
export function pathSecurityTemplate(pathSecurity) {
|
337
378
|
if (this.resolvedSpec.securitySchemes && pathSecurity) {
|
338
379
|
const orSecurityKeys1 = [];
|
@@ -343,7 +384,7 @@ export function pathSecurityTemplate(pathSecurity) {
|
|
343
384
|
const s = this.resolvedSpec.securitySchemes.find(ss => ss.apiKeyId === pathSecurityKey);
|
344
385
|
|
345
386
|
if (s) {
|
346
|
-
andKeyTypes.push(s
|
387
|
+
andKeyTypes.push(getTypeDisplayHeader(s));
|
347
388
|
andSecurityKeys1.push({ ...s,
|
348
389
|
scopes: pSecurity[pathSecurityKey]
|
349
390
|
});
|
@@ -51,20 +51,8 @@ export default async function ProcessSpec(specUrlOrObject, serverUrl = '') {
|
|
51
51
|
|
52
52
|
securitySchemes.push(securityObj);
|
53
53
|
});
|
54
|
-
} //
|
55
|
-
|
56
|
-
|
57
|
-
securitySchemes.forEach(v => {
|
58
|
-
if (v.type === 'http') {
|
59
|
-
v.typeDisplay = v.scheme === 'basic' ? getI18nText('authentication.http-basic') : 'HTTP Bearer';
|
60
|
-
} else if (v.type === 'apiKey') {
|
61
|
-
v.typeDisplay = `API Key (${v.name})`;
|
62
|
-
} else if (v.type === 'oauth2') {
|
63
|
-
v.typeDisplay = 'OAuth2.0';
|
64
|
-
} else {
|
65
|
-
v.typeDisplay = v.type;
|
66
|
-
}
|
67
|
-
}); // Servers
|
54
|
+
} // Servers
|
55
|
+
|
68
56
|
|
69
57
|
let servers = [];
|
70
58
|
|
@@ -516,7 +516,9 @@ class ApiRequest extends _lit.LitElement {
|
|
516
516
|
const requestBodyContainerEl = requestPanelEl.querySelector('.request-body-container');
|
517
517
|
let pathUrl = `${this.serverUrl.replace(/\/$/, '')}${this.path.replaceAll(' ', '')}`; // Generate URL using Path Params
|
518
518
|
|
519
|
+
const pathParameterMap = {};
|
519
520
|
pathParamEls.map(el => {
|
521
|
+
pathParameterMap[el.dataset.pname] = el.value;
|
520
522
|
pathUrl = pathUrl.replace(`{${el.dataset.pname}}`, encodeURIComponent(el.value) || '-');
|
521
523
|
}); // Handle relative serverUrls
|
522
524
|
|
@@ -531,15 +533,18 @@ class ApiRequest extends _lit.LitElement {
|
|
531
533
|
headers: new Headers()
|
532
534
|
}; // Query Params
|
533
535
|
|
536
|
+
const queryParameterMap = {};
|
534
537
|
queryParamEls.forEach(el => {
|
535
538
|
if (!el.dataset.array || el.dataset.array === 'false') {
|
536
539
|
if (el.value !== '') {
|
540
|
+
queryParameterMap[el.dataset.pname] = el.value;
|
537
541
|
fetchUrl.searchParams.append(el.dataset.pname, el.value);
|
538
542
|
}
|
539
543
|
} else {
|
540
544
|
const paramSerializeStyle = el.dataset.paramSerializeStyle;
|
541
545
|
const paramSerializeExplode = el.dataset.paramSerializeExplode;
|
542
546
|
const values = Array.isArray(el.value) ? el.value.filter(v => v !== '') : [];
|
547
|
+
queryParameterMap[el.dataset.pname] = values;
|
543
548
|
|
544
549
|
if (values.length > 0) {
|
545
550
|
if (paramSerializeStyle === 'spaceDelimited') {
|
@@ -747,6 +752,8 @@ class ApiRequest extends _lit.LitElement {
|
|
747
752
|
return {
|
748
753
|
fetchOptions,
|
749
754
|
fetchUrl,
|
755
|
+
path: pathParameterMap,
|
756
|
+
query: queryParameterMap,
|
750
757
|
curlParts: {
|
751
758
|
data: curlData,
|
752
759
|
form: curlForm
|
@@ -772,7 +779,9 @@ class ApiRequest extends _lit.LitElement {
|
|
772
779
|
const tryBtnEl = this.querySelectorAll('.btn-execute')[0];
|
773
780
|
const {
|
774
781
|
fetchOptions,
|
775
|
-
fetchUrl
|
782
|
+
fetchUrl,
|
783
|
+
path,
|
784
|
+
query
|
776
785
|
} = this.recomputeFetchOptions();
|
777
786
|
this.responseIsBlob = false;
|
778
787
|
this.respContentDisposition = '';
|
@@ -786,6 +795,8 @@ class ApiRequest extends _lit.LitElement {
|
|
786
795
|
const fetchRequest = {
|
787
796
|
explorerLocation: this.elementId,
|
788
797
|
url: fetchUrl.toString(),
|
798
|
+
path,
|
799
|
+
query,
|
789
800
|
options: fetchOptions,
|
790
801
|
...fetchOptions
|
791
802
|
};
|
@@ -6,6 +6,6 @@ exports.default = void 0;
|
|
6
6
|
var _lit = require("lit");
|
7
7
|
|
8
8
|
/* eslint-disable max-len */
|
9
|
-
var _default = (0, _lit.css)`.m-btn{border-radius:var(--border-radius);font-weight:600;display:inline-block;padding:6px 16px;font-size:var(--font-size-small);outline:0;line-height:1;text-align:center;white-space:nowrap;border:2px solid var(--primary-color);background-color:transparent;transition:background-color .2s;user-select:none;cursor:pointer;box-shadow:0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24)}.m-btn.primary{background-color:var(--primary-color);color:var(--primary-btn-text-color)}.m-btn.outline-primary{color:var(--primary-color);background-color:var(--bg);border:1px solid var(--bg)}.m-btn.outline-primary:hover{border:1px solid var(--bg)}.m-btn.thin-border{border-width:1px}.m-btn.large{padding:8px 14px}.m-btn.small{padding:5px 12px}.m-btn.tiny{padding:5px 6px}.m-btn.circle{border-radius:50%}.m-btn:hover{background-color:var(--primary-color);color:var(--primary-btn-text-color)}.m-btn.nav{border:2px solid var(--secondary-color)}.m-btn.nav:hover{background-color:var(--secondary-color)}.m-btn:disabled{background-color:var(--bg3);color:var(--fg3);border-color:var(--fg3);cursor:progress;opacity:.4}button,input,select,textarea{color:var(--fg);outline:0;background-color:var(--input-bg);border:1px solid var(--border-color);border-radius:var(--border-radius)}button{font-family:var(--font-regular)}input[type=file],input[type=password],input[type=text],select,textarea{font-family:var(--font-regular);font-weight:400;font-size:var(--font-size-small);transition:border .2s;padding:6px 5px}select{font-family:var(--font-regular);padding-right:30px;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2212%22%20height%3D%2212%22%3E%3Cpath%20d%3D%22M10.3%203.3L6%207.6%201.7%203.3A1%201%200%2000.3%204.7l5%205a1%201%200%20001.4%200l5-5a1%201%200%2010-1.4-1.4z%22%20fill%3D%22%23777777%22%2F%3E%3C%2Fsvg%3E");background-position:calc(100% - 5px) center;background-repeat:no-repeat;background-size:10px;-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer}select:hover{border-color:var(--primary-color)}input[type=password]::placeholder,input[type=text]::placeholder,textarea::placeholder{color:var(--placeholder-color);opacity:1}input[type=password]:active,input[type=password]:focus,input[type=text]:active,input[type=text]:focus,select:focus,textarea:active,textarea:focus{border:1px solid var(--primary-color)}input[type=file]{font-family:var(--font-regular);padding:2px;cursor:pointer;border:1px solid var(--primary-color);min-height:calc(var(--font-size-small) + 18px)}input[type=file]::-webkit-file-upload-button{font-family:var(--font-regular);font-size:var(--font-size-small);outline:0;cursor:pointer;padding:3px 8px;border:1px solid var(--primary-color);background-color:var(--primary-color);color:var(--primary-btn-text-color);border-radius:var(--border-radius);-webkit-appearance:none}pre,textarea{scrollbar-width:thin;scrollbar-color:var(--border-color) var(--input-bg)}pre::-webkit-scrollbar,textarea::-webkit-scrollbar{width:8px;height:8px}pre::-webkit-scrollbar-track,textarea::-webkit-scrollbar-track{background:var(--input-bg)}pre::-webkit-scrollbar-thumb,textarea::-webkit-scrollbar-thumb{border-radius:2px;background-color:var(--border-color)}.link{font-size:var(--font-size-small);text-decoration:underline;color:var(--blue);font-family:var(--font-mono);margin-bottom:2px}input[type=checkbox]:focus{outline:0}input[type=checkbox]{appearance:none;display:inline-block;background-color:var(--light-bg);border-radius:9px;cursor:pointer;height:18px;position:relative;transition:border .15s,padding .25s;min-width:36px;width:36px;vertical-align:top}input[type=checkbox]:after{position:absolute;background-color:var(--bg);border-radius:8px;content:'';top:0;left:0;right:16px;display:block;height:16px;transition:left .25s .1s,right .15s .175s}input[type=checkbox]:checked{box-shadow:inset 0 0 0 13px var(--primary-color);border-color:var(--primary-color)}input[type=checkbox]:checked:after{border:1px solid var(--primary-color);left:16px;right:1px;transition:border .25s,left .15s .25s,right .25s .175s}
|
9
|
+
var _default = (0, _lit.css)`.m-btn{border-radius:var(--border-radius);font-weight:600;display:inline-block;padding:6px 16px;font-size:var(--font-size-small);outline:0;line-height:1;text-align:center;white-space:nowrap;border:2px solid var(--primary-color);background-color:transparent;transition:background-color .2s;user-select:none;cursor:pointer;box-shadow:0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24)}.m-btn.primary{background-color:var(--primary-color);color:var(--primary-btn-text-color)}.m-btn.outline-primary{color:var(--primary-color);background-color:var(--bg);border:1px solid var(--bg)}.m-btn.outline-primary:hover{border:1px solid var(--bg)}.m-btn.thin-border{border-width:1px}.m-btn.large{padding:8px 14px}.m-btn.small{padding:5px 12px}.m-btn.tiny{padding:5px 6px}.m-btn.circle{border-radius:50%}.m-btn:hover{background-color:var(--primary-color);color:var(--primary-btn-text-color)}.m-btn.nav{border:2px solid var(--secondary-color)}.m-btn.nav:hover{background-color:var(--secondary-color)}.m-btn:disabled{background-color:var(--bg3);color:var(--fg3);border-color:var(--fg3);cursor:progress;opacity:.4}button,input,select,textarea{color:var(--fg);outline:0;background-color:var(--input-bg);border:1px solid var(--border-color);border-radius:var(--border-radius)}button{font-family:var(--font-regular)}input[type=file],input[type=password],input[type=text],select,textarea{font-family:var(--font-regular);font-weight:400;font-size:var(--font-size-small);transition:border .2s;padding:6px 5px}select{font-family:var(--font-regular);padding-right:30px;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2212%22%20height%3D%2212%22%3E%3Cpath%20d%3D%22M10.3%203.3L6%207.6%201.7%203.3A1%201%200%2000.3%204.7l5%205a1%201%200%20001.4%200l5-5a1%201%200%2010-1.4-1.4z%22%20fill%3D%22%23777777%22%2F%3E%3C%2Fsvg%3E");background-position:calc(100% - 5px) center;background-repeat:no-repeat;background-size:10px;-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer}select:hover{border-color:var(--primary-color)}input[type=password]::placeholder,input[type=text]::placeholder,textarea::placeholder{color:var(--placeholder-color);opacity:1}input[type=password]:active,input[type=password]:focus,input[type=text]:active,input[type=text]:focus,select:focus,textarea:active,textarea:focus{border:1px solid var(--primary-color)}input[type=file]{font-family:var(--font-regular);padding:2px;cursor:pointer;border:1px solid var(--primary-color);min-height:calc(var(--font-size-small) + 18px)}input[type=file]::-webkit-file-upload-button{font-family:var(--font-regular);font-size:var(--font-size-small);outline:0;cursor:pointer;padding:3px 8px;border:1px solid var(--primary-color);background-color:var(--primary-color);color:var(--primary-btn-text-color);border-radius:var(--border-radius);-webkit-appearance:none}pre,textarea{scrollbar-width:thin;scrollbar-color:var(--border-color) var(--input-bg)}pre::-webkit-scrollbar,textarea::-webkit-scrollbar{width:8px;height:8px}pre::-webkit-scrollbar-track,textarea::-webkit-scrollbar-track{background:var(--input-bg)}pre::-webkit-scrollbar-thumb,textarea::-webkit-scrollbar-thumb{border-radius:2px;background-color:var(--border-color)}.link{font-size:var(--font-size-small);text-decoration:underline;color:var(--blue);font-family:var(--font-mono);margin-bottom:2px}input[type=checkbox]:focus{outline:0}input[type=checkbox]{appearance:none;display:inline-block;background-color:var(--light-bg);border-radius:9px;cursor:pointer;height:18px;position:relative;transition:border .15s,padding .25s;min-width:36px;width:36px;vertical-align:top}input[type=checkbox]:after{position:absolute;background-color:var(--bg);border-radius:8px;content:'';top:0;left:0;right:16px;display:block;height:16px;transition:left .25s .1s,right .15s .175s}input[type=checkbox]:checked{box-shadow:inset 0 0 0 13px var(--primary-color);border-color:var(--primary-color)}input[type=checkbox]:checked:after{border:1px solid var(--primary-color);left:16px;right:1px;transition:border .25s,left .15s .25s,right .25s .175s}.oauth-client-input{display:flex;align-items:center;flex-grow:1;width:300px;max-width:300px;margin-top:1rem}input.oauth-client-secret{flex-grow:1;max-width:300px}`;
|
10
10
|
|
11
11
|
exports.default = _default;
|
@@ -217,9 +217,9 @@ async function checkForAuthToken(redirectToApiLocation) {
|
|
217
217
|
|
218
218
|
async function onInvokeOAuthFlow(apiKeyId, flowType, authUrl, tokenUrl, e) {
|
219
219
|
const authFlowDivEl = e.target.closest('.oauth-flow');
|
220
|
-
const clientId = authFlowDivEl.querySelector('
|
221
|
-
const clientSecret = authFlowDivEl.querySelector('
|
222
|
-
const sendClientSecretIn = authFlowDivEl.querySelector('
|
220
|
+
const clientId = authFlowDivEl.querySelector('#oauth-client-id') ? authFlowDivEl.querySelector('#oauth-client-id').value.trim() : '';
|
221
|
+
const clientSecret = authFlowDivEl.querySelector('#oauth-client-secret') ? authFlowDivEl.querySelector('#oauth-client-secret').value.trim() : '';
|
222
|
+
const sendClientSecretIn = authFlowDivEl.querySelector('#oauth-send-client-secret-in') ? authFlowDivEl.querySelector('#oauth-send-client-secret-in').value.trim() : 'header';
|
223
223
|
const checkedScopeEls = [...authFlowDivEl.querySelectorAll('input[type="checkbox"]:checked')];
|
224
224
|
const securityObj = this.resolvedSpec.securitySchemes.find(v => v.apiKeyId === apiKeyId);
|
225
225
|
let grantType = '';
|
@@ -307,9 +307,45 @@ function oAuthFlowTemplate(flowName, securityObj, authFlow) {
|
|
307
307
|
flowNameDisplay = flowName;
|
308
308
|
}
|
309
309
|
|
310
|
-
return (0, _lit.html)` <div class="oauth-flow" style="padding:10px 0;margin-bottom:10px"> <div class="tiny-title upper" style="margin-bottom:5px">${flowNameDisplay}</div> ${authorizationUrl ? (0, _lit.html)`<div><span style="width:75px;display:inline-block">Auth URL</span> <span class="mono-font"> ${authorizationUrl} </span></div>` : ''} ${tokenUrl ? (0, _lit.html)`<div><span style="width:75px;display:inline-block">Token URL</span> <span class="mono-font">${tokenUrl}</span></div>` : ''} ${refreshUrl ? (0, _lit.html)`<div><span style="width:75px;display:inline-block">Refresh URL</span> <span class="mono-font">${refreshUrl}</span></div>` : ''} ${flowName === 'authorizationCode' || flowName === 'clientCredentials' || flowName === 'implicit' ? (0, _lit.html)` ${authFlow.scopes ? (0, _lit.html)` <span> Scopes </span> <div class="oauth-scopes" part="section-auth-scopes" style="width:100%;display:flex;flex-direction:column;flex-wrap:wrap;margin:0 0 .125rem 0"> ${Object.entries(authFlow.scopes).map((scopeAndDescr, index) => (0, _lit.html)` <div class="m-checkbox" style="display:inline-flex;align-items:center"> <input type="checkbox" checked="checked" part="checkbox checkbox-auth-scope" id="${flowName}${index}" value="${scopeAndDescr[0]}"> <label for="${flowName}${index}" style="margin-left:5px"> <span class="mono-font">${scopeAndDescr[0]}</span> ${scopeAndDescr[0] !== scopeAndDescr[1] ? ` - ${scopeAndDescr[1] || ''}` : ''} </label> </div> `)} </div> ` : ''} <div style="display:flex"> <input type="text" part="textbox textbox-auth-client-id" value="${securityObj.clientId || ''}" placeholder="Client ID" spellcheck="false" class="oauth-client-
|
310
|
+
return (0, _lit.html)` <div class="oauth-flow" style="padding:10px 0;margin-bottom:10px"> <div class="tiny-title upper" style="margin-bottom:5px">${flowNameDisplay}</div> ${authorizationUrl ? (0, _lit.html)`<div><span style="width:75px;display:inline-block">Auth URL</span> <span class="mono-font"> ${authorizationUrl} </span></div>` : ''} ${tokenUrl ? (0, _lit.html)`<div><span style="width:75px;display:inline-block">Token URL</span> <span class="mono-font">${tokenUrl}</span></div>` : ''} ${refreshUrl ? (0, _lit.html)`<div><span style="width:75px;display:inline-block">Refresh URL</span> <span class="mono-font">${refreshUrl}</span></div>` : ''} ${flowName === 'authorizationCode' || flowName === 'clientCredentials' || flowName === 'implicit' ? (0, _lit.html)` ${authFlow.scopes ? (0, _lit.html)` <span> Scopes </span> <div class="oauth-scopes" part="section-auth-scopes" style="width:100%;display:flex;flex-direction:column;flex-wrap:wrap;margin:0 0 .125rem 0"> ${Object.entries(authFlow.scopes).map((scopeAndDescr, index) => (0, _lit.html)` <div class="m-checkbox" style="display:inline-flex;align-items:center"> <input type="checkbox" checked="checked" part="checkbox checkbox-auth-scope" id="${flowName}${index}" value="${scopeAndDescr[0]}"> <label for="${flowName}${index}" style="margin-left:5px"> <span class="mono-font">${scopeAndDescr[0]}</span> ${scopeAndDescr[0] !== scopeAndDescr[1] ? ` - ${scopeAndDescr[1] || ''}` : ''} </label> </div> `)} </div> ` : ''} <div style="display:flex"> <div> <input id="oauth-client-id" type="text" part="textbox textbox-auth-client-id" value="${securityObj.clientId || ''}" placeholder="Client ID" spellcheck="false" class="oauth-client-input"> ${flowName === 'clientCredentials' ? (0, _lit.html)` <input id="oauth-client-secret" type="password" part="textbox textbox-auth-client-secret" value="" placeholder="Client Secret" spellcheck="false" class="oauth-client-input"> <select id="oauth-send-client-secret-in" aria-label="oauth client secret location" style="margin-right:5px" class="oauth-client-input"> <option value="header" selected="selected"> Authorization Header </option> <option value="request-body"> Request Body </option> </select> ` : (0, _lit.html)`<div style="width:5px"></div>`} </div> ${flowName === 'authorizationCode' || flowName === 'clientCredentials' || flowName === 'implicit' ? (0, _lit.html)` <div class="oauth-client-input" style="margin-left:1rem"> <button class="m-btn thin-border" part="btn btn-outline" @click="${e => {
|
311
311
|
onInvokeOAuthFlow.call(this, apiKeyId, flowName, authorizationUrl, tokenUrl, e);
|
312
|
-
}}">GET TOKEN</button>` : ''} </div> <div class="oauth-resp-display red-text small-font-size"></div> ` : ''} </div> `;
|
312
|
+
}}">GET TOKEN</button> </div>` : ''} </div> <div class="oauth-resp-display red-text small-font-size"></div> ` : ''} </div> `;
|
313
|
+
}
|
314
|
+
|
315
|
+
function renderSecurityScheme(v) {
|
316
|
+
if (!v.type) {
|
317
|
+
return '';
|
318
|
+
}
|
319
|
+
|
320
|
+
if (v.type.toLowerCase() === 'apikey' || v.type.toLowerCase() === 'http' && v.scheme && v.scheme.toLowerCase() === 'bearer') {
|
321
|
+
var _v$bearerFormat, _v$bearerFormat2;
|
322
|
+
|
323
|
+
return (0, _lit.html)` <div style="padding-top:1rem"> ${v.type.toLowerCase() === 'apikey' ? (0, _lit.html)`Send <code>${v.name || 'API key'}</code> in <code>${v.in || 'the request'}</code> with the given value:` : (0, _lit.html)`Send <code>Authorization</code> in <code>header</code> containing the word <code>Bearer</code> followed by a space and then the ${(_v$bearerFormat = v.bearerFormat) !== null && _v$bearerFormat !== void 0 ? _v$bearerFormat : 'Token String'}.`} </div> <form style="height:50px;margin-top:1rem;padding:10px 0;margin-bottom:10px"> ${v.in === 'cookie' ? (0, _lit.html)` <div style="display:block"> <input type="text" value="${getCookieValue(v.apiKeyId)}" disabled="disabled" class="api-key-input" placeholder="IygRVGf54B59e0GAkKmigGfuiVlp/uhFfk2ifA+jMMJzau2F1jPldc09gPTfnMw13BFBxqUZIFDm55DPfwkb0A==" spellcheck="false" style="resize:horizontal;width:100%"> <br> <small> <strong>Cookies</strong> are set and configured by the remote service, therefore it is not possible to configure them from the browser. </small> </div>` : !v.finalKeyValue ? (0, _lit.html)` <input type="text" value="${v.value}" placeholder="${(_v$bearerFormat2 = v.bearerFormat) !== null && _v$bearerFormat2 !== void 0 ? _v$bearerFormat2 : 'api-token'}" spellcheck="false" class="api-key-input fs-exclude" data-hj-suppress data-sl="mask"> <button type="submit" class="m-btn thin-border" style="margin-left:5px" part="btn btn-outline" @click="${e => {
|
324
|
+
onApiKeyChange.call(this, v.apiKeyId, e);
|
325
|
+
}}"> ${(0, _index.getI18nText)('authentication.set')} </button>` : (0, _lit.html)`<span class="blue-text" style="margin-right:1rem">Key Applied</span> <button class="m-btn thin-border small" part="btn btn-outline" @click="${() => {
|
326
|
+
v.finalKeyValue = '';
|
327
|
+
this.requestUpdate();
|
328
|
+
}}">REMOVE</button>`} </form>`;
|
329
|
+
}
|
330
|
+
|
331
|
+
if (v.type.toLowerCase() === 'http' && v.scheme && v.scheme.toLowerCase() === 'basic') {
|
332
|
+
if (v.finalKeyValue) {
|
333
|
+
return (0, _lit.html)` <div style="padding-top:1rem">${(0, _index.getI18nText)('authentication.http-basic-desc')}</div> <div style="height:50px;margin-top:1rem;padding:10px 0;margin-bottom:10px"> <span class="blue-text" style="margin-right:1rem">Key Applied</span> <button class="m-btn thin-border small" part="btn btn-outline" @click="${() => {
|
334
|
+
v.finalKeyValue = '';
|
335
|
+
this.requestUpdate();
|
336
|
+
}}">REMOVE</button> </div>`;
|
337
|
+
}
|
338
|
+
|
339
|
+
return (0, _lit.html)` <div style="padding-top:1rem">${(0, _index.getI18nText)('authentication.http-basic-desc')}</div> <div style="height:50px;margin-top:1rem;padding:10px 0;margin-bottom:10px"> <form style="display:flex"> <input type="text" value="${v.user}" placeholder="${(0, _index.getI18nText)('authentication.username')}" spellcheck="false" class="api-key-user" style="width:100px"> <input class="api-key-password fs-exclude" data-hj-suppress data-sl="mask" type="password" value="${v.password}" placeholder="${(0, _index.getI18nText)('authentication.password')}" spellcheck="false" style="width:100px;margin:0 5px"> <button type="submit" class="m-btn thin-border" @click="${e => {
|
340
|
+
onApiKeyChange.call(this, v.apiKeyId, e);
|
341
|
+
}}" part="btn btn-outline"> ${v.finalKeyValue ? 'UPDATE' : (0, _index.getI18nText)('authentication.set')} </button> </form> </div>`;
|
342
|
+
}
|
343
|
+
|
344
|
+
if (v.type.toLowerCase() === 'oauth2' && Object.keys(v.flows).length) {
|
345
|
+
return (0, _lit.html)`${Object.keys(v.flows).map(f => oAuthFlowTemplate.call(this, f, v, v.flows[f]))}`;
|
346
|
+
}
|
347
|
+
|
348
|
+
return '';
|
313
349
|
}
|
314
350
|
|
315
351
|
function securitySchemeTemplate() {
|
@@ -320,20 +356,9 @@ function securitySchemeTemplate() {
|
|
320
356
|
}
|
321
357
|
|
322
358
|
const providedApiKeys = schemes.filter(v => v.finalKeyValue);
|
323
|
-
return (0, _lit.html)` <section id="auth" part="section-auth" class="observe-me ${this.renderStyle === 'focused' ? 'section-gap--focused-mode' : 'section-gap'}"> <slot name="authentication"> <div class="section-padding"> <slot name="authentication-header"> <div class="sub-title regular-font">${(0, _index.getI18nText)('headers.authentication')}</div> </slot> <div class="small-font-size" style="display:flex;align-items:center;min-height:
|
359
|
+
return (0, _lit.html)` <section id="auth" part="section-auth" class="observe-me ${this.renderStyle === 'focused' ? 'section-gap--focused-mode' : 'section-gap'}"> <slot name="authentication"> <div class="section-padding"> <slot name="authentication-header"> <div class="sub-title regular-font">${(0, _index.getI18nText)('headers.authentication')}</div> </slot> <div class="small-font-size" style="display:flex;align-items:center;min-height:40px"> ${providedApiKeys.length > 0 ? (0, _lit.html)` <div class="blue-text"> ${providedApiKeys.length} API key applied </div> <div style="flex:1"></div> <button class="m-btn thin-border" part="btn btn-outline" @click="${() => {
|
324
360
|
onClearAllApiKeys.call(this);
|
325
|
-
}}">CLEAR ALL API KEYS</button>` : (0, _lit.html)`<div class="red-text">${(0, _index.getI18nText)('authentication.no-api-key-applied')}</div>`} </div> ${schemes.length > 0 ? (0, _lit.html)` <table role="presentation" class="m-table" style="width:100%"> ${schemes.map(v => {
|
326
|
-
var _v$bearerFormat, _v$bearerFormat2;
|
327
|
-
|
328
|
-
return (0, _lit.html)` <tr> <td colspan="1" style="max-width:500px;overflow-wrap:break-word"> <div style="min-height:24px"> <span style="font-weight:700">${v.typeDisplay}</span> ${v.finalKeyValue ? (0, _lit.html)` <span class="blue-text"> ${v.finalKeyValue ? 'Key Applied' : ''} </span> <button class="m-btn thin-border small" part="btn btn-outline" @click="${() => {
|
329
|
-
v.finalKeyValue = '';
|
330
|
-
this.requestUpdate();
|
331
|
-
}}">REMOVE</button> ` : ''} </div> ${v.description ? (0, _lit.html)` <div class="m-markdown"> ${(0, _unsafeHtml.unsafeHTML)((0, _marked.marked)(v.description || ''))} </div>` : ''} </td> <td colspan="3"> ${v.type && (v.type.toLowerCase() === 'apikey' || v.type.toLowerCase() === 'http' && v.scheme && v.scheme.toLowerCase() === 'bearer') ? (0, _lit.html)` ${v.type.toLowerCase() === 'apikey' ? (0, _lit.html)`Send <code>${v.name}</code> in <code>${v.in}</code> with the given value:` : (0, _lit.html)`Send <code>Authorization</code> in <code>header</code> containing the word <code>Bearer</code> followed by a space and then the ${(_v$bearerFormat = v.bearerFormat) !== null && _v$bearerFormat !== void 0 ? _v$bearerFormat : 'Token String'}.`} <form style="display:flex"> ${v.in === 'cookie' ? (0, _lit.html)` <div style="display:block"> <input type="text" value="${getCookieValue(v.apiKeyId)}" disabled="disabled" class="api-key-input" placeholder="IygRVGf54B59e0GAkKmigGfuiVlp/uhFfk2ifA+jMMJzau2F1jPldc09gPTfnMw13BFBxqUZIFDm55DPfwkb0A==" spellcheck="false" style="resize:horizontal;width:100%"> <br> <small> <strong>Cookies</strong> are set and configured by the remote service, therefore it is not possible to configure them from the browser. </small> </div>` : (0, _lit.html)` <input type="text" value="${v.value}" placeholder="${(_v$bearerFormat2 = v.bearerFormat) !== null && _v$bearerFormat2 !== void 0 ? _v$bearerFormat2 : 'api-token'}" spellcheck="false" class="api-key-input fs-exclude" data-hj-suppress data-sl="mask"> <button type="submit" class="m-btn thin-border" style="margin-left:5px" part="btn btn-outline" @click="${e => {
|
332
|
-
onApiKeyChange.call(this, v.apiKeyId, e);
|
333
|
-
}}"> ${v.finalKeyValue ? 'UPDATE' : 'SET'} </button>`} </form>` : ''} ${v.type && v.type.toLowerCase() === 'http' && v.scheme && v.scheme.toLowerCase() === 'basic' ? (0, _lit.html)` ${(0, _index.getI18nText)('authentication.http-basic-desc')} <form style="display:flex"> <input type="text" value="${v.user}" placeholder="${(0, _index.getI18nText)('authentication.username')}" spellcheck="false" class="api-key-user" style="width:100px"> <input class="api-key-password fs-exclude" data-hj-suppress data-sl="mask" type="password" value="${v.password}" placeholder="${(0, _index.getI18nText)('authentication.password')}" spellcheck="false" style="width:100px;margin:0 5px"> <button type="submit" class="m-btn thin-border" @click="${e => {
|
334
|
-
onApiKeyChange.call(this, v.apiKeyId, e);
|
335
|
-
}}" part="btn btn-outline"> ${v.finalKeyValue ? 'UPDATE' : (0, _index.getI18nText)('authentication.set')} </button> </form>` : ''} </td> </tr> ${v.type.toLowerCase() === 'oauth2' ? (0, _lit.html)` <tr> <td colspan="2" style="border:none;padding-left:48px"> ${Object.keys(v.flows).map(f => oAuthFlowTemplate.call(this, f, v, v.flows[f]))} </td> </tr> ` : ''} `;
|
336
|
-
})} </table>` : ''} <slot name="authentication-footer"></slot> </div> </slot> </section> `;
|
361
|
+
}}">CLEAR ALL API KEYS</button>` : (0, _lit.html)`<div class="red-text">${(0, _index.getI18nText)('authentication.no-api-key-applied')}</div>`} </div> ${schemes.length > 0 ? (0, _lit.html)` <table role="presentation" class="m-table" style="width:100%"> ${schemes.map(v => (0, _lit.html)` <tr> <td colspan="1" style="max-width:500px;overflow-wrap:break-word"> <div style="min-height:24px;display:flex;flex-direction:column;justify-content:center;align-items:center"> <div style="display:flex;justify-content:center"> <span style="font-weight:700">${getTypeDisplayHeader(v)}</span> </div> </div> ${v.description ? (0, _lit.html)` <div class="m-markdown"> ${(0, _unsafeHtml.unsafeHTML)((0, _marked.marked)(v.description || ''))} </div>` : ''} </td> <td colspan="3">${renderSecurityScheme.call(this, v)}</td> </tr>`)} </table>` : ''} <slot name="authentication-footer"></slot> </div> </slot> </section> `;
|
337
362
|
}
|
338
363
|
|
339
364
|
function getOauthScopeTemplate(rawScopes) {
|
@@ -346,6 +371,22 @@ function getOauthScopeTemplate(rawScopes) {
|
|
346
371
|
return (0, _lit.html)` <div> <b>Required scopes:</b> <br> <div style="margin-left:8px"> ${scopes.map(scope => (0, _lit.html)`<span>${scope}</span> `)} </div> </div>`;
|
347
372
|
}
|
348
373
|
|
374
|
+
function getTypeDisplayHeader(securityScheme) {
|
375
|
+
if (securityScheme.type === 'apiKey') {
|
376
|
+
return `API Key (${securityScheme.name})`;
|
377
|
+
}
|
378
|
+
|
379
|
+
if (securityScheme.type === 'oauth2') {
|
380
|
+
return 'OAuth2.0';
|
381
|
+
}
|
382
|
+
|
383
|
+
if (securityScheme.type === 'http') {
|
384
|
+
return securityScheme.scheme === 'basic' ? (0, _index.getI18nText)('authentication.http-basic') : 'HTTP Bearer';
|
385
|
+
}
|
386
|
+
|
387
|
+
return securityScheme.type;
|
388
|
+
}
|
389
|
+
|
349
390
|
function pathSecurityTemplate(pathSecurity) {
|
350
391
|
if (this.resolvedSpec.securitySchemes && pathSecurity) {
|
351
392
|
const orSecurityKeys1 = [];
|
@@ -356,7 +397,7 @@ function pathSecurityTemplate(pathSecurity) {
|
|
356
397
|
const s = this.resolvedSpec.securitySchemes.find(ss => ss.apiKeyId === pathSecurityKey);
|
357
398
|
|
358
399
|
if (s) {
|
359
|
-
andKeyTypes.push(s
|
400
|
+
andKeyTypes.push(getTypeDisplayHeader(s));
|
360
401
|
andSecurityKeys1.push({ ...s,
|
361
402
|
scopes: pSecurity[pathSecurityKey]
|
362
403
|
});
|
@@ -63,20 +63,8 @@ async function ProcessSpec(specUrlOrObject, serverUrl = '') {
|
|
63
63
|
|
64
64
|
securitySchemes.push(securityObj);
|
65
65
|
});
|
66
|
-
} //
|
67
|
-
|
68
|
-
|
69
|
-
securitySchemes.forEach(v => {
|
70
|
-
if (v.type === 'http') {
|
71
|
-
v.typeDisplay = v.scheme === 'basic' ? (0, _index.getI18nText)('authentication.http-basic') : 'HTTP Bearer';
|
72
|
-
} else if (v.type === 'apiKey') {
|
73
|
-
v.typeDisplay = `API Key (${v.name})`;
|
74
|
-
} else if (v.type === 'oauth2') {
|
75
|
-
v.typeDisplay = 'OAuth2.0';
|
76
|
-
} else {
|
77
|
-
v.typeDisplay = v.type;
|
78
|
-
}
|
79
|
-
}); // Servers
|
66
|
+
} // Servers
|
67
|
+
|
80
68
|
|
81
69
|
let servers = [];
|
82
70
|
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "openapi-explorer",
|
3
|
-
"version": "2.1.
|
3
|
+
"version": "2.1.650",
|
4
4
|
"description": "OpenAPI Explorer - API viewer with dynamically generated components, documentation, and interaction console",
|
5
5
|
"author": "Authress Developers <developers@authress.io>",
|
6
6
|
"type": "module",
|