Skip to content

Commit

Permalink
STNG-133 Support for multiple third party auth headers
Browse files Browse the repository at this point in the history
  • Loading branch information
gj0dcsa committed Aug 16, 2024
1 parent f8d96a5 commit 97d9a30
Show file tree
Hide file tree
Showing 11 changed files with 173 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import lombok.Setter;
Expand Down Expand Up @@ -205,16 +207,26 @@ private ConformanceRequest _createConformanceRequest(
partyConfiguration.getRole(),
counterpartConfiguration.getName(),
counterpartConfiguration.getRole(),
counterpartConfiguration.getAuthHeaderName().isBlank()
? Map.ofEntries(
Map.entry("Api-Version", List.of(apiVersionHeaderValue)),
Map.entry("Content-Type", List.of(JsonToolkit.JSON_UTF_8)))
: Map.ofEntries(
Map.entry("Api-Version", List.of(apiVersionHeaderValue)),
Map.entry("Content-Type", List.of(JsonToolkit.JSON_UTF_8)),
Map.entry(
counterpartConfiguration.getAuthHeaderName(),
List.of(counterpartConfiguration.getAuthHeaderValue()))),
Stream.concat(
Stream.concat(
Stream.of(
Map.entry("Api-Version", List.of(apiVersionHeaderValue)),
Map.entry("Content-Type", List.of(JsonToolkit.JSON_UTF_8))),
counterpartConfiguration.getAuthHeaderName().isBlank()
? Stream.of()
: Stream.of(
Map.entry(
counterpartConfiguration.getAuthHeaderName(),
List.of(counterpartConfiguration.getAuthHeaderValue())))),
counterpartConfiguration.getExternalPartyAdditionalHeaders() == null
? Stream.of()
: Stream.of(counterpartConfiguration.getExternalPartyAdditionalHeaders())
.map(
httpHeaderConfiguration ->
Map.entry(
httpHeaderConfiguration.getHeaderName(),
List.of(httpHeaderConfiguration.getHeaderValue()))))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)),
jsonBody == null
? new ConformanceMessageBody("")
: new ConformanceMessageBody(jsonBody),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ public class CounterpartConfiguration {
private String url;
private String authHeaderName = "";
private String authHeaderValue = "";
private HttpHeaderConfiguration[] externalPartyAdditionalHeaders;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.dcsa.conformance.core.party;

import com.fasterxml.jackson.databind.JsonNode;
import lombok.*;

import static org.dcsa.conformance.core.toolkit.JsonToolkit.OBJECT_MAPPER;

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
public class HttpHeaderConfiguration {
private String headerName;
private String headerValue;

public JsonNode toJsonNode() {
return OBJECT_MAPPER.valueToTree(this);
}

@SneakyThrows
public static HttpHeaderConfiguration fromJsonNode(JsonNode jsonNode) {
return OBJECT_MAPPER.treeToValue(jsonNode, HttpHeaderConfiguration.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.dcsa.conformance.core.AbstractComponentFactory;
import org.dcsa.conformance.core.AbstractStandard;
import org.dcsa.conformance.core.party.CounterpartConfiguration;
import org.dcsa.conformance.core.party.HttpHeaderConfiguration;
import org.dcsa.conformance.core.party.PartyConfiguration;
import org.dcsa.conformance.sandbox.configuration.SandboxConfiguration;
import org.dcsa.conformance.sandbox.state.ConformancePersistenceProvider;
Expand Down Expand Up @@ -178,16 +179,28 @@ private JsonNode _getSandboxConfig(String userId, JsonNode requestNode) {
.findFirst()
.orElseThrow();

return OBJECT_MAPPER
.createObjectNode()
.put("sandboxId", sandboxConfiguration.getId())
.put("sandboxName", sandboxConfiguration.getName())
.put("sandboxUrl", sandboxPartyCounterpartConfig.getUrl())
.put("sandboxAuthHeaderName", sandboxConfiguration.getAuthHeaderName())
.put("sandboxAuthHeaderValue", sandboxConfiguration.getAuthHeaderValue())
.put("externalPartyUrl", externalPartyCounterpartConfig.getUrl())
.put("externalPartyAuthHeaderName", externalPartyCounterpartConfig.getAuthHeaderName())
.put("externalPartyAuthHeaderValue", externalPartyCounterpartConfig.getAuthHeaderValue());
ObjectNode jsonSandboxConfig = OBJECT_MAPPER
.createObjectNode()
.put("sandboxId", sandboxConfiguration.getId())
.put("sandboxName", sandboxConfiguration.getName())
.put("sandboxUrl", sandboxPartyCounterpartConfig.getUrl())
.put("sandboxAuthHeaderName", sandboxConfiguration.getAuthHeaderName())
.put("sandboxAuthHeaderValue", sandboxConfiguration.getAuthHeaderValue())
.put("externalPartyUrl", externalPartyCounterpartConfig.getUrl())
.put("externalPartyAuthHeaderName", externalPartyCounterpartConfig.getAuthHeaderName())
.put("externalPartyAuthHeaderValue", externalPartyCounterpartConfig.getAuthHeaderValue());

ArrayNode jsonAdditionalHeaders = OBJECT_MAPPER.createArrayNode();
HttpHeaderConfiguration[] additionalHeaders =
externalPartyCounterpartConfig.getExternalPartyAdditionalHeaders();
if (additionalHeaders != null) {
Arrays.stream(additionalHeaders)
.forEach(
headerNameAndValue -> jsonAdditionalHeaders.add(headerNameAndValue.toJsonNode()));
}
jsonSandboxConfig.set("externalPartyAdditionalHeaders", jsonAdditionalHeaders);

return jsonSandboxConfig;
}

private JsonNode _getSandboxStatus(String userId, JsonNode requestNode) {
Expand Down Expand Up @@ -219,6 +232,13 @@ private JsonNode _updateSandboxConfig(String userId, JsonNode requestNode) {
requestNode.get("externalPartyAuthHeaderName").asText());
externalPartyCounterpartConfig.setAuthHeaderValue(
requestNode.get("externalPartyAuthHeaderValue").asText());
JsonNode jsonHeaders = requestNode.get("externalPartyAdditionalHeaders");
if (jsonHeaders.isArray()) {
externalPartyCounterpartConfig.setExternalPartyAdditionalHeaders(
StreamSupport.stream(jsonHeaders.spliterator(), false)
.map(HttpHeaderConfiguration::fromJsonNode)
.toArray(HttpHeaderConfiguration[]::new));
}

if (!sandboxConfiguration.getOrchestrator().isActive()) {
Arrays.stream(sandboxConfiguration.getParties())
Expand Down
2 changes: 2 additions & 0 deletions webui/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ import { CreateSandboxComponent } from './pages/create-sandbox/create-sandbox.co
import { EditSandboxComponent } from './pages/edit-sandbox/edit-sandbox.component';
import { ReportComponent } from './pages/report/report.component';
import {TextWaitingComponent} from "./text/waiting/text-waiting.component";
import {EditHeaderComponent} from "./pages/edit-header/edit-header.component";

@NgModule({
declarations: [
AppComponent,
ConfirmationDialog,
CreateSandboxComponent,
EditHeaderComponent,
EditSandboxComponent,
EnvironmentComponent,
FooterComponent,
Expand Down
6 changes: 6 additions & 0 deletions webui/src/app/model/sandbox-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,10 @@ export interface SandboxConfig {
externalPartyUrl: string,
externalPartyAuthHeaderName: string,
externalPartyAuthHeaderValue: string,
externalPartyAdditionalHeaders: HeaderNameAndValue[]
}

export interface HeaderNameAndValue {
headerName: string,
headerValue: string,
}
28 changes: 28 additions & 0 deletions webui/src/app/pages/edit-header/edit-header.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<div>
<br />
<mat-form-field class="fullWidth">
<mat-label>Header name</mat-label>
<input
matInput
#headerNameInput
type = "text"
autocomplete="off"
name="headerNameTextField"
[(ngModel)]="headerNameAndValue.headerName"
/>
</mat-form-field>
</div>

<div>
<mat-form-field class="fullWidth">
<mat-label>Header value</mat-label>
<input
matInput
#headerValueInput
type = "text"
autocomplete="off"
name="headerValueTextField"
[(ngModel)]="headerNameAndValue.headerValue"
/>
</mat-form-field>
</div>
11 changes: 11 additions & 0 deletions webui/src/app/pages/edit-header/edit-header.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {Component, Input} from "@angular/core";
import {HeaderNameAndValue} from "src/app/model/sandbox-config";

@Component({
selector: 'app-edit-header',
templateUrl: './edit-header.component.html',
styleUrls: ['../../shared-styles.css']
})
export class EditHeaderComponent {
@Input() headerNameAndValue!: HeaderNameAndValue;
}
27 changes: 27 additions & 0 deletions webui/src/app/pages/edit-sandbox/edit-sandbox.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,33 @@
</mat-form-field>
</div>

<div class="pageSubtitle">Additional headers</div>
<br/>
<div>
<button
mat-mini-fab
color="primary"
type="button"
(click)="onAddHeader()"
><mat-icon>add</mat-icon></button>

&nbsp;

<button
mat-mini-fab
color="primary"
type="button"
[disabled]="updatedSandboxConfig.externalPartyAdditionalHeaders.length < 1"
(click)="onRemoveHeader()"
><mat-icon>remove</mat-icon></button>

<div *ngFor="let additionalHeader of updatedSandboxConfig.externalPartyAdditionalHeaders">
<app-edit-header [headerNameAndValue]="additionalHeader"></app-edit-header>
<hr/>
</div>
</div>

<br />
<br />
<div>
<button
Expand Down
25 changes: 18 additions & 7 deletions webui/src/app/pages/edit-sandbox/edit-sandbox.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class EditSandboxComponent {
async params => {
this.sandboxId = params['sandboxId'];
this.originalSandboxConfig = await this.conformanceService.getSandboxConfig(this.sandboxId);
this.updatedSandboxConfig = {...this.originalSandboxConfig};
this.updatedSandboxConfig = JSON.parse(JSON.stringify(this.originalSandboxConfig));
});
}

Expand All @@ -46,14 +46,24 @@ export class EditSandboxComponent {
}
}

onAddHeader() {
this.updatedSandboxConfig?.externalPartyAdditionalHeaders.push({headerName: '', headerValue: ''});
}

onRemoveHeader() {
this.updatedSandboxConfig?.externalPartyAdditionalHeaders.pop();
}

headerNameRegex = /^[!#$%&'*+.^_`|~\w-]+$/;
headerValueRegex = /^[\t\x20-\x7E\x80-\xFF]*$/;

cannotUpdate(): boolean {
if (!this.originalSandboxConfig || !this.updatedSandboxConfig) return true;
return (
this.updatedSandboxConfig.sandboxName === this.originalSandboxConfig.sandboxName
&& this.updatedSandboxConfig.externalPartyUrl === this.originalSandboxConfig.externalPartyUrl
&& this.updatedSandboxConfig.externalPartyAuthHeaderName === this.originalSandboxConfig.externalPartyAuthHeaderName
&& this.updatedSandboxConfig.externalPartyAuthHeaderValue === this.originalSandboxConfig.externalPartyAuthHeaderValue
);
for (let additionalHeader of this.updatedSandboxConfig.externalPartyAdditionalHeaders) {
if (!this.headerNameRegex.test(additionalHeader.headerName)) return true;
if (!this.headerValueRegex.test(additionalHeader.headerValue)) return true;
}
return JSON.stringify(this.originalSandboxConfig) === JSON.stringify(this.updatedSandboxConfig);
}

async onUpdate() {
Expand All @@ -65,6 +75,7 @@ export class EditSandboxComponent {
this.updatedSandboxConfig!.externalPartyUrl,
this.updatedSandboxConfig!.externalPartyAuthHeaderName,
this.updatedSandboxConfig!.externalPartyAuthHeaderValue,
this.updatedSandboxConfig!.externalPartyAdditionalHeaders,
);
this.router.navigate([
"/sandbox", this.sandboxId
Expand Down
4 changes: 3 additions & 1 deletion webui/src/app/service/conformance.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {Sandbox} from "../model/sandbox";
import {ScenarioDigest} from "../model/scenario";
import {ScenarioStatus} from "../model/scenario-status";
import {Standard} from "../model/standard";
import {SandboxConfig} from "../model/sandbox-config";
import {HeaderNameAndValue, SandboxConfig} from "../model/sandbox-config";
import {StandardModule} from "../model/standard-module";
import {SandboxStatus} from "../model/sandbox-status";

Expand Down Expand Up @@ -149,6 +149,7 @@ export class ConformanceService {
externalPartyUrl: string,
externalPartyAuthHeaderName: string,
externalPartyAuthHeaderValue: string,
externalPartyAdditionalHeaders: HeaderNameAndValue[],
): Promise<void> {
await this.apiService.call({
operation: "updateSandboxConfig",
Expand All @@ -157,6 +158,7 @@ export class ConformanceService {
externalPartyUrl,
externalPartyAuthHeaderName,
externalPartyAuthHeaderValue,
externalPartyAdditionalHeaders,
});
}
}

0 comments on commit 97d9a30

Please sign in to comment.