Skip to content

Commit

Permalink
Merge pull request #671 from phillip-kruger/master
Browse files Browse the repository at this point in the history
Adding the Instance methods options in swagger-ui (master)
  • Loading branch information
phillip-kruger committed Feb 8, 2021
2 parents 1876c91 + 559f197 commit 7369550
Show file tree
Hide file tree
Showing 4 changed files with 251 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
*
* @author Phillip Kruger (phillip.kruger@redhat.com)
*/
public class IndexCreator {
public class IndexHtmlCreator {

private IndexCreator() {
private IndexHtmlCreator() {
}

public static byte[] createIndexHtml() throws IOException {
Expand All @@ -37,8 +37,12 @@ public static byte[] createIndexHtml(Map<String, String> urls, String urlsPrimar
options = populateDefaults(options);
// Next sort out the url/urls
addUrlSection(urls, urlsPrimaryName, options);
// Add OAuth section
addOAuthSection(options);
// Add Preauth section
addPreauthorizeSection(options);

try (InputStream input = IndexCreator.class.getClassLoader()
try (InputStream input = IndexHtmlCreator.class.getClassLoader()
.getResourceAsStream("META-INF/resources/template/index.html");
InputStreamReader streamreader = new InputStreamReader(input, StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(streamreader);
Expand Down Expand Up @@ -117,6 +121,101 @@ private static Map<Option, String> populateDefaults(Map<Option, String> options)
return options;
}

private static void addPreauthorizeSection(Map<Option, String> options) {
if (options.containsKey(Option.preauthorizeSection) && options.get(Option.preauthorizeSection) != null) {
options.put(Option.preauthorizeSection, options.get(Option.preauthorizeSection));
} else if ((options.containsKey(Option.preauthorizeBasicAuthDefinitionKey) &&
options.containsKey(Option.preauthorizeBasicUsername) &&
options.containsKey(Option.preauthorizeBasicPassword))
||
(options.containsKey(Option.preauthorizeApiKeyAuthDefinitionKey) &&
options.containsKey(Option.preauthorizeApiKeyApiKeyValue))) {

try (StringWriter sw = new StringWriter()) {

sw.write("onComplete: function() {\n");
if (options.containsKey(Option.preauthorizeBasicAuthDefinitionKey) &&
options.containsKey(Option.preauthorizeBasicUsername) &&
options.containsKey(Option.preauthorizeBasicPassword)) {
sw.write("\t\t\tui.preauthorizeBasic('" + options.get(Option.preauthorizeBasicAuthDefinitionKey) + "', '"
+ options.get(Option.preauthorizeBasicUsername) + "', '"
+ options.get(Option.preauthorizeBasicPassword) + "');\n");
}
if (options.containsKey(Option.preauthorizeApiKeyAuthDefinitionKey) &&
options.containsKey(Option.preauthorizeApiKeyApiKeyValue)) {
sw.write("\t\t\tui.preauthorizeApiKey('" + options.get(Option.preauthorizeApiKeyAuthDefinitionKey) + "', '"
+ options.get(Option.preauthorizeApiKeyApiKeyValue) + "');\n");
}
sw.write("\t\t}\n");

String preauthorizeSection = sw.toString();

options.put(Option.preauthorizeSection, preauthorizeSection);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}

private static void addOAuthSection(Map<Option, String> options) {
if (options.containsKey(Option.initOAuthSection) && options.get(Option.initOAuthSection) != null) {
options.put(Option.initOAuthSection, options.get(Option.initOAuthSection));
} else if (options.containsKey(Option.oauthClientId) ||
options.containsKey(Option.oauthClientSecret) ||
options.containsKey(Option.oauthRealm) ||
options.containsKey(Option.oauthAppName) ||
options.containsKey(Option.oauthScopeSeparator) ||
options.containsKey(Option.oauthScopes) ||
options.containsKey(Option.oauthAdditionalQueryStringParams) ||
options.containsKey(Option.oauthUseBasicAuthenticationWithAccessCodeGrant) ||
options.containsKey(Option.oauthUsePkceWithAuthorizationCodeGrant)) {

try (StringWriter sw = new StringWriter()) {

sw.write("ui.initOAuth({\n");
if (options.containsKey(Option.oauthClientId)) {
sw.write("\t\tclientId: '" + options.get(Option.oauthClientId) + "',\n");
}
if (options.containsKey(Option.oauthClientSecret)) {
sw.write("\t\tclientSecret: '" + options.get(Option.oauthClientSecret) + "',\n");
}
if (options.containsKey(Option.oauthRealm)) {
sw.write("\t\trealm: '" + options.get(Option.oauthRealm) + "',\n");
}
if (options.containsKey(Option.oauthAppName)) {
sw.write("\t\tappName: '" + options.get(Option.oauthAppName) + "',\n");
}
if (options.containsKey(Option.oauthScopeSeparator)) {
sw.write("\t\tscopeSeparator: '" + options.get(Option.oauthScopeSeparator) + "',\n");
}
if (options.containsKey(Option.oauthScopes)) {
sw.write("\t\tscopes: '" + options.get(Option.oauthScopes) + "',\n");
}
if (options.containsKey(Option.oauthAdditionalQueryStringParams)) {
sw.write(
"\t\tadditionalQueryStringParams: " + options.get(Option.oauthAdditionalQueryStringParams) + ",\n");
}
if (options.containsKey(Option.oauthUseBasicAuthenticationWithAccessCodeGrant)) {
sw.write("\t\tuseBasicAuthenticationWithAccessCodeGrant: "
+ options.get(Option.oauthUseBasicAuthenticationWithAccessCodeGrant) + ",\n");
}
if (options.containsKey(Option.oauthUsePkceWithAuthorizationCodeGrant)) {
sw.write(
"\t\tusePkceWithAuthorizationCodeGrant: "
+ options.get(Option.oauthUsePkceWithAuthorizationCodeGrant)
+ "\n");
}
sw.write("\t})");

String initOAuth = sw.toString();

options.put(Option.initOAuthSection, initOAuth);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}

private static void addUrlSection(Map<String, String> urls, String urlsPrimaryName, Map<Option, String> options) {
// If you added a urlSection, we assume you know what you are doing
if (!options.containsKey(Option.urlSection)) {
Expand Down Expand Up @@ -210,10 +309,11 @@ private static void addUrlSection(Map<String, String> urls, String urlsPrimaryNa
// Authorization
DEFAULT_OPTIONS.put(Option.persistAuthorization, null);

// TODO: Instance methods
// initOAuth
// preauthorizeBasic
// preauthorizeApiKey
DEFAULT_OPTIONS.put(Option.initOAuthSection, null);

// preauthorize
DEFAULT_OPTIONS.put(Option.preauthorizeSection, null);

DEFAULT_OPTIONS.put(Option.layout, "StandaloneLayout");
DEFAULT_OPTIONS.put(Option.plugins, "[SwaggerUIBundle.plugins.DownloadUrl]");
Expand Down
20 changes: 19 additions & 1 deletion ui/open-api-ui/src/main/java/io/smallrye/openapi/ui/Option.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,23 @@ public enum Option {
persistAuthorization,
layout,
plugins,
presets
presets,
// OAuth related
initOAuthSection,
oauthClientId,
oauthClientSecret,
oauthRealm,
oauthAppName,
oauthScopeSeparator,
oauthScopes,
oauthAdditionalQueryStringParams,
oauthUseBasicAuthenticationWithAccessCodeGrant,
oauthUsePkceWithAuthorizationCodeGrant,
// Preauthorize
preauthorizeSection,
preauthorizeBasicAuthDefinitionKey,
preauthorizeBasicUsername,
preauthorizeBasicPassword,
preauthorizeApiKeyAuthDefinitionKey,
preauthorizeApiKeyApiKeyValue
}
81 changes: 41 additions & 40 deletions ui/open-api-ui/src/main/resources/template/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,51 +14,52 @@
<body>
<div id="swagger-ui"></div>
<footer id="footer">${footer}</footer>
<script src="swagger-ui-bundle.js" charset="UTF-8"> </script>
<script src="swagger-ui-bundle.js" charset="UTF-8"></script>
<script src="swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
<script>

window.onload = function() {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
${urlSection},
dom_id: '${domId}',
deepLinking: ${deepLinking},
displayOperationId: ${displayOperationId},
defaultModelsExpandDepth: ${defaultModelsExpandDepth},
defaultModelExpandDepth: ${defaultModelExpandDepth},
defaultModelRendering: '${defaultModelRendering}',
displayRequestDuration: ${displayRequestDuration},
docExpansion: '${docExpansion}',
filter: ${filter},
maxDisplayedTags: ${maxDisplayedTags},
operationsSorter: '${operationsSorter}',
showExtensions: ${showExtensions},
showCommonExtensions: ${showCommonExtensions},
tagsSorter: '${tagsSorter}',
onComplete: ${onComplete},
syntaxHighlight: ${syntaxHighlight},
oauth2RedirectUrl: '${oauth2RedirectUrl}',
requestInterceptor: '${requestInterceptor}',
request.curlOptions: ${requestCurlOptions},
responseInterceptor: '${responseInterceptor}',
showMutatedRequest: '${showMutatedRequest}',
supportedSubmitMethods: ${supportedSubmitMethods},
validatorUrl: '${validatorUrl}',
withCredentials: ${withCredentials},
modelPropertyMacro: '${modelPropertyMacro}',
parameterMacro: '${parameterMacro}',
persistAuthorization: ${persistAuthorization},
presets: ${presets},
plugins: ${plugins},
layout: '${layout}'
})
// End Swagger UI call region
window.onload = function() {
const ui = SwaggerUIBundle({
${urlSection},
dom_id: '${domId}',
deepLinking: ${deepLinking},
displayOperationId: ${displayOperationId},
defaultModelsExpandDepth: ${defaultModelsExpandDepth},
defaultModelExpandDepth: ${defaultModelExpandDepth},
defaultModelRendering: '${defaultModelRendering}',
displayRequestDuration: ${displayRequestDuration},
docExpansion: '${docExpansion}',
filter: ${filter},
maxDisplayedTags: ${maxDisplayedTags},
operationsSorter: '${operationsSorter}',
showExtensions: ${showExtensions},
showCommonExtensions: ${showCommonExtensions},
tagsSorter: '${tagsSorter}',
onComplete: ${onComplete},
syntaxHighlight: ${syntaxHighlight},
oauth2RedirectUrl: '${oauth2RedirectUrl}',
requestInterceptor: '${requestInterceptor}',
request.curlOptions: ${requestCurlOptions},
responseInterceptor: '${responseInterceptor}',
showMutatedRequest: '${showMutatedRequest}',
supportedSubmitMethods: ${supportedSubmitMethods},
validatorUrl: '${validatorUrl}',
withCredentials: ${withCredentials},
modelPropertyMacro: '${modelPropertyMacro}',
parameterMacro: '${parameterMacro}',
persistAuthorization: ${persistAuthorization},
presets: ${presets},
plugins: ${plugins},
layout: '${layout}',
${preauthorizeSection}
})

window.ui = ui
${initOAuthSection}

window.ui = ui

document.getElementsByClassName("link")[0].innerHTML = "<a href='${selfHref}'><img src='${logoHref}' alt='${title}' height='44' align='middle'></a>";
}
document.getElementsByClassName("link")[0].innerHTML = "<a href='${selfHref}'><img src='${logoHref}' alt='${title}' height='44' align='middle'></a>";
}
</script>
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class IndexCreatorTest {

@Test
public void testCreateDefault() throws IOException {
byte[] indexHtml = IndexCreator.createIndexHtml();
byte[] indexHtml = IndexHtmlCreator.createIndexHtml();
assertNotNull(indexHtml);

String s = new String(indexHtml);
Expand All @@ -39,7 +39,7 @@ public void testCreateVanilla() throws IOException {
options.put(Option.logoHref, null);
options.put(Option.themeHref, null);

byte[] indexHtml = IndexCreator.createIndexHtml(options);
byte[] indexHtml = IndexHtmlCreator.createIndexHtml(options);
assertNotNull(indexHtml);

String s = new String(indexHtml);
Expand All @@ -59,7 +59,7 @@ public void testCreateWithStringBooleanOption() throws IOException {
options.put(Option.syntaxHighlight, "false");
options.put(Option.filter, "bla");

byte[] indexHtml = IndexCreator.createIndexHtml(options);
byte[] indexHtml = IndexHtmlCreator.createIndexHtml(options);
assertNotNull(indexHtml);

String s = new String(indexHtml);
Expand All @@ -84,7 +84,7 @@ public void testCreateWithMultipleUrls() throws IOException {
urls.put("Default", "/swagger");
urls.put("Production", "/api");

byte[] indexHtml = IndexCreator.createIndexHtml(urls, "Production", options);
byte[] indexHtml = IndexHtmlCreator.createIndexHtml(urls, "Production", options);
assertNotNull(indexHtml);

String s = new String(indexHtml);
Expand All @@ -105,7 +105,7 @@ public void testCreateWithMultipleUrl() throws IOException {
Map<String, String> urls = new HashMap<>();
urls.put("Default", "/closeapi");

byte[] indexHtml = IndexCreator.createIndexHtml(urls, "Close", null);
byte[] indexHtml = IndexHtmlCreator.createIndexHtml(urls, "Close", null);
assertNotNull(indexHtml);

String s = new String(indexHtml);
Expand All @@ -119,4 +119,84 @@ public void testCreateWithMultipleUrl() throws IOException {
assertTrue(s.contains("deepLinking: true,"));
assertFalse(s.contains("urls.primaryName: 'Close',"));
}

@Test
public void testCreateWithInitOAuth() throws IOException {
Map<Option, String> options = new HashMap<>();
options.put(Option.oauthClientId, "your-client-id");
options.put(Option.oauthClientSecret, "your-client-secret-if-required");
options.put(Option.oauthRealm, "your-realms");
options.put(Option.oauthAppName, "your-app-name");
options.put(Option.oauthScopeSeparator, " ");
options.put(Option.oauthScopes, "openid profile");
options.put(Option.oauthAdditionalQueryStringParams, "{test: \"hello\"}");
options.put(Option.oauthUsePkceWithAuthorizationCodeGrant, "true");

byte[] indexHtml = IndexHtmlCreator.createIndexHtml(options);
assertNotNull(indexHtml);

String s = new String(indexHtml);

assertTrue(s.contains("<title>SmallRye OpenAPI UI</title>"));

assertTrue(s.contains("clientId: 'your-client-id'"));
assertTrue(s.contains("clientSecret: 'your-client-secret-if-required'"));
assertTrue(s.contains("realm: 'your-realms'"));
assertTrue(s.contains("appName: 'your-app-name'"));
assertTrue(s.contains("scopeSeparator: ' '"));
assertTrue(s.contains("scopes: 'openid profile'"));
assertTrue(s.contains("additionalQueryStringParams: {test: \"hello\"}"));
assertTrue(s.contains("usePkceWithAuthorizationCodeGrant: true"));
}

@Test
public void testCreateWithPreauthorizeBasic() throws IOException {
Map<Option, String> options = new HashMap<>();
options.put(Option.preauthorizeBasicAuthDefinitionKey, "basicAuth");
options.put(Option.preauthorizeBasicUsername, "username");
options.put(Option.preauthorizeBasicPassword, "password");

byte[] indexHtml = IndexHtmlCreator.createIndexHtml(options);
assertNotNull(indexHtml);

String s = new String(indexHtml);

assertTrue(s.contains("<title>SmallRye OpenAPI UI</title>"));
assertTrue(s.contains("ui.preauthorizeBasic('basicAuth', 'username', 'password');"));
}

@Test
public void testCreateWithPreauthorizeApiKey() throws IOException {
Map<Option, String> options = new HashMap<>();
options.put(Option.preauthorizeApiKeyAuthDefinitionKey, "api_key");
options.put(Option.preauthorizeApiKeyApiKeyValue, "abcde12345");

byte[] indexHtml = IndexHtmlCreator.createIndexHtml(options);
assertNotNull(indexHtml);

String s = new String(indexHtml);

assertTrue(s.contains("<title>SmallRye OpenAPI UI</title>"));
assertTrue(s.contains("ui.preauthorizeApiKey('api_key', 'abcde12345');"));
}

@Test
public void testCreateWithPreauthorizeBoth() throws IOException {
Map<Option, String> options = new HashMap<>();
options.put(Option.preauthorizeBasicAuthDefinitionKey, "basicAuth");
options.put(Option.preauthorizeBasicUsername, "username");
options.put(Option.preauthorizeBasicPassword, "password");
options.put(Option.preauthorizeApiKeyAuthDefinitionKey, "api_key");
options.put(Option.preauthorizeApiKeyApiKeyValue, "abcde12345");

byte[] indexHtml = IndexHtmlCreator.createIndexHtml(options);
assertNotNull(indexHtml);

String s = new String(indexHtml);

assertTrue(s.contains("<title>SmallRye OpenAPI UI</title>"));
assertTrue(s.contains("ui.preauthorizeApiKey('api_key', 'abcde12345');"));
assertTrue(s.contains("<title>SmallRye OpenAPI UI</title>"));
assertTrue(s.contains("ui.preauthorizeBasic('basicAuth', 'username', 'password');"));
}
}

0 comments on commit 7369550

Please sign in to comment.