Skip to content

Commit a751d96

Browse files
authored
Merge branch 'develop' into cda-gui/review-and-improvements
2 parents 94fa8c6 + 28e6588 commit a751d96

File tree

16 files changed

+200
-117
lines changed

16 files changed

+200
-117
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
- name: checkout code
3535
uses: actions/checkout@v5.0.0
3636
- name: setup java
37-
uses: actions/setup-java@v5.0.0
37+
uses: actions/setup-java@v5.2.0
3838
with:
3939
distribution: 'temurin'
4040
java-version: ${{matrix.jdk}}
@@ -60,7 +60,7 @@ jobs:
6060
- name: checkout code
6161
uses: actions/checkout@v5.0.0
6262
- name: setup java
63-
uses: actions/setup-java@v5.0.0
63+
uses: actions/setup-java@v5.2.0
6464
with:
6565
distribution: 'temurin'
6666
java-version: 11

.github/workflows/codeql.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
with:
2222
languages: 'java'
2323
- name: setup java
24-
uses: actions/setup-java@v5.0.0
24+
uses: actions/setup-java@v5.2.0
2525
with:
2626
java-version: '11'
2727
java-package: jdk

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ jobs:
6161
with:
6262
ref: ${{inputs.branch}}
6363
- name: setup java
64-
uses: actions/setup-java@v5.0.0
64+
uses: actions/setup-java@v5.2.0
6565
with:
6666
distribution: 'temurin'
6767
java-version: '11'
@@ -84,7 +84,7 @@ jobs:
8484
id: create_release
8585
# Allow testing without creating a release
8686
if: github.event_name != 'pull_request' && (github.event.ref == 'refs/heads/develop' || startsWith(github.event.ref, 'refs/tags'))
87-
uses: softprops/action-gh-release@v2.3.2
87+
uses: softprops/action-gh-release@v2.5.0
8888
with:
8989
files: cwms-data-api/build/libs/cwms-data-api-${{env.VERSION}}.war
9090
tag_name: ${{env.VERSION}}

Dockerfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ ENV cwms.dataapi.access.providers="KeyAccessManager,OpenID"
5656
ENV cwms.dataapi.access.openid.wellKnownUrl="https://<prefix>/.well-known/openid-configuration"
5757
ENV cwms.dataapi.access.openid.issuer="<issuer>"
5858
ENV cwms.dataapi.access.openid.timeout="604800"
59+
# Putting default values here to easy configuration
60+
ENV cwms.dataapi.access.openid.clientId=cwms
61+
ENV cwms.dataapi.access.openid.idpHint=federation-eams
5962
#ENV cwms.dataapi.access.openid.altAuthUrl="https://identityc-test.cwbi.us/auth/realms/cwbi"
6063

6164
# used to simplify redeploy in certain contexts. Update to match -<marker> in image label

cda-gui/package-lock.json

Lines changed: 15 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cda-gui/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"react-dom": "^18.2.0",
3030
"react-icons": "^5.0.1",
3131
"react-router-dom": "^7.1.2",
32-
"swagger-ui-dist": "^5.17.7",
32+
"swagger-ui-dist": "^5.29.5",
3333
"use-debounce": "^10.0.5"
3434
},
3535
"devDependencies": {
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<!doctype html>
2+
<html lang="en-US">
3+
<body>
4+
<script src="oauth2-redirect.js"></script>
5+
</body>
6+
</html>

cda-gui/public/oauth2-redirect.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"use strict"
2+
function run () {
3+
var oauth2 = window.opener.swaggerUIRedirectOauth2
4+
var sentState = oauth2.state
5+
var redirectUrl = oauth2.redirectUrl
6+
var isValid, qp, arr
7+
8+
if (/code|token|error/.test(window.location.hash)) {
9+
qp = window.location.hash.substring(1).replace("?", "&")
10+
} else {
11+
qp = location.search.substring(1)
12+
}
13+
14+
arr = qp.split("&")
15+
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace("=", '":"') + '"' })
16+
qp = qp ? JSON.parse("{" + arr.join() + "}",
17+
function (key, value) {
18+
return key === "" ? value : decodeURIComponent(value)
19+
}
20+
) : {}
21+
22+
isValid = qp.state === sentState
23+
24+
if ((
25+
oauth2.auth.schema.get("flow") === "accessCode" ||
26+
oauth2.auth.schema.get("flow") === "authorizationCode" ||
27+
oauth2.auth.schema.get("flow") === "authorization_code"
28+
) && !oauth2.auth.code) {
29+
if (!isValid) {
30+
oauth2.errCb({
31+
authId: oauth2.auth.name,
32+
source: "auth",
33+
level: "warning",
34+
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
35+
})
36+
}
37+
38+
if (qp.code) {
39+
delete oauth2.state
40+
oauth2.auth.code = qp.code
41+
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl})
42+
} else {
43+
let oauthErrorMsg
44+
if (qp.error) {
45+
oauthErrorMsg = "["+qp.error+"]: " +
46+
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
47+
(qp.error_uri ? "More info: "+qp.error_uri : "")
48+
}
49+
50+
oauth2.errCb({
51+
authId: oauth2.auth.name,
52+
source: "auth",
53+
level: "error",
54+
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server"
55+
})
56+
}
57+
} else {
58+
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl})
59+
}
60+
window.close()
61+
}
62+
63+
if( document.readyState !== "loading" ) {
64+
run()
65+
} else {
66+
document.addEventListener("DOMContentLoaded", function () {
67+
run()
68+
})
69+
}

