Skip to content

Commit

Permalink
chore(match expression): visualizer should have title
Browse files Browse the repository at this point in the history
  • Loading branch information
aali309 committed Jul 17, 2023
1 parent 13db028 commit 87607b9
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 31 deletions.
2 changes: 2 additions & 0 deletions src/app/Rules/CreateRule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import {
Button,
Card,
CardBody,
CardTitle,
Form,
FormGroup,
FormSelect,
Expand Down Expand Up @@ -659,6 +660,7 @@ const Comp: React.FC = () => {
</GridItem>
<GridItem xl={7} order={{ xl: '1', default: '0' }}>
<Card isFullHeight>
<CardTitle>Match Expression Visualizer</CardTitle>
<CardBody className="overflow-auto" data-quickstart-id="match-expr-card">
<MatchExpressionVisualizer />
</CardBody>
Expand Down
116 changes: 85 additions & 31 deletions src/app/Shared/Services/Login.service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import { Base64 } from 'js-base64';
import { combineLatest, Observable, ObservableInput, of, ReplaySubject } from 'rxjs';
import { fromFetch } from 'rxjs/fetch';
import { catchError, concatMap, debounceTime, distinctUntilChanged, first, map, tap } from 'rxjs/operators';
import { ApiV2Response, HttpError } from './Api.service';
import { ApiV2Response } from './Api.service';
import { Credential, AuthCredentials } from './AuthCredentials.service';
import { isQuotaExceededError } from './Report.service';
import { SettingsService } from './Settings.service';
Expand Down Expand Up @@ -108,9 +108,7 @@ export class LoginService {
headers: this.getAuthHeaders(token, method),
}).pipe(
concatMap((response) => {
if (!this.authMethod.isStopped) {
this.completeAuthMethod(response.headers.get('X-WWW-Authenticate') || '');
}
this.updateAuthMethod(response.headers.get('X-WWW-Authenticate') || '');

if (response.status === 302) {
const redirectUrl = response.headers.get('X-Location');
Expand All @@ -133,7 +131,7 @@ export class LoginService {
return jsonResp.meta.status === 'OK';
}),
catchError((e: Error): ObservableInput<boolean> => {
window.console.error(JSON.stringify(e));
window.console.error(JSON.stringify(e, Object.getOwnPropertyNames(e)));
this.authMethod.complete();
return of(false);
})
Expand Down Expand Up @@ -173,7 +171,9 @@ export class LoginService {
}

getAuthMethod(): Observable<AuthMethod> {
return this.authMethod.asObservable();
return this.authMethod
.asObservable()
.pipe(distinctUntilChanged(), debounceTime(this.settings.webSocketDebounceMs()));
}

getUsername(): Observable<string> {
Expand All @@ -197,45 +197,97 @@ export class LoginService {
const token = parts[0];
const method = parts[1];

return fromFetch(`${this.authority}/api/v2.1/logout`, {
// Call the logout backend endpoint
const resp = fromFetch(`${this.authority}/api/v2.1/logout`, {
credentials: 'include',
mode: 'cors',
method: 'POST',
body: null,
headers: this.getAuthHeaders(token, method),
});
return combineLatest([of(method), resp]);
}),
concatMap((response) => {
if (response.status === 302) {
concatMap(([method, response]) => {
if (method === AuthMethod.BEARER) {
// Assume Bearer method means OpenShift
const redirectUrl = response.headers.get('X-Location');
if (!redirectUrl) {
throw new HttpError(response);
// On OpenShift, the backend logout endpoint should respond with a redirect
if (response.status !== 302 || !redirectUrl) {
throw new Error('Could not find OAuth logout endpoint');
}

return fromFetch(redirectUrl, {
credentials: 'include',
mode: 'cors',
method: 'POST',
body: null,
});
} else {
return of(response);
}
}),
map((response) => response.ok),
tap((responseOk) => {
if (responseOk) {
this.resetSessionState();
this.navigateToLoginPage();
return this.openshiftLogout(redirectUrl);
}
return of(response).pipe(
map((response) => response.ok),
tap(() => {
this.resetSessionState();
this.resetAuthMethod();
this.navigateToLoginPage();
})
);
}),
catchError((e: Error): ObservableInput<boolean> => {
window.console.error(JSON.stringify(e));
window.console.error(JSON.stringify(e, Object.getOwnPropertyNames(e)));
return of(false);
})
);
}

private openshiftLogout(logoutUrl: string): Observable<boolean> {
// Query the backend auth endpoint. On OpenShift, without providing a
// token, this should return a redirect to OpenShift's OAuth login.
const resp = fromFetch(`${this.authority}/api/v2.1/auth`, {
credentials: 'include',
mode: 'cors',
method: 'POST',
body: null,
});

return resp.pipe(
first(),
map((response) => {
// Fail if we don't get a valid redirect URL for the user to log
// back in.
const loginUrlString = response.headers.get('X-Location');
if (response.status !== 302 || !loginUrlString) {
throw new Error('Could not find OAuth login endpoint');
}

const loginUrl = new URL(loginUrlString);
if (!loginUrl) {
throw new Error(`OAuth login endpoint is invalid: ${loginUrlString}`);
}
return loginUrl;
}),
tap(() => {
this.resetSessionState();
this.resetAuthMethod();
}),
map((loginUrl) => {
// Create a hidden form to submit to the OAuth server's
// logout endpoint. The "then" parameter will redirect back
// to the login/authorize endpoint once logged out.
const form = document.createElement('form');
form.id = 'logoutForm';
form.action = logoutUrl;
form.method = 'POST';

const input = document.createElement('input');
// The OAuth server is strict about valid redirects. Convert
// the result from our auth response into a relative URL.
input.value = `${loginUrl.pathname}${loginUrl.search}`;
input.name = 'then';
input.type = 'hidden';

form.appendChild(input);
document.body.appendChild(form);

form.submit();
return true;
})
);
}

setSessionState(state: SessionState): void {
this.sessionState.next(state);
}
Expand All @@ -247,9 +299,12 @@ export class LoginService {
this.sessionState.next(SessionState.NO_USER_SESSION);
}

private navigateToLoginPage(): void {
private resetAuthMethod(): void {
this.authMethod.next(AuthMethod.UNKNOWN);
this.removeCacheItem(this.AUTH_METHOD_KEY);
}

private navigateToLoginPage(): void {
const url = new URL(window.location.href.split('#')[0]);
window.location.href = url.pathname.match(/\/settings/i) ? '/' : url.pathname;
}
Expand Down Expand Up @@ -281,7 +336,7 @@ export class LoginService {
}
}

private completeAuthMethod(method: string): void {
private updateAuthMethod(method: string): void {
let validMethod = method as AuthMethod;

if (!Object.values(AuthMethod).includes(validMethod)) {
Expand All @@ -290,7 +345,6 @@ export class LoginService {

this.authMethod.next(validMethod);
this.setCacheItem(this.AUTH_METHOD_KEY, validMethod);
this.authMethod.complete();
}

private getCacheItem(key: string): string {
Expand Down

0 comments on commit 87607b9

Please sign in to comment.