Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ yarn dev
### [Mail](#mail)

In the default `application.properties` the mail host is `localhost` and the port is `1025`. Run mailpit to capture mails.
See <https://github.com/axllent/mailpit>
See <https://github.com/axllent/mailpit>.

### [Local endpoints](#local-endpoints)

Expand Down
8 changes: 4 additions & 4 deletions client/src/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,8 @@ export function parseMedaDataUrl(url) {
return postPutJson("/api/v1/manage/parse", {url: url}, "POST");
}

export function getIdentityProviders(environment) {
return fetchJson(`/api/v1/manage/identity-providers/${environment}`);
export function getIdentityProviders() {
return fetchJson(`/api/v1/manage/identity-providers`);
}

export function getServiceProvidersAllowed(organizationId) {
Expand All @@ -264,8 +264,8 @@ export function getPolicyByIdentityProvider(organizationId) {
return fetchJson(`/api/v1/manage/identity-provider/policies?organizationId=${organizationId}`);
}

export function uniqueEntityID(environment, entityID) {
return postPutJson(`/api/v1/manage/unique-entity-id/${environment}`, {entityID: entityID}, "POST");
export function uniqueEntityID(entityID) {
return postPutJson(`/api/v1/manage/unique-entity-id`, {entityID: entityID}, "POST");
}

export function arp() {
Expand Down
13 changes: 7 additions & 6 deletions client/src/components/ApplicationConnectionHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {Chip, ChipType, Loader} from "@surfnet/sds";
import {hasApplicationDeleteAccess} from "../utils/Permissions.js";
import {ConnectionInUseWarning, units} from "../connection/ConnectionInUseWarning.jsx";

export const ApplicationConnectionHeader = ({tabs, application, user, currentTab, setTab}) => {
export const ApplicationConnectionHeader = ({tabs, application, user, currentTab, setTab, currentOrganization}) => {

const [dropDownActive, setDropDownActive] = useState(false);
const [confirmation, setConfirmation] = useState({});
Expand Down Expand Up @@ -53,11 +53,12 @@ export const ApplicationConnectionHeader = ({tabs, application, user, currentTab
} else {
setLoading(true);
setAffectedIdentityProviders([]);
deleteApplicationById(application.id).then(() => {
setConfirmation({});
navigate("/home");
setLoading(false);
})
deleteApplicationById(application.id)
.then(() => {
setConfirmation({});
navigate("/organization/" + currentOrganization.id);
setLoading(false);
})
}
}

Expand Down
5 changes: 2 additions & 3 deletions client/src/connection/ConnectionAlert.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, {useState} from "react";
import I18n from "../locale/I18n";
import {Alert, AlertType} from "@surfnet/sds";
import {isEmpty, splitListSemantically} from "../utils/Utils.js";
import {CONNECTION_STATUSES, ENVIRONMENTS} from "../utils/Manage.js";
import {CONNECTION_STATUSES} from "../utils/Manage.js";


export const ConnectionAlert = ({
Expand All @@ -23,8 +23,7 @@ export const ConnectionAlert = ({
let connectionsNeedActivationNames = [];
if (application.signedContract && !isEmpty(application.connections)) {
const names = application.connections
.filter(conn => conn.environment === ENVIRONMENTS.PROD &&
(conn.status === CONNECTION_STATUSES.COMPLETE || conn.status === CONNECTION_STATUSES.IN_PROGRESS))
.filter(conn => conn.status === CONNECTION_STATUSES.COMPLETE || conn.status === CONNECTION_STATUSES.IN_PROGRESS)
.map(conn => conn.name);
connectionsNeedActivationNames = splitListSemantically(names, I18n.t("forms.and"));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import "./Testing.scss";
import "./ConnectionInstance.scss";
import React, {Fragment, useEffect, useMemo, useRef, useState} from "react";
import I18n from "../locale/I18n";
import {
Expand Down Expand Up @@ -52,7 +52,6 @@ import {
} from "../utils/Connection.js";
import {
CONNECTION_STATUSES,
ENVIRONMENTS,
identityProviderOption,
identityProviderOptions,
PROTOCOLS
Expand All @@ -72,6 +71,7 @@ const sections = {
technical: "technical",
informationProfile: "informationProfile",
testIdP: "testIdP",
visibility: "visibility",
overview: "overview"
}

Expand All @@ -93,7 +93,7 @@ const modals = {
deletionWarning: "deletionWarning",
}

export const Testing = ({
export const ConnectionInstance = ({
application,
connection,
setConnection,
Expand Down Expand Up @@ -142,9 +142,8 @@ export const Testing = ({
const [changeRequestsKeys, setChangeRequestsKeys] = useState([]);
const [affectedIdentityProviders, setAffectedIdentityProviders] = useState([]);

const connections = useMemo(() => application.connections
.filter(conn => isProduction ? conn.environment === ENVIRONMENTS.PROD : conn.environment === ENVIRONMENTS.TEST),
[application, isProduction]);
const connections = useMemo(() => application.connections,
[application]);

const redirectUrlRefs = useRef([]);
const acsLocationRefs = useRef([]);
Expand All @@ -153,7 +152,7 @@ export const Testing = ({
if (!isEmpty(connectionId)) {
const conn = application.connections.find(c => c.id === parseInt(connectionId, 10));
if (isEmpty(conn)) {
navigate(`/connection/${application.id}/${isProduction ? "prod" : "testing"}`);
navigate(`/connection/${application.id}/instances`);
} else {
showConnectionDetails(conn);
}
Expand All @@ -180,6 +179,9 @@ export const Testing = ({
case sections.testIdP: {
return !connection.id || (!finished || !testIdPValid());
}
case sections.visibility: {
return !connection.id;
}
case sections.pendingChanges: {
return false;
}
Expand All @@ -205,7 +207,6 @@ export const Testing = ({
//To prevent update instead of create
["id", "manageEid", "manageIdentifier", "manageVersion", "createdAt", "updatedAt"]
.forEach(attr => delete convertedConnection[attr]);
convertedConnection.environment = isProduction ? ENVIRONMENTS.PROD : ENVIRONMENTS.TEST
convertedConnection.status = CONNECTION_STATUSES.OPEN;
convertedConnection.entityID = "";
if (convertedConnection.protocol.value === PROTOCOLS.OIDC10_RP) {
Expand Down Expand Up @@ -249,7 +250,7 @@ export const Testing = ({
}

const testIdPValid = () => {
return connection.environment === ENVIRONMENTS.PROD || !isEmpty(connection.allowedEntities);
return connection.status === CONNECTION_STATUSES.PROD_READY;
}

const changeSection = sectionName => {
Expand Down Expand Up @@ -411,7 +412,7 @@ export const Testing = ({
setLoading(true);
setAffectedIdentityProviders([]);
deleteConnectionById(connection.id).then(() => {
refresh(isProduction ? "prod" : "testing");
refresh("instances");
setConfirmation({open: false});
setLoading(false);
setFlash(I18n.t("connection.flash.deleted", {
Expand Down Expand Up @@ -452,7 +453,7 @@ export const Testing = ({
}

const onBlurEntityID = (e) => {
uniqueEntityID(connection.environment, e.target.value).then(res => {
uniqueEntityID(e.target.value).then(res => {
const duplicated = (connection.status === !CONNECTION_STATUSES.OPEN && res.length > 1) ||
(connection.status === CONNECTION_STATUSES.OPEN && res.length > 0)
setDuplicateEntityID(duplicated);
Expand Down Expand Up @@ -495,8 +496,7 @@ export const Testing = ({
isAlert={changeRequestsKeys.includes("name")}
placeholder={I18n.t("connection.connectionPlaceholder",
{
application: application.name,
environment: connection.environment.toUpperCase()
application: application.name
})}
/>
{(!initial && isEmpty(connection.name)) &&
Expand Down Expand Up @@ -1101,7 +1101,10 @@ export const Testing = ({
return renderInformationProfileSection();
}
case sections.testIdP: {
return isProduction ? renderVisibilitySection() : renderTestIdPSection();
return renderTestIdPSection();
}
case sections.visibility: {
return renderVisibilitySection();
}
case sections.overview: {
return isOidc ? renderOIDCOverview() : renderSAMLOverview();
Expand Down Expand Up @@ -1136,6 +1139,9 @@ export const Testing = ({
}
return !testIdPValid();
}
case sections.visibility: {
return true;
}
case sections.pendingChanges: {
return false;
}
Expand Down Expand Up @@ -1225,7 +1231,7 @@ export const Testing = ({
const backToConnections = () => {
refresh();
setConnection(null);
navigate(`/connection/${application.id}/${isProduction ? "prod" : "testing"}`);
navigate(`/connection/${application.id}/instances`);
window.scrollTo({top: 0, behavior: "smooth"});
changeSection(sections.technical);
}
Expand All @@ -1244,8 +1250,8 @@ export const Testing = ({
const submitTxt = requiresChangeRequest ? I18n.t("connection.requiresChangeRequest") : isComplete ? I18n.t("connection.save") : I18n.t("connection.saveAndNext");
return (
<>
<div className="testing-header">
<h2>{I18n.t(`connection.${isComplete ? "existing" : "new"}Connection${isProduction ? "Prod" : ""}`, {name: connection.name})}</h2>
<div className="connection-instance-header">
<h2>{I18n.t(`connection.${isComplete ? "existing" : "new"}Connection`, {name: connection.name})}</h2>
{(isProduction && application.signedContract && (connection.status === CONNECTION_STATUSES.COMPLETE || connection.status === CONNECTION_STATUSES.IN_PROGRESS)) &&
<div className="action-button">
<Button txt={I18n.t("connection.connections.requestProductionStatus")}
Expand Down Expand Up @@ -1280,7 +1286,7 @@ export const Testing = ({
</section>}
</div>}
</div>
<div className="testing">
<div className="connection-instance">
<section className="left">
<div className="status-menu">
{Object.values(sections)
Expand Down Expand Up @@ -1341,7 +1347,7 @@ export const Testing = ({
}

const showConnectionDetails = (conn, queryParameters = "") => {
navigate(`/connection/${application.id}/${isProduction ? "prod" : "testing"}/${conn.id}${queryParameters}`);
navigate(`/connection/${application.id}/instances/${conn.id}${queryParameters}`);
const section = updateChangeRequestKeys(conn);
setConnection(conn);
changeSection(section);
Expand Down Expand Up @@ -1425,18 +1431,17 @@ export const Testing = ({
appInformationComplete={appInformationComplete}
productionConnectionNeedsActivation={productionConnectionNeedsActivation}/>}
<div className="header">
<h3>{I18n.t(`connection.${isProduction ? "production" : "test"}.connections`)}</h3>
<h3>{I18n.t("connection.instances")}</h3>
<Button txt={I18n.t("testing.newConnection")}
type={ButtonType.Secondary}
onClick={() => initConnection(isProduction ? ENVIRONMENTS.PROD : ENVIRONMENTS.TEST, true)}/>
onClick={() => initConnection(true)}/>
</div>
{!isEmpty(connections) && renderConnectionsTable(connections)}
{isEmpty(connections) &&
<p dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(I18n.t("testing.zeroState",
{
name: application.name,
type: I18n.t(`testing.${isProduction ? "production" : "test"}`)
name: application.name
}))
}}/>}
</div>
Expand All @@ -1450,7 +1455,7 @@ export const Testing = ({
&& !isEmpty(connection);
const {open, cancel, action, modal, okButton, question, header} = confirmation;
return (
<div className="testing-container">
<div className="connection-instance-container">
{open && <ConfirmationDialog confirm={action}
cancel={cancel}
confirmationHeader={header}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

$width-percentage: 75%;

.testing-container {
.connection-instance-container {
padding: 25px 50px;
background-color: white;

.testing-header {
.connection-instance-header {
display: flex;
align-items: center;
margin-bottom: 25px;
Expand Down Expand Up @@ -48,7 +48,7 @@ $width-percentage: 75%;
}
}

.testing {
.connection-instance {
display: flex;
gap: 35px;
width: $width-percentage;
Expand Down
27 changes: 8 additions & 19 deletions client/src/connection/Overview.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import "./Overview.scss";
import React from "react";
import I18n from "../locale/I18n";
import {STATUS_LINK_TYPE, StatusLink} from "../components/StatusLink.jsx";
import {ENVIRONMENTS} from "../utils/Manage.js";
import {ConnectionAlert} from "./ConnectionAlert.jsx";


Expand All @@ -23,38 +22,28 @@ export const Overview = ({
appInformationComplete={appInformationComplete}
productionConnectionNeedsActivation={productionConnectionNeedsActivation}/>
<div className="application-connection">
<section className="sub-part">
<h2>{I18n.t("connection.test.name")}</h2>
<StatusLink info={I18n.t("connection.test.connections")}
action={() => initConnection(ENVIRONMENTS.TEST)}
status={testConnectionComplete ? STATUS_LINK_TYPE.ACTIVE : STATUS_LINK_TYPE.PENDING}/>
</section>
<section className="sub-part">
<h2>{I18n.t("connection.team.name")}</h2>
<StatusLink info={I18n.t("connection.team.members")}
action={() => setTab("appteam")}
status={STATUS_LINK_TYPE.TEAM}/>
</section>
<section className="sub-part">
<h2>{I18n.t("connection.production.name")}</h2>
<StatusLink info={I18n.t("connection.production.connections")}
action={() => initConnection(ENVIRONMENTS.PROD)}
disabled={!testConnectionComplete}
<StatusLink info={I18n.t("connection.production.connections", {app: application.name})}
action={() => initConnection()}
status={!productionConnectionComplete ? STATUS_LINK_TYPE.PENDING :
productionConnectionNeedsActivation ? STATUS_LINK_TYPE.ALERT : STATUS_LINK_TYPE.ACTIVE}/>
<StatusLink info={I18n.t("connection.production.catalogue")}
action={() => setTab("application")}
disabled={!testConnectionComplete}
status={appInformationComplete ? STATUS_LINK_TYPE.ACTIVE : STATUS_LINK_TYPE.PENDING}/>
<StatusLink info={I18n.t("connection.production.contract")}
action={() => setTab("contract")}
// disabled={!appInformationComplete || !testConnectionComplete}
disabled={!testConnectionComplete}
status={application.signedContract ? STATUS_LINK_TYPE.ACTIVE : STATUS_LINK_TYPE.PENDING}/>
<p className={`${productionConnectionComplete} ? "":"pending`}>
{I18n.t("connection.production.disclaimer")}
</p>
</section>
<section className="sub-part">
<h2>{I18n.t("connection.team.name")}</h2>
<StatusLink info={I18n.t("connection.team.members")}
action={() => setTab("appteam")}
status={STATUS_LINK_TYPE.TEAM}/>
</section>
</div>
</div>
)
Expand Down
Loading
Loading