cda-gui/src/pages/swagger-ui/index.jsx

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,63 @@ import { useEffect } from "react";
55
import { getBasePath } from "../../utils/base";
66

77
export default function SwaggerUI() {
8-
useEffect(() => {
9-
// document.querySelector("#swagger-ui").prepend(Index)
10-
// TODO: Add page index to top of page
11-
// Alter the page title to match the swagger page
12-
document.title = "CWMS Data API for Data Retrieval - Swagger UI";
13-
// Begin Swagger UI call region
14-
// TODO: add endpoint that dynamic returns swagger generated doc
15-
SwaggerUIBundle({
16-
url: getBasePath() + "/swagger-docs",
17-
dom_id: "#swagger-ui",
18-
deepLinking: false,
19-
presets: [SwaggerUIBundle.presets.apis],
20-
plugins: [SwaggerUIBundle.plugins.DownloadUrl],
21-
requestInterceptor: (req) => {
22-
// Add a cache-busting query param
23-
const sep = req.url.includes("?") ? "&" : "?";
24-
req.url = `${req.url}${sep}_cb=${Date.now()}`;
8+
useEffect(() => {
9+
// document.querySelector("#swagger-ui").prepend(Index)
10+
// TODO: Add page index to top of page
11+
// Alter the page title to match the swagger page
12+
document.title = "CWMS Data API for Data Retrieval - Swagger UI";
13+
// Begin Swagger UI call region
14+
// TODO: add endpoint that dynamic returns swagger generated doc
2515

26-
// Also ask intermediaries not to serve from cache
27-
req.headers["Cache-Control"] = "no-cache, no-store, max-age=0";
28-
req.headers["Pragma"] = "no-cache";
16+
const ui = SwaggerUIBundle({
17+
url: getBasePath() + "/swagger-docs",
18+
19+
dom_id: "#swagger-ui",
20+
deepLinking: false,
21+
presets: [SwaggerUIBundle.presets.apis],
22+
plugins: [SwaggerUIBundle.plugins.DownloadUrl],
23+
requestInterceptor: (req) => {
24+
// Add a cache-busting query param... but only if it's to our api. Some
25+
// external systems, like keycloak, don't allow random unknown parameters.
26+
const origin = window.location.origin;
27+
const re = new RegExp(`^${origin}.*`)
28+
if (re.test(req.url))
29+
{
30+
const sep = req.url.includes("?") ? "&" : "?";
31+
req.url = `${req.url}${sep}_cb=${Date.now()}`;
2932

30-
return req;
31-
},
32-
});
33-
}, []);
33+
// Also ask intermediaries not to serve from cache
34+
req.headers["Cache-Control"] = "no-cache, no-store, max-age=0";
35+
req.headers["Pragma"] = "no-cache";
36+
}
37+
return req;
38+
},
39+
onComplete: () => {
40+
const spec = JSON.parse(ui.spec().get("spec"));
41+
for (const schemeName in spec.components.securitySchemes) {
42+
const scheme = spec.components.securitySchemes[schemeName];
43+
if (scheme.type === "openIdConnect") {
44+
let additionalParams = null;
45+
let hints = scheme["x-kc_idp_hint"];
46+
if (hints) {
47+
additionalParams = {
48+
// Since getting the interface to allow users to choose
49+
// is likely impossible, we will assume the first in the list
50+
// is the "primary" auth system
51+
"kc_idp_hint": hints.values[0]
52+
};
53+
}
54+
ui.initOAuth({
55+
clientId: scheme["x-oidc-client-id"],
56+
usePkceWithAuthorizationCodeGrant: true,
57+
additionalQueryStringParams: additionalParams,
58+
});
59+
break;
60+
}
61+
}
62+
},
63+
});
64+
}, []);
3465

3566
return <div id="swagger-ui"></div>;
3667
}

cda-gui/vite.config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ const normalizePath = (value, fallback = "/cwms-data") => {
1919

2020
// https://vitejs.dev/config/
2121
export default defineConfig(({ mode }) => {
22-
const env = loadEnv(mode, ".", "");
22+
const env = loadEnv(mode, process.cwd(), "");
2323
const BASE_PATH = env.VITE_BASE_PATH || "/cwms-data";
2424
const CDA_PATH = normalizePath(env.VITE_CDA_URL, BASE_PATH);
2525
const proxyTarget = env.VITE_CDA_PROXY_TARGET || "https://cwms-data.usace.army.mil";
26-
26+
2727
return {
2828
base: BASE_PATH,
2929
plugins: [react()],

0 commit comments

Comments
 (0)