From 9a8285bf36b45bda19c65e3e234ae883f08baec6 Mon Sep 17 00:00:00 2001 From: Okke Harsta Date: Fri, 10 Apr 2026 17:27:29 +0200 Subject: [PATCH 1/4] WIP for no prod and test --- client/src/api/index.js | 8 +- client/src/connection/ConnectionAlert.jsx | 5 +- .../{Testing.jsx => ConnectionInstance.jsx} | 39 ++- .../{Testing.scss => ConnectionInstance.scss} | 6 +- client/src/connection/Overview.jsx | 5 +- client/src/locale/en.js | 5 +- client/src/locale/nl.js | 5 +- client/src/pages/Connection.jsx | 60 +---- client/src/pages/Organization.jsx | 5 +- client/src/utils/Manage.js | 4 - .../access/api/ApplicationController.java | 6 +- .../java/access/api/ConnectionController.java | 22 +- .../api/IdentityProviderController.java | 19 +- .../java/access/api/ManageController.java | 26 +- .../access/api/OrganizationController.java | 8 +- .../java/access/api/PublicController.java | 7 +- .../main/java/access/api/UserController.java | 6 +- .../manage/ConnectionProviderConverter.java | 15 +- .../main/java/access/manage/LocalManage.java | 33 ++- .../src/main/java/access/manage/Manage.java | 24 +- .../access/manage/ManageAuthorization.java | 4 +- .../main/java/access/manage/ManageConf.java | 21 +- .../access/manage/PolicyAccessRights.java | 3 +- .../main/java/access/manage/RemoteManage.java | 241 +++++++----------- .../main/java/access/model/Connection.java | 22 +- .../main/java/access/model/Environment.java | 6 - .../security/CustomOidcUserService.java | 3 +- server/src/main/resources/application.yml | 19 +- .../V14_0__drop_connection_environment.sql | 1 + .../test/java/access/AbstractMailTest.java | 3 +- server/src/test/java/access/AbstractTest.java | 28 +- .../access/api/ApplicationControllerTest.java | 9 +- .../access/api/ConnectionControllerTest.java | 9 +- .../api/IdentityProviderControllerTest.java | 36 +-- .../java/access/api/InviteControllerTest.java | 3 +- .../java/access/api/ManageControllerTest.java | 24 +- .../api/OrganizationControllerTest.java | 6 +- .../java/access/api/PublicControllerTest.java | 3 +- .../java/access/api/UserControllerTest.java | 3 +- .../ConnectionProviderConverterTest.java | 2 +- .../access/manage/PolicyAccessRightsTest.java | 5 +- .../java/access/manage/RemoteManageTest.java | 9 +- .../java/access/stats/StatisticsMockTest.java | 2 +- 43 files changed, 308 insertions(+), 462 deletions(-) rename client/src/connection/{Testing.jsx => ConnectionInstance.jsx} (98%) rename client/src/connection/{Testing.scss => ConnectionInstance.scss} (99%) delete mode 100644 server/src/main/java/access/model/Environment.java create mode 100644 server/src/main/resources/db/mysql/migration/V14_0__drop_connection_environment.sql diff --git a/client/src/api/index.js b/client/src/api/index.js index fdebce0b..98d7487f 100644 --- a/client/src/api/index.js +++ b/client/src/api/index.js @@ -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) { @@ -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() { diff --git a/client/src/connection/ConnectionAlert.jsx b/client/src/connection/ConnectionAlert.jsx index 497ee9ac..94c462e6 100644 --- a/client/src/connection/ConnectionAlert.jsx +++ b/client/src/connection/ConnectionAlert.jsx @@ -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 = ({ @@ -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")); } diff --git a/client/src/connection/Testing.jsx b/client/src/connection/ConnectionInstance.jsx similarity index 98% rename from client/src/connection/Testing.jsx rename to client/src/connection/ConnectionInstance.jsx index 0d8bae1e..6807fd4f 100644 --- a/client/src/connection/Testing.jsx +++ b/client/src/connection/ConnectionInstance.jsx @@ -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 { @@ -52,7 +52,6 @@ import { } from "../utils/Connection.js"; import { CONNECTION_STATUSES, - ENVIRONMENTS, identityProviderOption, identityProviderOptions, PROTOCOLS @@ -93,7 +92,7 @@ const modals = { deletionWarning: "deletionWarning", } -export const Testing = ({ +export const ConnectionInstance = ({ application, connection, setConnection, @@ -141,9 +140,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([]); @@ -152,7 +150,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); } @@ -204,7 +202,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) { @@ -247,7 +244,7 @@ export const Testing = ({ } const testIdPValid = () => { - return connection.environment === ENVIRONMENTS.PROD || !isEmpty(connection.allowedEntities); + return isProduction || !isEmpty(connection.allowedEntities); } const changeSection = sectionName => { @@ -409,7 +406,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", { @@ -450,7 +447,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); @@ -493,8 +490,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)) && @@ -1206,7 +1202,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); } @@ -1225,7 +1221,7 @@ export const Testing = ({ const submitTxt = requiresChangeRequest ? I18n.t("connection.requiresChangeRequest") : isComplete ? I18n.t("connection.save") : I18n.t("connection.saveAndNext"); return ( <> -
+

{I18n.t(`connection.${isComplete ? "existing" : "new"}Connection${isProduction ? "Prod" : ""}`, {name: connection.name})}

{(isProduction && application.signedContract && (connection.status === CONNECTION_STATUSES.COMPLETE || connection.status === CONNECTION_STATUSES.IN_PROGRESS)) &&
@@ -1261,7 +1257,7 @@ export const Testing = ({ }
}
-
+
{Object.values(sections) @@ -1322,7 +1318,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); @@ -1406,18 +1402,17 @@ export const Testing = ({ appInformationComplete={appInformationComplete} productionConnectionNeedsActivation={productionConnectionNeedsActivation}/>}
-

{I18n.t(`connection.${isProduction ? "production" : "test"}.connections`)}

+

{I18n.t("connection.instances")}

{!isEmpty(connections) && renderConnectionsTable(connections)} {isEmpty(connections) &&

}

@@ -1431,7 +1426,7 @@ export const Testing = ({ && !isEmpty(connection); const {open, cancel, action, modal, okButton, question, header} = confirmation; return ( -
+
{open &&

{I18n.t("connection.test.name")}

initConnection(ENVIRONMENTS.TEST)} + action={() => initConnection()} status={testConnectionComplete ? STATUS_LINK_TYPE.ACTIVE : STATUS_LINK_TYPE.PENDING}/>
@@ -38,7 +37,7 @@ export const Overview = ({

{I18n.t("connection.production.name")}

initConnection(ENVIRONMENTS.PROD)} + action={() => initConnection()} disabled={!testConnectionComplete} status={!productionConnectionComplete ? STATUS_LINK_TYPE.PENDING : productionConnectionNeedsActivation ? STATUS_LINK_TYPE.ALERT : STATUS_LINK_TYPE.ACTIVE}/> diff --git a/client/src/locale/en.js b/client/src/locale/en.js index 9cef7a34..e8d9c124 100644 --- a/client/src/locale/en.js +++ b/client/src/locale/en.js @@ -295,6 +295,7 @@ const en = { }, connection: { overview: "Overview", + instances: "Connections", testing: "Test", prod: "Production", application: "App information", @@ -352,7 +353,7 @@ const en = { supportTicket: "Create a support ticket", mailToSurf: "mailto:surf@info.nl", connectionName: "Connection name", - connectionPlaceholder: "e.g. {{application}}-{{environment}}", + connectionPlaceholder: "e.g. {{application}}-connection", protocol: "Protocol", protocolTooltip: "When a connection is registered within SURFconext, it is no longer possible to change the protocol. If you want, you can delete this connection and create another with a different protocol.", clientID: "Client ID", @@ -598,7 +599,7 @@ const en = { status: "Status", protocol: "Protocol", details: "Details", - zeroState: "Application {{name}} has no {{type}} connections yet.", + zeroState: "Application {{name}} has no connections yet.", production: "production", test: "test", }, diff --git a/client/src/locale/nl.js b/client/src/locale/nl.js index 0ca5efbf..f1495556 100644 --- a/client/src/locale/nl.js +++ b/client/src/locale/nl.js @@ -295,6 +295,7 @@ const nl = { }, connection: { overview: "Overzicht", + instances: "Verbindingen", testing: "Test", prod: "Productie", application: "App‑informatie", @@ -352,7 +353,7 @@ const nl = { supportTicket: "Maak een support‑ticket", mailToSurf: "mailto:surf@info.nl", connectionName: "Verbindingsnaam", - connectionPlaceholder: "bijv. {{application}}-{{environment}}", + connectionPlaceholder: "bijv. {{application}}-verbinding", protocol: "Protocol", protocolTooltip: "Wanneer een verbinding wordt geregistreerd binnen SURFconext, kan het protocol niet meer worden gewijzigd. Als je een ander protocol wilt, kun je deze verbinding verwijderen en een nieuwe met een ander protocol aanmaken.", clientID: "Client‑ID", @@ -598,7 +599,7 @@ const nl = { status: "Status", protocol: "Protocol", details: "Details", - zeroState: "Applicatie {{name}} heeft nog geen {{type}}‑verbindingen.", + zeroState: "Applicatie {{name}} heeft nog geen verbindingen.", production: "productie", test: "test", }, diff --git a/client/src/pages/Connection.jsx b/client/src/pages/Connection.jsx index 49f8c095..e5880dcb 100644 --- a/client/src/pages/Connection.jsx +++ b/client/src/pages/Connection.jsx @@ -5,10 +5,10 @@ import {useNavigate, useParams} from "react-router-dom"; import {useAppStore} from "../stores/AppStore.js"; import {ApplicationConnectionHeader} from "../components/ApplicationConnectionHeader.jsx"; import {Overview} from "../connection/Overview.jsx"; -import {Testing} from "../connection/Testing.jsx"; +import {ConnectionInstance} from "../connection/ConnectionInstance.jsx"; import {getApplicationById, getIdentityProviders} from "../api/index.js"; import {Loader} from "@surfnet/sds"; -import {APPLICATION_STATUSES, CONNECTION_STATUSES, ENVIRONMENTS, PROTOCOLS} from "../utils/Manage.js"; +import {APPLICATION_STATUSES, CONNECTION_STATUSES, PROTOCOLS} from "../utils/Manage.js"; import {AppInformation} from "../connection/AppInformation.jsx"; import { contactSectionValid, @@ -23,7 +23,7 @@ import {isEmpty} from "../utils/Utils.js"; import {mainMenuItems} from "../utils/MenuItems.js"; import {useShallow} from "zustand/react/shallow"; -const tabNames = ["overview", "testing", "prod", "application", "contract", "appteam"] +const tabNames = ["overview", "instances", "application", "contract", "appteam"] const protocolOptions = Object.values(PROTOCOLS).map(protocol => ({ value: protocol, @@ -46,7 +46,6 @@ export const Connection = () => { const [currentTab, setCurrentTab] = useState(tab); const [connection, setConnection] = useState(null); const [identityProviders, setIdentityProviders] = useState([]); - const [prodIdentityProviders, setProdIdentityProviders] = useState([]); const [loading, setLoading] = useState(true); const [dirty, setDirty] = useState(false); @@ -79,13 +78,8 @@ export const Connection = () => { {value: res.name} ] }); - Promise.all([ - getIdentityProviders(ENVIRONMENTS.TEST), - getIdentityProviders(ENVIRONMENTS.PROD) - ]).then(providers => { - setIdentityProviders(providers[0]); - setProdIdentityProviders(providers[1]); - + getIdentityProviders().then(providers => { + setIdentityProviders(providers); }) }) }, [applicationId, arp]); @@ -99,17 +93,14 @@ export const Connection = () => { return { testConnectionComplete: !isEmpty(application.connections) && application.connections - .filter(conn => conn.environment === ENVIRONMENTS.TEST) .some(conn => conn.status !== CONNECTION_STATUSES.OPEN), productionConnectionComplete: !isEmpty(application.connections) && application.connections - .filter(conn => conn.environment === ENVIRONMENTS.PROD) - .some(conn => conn.status !== CONNECTION_STATUSES.OPEN), + .some(conn => conn.status === CONNECTION_STATUSES.PENDING_PROD || conn.status === CONNECTION_STATUSES.PROD_READY), appInformationComplete: logoSectionValid(application) && contactSectionValid(application) && privacySectionValid(privacy, application) && application.status !== APPLICATION_STATUSES.OPEN, productionConnectionNeedsActivation: application.signedContract && !isEmpty(application.connections) && application.connections - .filter(conn => conn.environment === ENVIRONMENTS.PROD) .some(conn => conn.status === CONNECTION_STATUSES.COMPLETE || conn.status === CONNECTION_STATUSES.IN_PROGRESS) } }, [application, privacy]); @@ -129,11 +120,10 @@ export const Connection = () => { }) } - const initConnection = (environment = ENVIRONMENTS.TEST, forceNew = false) => { + const initConnection = (forceNew = false) => { const iDps = config.identityProviders; setConnection({ new: forceNew, - environment: environment, protocol: protocolOptions[0], grantTypes: ["authorization_code"], pkce: false, @@ -150,16 +140,15 @@ export const Connection = () => { visibility: visibilities.visible_to_all, connectOption: connectOptions.connect_with_interaction }); - const newTab = environment === ENVIRONMENTS.TEST ? "testing" : "prod"; - setCurrentTab(newTab); - navigate(`/connection/${applicationId}/${newTab}`); + setCurrentTab("instances"); + navigate(`/connection/${applicationId}/instances`); } const changeTab = (newTab, action = null) => { if (dirty) { refresh() } - if (currentTab === "testing" || currentTab === "prod") { + if (currentTab === "instances") { //force the overview setConnection(null); } @@ -181,8 +170,8 @@ export const Connection = () => { productionConnectionNeedsActivation={productionConnectionNeedsActivation} /> } - case "testing": { - return { setTab={changeTab} profileOptions={profileOptions} identityProviders={identityProviders} - isProduction={false} - setDirty={setDirty} - connectionId={connectionId} - - /> - } - case "prod": { - return { ({ name: name, disabled: - (name === "prod" && !testConnectionComplete) || (name === "application" && false) || //!testConnectionComplete) || (name === "contract" && false)//!productionConnectionComplete) }))} diff --git a/client/src/pages/Organization.jsx b/client/src/pages/Organization.jsx index b3387987..a181123e 100644 --- a/client/src/pages/Organization.jsx +++ b/client/src/pages/Organization.jsx @@ -14,7 +14,7 @@ import CardView from "@surfnet/sds/icons/functional-icons/card-view.svg"; import ListView from "@surfnet/sds/icons/functional-icons/list-or-table-view.svg"; import DOMPurify from "dompurify"; import {convertServerApplicationToClient} from "../utils/Application.js"; -import {CONNECTION_STATUSES, ENVIRONMENTS} from "../utils/Manage.js"; +import {CONNECTION_STATUSES} from "../utils/Manage.js"; import { authorities, currentUserMembershipAuthority, @@ -85,7 +85,8 @@ const Organization = () => { } const renderApplicationStatus = application => { - const prodConnections = (application.connections || []).filter(conn => conn.environment === ENVIRONMENTS.PROD); + const prodConnections = (application.connections || []).filter(conn => + conn.status === CONNECTION_STATUSES.PENDING_PROD || conn.status === CONNECTION_STATUSES.PROD_READY); // eslint-disable-next-line no-useless-assignment let status = ""; if (prodConnections.length === 0) { diff --git a/client/src/utils/Manage.js b/client/src/utils/Manage.js index 205af03d..057da832 100644 --- a/client/src/utils/Manage.js +++ b/client/src/utils/Manage.js @@ -64,10 +64,6 @@ export const ORGANIZATION_STATUSES = { PENDING_APPROVAL: "PENDING_APPROVAL", APPROVED: "APPROVED", DISAPPROVED: "DISAPPROVED" } -export const ENVIRONMENTS = { - TEST: "TEST", PROD: "PROD" -} - export const CHANGE_REQUEST_TYPE = { PRODUCTION_STATUS_REQUEST: "ProductionStatusRequest", LINK_REQUEST: "LinkRequest", diff --git a/server/src/main/java/access/api/ApplicationController.java b/server/src/main/java/access/api/ApplicationController.java index fd520518..5466f829 100644 --- a/server/src/main/java/access/api/ApplicationController.java +++ b/server/src/main/java/access/api/ApplicationController.java @@ -12,7 +12,6 @@ import access.model.Connection; import access.model.ConnectionStatus; import access.model.EntityType; -import access.model.Environment; import access.model.ImportEntityRequest; import access.model.MigrateApplicationRequest; import access.model.Organization; @@ -165,7 +164,7 @@ public ResponseEntity find(User user, @PathVariable("applicationId" connectionRepository.save(connection); } if (connection.getStatus().equals(ConnectionStatus.PROD_READY)) { - connection.convertChangeRequests(manage.getChangeRequests(Environment.PROD, connection)); + connection.convertChangeRequests(manage.getChangeRequests(connection)); } }); Map provider = latestChangedProvider.get(); @@ -353,8 +352,7 @@ public ResponseEntity> importEntity(User user, (String) metaDataFields.get("name:en"), application, new HashMap<>(),// We will fill the metadata later - EntityType.valueOf((String) serviceProvider.get("type")), - Environment.PROD + EntityType.valueOf((String) serviceProvider.get("type")) ); connection.setSecretSet(true); connection.setStatus(ConnectionStatus.PENDING_PROD); diff --git a/server/src/main/java/access/api/ConnectionController.java b/server/src/main/java/access/api/ConnectionController.java index 6b31a118..8643c967 100644 --- a/server/src/main/java/access/api/ConnectionController.java +++ b/server/src/main/java/access/api/ConnectionController.java @@ -14,7 +14,6 @@ import access.model.Connection; import access.model.ConnectionStatus; import access.model.EntityType; -import access.model.Environment; import access.model.Organization; import access.model.User; import access.repository.ApplicationRepository; @@ -112,7 +111,7 @@ public ResponseEntity find(User user, @PathVariable("connectionId") connectionRepository.save(connection); } if (connection.getStatus().equals(ConnectionStatus.PROD_READY)) { - connection.convertChangeRequests(manage.getChangeRequests(Environment.PROD, connection)); + connection.convertChangeRequests(manage.getChangeRequests(connection)); } } return ResponseEntity.ok(connection); @@ -171,7 +170,7 @@ public ResponseEntity update(User user, @Validated @RequestBody Conn if (connection.changeRequestRequired()) { //Not allowed to sync the connection to Manage. Create ChangeRequests connection = this.productionReadyChangeRequests(connection, user); - connection.convertChangeRequests(manage.getChangeRequests(Environment.PROD, connection)); + connection.convertChangeRequests(manage.getChangeRequests(connection)); } else { connection = saveConnection(connection); } @@ -183,7 +182,7 @@ public ResponseEntity update(User user, @Validated @RequestBody Conn public ResponseEntity>> changeRequests(User user, @PathVariable("connectionId") Long connectionId) { Connection connection = findConnectionForAuthorizedUser(user, connectionId); - List> changeRequests = manage.getChangeRequests(connection.getEnvironment(), connection); + List> changeRequests = manage.getChangeRequests(connection); return ResponseEntity.ok(changeRequests); } @@ -204,7 +203,7 @@ public ResponseEntity> requestProductionStatus(User user, @PathVariable("connectionId") Long connectionId) { Connection connection = findConnectionForAuthorizedUser(user, connectionId); - String changeRequestURL = manage.changeRequestURL(connection.getEnvironment(), connection); + String changeRequestURL = manage.changeRequestURL(connection); Map provider = manage.providerByConnection(connection); String entityId = (String) ((Map) provider.get("data")).get("entityid"); @@ -234,7 +233,7 @@ public ResponseEntity> requestProductionStatus(User user, RequestType.ProductionStatusRequest); changeRequest.setTicketKey(jiraKey); changeRequest.setAuditData(auditData); - Map changeRequestResponse = manage.createChangeRequest(connection.getEnvironment(), changeRequest); + Map changeRequestResponse = manage.createChangeRequest(changeRequest); LOG.debug("Change request response from manage: " + changeRequestResponse); @@ -291,11 +290,10 @@ private boolean isNewChangeRequestDuplicate(List> existingCh @SuppressWarnings("unchecked") private Connection productionReadyChangeRequests(Connection connection, User user) { - Environment environment = connection.getEnvironment(); - String changeRequestURL = manage.changeRequestURL(environment, connection); + String changeRequestURL = manage.changeRequestURL(connection); Map provider = manage.providerByConnection(connection); connection.updateRemoteManageData(provider); - List> existingChangeRequests = manage.getChangeRequests(Environment.PROD, connection); + List> existingChangeRequests = manage.getChangeRequests(connection); Optional changeRequestOptional = connectionProviderConverter.deduceChangeRequests(connection, provider); boolean isDuplicate = isNewChangeRequestDuplicate(existingChangeRequests, changeRequestOptional); if (changeRequestOptional.isPresent() && !isDuplicate) { @@ -323,7 +321,7 @@ private Connection productionReadyChangeRequests(Connection connection, User use ChangeRequest changeRequest = changeRequestOptional.get(); changeRequest.setTicketKey(jiraKey); changeRequest.setAuditData(auditData); - manage.createChangeRequest(environment, changeRequest); + manage.createChangeRequest(changeRequest); } else { //Now we need to ensure that previous change requests, with the same pathUpdate and value a List, does not overwrite changes //And therefore we don't create a new change request, but update the existing one @@ -363,14 +361,14 @@ private Connection productionReadyChangeRequests(Connection connection, User use } }); ChangeRequest changeRequest = objectMapper.convertValue(existingChangeRequest, ChangeRequest.class); - manage.updateChangeRequest(Environment.PROD, changeRequest); + manage.updateChangeRequest(changeRequest); } } //Now the tricky bit, we must fetch the changeRequest after they are created and return the data based on the provider connection.mergeMetaData(provider, true); connection = connectionRepository.save(connection); - connection.convertChangeRequests(manage.getChangeRequests(Environment.PROD, connection)); + connection.convertChangeRequests(manage.getChangeRequests(connection)); return connection; } diff --git a/server/src/main/java/access/api/IdentityProviderController.java b/server/src/main/java/access/api/IdentityProviderController.java index 9d14770f..7a12c45d 100644 --- a/server/src/main/java/access/api/IdentityProviderController.java +++ b/server/src/main/java/access/api/IdentityProviderController.java @@ -14,7 +14,6 @@ import access.model.ConnectionRequest; import access.model.DisconnectionRequest; import access.model.EntityType; -import access.model.Environment; import access.model.Organization; import access.model.OrganizationMembership; import access.model.User; @@ -82,7 +81,7 @@ public ResponseEntity> connect(User user, @RequestBody @Vali .orElseThrow(() -> new NotFoundException("Organization with manageIdentifier not found: " + idpManageIdentifier)); Map serviceProvider = manage.providerByManageIdentifier(connectionRequest.getEntityType(), - connectionRequest.getApplicationManageIdentifier(), Environment.PROD); + connectionRequest.getApplicationManageIdentifier()); boolean memberRequest = !user.isSuperUser(); if (memberRequest) { @@ -112,7 +111,7 @@ public ResponseEntity> connect(User user, @RequestBody @Vali return Results.createResult(); } - Map identityProvider = manage.providerByManageIdentifier(EntityType.saml20_idp, idpManageIdentifier, Environment.PROD); + Map identityProvider = manage.providerByManageIdentifier(EntityType.saml20_idp, idpManageIdentifier); //See https://github.com/OpenConext/OpenConext-access/wiki/Service-Connect-Flow //Now check if the connection can be made automatically @@ -175,7 +174,7 @@ public ResponseEntity> connect(User user, @RequestBody @Vali changeRequest.setTicketKey(jiraKey); changeRequest.setAuditData(auditData); - manage.createChangeRequest(Environment.PROD, changeRequest); + manage.createChangeRequest(changeRequest); return ResponseEntity.status(HttpStatus.CREATED).body( Map.of("status", HttpStatus.CREATED.value(), "jiraKey", jiraKey)); @@ -192,10 +191,10 @@ public ResponseEntity> disconnect(User user, @RequestBody @V .orElseThrow(() -> new NotFoundException("Organization with manageIdentifier not found: " + idpManageIdentifier)); Map serviceProvider = manage.providerByManageIdentifier(disconnectionRequest.getEntityType(), - disconnectionRequest.getApplicationManageIdentifier(), Environment.PROD); + disconnectionRequest.getApplicationManageIdentifier()); confirmOrganizationMembership(user, organization, Authority.ADMIN); - Map identityProvider = manage.providerByManageIdentifier(EntityType.saml20_idp, idpManageIdentifier, Environment.PROD); + Map identityProvider = manage.providerByManageIdentifier(EntityType.saml20_idp, idpManageIdentifier); String changeRequestURL = manage.changeRequestURLConnectionRequest(EntityType.saml20_idp, idpManageIdentifier); @@ -231,7 +230,7 @@ public ResponseEntity> disconnect(User user, @RequestBody @V RequestType.UnlinkRequest); changeRequest.setTicketKey(jiraKey); changeRequest.setAuditData(auditData); - manage.createChangeRequest(Environment.PROD, changeRequest); + manage.createChangeRequest(changeRequest); return ResponseEntity.status(HttpStatus.CREATED).body( Map.of("status", HttpStatus.CREATED.value(), "jiraKey", jiraKey)); @@ -263,10 +262,10 @@ private void doCancelRequest(User user, ConnectionRequest connectionRequest, Pat .orElseThrow(() -> new NotFoundException("Organization with manageIdentifier not found: " + idpManageIdentifier)); Map serviceProvider = manage.providerByManageIdentifier(connectionRequest.getEntityType(), - connectionRequest.getApplicationManageIdentifier(), Environment.PROD); + connectionRequest.getApplicationManageIdentifier()); confirmOrganizationMembership(user, organization, Authority.ADMIN); - Map identityProvider = manage.providerByManageIdentifier(EntityType.saml20_idp, idpManageIdentifier, Environment.PROD); + Map identityProvider = manage.providerByManageIdentifier(EntityType.saml20_idp, idpManageIdentifier); List> changeRequests = manage.getChangeRequestsIdentityProvider(identityProvider); String serviceProviderEntityID = getEntityID(serviceProvider); @@ -280,7 +279,7 @@ private void doCancelRequest(User user, ConnectionRequest connectionRequest, Pat .getOrDefault("allowedEntities", Map.of()).get("name"))) .toList(); //First delete all manage change request - this is most likely to succeed - openChangeRequests.forEach(changeRequest -> manage.rejectChangeRequest(Environment.PROD, new ChangeRequest(changeRequest))); + openChangeRequests.forEach(changeRequest -> manage.rejectChangeRequest(new ChangeRequest(changeRequest))); //Then update all Jira comments, this API is not so stable String comment = "Ticket can be closed by request of the requestor"; openChangeRequests.forEach(changeRequest -> jiraClient.comment((String) changeRequest.get("ticketKey"), comment)); diff --git a/server/src/main/java/access/api/ManageController.java b/server/src/main/java/access/api/ManageController.java index 84726bc6..88bde8a8 100644 --- a/server/src/main/java/access/api/ManageController.java +++ b/server/src/main/java/access/api/ManageController.java @@ -10,7 +10,6 @@ import access.manage.PolicyAccessRights; import access.manage.PolicyDefinition; import access.model.EntityType; -import access.model.Environment; import access.model.Organization; import access.model.User; import access.repository.OrganizationRepository; @@ -116,11 +115,11 @@ public ResponseEntity> parse(@RequestBody Map req } - @GetMapping("/identity-providers/{environment}") - public ResponseEntity>> identityProviders(@PathVariable("environment") Environment environment) { - LOG.debug("/identityProviders for " + environment); + @GetMapping("/identity-providers") + public ResponseEntity>> identityProviders() { + LOG.debug("/identityProviders"); - List> providers = manage.providers(environment, EntityType.saml20_idp); + List> providers = manage.providers(EntityType.saml20_idp); return ResponseEntity.ok(providers); } @@ -134,11 +133,11 @@ public ResponseEntity>> serviceProviders(@PathVariable List> serviceProviders = List.of(); if (isIdentityProvider) { Map identityProvider = manage.providerByManageIdentifier( - EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + EntityType.saml20_idp, organization.getManageIdentifier()); Map data = getData(identityProvider); boolean allowedall = (boolean) data.getOrDefault("allowedall", false); if (allowedall) { - serviceProviders = manage.serviceProvidersLight(Environment.PROD); + serviceProviders = manage.serviceProvidersLight(); } else { List> allowedEntities = (List>) data.get("allowedEntities"); List names = allowedEntities.stream().map(allowedEntity -> allowedEntity.get("name")).toList(); @@ -159,7 +158,7 @@ public ResponseEntity>> identityProviderPolicies(@Param confirmInstitutionAdmin(user, organization); - Map provider = this.manage.providerByManageIdentifier(EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + Map provider = this.manage.providerByManageIdentifier(EntityType.saml20_idp, organization.getManageIdentifier()); List> policies = this.manage.policiesByIdentityProvider((String) getData(provider).get("entityid")); return ResponseEntity.ok(policies); @@ -226,7 +225,7 @@ public ResponseEntity> updatePolicy(User user, public ResponseEntity deletePolicy(User user, @RequestParam("organizationId") Long organizationId, @PathVariable String policyId) { - Map policy = manage.providerByManageIdentifier(EntityType.policy, policyId, Environment.PROD); + Map policy = manage.providerByManageIdentifier(EntityType.policy, policyId); Organization organization = organizationRepository.getReferenceById(organizationId); @@ -238,14 +237,13 @@ public ResponseEntity deletePolicy(User user, } - @PostMapping("/unique-entity-id/{environment}") - public ResponseEntity>> providersByEntityId(@PathVariable("environment") Environment environment, - @RequestBody Map data) { + @PostMapping("/unique-entity-id") + public ResponseEntity>> providersByEntityId(@RequestBody Map data) { LOG.debug("/unique-entity-id for " + data); String entityID = data.get("entityID"); //It does not matter which entityType we use, all services will be queried - List> providers = manage.uniqueEntityId(environment, EntityType.saml20_sp, entityID); + List> providers = manage.uniqueEntityId(EntityType.saml20_sp, entityID); return ResponseEntity.ok(providers); } @@ -282,7 +280,7 @@ public ResponseEntity>> allowedAttributes() { public ResponseEntity> rejectChangeRequest(User user, @RequestBody ChangeRequest changeRequest) { LOG.debug("/reject-change-request " + changeRequest + " by " + user.getEmail()); //change request has non guessable identifier - manage.rejectChangeRequest(Environment.PROD, changeRequest); + manage.rejectChangeRequest(changeRequest); jiraClient.comment(changeRequest.getTicketKey(), "Ticket can be closed by request of the requestor"); diff --git a/server/src/main/java/access/api/OrganizationController.java b/server/src/main/java/access/api/OrganizationController.java index d8720492..2ddad291 100644 --- a/server/src/main/java/access/api/OrganizationController.java +++ b/server/src/main/java/access/api/OrganizationController.java @@ -99,13 +99,13 @@ public ResponseEntity> findOrganizationDetailById(User user, String.format("User %s is not a member of organization %s", user.getEmail(), id))); organization.getApplications().forEach(application -> { - //We only fetch change-requests for applications with one production status + //We only fetch change-requests for applications with one production connection List prodConnections = application.getConnections().stream() - .filter(conn -> conn.getEnvironment().equals(Environment.PROD)) + .filter(Connection::isProductionConnection) .toList(); if (prodConnections.size() == 1) { prodConnections.forEach(connection -> - connection.convertChangeRequests(manage.getChangeRequests(Environment.PROD, connection))); + connection.convertChangeRequests(manage.getChangeRequests(connection))); } }); @@ -152,7 +152,7 @@ public ResponseEntity findMyOrganization(User user, confirmOrganizationMembership(userFromDB, organization, Authority.GUEST); if (StringUtils.hasText(organization.getManageIdentifier())) { - Map provider = manage.providerByManageIdentifier(EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + Map provider = manage.providerByManageIdentifier(EntityType.saml20_idp, organization.getManageIdentifier()); if (organization.mergeMetaData(provider, false)) { organizationRepository.save(organization); } diff --git a/server/src/main/java/access/api/PublicController.java b/server/src/main/java/access/api/PublicController.java index c5afb983..1dc249ff 100644 --- a/server/src/main/java/access/api/PublicController.java +++ b/server/src/main/java/access/api/PublicController.java @@ -3,7 +3,6 @@ import access.config.Config; import access.manage.Manage; import access.model.EntityType; -import access.model.Environment; import lombok.SneakyThrows; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -43,7 +42,7 @@ public PublicController(Manage manage, Config config) { @GetMapping("/service-providers") public ResponseEntity>> serviceProviders(Authentication authentication) { LOG.debug("/serviceProviders"); - List> providers = manage.serviceProvidersLight(Environment.PROD); + List> providers = manage.serviceProvidersLight(); if (authentication == null) { providers.removeIf(provider -> removeNonPublicProvider(provider)); } else { @@ -70,7 +69,7 @@ public ResponseEntity>> serviceProviders(Authentication @GetMapping("/identity-providers") public ResponseEntity>> identityProviders() { LOG.debug("/identityProviders"); - return ResponseEntity.ok(manage.identityProvidersLight(Environment.PROD)); + return ResponseEntity.ok(manage.identityProvidersLight()); } @GetMapping("/service-provider-detail/{type}/{identifier}") @@ -79,7 +78,7 @@ public ResponseEntity> serviceProviderDetail( @PathVariable("identifier") String identifier) { LOG.debug("/identityProviders"); Map provider = manage - .providerByManageIdentifier(entityType, identifier, Environment.PROD); + .providerByManageIdentifier(entityType, identifier); getMetaDataFields(getData(provider)).keySet() .removeIf(key -> key.startsWith("contacts:")); return ResponseEntity.ok(provider); diff --git a/server/src/main/java/access/api/UserController.java b/server/src/main/java/access/api/UserController.java index 7f6289a0..f7cddcc4 100644 --- a/server/src/main/java/access/api/UserController.java +++ b/server/src/main/java/access/api/UserController.java @@ -108,6 +108,8 @@ public ResponseEntity me(@Parameter(hidden = true) User user, Authenticati userFromDB.setChangeRequests(changeRequests); // Provision the user into the organization, if no organization is created yet, create it on the fly + LOG.debug(String.format("DEBUG: manageIdentifier=%s, memberships=%d", manageIdentifier, userFromDB.getOrganizationMemberships().size())); + userFromDB.getOrganizationMemberships().forEach(om -> LOG.debug(String.format("DEBUG: org=%s, orgManageId=%s", om.getOrganization().getName(), om.getOrganization().getManageIdentifier()))); if (userFromDB.getOrganizationMemberships().stream() .noneMatch(organizationMembership -> organizationMembership.getOrganization() .getManageIdentifier().equals(manageIdentifier))) { @@ -132,6 +134,8 @@ public ResponseEntity me(@Parameter(hidden = true) User user, Authenticati } } userRepository.save(userFromDB); + LOG.debug(String.format("DEBUG FINAL: memberships=%d", userFromDB.getOrganizationMemberships().size())); + userFromDB.getOrganizationMemberships().forEach(om -> LOG.debug(String.format("DEBUG FINAL: org=%s, orgId=%d, authority=%s", om.getOrganization().getName(), om.getOrganization().getId(), om.getAuthority()))); return ResponseEntity.ok(userFromDB); } @@ -154,7 +158,7 @@ public ResponseEntity organizationSwitch(@Parameter(hidden = true) User us userFromDB.setExternalUser(!isInternalUserFromOrganization); if (isInternalUserFromOrganization) { Map identityProvider = manage.providerByManageIdentifier( - EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + EntityType.saml20_idp, organization.getManageIdentifier()); userFromDB.setIdentityProvider(identityProvider); List> changeRequests = manage.getChangeRequestsIdentityProvider(identityProvider); userFromDB.setChangeRequests(changeRequests); diff --git a/server/src/main/java/access/manage/ConnectionProviderConverter.java b/server/src/main/java/access/manage/ConnectionProviderConverter.java index 354992bf..87041dc8 100644 --- a/server/src/main/java/access/manage/ConnectionProviderConverter.java +++ b/server/src/main/java/access/manage/ConnectionProviderConverter.java @@ -4,7 +4,6 @@ import access.model.ConnectOptions; import access.model.Connection; import access.model.EntityType; -import access.model.Environment; import access.model.State; import access.model.Visibility; import com.fasterxml.jackson.core.type.TypeReference; @@ -37,14 +36,12 @@ public class ConnectionProviderConverter { private final List excludedAttributes = List.of("revisionnote"); private final List excludedMergeAttributesPaths = List.of("arp.attributes"); - private final State defaultTestState; - private final State defaultProdState; + private final State defaultState; private final ObjectMapper objectMapper; @SneakyThrows - public ConnectionProviderConverter(ObjectMapper objectMapper, State defaultTestState, State defaultProdState) { - this.defaultTestState = defaultTestState; - this.defaultProdState = defaultProdState; + public ConnectionProviderConverter(ObjectMapper objectMapper, State defaultState) { + this.defaultState = defaultState; this.objectMapper = objectMapper; this.privacyInfo = objectMapper.readValue(new ClassPathResource("/metadata/Privacy.json").getInputStream(), new TypeReference<>() { }); @@ -86,7 +83,7 @@ public Map convert(Connection connection, data.put("entityid", connectionMetaData.get("entityID")); //Don't override the state, if previously set if (!StringUtils.hasText((String) data.get("state"))) { - data.put("state", (connection.getEnvironment().equals(Environment.TEST) ? defaultTestState : defaultProdState).name()); + data.put("state", defaultState.name()); } metaDataFields.put("name:en", connection.getName()); @@ -118,9 +115,7 @@ public Map convert(Connection connection, } mergeAttributeReleasePolicies(connectionMetaData, data); - if (connection.getEnvironment().equals(Environment.TEST)) { - mergeAllowedEntities(data, connectionMetaData); - } + mergeAllowedEntities(data, connectionMetaData); if (EntityType.oidc10_rp.equals(connection.getProtocol())) { List grantTypes = (List) connectionMetaData.get("grantTypes"); diff --git a/server/src/main/java/access/manage/LocalManage.java b/server/src/main/java/access/manage/LocalManage.java index 2ec10d1b..47de42bf 100644 --- a/server/src/main/java/access/manage/LocalManage.java +++ b/server/src/main/java/access/manage/LocalManage.java @@ -3,7 +3,6 @@ import access.exception.NotFoundException; import access.model.Connection; import access.model.EntityType; -import access.model.Environment; import access.model.Organization; import access.model.User; import com.fasterxml.jackson.core.type.TypeReference; @@ -60,7 +59,7 @@ private List> initialize(EntityType entityType, String stati } @Override - public List> providers(Environment environment, EntityType... entityTypes) { + public List> providers(EntityType... entityTypes) { LOG.debug("providers for : " + List.of(entityTypes)); //Ensure it is mutable @@ -73,11 +72,10 @@ public List> providers(Environment environment, EntityType.. public Map providerByConnection(Connection connection) { String manageIdentifier = connection.getManageIdentifier(); EntityType protocol = connection.getProtocol(); - Environment environment = connection.getEnvironment(); LOG.debug("providerById for : " + protocol); - List> providers = providers(environment, protocol); + List> providers = providers(protocol); return providers.stream() .filter(provider -> provider.get("id").equals(manageIdentifier)) .findFirst() @@ -85,10 +83,10 @@ public Map providerByConnection(Connection connection) { } @Override - public Map providerByManageIdentifier(EntityType entityType, String manageIdentifier, Environment environment) { + public Map providerByManageIdentifier(EntityType entityType, String manageIdentifier) { LOG.debug("providerById for : " + entityType); - List> providers = providers(environment, entityType); + List> providers = providers(entityType); return providers.stream() .filter(provider -> provider.get("id").equals(manageIdentifier)) .findFirst() @@ -97,7 +95,7 @@ public Map providerByManageIdentifier(EntityType entityType, Str @Override public Map saveIdentityProvider(Organization organization) { - Map provider = providerByManageIdentifier(EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + Map provider = providerByManageIdentifier(EntityType.saml20_idp, organization.getManageIdentifier()); Map data = getData(provider); Map metaDataFields = getMetaDataFields(data); converter.convertContactPersons(organization.getMetaData(), metaDataFields); @@ -167,7 +165,7 @@ public List> serviceProvidersByEntityID(List entityI } @Override - public List> uniqueEntityId(Environment environment, EntityType entityType, String entityID) { + public List> uniqueEntityId(EntityType entityType, String entityID) { return Stream.of(EntityType.values()) .flatMap(type -> this.allProviders.get(type).stream()) .filter(provider -> ((Map) provider.get("data")).get("entityid").equals(entityID)) @@ -175,22 +173,22 @@ public List> uniqueEntityId(Environment environment, EntityT } @Override - public Map createChangeRequest(Environment environment, ChangeRequest changeRequest) { + public Map createChangeRequest(ChangeRequest changeRequest) { return Map.of(); } @Override - public Map updateChangeRequest(Environment environment, ChangeRequest changeRequest) { + public Map updateChangeRequest(ChangeRequest changeRequest) { return Map.of(); } @Override - public void rejectChangeRequest(Environment environment, ChangeRequest changeRequest) { + public void rejectChangeRequest(ChangeRequest changeRequest) { //noop } @Override - public List> getChangeRequests(Environment environment, Connection connection) { + public List> getChangeRequests(Connection connection) { return List.of(); } @@ -200,7 +198,7 @@ public List> getChangeRequestsIdentityProvider(Map> identityProvidersByInstitutionalGUID(Environment environment, String organisationGUID) { + public List> identityProvidersByInstitutionalGUID(String organisationGUID) { return this.allProviders.get(EntityType.saml20_idp).stream() .filter(provider -> { Map data = getData(provider); @@ -221,12 +219,12 @@ public List> identityProvidersByInstitutionalGUID(Environmen } @Override - public List> identityProvidersLight(Environment environment) { + public List> identityProvidersLight() { return this.allProviders.get(EntityType.saml20_idp); } @Override - public List> serviceProvidersLight(Environment environment) { + public List> serviceProvidersLight() { List> providers = new ArrayList<>(); providers.addAll(this.allProviders.get(EntityType.saml20_sp)); providers.addAll(this.allProviders.get(EntityType.oidc10_rp)); @@ -245,8 +243,7 @@ public Map stats() { @Override public List> identityProvidersByAllowedConnections(List connections) { List entityIdentifiers = connections.stream() - .filter(connection -> StringUtils.hasText(connection.getManageIdentifier()) && - connection.getEnvironment().equals(Environment.PROD)) + .filter(connection -> StringUtils.hasText(connection.getManageIdentifier())) .map(connection -> { Map provider = this.providerByConnection(connection); Map data = (Map) provider.get("data"); diff --git a/server/src/main/java/access/manage/Manage.java b/server/src/main/java/access/manage/Manage.java index 30022781..c14cabb3 100644 --- a/server/src/main/java/access/manage/Manage.java +++ b/server/src/main/java/access/manage/Manage.java @@ -6,11 +6,11 @@ public interface Manage { - List> providers(Environment environment, EntityType... entityTypes); + List> providers(EntityType... entityTypes); Map providerByConnection(Connection connection); - Map providerByManageIdentifier(EntityType entityType, String manageIdentifier, Environment environment); + Map providerByManageIdentifier(EntityType entityType, String manageIdentifier); Map saveIdentityProvider(Organization organization); @@ -24,29 +24,29 @@ public interface Manage { List> serviceProvidersByEntityID(List entityIdentifiers); - List> uniqueEntityId(Environment environment, EntityType entityType, String entityID); + List> uniqueEntityId(EntityType entityType, String entityID); - Map createChangeRequest(Environment environment, ChangeRequest changeRequest); + Map createChangeRequest(ChangeRequest changeRequest); - void rejectChangeRequest(Environment environment, ChangeRequest changeRequest); + void rejectChangeRequest(ChangeRequest changeRequest); - Map updateChangeRequest(Environment environment, ChangeRequest changeRequest); + Map updateChangeRequest(ChangeRequest changeRequest); - List> getChangeRequests(Environment environment, Connection connection); + List> getChangeRequests(Connection connection); List> getChangeRequestsIdentityProvider(Map identityProvider); - String changeRequestURL(Environment environment, Connection connection); + String changeRequestURL(Connection connection); String changeRequestURLConnectionRequest(EntityType entityType, String manageIdentifier); - List> identityProvidersByInstitutionalGUID(Environment environment, String organisationGUID); + List> identityProvidersByInstitutionalGUID(String organisationGUID); Map stats(); - List> identityProvidersLight(Environment environment); + List> identityProvidersLight(); - List> serviceProvidersLight(Environment environment); + List> serviceProvidersLight(); List> identityProvidersByAllowedConnections(List connections); @@ -96,4 +96,4 @@ default Map baseStructureProvider() { result.put("data", data); return result; } -} \ No newline at end of file +} diff --git a/server/src/main/java/access/manage/ManageAuthorization.java b/server/src/main/java/access/manage/ManageAuthorization.java index 9b88d833..90cd53a0 100644 --- a/server/src/main/java/access/manage/ManageAuthorization.java +++ b/server/src/main/java/access/manage/ManageAuthorization.java @@ -1,6 +1,4 @@ package access.manage; -import access.model.Environment; - -public record ManageAuthorization(String url, String user, String password, Environment environment) { +public record ManageAuthorization(String url, String user, String password) { } diff --git a/server/src/main/java/access/manage/ManageConf.java b/server/src/main/java/access/manage/ManageConf.java index 612ba7d1..6fc27c7d 100644 --- a/server/src/main/java/access/manage/ManageConf.java +++ b/server/src/main/java/access/manage/ManageConf.java @@ -1,7 +1,6 @@ package access.manage; -import access.model.Environment; import access.model.State; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Value; @@ -14,29 +13,23 @@ public class ManageConf { @Bean - public Manage manage(@Value("${manage.test.url}") String testUrl, - @Value("${manage.test.user}") String testUser, - @Value("${manage.test.password}") String testPassword, - @Value("${manage.prod.url}") String prodUrl, - @Value("${manage.prod.user}") String prodUser, - @Value("${manage.prod.password}") String prodPassword, + public Manage manage(@Value("${manage.url}") String url, + @Value("${manage.user}") String user, + @Value("${manage.password}") String password, @Value("${manage.enabled}") boolean enabled, @Value("${manage.staticManageDirectory}") String staticManageDirectory, - @Value("${manage.activeManage}") Environment activeEnvironment, ConnectionProviderConverter converter, ObjectMapper objectMapper) throws IOException { - ManageAuthorization testAuthorization = new ManageAuthorization(testUrl, testUser, testPassword, Environment.TEST); - ManageAuthorization prodAuthorization = new ManageAuthorization(prodUrl, prodUser, prodPassword, Environment.PROD); - return enabled ? new RemoteManage(testAuthorization, prodAuthorization, converter, activeEnvironment, objectMapper) : + ManageAuthorization authorization = new ManageAuthorization(url, user, password); + return enabled ? new RemoteManage(authorization, converter, objectMapper) : new LocalManage(converter, objectMapper, staticManageDirectory); } @Bean public ConnectionProviderConverter connectionProviderConverter( - @Value("${manage.test.defaultState}") State defaultTestState, - @Value("${manage.prod.defaultState}") State defaultProdState, + @Value("${manage.defaultState}") State defaultState, ObjectMapper objectMapper) { - return new ConnectionProviderConverter(objectMapper, defaultTestState, defaultProdState); + return new ConnectionProviderConverter(objectMapper, defaultState); } } diff --git a/server/src/main/java/access/manage/PolicyAccessRights.java b/server/src/main/java/access/manage/PolicyAccessRights.java index 488a1f02..9607a60e 100644 --- a/server/src/main/java/access/manage/PolicyAccessRights.java +++ b/server/src/main/java/access/manage/PolicyAccessRights.java @@ -2,7 +2,6 @@ import access.exception.UserRestrictionException; import access.model.EntityType; -import access.model.Environment; import access.model.Organization; import access.model.User; @@ -22,7 +21,7 @@ default void confirmPolicyAccess(User user, if (user.isSuperUser()) { return; } - Map identityProvider = manage.providerByManageIdentifier(EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + Map identityProvider = manage.providerByManageIdentifier(EntityType.saml20_idp, organization.getManageIdentifier()); Map data = getData(identityProvider); List entityId = List.of((String) data.get("entityid")); //Is the IdP of the Policy the same as the IdP of the User? diff --git a/server/src/main/java/access/manage/RemoteManage.java b/server/src/main/java/access/manage/RemoteManage.java index 214edcde..eea5c34f 100644 --- a/server/src/main/java/access/manage/RemoteManage.java +++ b/server/src/main/java/access/manage/RemoteManage.java @@ -3,7 +3,6 @@ import access.exception.NotFoundException; import access.model.Connection; import access.model.EntityType; -import access.model.Environment; import access.model.Organization; import access.model.State; import access.model.User; @@ -42,36 +41,26 @@ public class RemoteManage implements Manage { private static final ParameterizedTypeReference> PARAMETERIZED_TYPE_REFERENCE = new ParameterizedTypeReference<>() { }; - //Because of the custom error handling, we need to use Buffering - private final Map restTemplates; + private final RestTemplate restTemplate; + private final String url; private final Map queries; private final ConnectionProviderConverter converter; - private final ManageAuthorization testAuthorization; - private final ManageAuthorization productionAuthorization; - private final Environment activeEnvironment; - public RemoteManage(ManageAuthorization testAuthorization, - ManageAuthorization productionAuthorization, + public RemoteManage(ManageAuthorization authorization, ConnectionProviderConverter converter, - Environment activeEnvironment, ObjectMapper objectMapper) throws IOException { - this.testAuthorization = testAuthorization; - this.productionAuthorization = productionAuthorization; this.converter = converter; - this.activeEnvironment = activeEnvironment; + this.url = authorization.url(); this.queries = objectMapper.readValue(new ClassPathResource("/manage/query_templates.json").getInputStream(), new TypeReference<>() { }); ResponseErrorHandler resilientErrorHandler = new ResilientErrorHandler(objectMapper); - this.restTemplates = Map.of( - Environment.TEST, RestTemplateFactory.buildRestTemplate(resilientErrorHandler, testAuthorization.user(), testAuthorization.password()), - Environment.PROD, RestTemplateFactory.buildRestTemplate(resilientErrorHandler, productionAuthorization.user(), productionAuthorization.password()) - ); + this.restTemplate = RestTemplateFactory.buildRestTemplate(resilientErrorHandler, authorization.user(), authorization.password()); } @Override - public List> providers(Environment environment, EntityType... entityTypes) { + public List> providers(EntityType... entityTypes) { LOG.debug("Providers for entityTypes: " + List.of(entityTypes)); - return Stream.of(entityTypes).map(entityType -> this.getRemoteMetaData(environment, entityType.name(), false)) + return Stream.of(entityTypes).map(entityType -> this.getRemoteMetaData(entityType.name(), false)) .flatMap(List::stream) .toList(); } @@ -80,17 +69,14 @@ public List> providers(Environment environment, EntityType.. public Map providerByConnection(Connection connection) { String manageIdentifier = connection.getManageIdentifier(); EntityType protocol = connection.getProtocol(); - Environment environment = connection.getEnvironment(); LOG.debug("providerById: " + protocol); - return providerDetails(environment, protocol, manageIdentifier); + return providerDetails(protocol, manageIdentifier); } - private Map providerDetails(Environment environment, EntityType protocol, String manageIdentifier) { - String url = environmentUrl(environment); + private Map providerDetails(EntityType protocol, String manageIdentifier) { String queryUrl = String.format("%s/manage/api/internal/metadata/%s/%s", url, protocol.name(), manageIdentifier); - RestTemplate restTemplate = environmentRestTemplate(environment); ResponseEntity responseEntity = restTemplate.getForEntity(queryUrl, Map.class); if (responseEntity.getStatusCode().equals(HttpStatus.OK)) { return sanitizeProvider(responseEntity.getBody()); @@ -98,16 +84,16 @@ private Map providerDetails(Environment environment, EntityType return responseEntity.getBody(); } - public Map providerByManageIdentifier(EntityType entityType, String manageIdentifier, Environment environment) { + public Map providerByManageIdentifier(EntityType entityType, String manageIdentifier) { LOG.debug("providerById: " + entityType); - return providerDetails(environment, entityType, manageIdentifier); + return providerDetails(entityType, manageIdentifier); } @SneakyThrows @Override public Map saveIdentityProvider(Organization organization) { - Map provider = providerByManageIdentifier(EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + Map provider = providerByManageIdentifier(EntityType.saml20_idp, organization.getManageIdentifier()); Map metaDataFields = getMetaDataFields(getData(provider)); Map metaDataOrganization = organization.getMetaData(); converter.convertContactPersons(metaDataOrganization, metaDataFields); @@ -128,8 +114,6 @@ public Map saveProvider(Connection connection) { //Attribute Release Policies that are not available in Access //We can't update everything if the connection is production ready, only the application data Map provider = converter.convert(connection, remoteProvider, connection.changeRequestRequired()); - RestTemplate restTemplate = environmentRestTemplate(connection.getEnvironment()); - String url = environmentUrl(connection.getEnvironment()); HttpMethod httpMethod = StringUtils.hasText(connection.getManageIdentifier()) ? HttpMethod.PUT : HttpMethod.POST; ResponseEntity> responseEntity = restTemplate.exchange(String.format("%s/manage/api/internal/metadata", url), httpMethod, new HttpEntity<>(provider), PARAMETERIZED_TYPE_REFERENCE); @@ -142,8 +126,6 @@ public Map updateProvider(Map provider) { } private Map internalSaveProvider(Map provider) { - RestTemplate restTemplate = environmentRestTemplate(Environment.PROD); - String url = environmentUrl(Environment.PROD); ResponseEntity> responseEntity = restTemplate.exchange(String.format("%s/manage/api/internal/metadata", url), HttpMethod.PUT, new HttpEntity<>(provider), PARAMETERIZED_TYPE_REFERENCE); return checkNoChangeResponse(responseEntity, provider); @@ -151,80 +133,69 @@ private Map internalSaveProvider(Map provider) { @Override public void deleteProvider(Connection connection) { - Environment environment = connection.getEnvironment(); - RestTemplate restTemplate = environmentRestTemplate(environment); - String url = String.format("%s/manage/api/internal/metadata/%s/%s", - environmentUrl(environment), + String deleteUrl = String.format("%s/manage/api/internal/metadata/%s/%s", + url, connection.getProtocol(), connection.getManageIdentifier()); - restTemplate.exchange(URI.create(url), HttpMethod.DELETE, null, Void.class); + restTemplate.exchange(URI.create(deleteUrl), HttpMethod.DELETE, null, Void.class); } @Override - public void rejectChangeRequest(Environment environment, ChangeRequest changeRequest) { - RestTemplate restTemplate = environmentRestTemplate(environment); - String url = String.format("%s/manage/api/internal/change-requests/reject", - environmentUrl(environment)); - restTemplate.put(URI.create(url), changeRequest); + public void rejectChangeRequest(ChangeRequest changeRequest) { + String rejectUrl = String.format("%s/manage/api/internal/change-requests/reject", url); + restTemplate.put(URI.create(rejectUrl), changeRequest); } @Override - public List> uniqueEntityId(Environment environment, EntityType entityType, String entityID) { - RestTemplate restTemplate = environmentRestTemplate(environment); - String url = environmentUrl(environment); + public List> uniqueEntityId(EntityType entityType, String entityID) { String queryUrl = String.format("%s/manage/api/internal/uniqueEntityId/%s", url, entityType.name()); return restTemplate.postForEntity(queryUrl, Map.of("entityid", entityID), List.class).getBody(); } @Override - public Map createChangeRequest(Environment environment, ChangeRequest changeRequest) { - return doSaveChangeRequest(environment, changeRequest, HttpMethod.POST); + public Map createChangeRequest(ChangeRequest changeRequest) { + return doSaveChangeRequest(changeRequest, HttpMethod.POST); } @Override - public Map updateChangeRequest(Environment environment, ChangeRequest changeRequest) { - return doSaveChangeRequest(environment, changeRequest, HttpMethod.PUT); + public Map updateChangeRequest(ChangeRequest changeRequest) { + return doSaveChangeRequest(changeRequest, HttpMethod.PUT); } - private Map doSaveChangeRequest(Environment environment, ChangeRequest changeRequest, HttpMethod post) { - RestTemplate restTemplate = environmentRestTemplate(environment); - String url = String.format("%s/manage/api/internal/change-requests", environmentUrl(environment)); + private Map doSaveChangeRequest(ChangeRequest changeRequest, HttpMethod method) { + String changeUrl = String.format("%s/manage/api/internal/change-requests", url); HttpEntity requestEntity = new HttpEntity<>(changeRequest); - ResponseEntity> responseEntity = restTemplate.exchange(url, post, requestEntity, + ResponseEntity> responseEntity = restTemplate.exchange(changeUrl, method, requestEntity, PARAMETERIZED_TYPE_REFERENCE); return responseEntity.getBody(); } @Override - public List> getChangeRequests(Environment environment, Connection connection) { - RestTemplate restTemplate = environmentRestTemplate(environment); - String url = String.format("%s/manage/api/internal/change-requests/%s/%s", - environmentUrl(environment), + public List> getChangeRequests(Connection connection) { + String changeUrl = String.format("%s/manage/api/internal/change-requests/%s/%s", + url, connection.getProtocol().name(), connection.getManageIdentifier()); - return restTemplate.getForEntity(url, List.class).getBody(); + return restTemplate.getForEntity(changeUrl, List.class).getBody(); } @Override public List> getChangeRequestsIdentityProvider(Map identityProvider) { - RestTemplate restTemplate = environmentRestTemplate(activeEnvironment); - String url = String.format("%s/manage/api/internal/change-requests/%s/%s", - environmentUrl(activeEnvironment), + String changeUrl = String.format("%s/manage/api/internal/change-requests/%s/%s", + url, EntityType.saml20_idp.name(), identityProvider.get("id")); - return restTemplate.getForEntity(url, List.class).getBody(); + return restTemplate.getForEntity(changeUrl, List.class).getBody(); } @Override - public String changeRequestURL(Environment environment, Connection connection) { - String url = this.environmentUrl(environment); + public String changeRequestURL(Connection connection) { return String.format("%s/metadata/%s/%s/requests", url, connection.getProtocol().name(), connection.getManageIdentifier()); } @Override public String changeRequestURLConnectionRequest(EntityType entityType, String manageIdentifier) { - String url = this.environmentUrl(Environment.PROD); return String.format("%s/metadata/%s/%s/requests", url, entityType.name(), manageIdentifier); } @@ -241,11 +212,11 @@ public Map identityProviderByEntityID(String entityID) { Map baseQuery = getBaseQuery(true); baseQuery.put("entityid", entityID); - String url = String.format("%s/manage/api/internal/search/%s", - environmentUrl(activeEnvironment), - EntityType.saml20_idp.name()); - List> identityProviders = environmentRestTemplate(activeEnvironment).postForObject( + String queryUrl = String.format("%s/manage/api/internal/search/%s", url, + EntityType.saml20_idp.name()); + List> identityProviders = restTemplate.postForObject( + queryUrl, baseQuery, List.class); if (identityProviders.isEmpty()) { throw new NotFoundException("No identityProviders found for entityID: " + entityID); @@ -261,11 +232,11 @@ public List> serviceProvidersByEntityID(List entityI baseQuery.put("entityid", entityIdentifiers); return Stream.of(EntityType.oidc10_rp, EntityType.saml20_sp) .flatMap(entityType -> { - String url = String.format("%s/manage/api/internal/search/%s", - environmentUrl(activeEnvironment), - entityType.name()); - List> providers = environmentRestTemplate(activeEnvironment).postForObject( + String queryUrl = String.format("%s/manage/api/internal/search/%s", url, + entityType.name()); + List> providers = restTemplate.postForObject( + queryUrl, baseQuery, List.class); return providers.stream(); @@ -273,38 +244,38 @@ public List> serviceProvidersByEntityID(List entityI } @Override - public List> identityProvidersByInstitutionalGUID(Environment environment, String organisationGUID) { + public List> identityProvidersByInstitutionalGUID(String organisationGUID) { LOG.debug("identityProviderByInstitutionalGUID for : " + organisationGUID); Map baseQuery = getBaseQuery(true); baseQuery.put("metaDataFields.coin:institution_guid", organisationGUID); - String url = String.format("%s/manage/api/internal/search/%s", - environmentUrl(environment), - EntityType.saml20_idp.name()); - return environmentRestTemplate(environment).postForObject( + String queryUrl = String.format("%s/manage/api/internal/search/%s", url, + EntityType.saml20_idp.name()); + return restTemplate.postForObject( + queryUrl, baseQuery, List.class); } @Override - public List> identityProvidersLight(Environment environment) { - LOG.debug("identityProvidersLight for environment: " + environment); + public List> identityProvidersLight() { + LOG.debug("identityProvidersLight"); Map baseQuery = getBaseQuery(false); ((List) baseQuery.get("REQUESTED_ATTRIBUTES")).add("metaDataFields.coin:institution_type"); - String url = String.format("%s/manage/api/internal/search/%s", - environmentUrl(environment), - EntityType.saml20_idp.name()); - return environmentRestTemplate(environment).postForObject( + String queryUrl = String.format("%s/manage/api/internal/search/%s", url, + EntityType.saml20_idp.name()); + return restTemplate.postForObject( + queryUrl, baseQuery, List.class); } @Override - public List> serviceProvidersLight(Environment environment) { - LOG.debug("serviceProvidersLight for environment: " + environment); + public List> serviceProvidersLight() { + LOG.debug("serviceProvidersLight"); Map baseQuery = getBaseQuery(false); List requestedAttributes = (List) baseQuery.get("REQUESTED_ATTRIBUTES"); @@ -313,18 +284,18 @@ public List> serviceProvidersLight(Environment environment) requestedAttributes.add("metaDataFields.coin:ss:idp_visible_only"); requestedAttributes.add("metaDataFields.application_tags"); - String url = String.format("%s/manage/api/internal/search/%s", - environmentUrl(environment), - EntityType.saml20_sp.name()); - List> serviceProviders = environmentRestTemplate(environment).postForObject( + String queryUrl = String.format("%s/manage/api/internal/search/%s", url, + EntityType.saml20_sp.name()); + List> serviceProviders = restTemplate.postForObject( + queryUrl, baseQuery, List.class); - url = String.format("%s/manage/api/internal/search/%s", - environmentUrl(environment), - EntityType.oidc10_rp.name()); - List> relyingParties = environmentRestTemplate(environment).postForObject( + queryUrl = String.format("%s/manage/api/internal/search/%s", url, + EntityType.oidc10_rp.name()); + List> relyingParties = restTemplate.postForObject( + queryUrl, baseQuery, List.class); serviceProviders.addAll(relyingParties); @@ -335,18 +306,14 @@ public List> serviceProvidersLight(Environment environment) public Map stats() { LOG.debug("stats"); - String url = String.format("%s/manage/api/internal/stats", - environmentUrl(Environment.PROD), - EntityType.saml20_idp.name()); - return environmentRestTemplate(Environment.PROD) - .getForEntity(url, Map.class).getBody(); + String statsUrl = String.format("%s/manage/api/internal/stats", url); + return restTemplate.getForEntity(statsUrl, Map.class).getBody(); } @Override public List> identityProvidersByAllowedConnections(List connections) { List> body = connections.stream() .filter(connection -> StringUtils.hasText(connection.getManageIdentifier()) && - connection.getEnvironment().equals(Environment.PROD) && connection.getState().equals(State.prodaccepted)) .map(connection -> Map.of( "id", connection.getManageIdentifier(), @@ -356,10 +323,8 @@ public List> identityProvidersByAllowedConnections(List> policiesByServiceProvider(String identityProvid identityProviderOrCondition ) ); - RestTemplate restTemplate = environmentRestTemplate(Environment.PROD); - String url = String.format("%s/manage/api/internal/rawSearch/%s", - environmentUrl(Environment.PROD), EntityType.policy); - return restTemplate.postForEntity(url, query, List.class).getBody(); + String queryUrl = String.format("%s/manage/api/internal/rawSearch/%s", + url, EntityType.policy); + return restTemplate.postForEntity(queryUrl, query, List.class).getBody(); } @Override @@ -394,68 +358,55 @@ public List> policiesByIdentityProvider(String identityProvi Map query = Map.of( "data.identityProviderIds.name", identityProviderEntityId ); - RestTemplate restTemplate = environmentRestTemplate(Environment.PROD); - String url = String.format("%s/manage/api/internal/rawSearch/%s", - environmentUrl(Environment.PROD), EntityType.policy); - return restTemplate.postForEntity(url, query, List.class).getBody(); + String queryUrl = String.format("%s/manage/api/internal/rawSearch/%s", + url, EntityType.policy); + return restTemplate.postForEntity(queryUrl, query, List.class).getBody(); } @Override public Map createPolicy(Map policy) { - RestTemplate restTemplate = environmentRestTemplate(Environment.PROD); - String url = String.format("%s/manage/api/internal/metadata", - environmentUrl(Environment.PROD)); - return restTemplate.postForEntity(url, policy, Map.class).getBody(); + String policyUrl = String.format("%s/manage/api/internal/metadata", url); + return restTemplate.postForEntity(policyUrl, policy, Map.class).getBody(); } @Override public Map updatePolicy(Map policy) { - RestTemplate restTemplate = environmentRestTemplate(Environment.PROD); - String url = String.format("%s/manage/api/internal/metadata", - environmentUrl(Environment.PROD)); - ResponseEntity> responseEntity = restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(policy), PARAMETERIZED_TYPE_REFERENCE); + String policyUrl = String.format("%s/manage/api/internal/metadata", url); + ResponseEntity> responseEntity = restTemplate.exchange(policyUrl, HttpMethod.PUT, new HttpEntity<>(policy), PARAMETERIZED_TYPE_REFERENCE); return checkNoChangeResponse(responseEntity, policy); } @Override public List> uniquePolicyName(Map properties) { - RestTemplate restTemplate = environmentRestTemplate(Environment.PROD); - String url = String.format("%s/manage/api/internal/uniquePolicyName/policy", - environmentUrl(Environment.PROD)); - return restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(properties), List.class).getBody(); + String policyUrl = String.format("%s/manage/api/internal/uniquePolicyName/policy", url); + return restTemplate.exchange(policyUrl, HttpMethod.POST, new HttpEntity<>(properties), List.class).getBody(); } @Override public List> allowedAttributes() { - RestTemplate restTemplate = environmentRestTemplate(Environment.PROD); - String url = String.format("%s/manage/api/internal/protected/allowed-attributes", - environmentUrl(Environment.PROD)); - return restTemplate.getForObject(url, List.class); + String attrUrl = String.format("%s/manage/api/internal/protected/allowed-attributes", url); + return restTemplate.getForObject(attrUrl, List.class); } @Override public void deletePolicy(Map policy) { - RestTemplate restTemplate = environmentRestTemplate(Environment.PROD); - String url = String.format("%s/manage/api/internal/metadata/%s/%s", - environmentUrl(Environment.PROD), EntityType.policy.name(), policy.get("id")); - restTemplate.delete(url); + String policyUrl = String.format("%s/manage/api/internal/metadata/%s/%s", + url, EntityType.policy.name(), policy.get("id")); + restTemplate.delete(policyUrl); } @Override public Map>> autoCompleteEntities(EntityType type, String query) { - RestTemplate restTemplate = environmentRestTemplate(Environment.PROD); - String url = String.format("%s/manage/api/internal/autocomplete/%s?query=%s", - environmentUrl(Environment.PROD), + String queryUrl = String.format("%s/manage/api/internal/autocomplete/%s?query=%s", + url, type.name(), URLEncoder.encode(query, Charset.defaultCharset())); - return restTemplate.getForObject(url, Map.class); + return restTemplate.getForObject(queryUrl, Map.class); } @Override public void connectWithoutInteraction(Map identityProvider, Map serviceProvider, User user) { - RestTemplate restTemplate = environmentRestTemplate(Environment.PROD); - String url = String.format("%s/manage/api/internal/connectWithoutInteraction", - environmentUrl(Environment.PROD)); + String connectUrl = String.format("%s/manage/api/internal/connectWithoutInteraction", url); Map bodyMap = new HashMap<>(); bodyMap.put("idpId", (String) getData(identityProvider).get("entityid")); bodyMap.put("spId", (String) getData(serviceProvider).get("entityid")); @@ -463,13 +414,13 @@ public void connectWithoutInteraction(Map identityProvider, Map< bodyMap.put("user", user.getName()); bodyMap.put("userUrn", user.getSub()); //Fire and forget. An exception will be thrown by the restTemplate if the return is not 20X - restTemplate.put(url, bodyMap); + restTemplate.put(connectUrl, bodyMap); } - private List> getRemoteMetaData(Environment environment, String type, boolean allAttributes) { + private List> getRemoteMetaData(String type, boolean allAttributes) { Map baseQuery = getBaseQuery(allAttributes); - String url = String.format("%s/manage/api/internal/search/%s", environmentUrl(environment), type); - return environmentRestTemplate(environment).postForObject(url, baseQuery, List.class); + String queryUrl = String.format("%s/manage/api/internal/search/%s", url, type); + return restTemplate.postForObject(queryUrl, baseQuery, List.class); } private Map getBaseQuery(boolean allAttributes) { @@ -483,14 +434,6 @@ private Map getBaseQuery(boolean allAttributes) { return baseQuery; } - private String environmentUrl(Environment environment) { - return environment.equals(Environment.TEST) ? this.testAuthorization.url() : this.productionAuthorization.url(); - } - - private RestTemplate environmentRestTemplate(Environment environment) { - return restTemplates.get(environment); - } - private Map checkNoChangeResponse(ResponseEntity> responseEntity, Map provider) { Map body = responseEntity.getBody(); if (body == null || ResilientErrorHandler.ignoreError(body)) { diff --git a/server/src/main/java/access/model/Connection.java b/server/src/main/java/access/model/Connection.java index f6b0391e..6876804d 100644 --- a/server/src/main/java/access/model/Connection.java +++ b/server/src/main/java/access/model/Connection.java @@ -62,11 +62,6 @@ public class Connection implements NameHolder { @NotNull private EntityType protocol = EntityType.oidc10_rp; - @Enumerated(EnumType.STRING) - @Column - @NotNull - private Environment environment = Environment.TEST; - @Enumerated(EnumType.STRING) @Column @NotNull @@ -98,12 +93,11 @@ public class Connection implements NameHolder { @Transient private List> changeRequests = new ArrayList<>(); - public Connection(String name, Application application, Map metaData, EntityType protocol, Environment environment) { + public Connection(String name, Application application, Map metaData, EntityType protocol) { this.name = name; this.application = application; this.metaData = new HashMap<>(metaData); this.protocol = protocol; - this.environment = environment; this.createdAt = Instant.now(); this.updatedAt = Instant.now(); this.manageVersion = 0; @@ -134,7 +128,6 @@ public void merge(Connection connectionData) { this.name = connectionData.name; this.metaData = connectionData.metaData; this.protocol = connectionData.protocol; - this.environment = connectionData.environment; this.status = connectionData.status; } @@ -191,12 +184,11 @@ public boolean mergeMetaData(Map provider, boolean force) { .getOrDefault("coin:dashboard_connect_option", ConnectOptions.connect_with_interaction.name()); this.metaData.put("connectOption", connectOption); /* - * Business logic. If a status for a production connection is pending production and the state has changed + * Business logic. If a connection status is pending production and the state has changed * to prodaccepted, then we set the status to production ready */ this.state = State.valueOf((String) data.getOrDefault("state", "testaccepted")); - if (this.environment.equals(Environment.PROD) && - ConnectionStatus.PENDING_PROD.equals(this.status) && + if (ConnectionStatus.PENDING_PROD.equals(this.status) && this.state.equals(State.prodaccepted)) { this.status = ConnectionStatus.PROD_READY; } @@ -212,10 +204,14 @@ public void updateRemoteManageData(Map provider) { this.state = State.valueOf((String) data.getOrDefault("state", "testaccepted")); } + @JsonIgnore + public boolean isProductionConnection() { + return this.status.equals(ConnectionStatus.PENDING_PROD) || this.status.equals(ConnectionStatus.PROD_READY); + } + @JsonIgnore public boolean changeRequestRequired() { - return this.environment.equals(Environment.PROD) && - this.status.equals(ConnectionStatus.PROD_READY); + return this.status.equals(ConnectionStatus.PROD_READY); } @PreUpdate diff --git a/server/src/main/java/access/model/Environment.java b/server/src/main/java/access/model/Environment.java deleted file mode 100644 index 62b930e9..00000000 --- a/server/src/main/java/access/model/Environment.java +++ /dev/null @@ -1,6 +0,0 @@ -package access.model; - -public enum Environment { - - TEST, PROD -} diff --git a/server/src/main/java/access/security/CustomOidcUserService.java b/server/src/main/java/access/security/CustomOidcUserService.java index 6b85bf29..1f89e255 100644 --- a/server/src/main/java/access/security/CustomOidcUserService.java +++ b/server/src/main/java/access/security/CustomOidcUserService.java @@ -1,7 +1,6 @@ package access.security; import access.manage.Manage; -import access.model.Environment; import access.model.Institution; import access.model.User; import access.repository.UserRepository; @@ -68,7 +67,7 @@ public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2Authenticatio if (institutionAdmin && StringUtils.hasText(organizationGuid)) { String authenticatingAuthority = (String) claims.get("authenticating_authority"); - List> identityProviders = manage.identityProvidersByInstitutionalGUID(Environment.PROD, organizationGuid); + List> identityProviders = manage.identityProvidersByInstitutionalGUID(organizationGuid); //If there are multiple identityProviders with the same organizationGuid, we pick the one that was used to login Optional> optionalIdentityProvider = identityProviders.isEmpty() ? Optional.empty() : Optional.of(identityProviders.stream() diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml index 2ff2c5cd..42778440 100644 --- a/server/src/main/resources/application.yml +++ b/server/src/main/resources/application.yml @@ -159,20 +159,11 @@ email: manage: enabled: True # enabled: False - # which manage environment do we use the fetch the identity provider of the user, either TEST or PROD - activeManage: TEST - test: - url: "https://manage.test2.surfconext.nl" -# url: "http://localhost:8081" - user: openconextaccess - password: secret - defaultState: prodaccepted - prod: - url: "https://manage.test2.surfconext.nl" -# url: "http://localhost:8081" - user: openconextaccess - password: secret - defaultState: testaccepted + url: "https://manage.test2.surfconext.nl" +# url: "http://localhost:8081" + user: openconextaccess + password: secret + defaultState: prodaccepted # If manage is disabled (e.g. enabled: False) the staticManageDirectory is the directory where the {metadata_type}.json files # are located. This can also be an absolute file path, e.g. file:///opt/openconext/invite/manage staticManageDirectory: classpath:/manage diff --git a/server/src/main/resources/db/mysql/migration/V14_0__drop_connection_environment.sql b/server/src/main/resources/db/mysql/migration/V14_0__drop_connection_environment.sql new file mode 100644 index 00000000..f1c1787e --- /dev/null +++ b/server/src/main/resources/db/mysql/migration/V14_0__drop_connection_environment.sql @@ -0,0 +1 @@ +ALTER TABLE `connections` DROP COLUMN `environment`; diff --git a/server/src/test/java/access/AbstractMailTest.java b/server/src/test/java/access/AbstractMailTest.java index 678bcd12..4212056b 100644 --- a/server/src/test/java/access/AbstractMailTest.java +++ b/server/src/test/java/access/AbstractMailTest.java @@ -26,9 +26,8 @@ "spring.security.oauth2.client.provider.oidcng.token-uri=http://localhost:8081/token", "spring.security.oauth2.client.provider.oidcng.user-info-uri=http://localhost:8081/user-info", "spring.security.oauth2.client.provider.oidcng.jwk-set-uri=http://localhost:8081/jwk-set", - "manage.test.url=http://localhost:8081", + "manage.url=http://localhost:8081", "manage.enabled=true", - "manage.prod.url=http://localhost:8081", "jira.enabled=false", "s3storage.url=http://localhost:8081" }) diff --git a/server/src/test/java/access/AbstractTest.java b/server/src/test/java/access/AbstractTest.java index 771e495e..09d7ef99 100644 --- a/server/src/test/java/access/AbstractTest.java +++ b/server/src/test/java/access/AbstractTest.java @@ -82,9 +82,8 @@ "spring.security.oauth2.client.provider.oidcng.token-uri=http://localhost:8081/token", "spring.security.oauth2.client.provider.oidcng.user-info-uri=http://localhost:8081/user-info", "spring.security.oauth2.client.provider.oidcng.jwk-set-uri=http://localhost:8081/jwk-set", - "manage.test.url=http://localhost:8081", + "manage.url=http://localhost:8081", "manage.enabled=true", - "manage.prod.url=http://localhost:8081", "jira.enabled=false", "s3storage.url=http://localhost:8081", "invite.enabled=true", @@ -182,7 +181,7 @@ protected void beforeEach() throws Exception { this.doSeed(); } if (this.localManage == null) { - ConnectionProviderConverter converter = new ConnectionProviderConverter(objectMapper, State.testaccepted, State.prodaccepted); + ConnectionProviderConverter converter = new ConnectionProviderConverter(objectMapper, State.testaccepted); this.localManage = new LocalManage(converter, objectMapper, staticManageDirectory); } } @@ -452,8 +451,8 @@ protected void stubForGetProvider(Connection connection) { } @SneakyThrows - protected Map stubForGetProvider(EntityType entityType, String manageIdentifier, Environment environment) { - Map provider = localManage.providerByManageIdentifier(entityType, manageIdentifier, environment); + protected Map stubForGetProvider(EntityType entityType, String manageIdentifier) { + Map provider = localManage.providerByManageIdentifier(entityType, manageIdentifier); String body = objectMapper.writeValueAsString(provider); stubFor(get(String.format("/manage/api/internal/metadata/%s/%s", entityType.name(), @@ -465,9 +464,9 @@ protected Map stubForGetProvider(EntityType entityType, String m } @SneakyThrows - protected Map stubForGetProvider(EntityType entityType, String manageIdentifier, Environment environment, + protected Map stubForGetProvider(EntityType entityType, String manageIdentifier, String actualManageIdentifier) { - Map provider = localManage.providerByManageIdentifier(entityType, actualManageIdentifier, environment); + Map provider = localManage.providerByManageIdentifier(entityType, actualManageIdentifier); String body = objectMapper.writeValueAsString(provider); stubFor(get(String.format("/manage/api/internal/metadata/%s/%s", entityType.name(), @@ -506,7 +505,7 @@ protected void stubForStats() { @SneakyThrows protected void stubForIdentityProviderByInstitutionalGUID(String organisationGuid) { - List> providers = localManage.identityProvidersByInstitutionalGUID(Environment.PROD, organisationGuid); + List> providers = localManage.identityProvidersByInstitutionalGUID(organisationGuid); String body = objectMapper.writeValueAsString(providers); stubFor(post(urlPathMatching("/manage/api/internal/search/saml20_idp")) .willReturn(aResponse() @@ -529,7 +528,7 @@ protected Map stubForIdentityProviderByEntityId(String entityId) @SneakyThrows protected void stubForIdentityProviders() { - List> providers = localManage.providers(Environment.TEST, EntityType.saml20_idp); + List> providers = localManage.providers(EntityType.saml20_idp); String body = objectMapper.writeValueAsString(providers); stubFor(post(urlPathMatching("/manage/api/internal/search/saml20_idp")) .willReturn(aResponse().withHeader("Content-Type", "application/json") @@ -561,8 +560,8 @@ protected void stubForPolicyByIdentityProvider(String identityProviderEntityId) @SneakyThrows protected void stubForServiceProviders() { - List> providers = localManage.providers(Environment.TEST, EntityType.saml20_sp); - List> relyingParties = localManage.providers(Environment.TEST, EntityType.oidc10_rp); + List> providers = localManage.providers(EntityType.saml20_sp); + List> relyingParties = localManage.providers(EntityType.oidc10_rp); String body = objectMapper.writeValueAsString(providers); stubFor(post(urlPathMatching("/manage/api/internal/search/saml20_sp")) .willReturn(aResponse().withHeader("Content-Type", "application/json") @@ -579,7 +578,6 @@ protected Connection connection(EntityType entityType, String manageIdentifier) Connection connection = new Connection(); connection.setManageIdentifier(manageIdentifier); connection.setProtocol(entityType); - connection.setEnvironment(Environment.PROD); connection.setState(State.prodaccepted); return connection; } @@ -643,8 +641,7 @@ private void doSeed() { List.of(Map.of("value", "*", "source", "idp", "motivation", "Default for profile")) ), "motivation", "Please")), - EntityType.oidc10_rp, - Environment.TEST); + EntityType.oidc10_rp); Connection buddyCheckConnectionProd = new Connection(BUDDY_CHECK_PROD, buddyCheck, Map.of( "contactPersons", List.of(new Contact("technical", "John", "Doe", "jdoe@example.com")), "entityID", "https://engine.test.surfconext.nl", @@ -657,8 +654,7 @@ private void doSeed() { List.of(Map.of("value", "*", "source", "idp", "motivation", "Default for profile")) ), "motivation", "Please")), - EntityType.oidc10_rp, - Environment.PROD); + EntityType.oidc10_rp); //Need to mimic a pending production connection buddyCheckConnectionProd.setManageIdentifier(MANAGE_IDENTIFIER); buddyCheckConnectionProd.setManageVersion(1); diff --git a/server/src/test/java/access/api/ApplicationControllerTest.java b/server/src/test/java/access/api/ApplicationControllerTest.java index 1f92e785..9b56c2e5 100644 --- a/server/src/test/java/access/api/ApplicationControllerTest.java +++ b/server/src/test/java/access/api/ApplicationControllerTest.java @@ -8,7 +8,6 @@ import access.model.Connection; import access.model.ConnectionStatus; import access.model.EntityType; -import access.model.Environment; import access.model.ImportEntityRequest; import access.model.MigrateApplicationRequest; import access.model.Organization; @@ -199,7 +198,7 @@ void updateMetaDataChanged() { applicationData.put("organization", Map.of("id", organization.getId())); //The details of the connections are retrieved - super.stubForGetProvider(EntityType.oidc10_rp, MANAGE_IDENTIFIER, Environment.PROD, "5"); + super.stubForGetProvider(EntityType.oidc10_rp, MANAGE_IDENTIFIER, "5"); Connection connectionProd = connectionRepository.findById(seedIdentifiers.get(BUDDY_CHECK_PROD)).get(); connectionProd.setManageIdentifier("5"); super.stubForSaveProvider(connectionProd); @@ -334,7 +333,7 @@ void migrate() { seedIdentifiers.get(BUDDY_CHECK), seedIdentifiers.get(FAR_WIND) ); - stubForGetProvider(EntityType.oidc10_rp, MANAGE_IDENTIFIER, Environment.PROD, "5"); + stubForGetProvider(EntityType.oidc10_rp, MANAGE_IDENTIFIER, "5"); Connection connectionProd = connectionRepository.findById(seedIdentifiers.get(BUDDY_CHECK_PROD)).get(); connectionProd.setManageIdentifier("5"); super.stubForSaveProvider(connectionProd); @@ -359,7 +358,7 @@ void migrate() { void importEntity() { AccessCookieFilter accessCookieFilter = mockLoginFlow(SUPER_SUB); - Map provider = localManage.providerByManageIdentifier(EntityType.oidc10_rp, "10", Environment.PROD); + Map provider = localManage.providerByManageIdentifier(EntityType.oidc10_rp, "10"); ImportEntityRequest importEntityRequest = new ImportEntityRequest( seedIdentifiers.get(FAR_WIND), null, @@ -388,7 +387,7 @@ void importEntity() { void importEntityExistingApplication() { AccessCookieFilter accessCookieFilter = mockLoginFlow(SUPER_SUB); - Map provider = localManage.providerByManageIdentifier(EntityType.oidc10_rp, "10", Environment.PROD); + Map provider = localManage.providerByManageIdentifier(EntityType.oidc10_rp, "10"); ImportEntityRequest importEntityRequest = new ImportEntityRequest( seedIdentifiers.get(FAR_WIND), seedIdentifiers.get(NITRO_MAP), diff --git a/server/src/test/java/access/api/ConnectionControllerTest.java b/server/src/test/java/access/api/ConnectionControllerTest.java index 5bb6a4bd..ef9f5c13 100644 --- a/server/src/test/java/access/api/ConnectionControllerTest.java +++ b/server/src/test/java/access/api/ConnectionControllerTest.java @@ -7,7 +7,6 @@ import access.model.Connection; import access.model.ConnectionStatus; import access.model.EntityType; -import access.model.Environment; import access.model.GrantType; import access.model.State; import com.fasterxml.jackson.core.JsonProcessingException; @@ -44,7 +43,7 @@ void create() { "grantTypes", List.of("authorization_code") ); - Connection connection = new Connection("New Connection", application, metaData, EntityType.oidc10_rp, Environment.TEST); + Connection connection = new Connection("New Connection", application, metaData, EntityType.oidc10_rp); //Otherwise rest-assured does not deserialize the Application Map connectionData = objectMapper.convertValue(connection, new TypeReference<>() { }); @@ -74,7 +73,7 @@ void createInvalid() { "grants", List.of("authorization_code") ); - Connection connection = new Connection("New Connection", application, metaData, EntityType.oidc10_rp, Environment.TEST); + Connection connection = new Connection("New Connection", application, metaData, EntityType.oidc10_rp); //Otherwise rest-assured does not deserialize the Application Map connectionData = objectMapper.convertValue(connection, new TypeReference<>() { }); @@ -177,7 +176,7 @@ void updateAndCreateChangeRequest() { redirectUrls.add("https://redirect.nl"); metaData.put("claimsInIdToken", true); - Map provider = localManage.providerByManageIdentifier(EntityType.oidc10_rp, "10", Environment.PROD); + Map provider = localManage.providerByManageIdentifier(EntityType.oidc10_rp, "10"); metaData.put("arp", ManageData.getData(provider).get("arp")); //Otherwise rest-assured does not deserialize the Application @@ -239,7 +238,7 @@ void updateAndCreateChangeRequestWithArp() { redirectUrls.add("https://redirect.nl"); metaData.put("claimsInIdToken", true); - Map provider = localManage.providerByManageIdentifier(EntityType.oidc10_rp, "10", Environment.PROD); + Map provider = localManage.providerByManageIdentifier(EntityType.oidc10_rp, "10"); metaData.put("arp", ManageData .getData(provider).get("arp")); //Otherwise rest-assured does not deserialize the Application diff --git a/server/src/test/java/access/api/IdentityProviderControllerTest.java b/server/src/test/java/access/api/IdentityProviderControllerTest.java index 78f09bda..4ba3bd11 100644 --- a/server/src/test/java/access/api/IdentityProviderControllerTest.java +++ b/server/src/test/java/access/api/IdentityProviderControllerTest.java @@ -37,8 +37,8 @@ void memberConnectionRequest() { "Connect..." ); //Need to stub manage calls for SP and IdP retrieval - super.stubForGetProvider(EntityType.saml20_sp, "3", Environment.PROD); - super.stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + super.stubForGetProvider(EntityType.saml20_sp, "3"); + super.stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier()); given() .when() @@ -74,8 +74,8 @@ void memberConnectionRequestSuperUserRecipientFallback() { "Connect..." ); //Need to stub manage calls for SP and IdP retrieval - super.stubForGetProvider(EntityType.saml20_sp, "3", Environment.PROD); - super.stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + super.stubForGetProvider(EntityType.saml20_sp, "3"); + super.stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier()); given() .when() @@ -107,8 +107,8 @@ void memberConnectionRequestNotAllowed() { "Connect..." ); //Need to stub manage calls for SP and IdP retrieval - super.stubForGetProvider(EntityType.saml20_sp, "3", Environment.PROD); - super.stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + super.stubForGetProvider(EntityType.saml20_sp, "3"); + super.stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier()); given() .when() @@ -155,8 +155,8 @@ void adminConnectionRequest() { "Connect..." ); //Need to stub manage calls for SP and IdP retrieval - super.stubForGetProvider(EntityType.saml20_sp, "3", Environment.PROD); - super.stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + super.stubForGetProvider(EntityType.saml20_sp, "3"); + super.stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier()); /// Stub for POST new change request Map manageResponse = Map.of("id", "1"); @@ -189,8 +189,8 @@ void adminConnectionRequestNoInteractionWithEmail() { "Connect..." ); //Need to stub manage calls for SP and IdP retrieval - see src/main/resources/manage/*.json - super.stubForGetProvider(EntityType.oidc10_rp, "5", Environment.PROD); - super.stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + super.stubForGetProvider(EntityType.oidc10_rp, "5"); + super.stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier()); /// Stub for POST connectWithoutInteraction stubFor(put(urlPathMatching("/manage/api/internal/connectWithoutInteraction")).willReturn(aResponse() @@ -229,8 +229,8 @@ void adminConnectionRequestNoInteractionWithoutEmail() { "Connect..." ); //Need to stub manage calls for SP and IdP retrieval - see src/main/resources/manage/*.json - super.stubForGetProvider(EntityType.oidc10_rp, "6", Environment.PROD); - super.stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + super.stubForGetProvider(EntityType.oidc10_rp, "6"); + super.stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier()); /// Stub for POST connectWithoutInteraction stubFor(put(urlPathMatching("/manage/api/internal/connectWithoutInteraction")).willReturn(aResponse() @@ -263,8 +263,8 @@ void adminDisconnectionRequest() { "Connect..." ); //Need to stub manage calls for SP and IdP retrieval - super.stubForGetProvider(EntityType.saml20_sp, "3", Environment.PROD); - super.stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + super.stubForGetProvider(EntityType.saml20_sp, "3"); + super.stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier()); /// Stub for POST new change request Map manageResponse = Map.of("id", "1"); @@ -297,8 +297,8 @@ void cancelConnectionRequest() { "Connect..." ); //Need to stub manage calls for SP and IdP retrieval - Map provider = super.stubForGetProvider(EntityType.saml20_sp, "3", Environment.PROD); - super.stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + Map provider = super.stubForGetProvider(EntityType.saml20_sp, "3"); + super.stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier()); /// Stub for GET all change requests ChangeRequest changeRequest = new ChangeRequest( UUID.randomUUID().toString(), @@ -336,8 +336,8 @@ void cancelDisconnectionRequest() { "Connect..." ); //Need to stub manage calls for SP and IdP retrieval - Map provider = super.stubForGetProvider(EntityType.saml20_sp, "3", Environment.PROD); - super.stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + Map provider = super.stubForGetProvider(EntityType.saml20_sp, "3"); + super.stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier()); /// Stub for GET all change requests ChangeRequest changeRequest = new ChangeRequest( UUID.randomUUID().toString(), diff --git a/server/src/test/java/access/api/InviteControllerTest.java b/server/src/test/java/access/api/InviteControllerTest.java index 353c37ec..9b04a722 100644 --- a/server/src/test/java/access/api/InviteControllerTest.java +++ b/server/src/test/java/access/api/InviteControllerTest.java @@ -3,7 +3,6 @@ import access.AbstractTest; import access.AccessCookieFilter; import access.model.EntityType; -import access.model.Environment; import access.model.Organization; import com.fasterxml.jackson.core.type.TypeReference; import io.restassured.common.mapper.TypeRef; @@ -224,7 +223,7 @@ void rolesSummary() { AccessCookieFilter accessCookieFilter = openIDConnectFlow("/api/v1/users/me", SUPER_SUB); Organization organization = organizationRepository.findById(seedIdentifiers.get(SHARE_LOGICS)).get(); - stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier()); List> roles = given() .when() .filter(accessCookieFilter.cookieFilter()) diff --git a/server/src/test/java/access/api/ManageControllerTest.java b/server/src/test/java/access/api/ManageControllerTest.java index ce4d2e46..b707c5e2 100644 --- a/server/src/test/java/access/api/ManageControllerTest.java +++ b/server/src/test/java/access/api/ManageControllerTest.java @@ -3,7 +3,7 @@ import access.AbstractTest; import access.AccessCookieFilter; import access.model.EntityType; -import access.model.Environment; +import access.model.EntityType; import access.model.Organization; import access.security.InstitutionAdmin; import com.fasterxml.jackson.core.JsonProcessingException; @@ -91,8 +91,7 @@ void identityProviders() { .filter(accessCookieFilter.cookieFilter()) .accept(ContentType.JSON) .contentType(ContentType.JSON) - .pathParam("environment", Environment.TEST) - .get("/api/v1/manage/identity-providers/{environment}") + .get("/api/v1/manage/identity-providers") .as(new TypeRef<>() { }); assertEquals(3, identityProviders.size()); @@ -132,7 +131,7 @@ void policyByServiceProvider() { //Stub the actual call to fetch the policies for a SP this.stubForPolicyByServiceProvider("http://mock-idp", serviceProviderEntityId); //The IdP is fetched to check the allowed entities - this.stubForGetProvider(EntityType.saml20_idp, "7", Environment.PROD); + this.stubForGetProvider(EntityType.saml20_idp, "7"); Organization organization = organizationRepository.findById(seedIdentifiers.get(SHARE_LOGICS)).get(); List> policies = given() @@ -157,7 +156,7 @@ void policyByIdentityProvider() { Organization organization = organizationRepository.findById(seedIdentifiers.get(SHARE_LOGICS)).get(); //Stub the actual call to fetch the policies for a IdP - this.stubForGetProvider(EntityType.saml20_idp, "7", Environment.PROD); + this.stubForGetProvider(EntityType.saml20_idp, "7"); this.stubForPolicyByIdentityProvider("http://mock-idp"); List> policies = given() @@ -184,7 +183,7 @@ void policyByServiceProviderNotAllowed() { String serviceProviderEntityId = "nope"; //The IdP is fetched to check the allowed entities - this.stubForGetProvider(EntityType.saml20_idp, "7", Environment.PROD); + this.stubForGetProvider(EntityType.saml20_idp, "7"); Organization organization = organizationRepository.findById(seedIdentifiers.get(SHARE_LOGICS)).get(); given() @@ -205,7 +204,7 @@ void policyByServiceProviderNotAllowed() { void uniqueEntityId() { AccessCookieFilter accessCookieFilter = mockLoginFlow(MANAGE_SUB); String entityID = "https://network"; - List> providers = localManage.uniqueEntityId(Environment.TEST, EntityType.saml20_idp, entityID); + List> providers = localManage.uniqueEntityId(EntityType.saml20_idp, entityID); String body = objectMapper.writeValueAsString(providers); stubFor(post(urlPathMatching("/manage/api/internal/uniqueEntityId/saml20_sp")) .willReturn(aResponse().withHeader("Content-Type", "application/json") @@ -217,9 +216,8 @@ void uniqueEntityId() { .filter(accessCookieFilter.cookieFilter()) .accept(ContentType.JSON) .contentType(ContentType.JSON) - .pathParam("environment", Environment.TEST) .body(Map.of("entityID", entityID)) - .post("/api/v1/manage/unique-entity-id/{environment}") + .post("/api/v1/manage/unique-entity-id") .as(new TypeRef<>() { }); assertEquals(1, serviceProviders.size()); @@ -328,9 +326,9 @@ void uniquePolicyName() throws Exception { void updatePolicy() throws Exception { AccessCookieFilter accessCookieFilter = openIDConnectFlow("/api/v1/users/me", ADMIN_SUB); - Map policyFromDB = super.stubForGetProvider(EntityType.policy, "1", Environment.PROD); + Map policyFromDB = super.stubForGetProvider(EntityType.policy, "1"); Organization organization = organizationRepository.findById(seedIdentifiers.get(SHARE_LOGICS)).get(); - stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier()); stubFor(put(urlPathMatching("/manage/api/internal/metadata")) .willReturn(aResponse().withHeader("Content-Type", "application/json") @@ -356,9 +354,9 @@ void deletePolicy() throws Exception { AccessCookieFilter accessCookieFilter = openIDConnectFlow("/api/v1/users/me", ADMIN_SUB); // See server/src/main/resources/manage/policy.json String manageIdentifier = "1"; - super.stubForGetProvider(EntityType.policy, "1", Environment.PROD); + super.stubForGetProvider(EntityType.policy, "1"); Organization organization = organizationRepository.findById(seedIdentifiers.get(SHARE_LOGICS)).get(); - stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD); + stubForGetProvider(EntityType.saml20_idp, organization.getManageIdentifier()); String url = String.format("/manage/api/internal/metadata/%s/%s", EntityType.policy.name(), manageIdentifier); diff --git a/server/src/test/java/access/api/OrganizationControllerTest.java b/server/src/test/java/access/api/OrganizationControllerTest.java index 7382ecc5..2faf6580 100644 --- a/server/src/test/java/access/api/OrganizationControllerTest.java +++ b/server/src/test/java/access/api/OrganizationControllerTest.java @@ -322,7 +322,7 @@ void mineOrganizationWithIdentityProvider() { AccessCookieFilter accessCookieFilter = mockLoginFlow(MANAGE_SUB); //See seed for SHARE_LOGICS, which has a manage identifier of "7" - stubForGetProvider(EntityType.saml20_idp, "7", Environment.PROD); + stubForGetProvider(EntityType.saml20_idp, "7"); Map organization = given() .when() @@ -366,7 +366,7 @@ void organizationWithApplications() { Map buddyCheckApp = applications.stream().filter(app -> app.get("name").equals(BUDDY_CHECK)) .findFirst().get(); List> connections = (List>) buddyCheckApp.get("connections"); - Map buddyCheckProd = connections.stream().filter(conn -> conn.get("environment").equals(Environment.PROD.name())) + Map buddyCheckProd = connections.stream().filter(conn -> conn.get("status").equals(ConnectionStatus.PENDING_PROD.name())) .findFirst().get(); List> changeRequests = (List>) buddyCheckProd.get("changeRequests"); assertEquals(2, changeRequests.size()); @@ -476,7 +476,7 @@ void updateInternalOrganizationMetaData() { Long organizationId = seedIdentifiers.get(LOGISTICS); Map metaData = objectMapper.readValue(new ClassPathResource("/client-metadata/update-organization.json").getInputStream(), Map.class); - stubForGetProvider(EntityType.saml20_idp, "8", Environment.PROD); + stubForGetProvider(EntityType.saml20_idp, "8"); stubFor(put(urlPathMatching("/manage/api/internal/metadata")) .willReturn(aResponse().withHeader("Content-Type", "application/json") .withBody("{}") diff --git a/server/src/test/java/access/api/PublicControllerTest.java b/server/src/test/java/access/api/PublicControllerTest.java index 398d850e..0f440fa8 100644 --- a/server/src/test/java/access/api/PublicControllerTest.java +++ b/server/src/test/java/access/api/PublicControllerTest.java @@ -3,7 +3,6 @@ import access.AbstractTest; import access.AccessCookieFilter; import access.model.EntityType; -import access.model.Environment; import io.restassured.common.mapper.TypeRef; import io.restassured.http.ContentType; import lombok.SneakyThrows; @@ -85,7 +84,7 @@ void identityProviders() { @SneakyThrows @Test void serviceProviderDetail() { - Map provider = localManage.providerByManageIdentifier(EntityType.saml20_sp, "1", Environment.PROD); + Map provider = localManage.providerByManageIdentifier(EntityType.saml20_sp, "1"); String body = objectMapper.writeValueAsString(provider); stubFor(get(String.format("/manage/api/internal/metadata/%s/%s", EntityType.saml20_sp.name(), diff --git a/server/src/test/java/access/api/UserControllerTest.java b/server/src/test/java/access/api/UserControllerTest.java index 1c367e7e..befd5495 100644 --- a/server/src/test/java/access/api/UserControllerTest.java +++ b/server/src/test/java/access/api/UserControllerTest.java @@ -5,7 +5,6 @@ import access.UserInfoEnhancer; import access.model.Authority; import access.model.EntityType; -import access.model.Environment; import access.model.Institution; import access.model.Organization; import access.model.OrganizationMembership; @@ -118,7 +117,7 @@ void meManagerWithMockLogin() { void swichOrganizationManagerWithMockLogin() { AccessCookieFilter accessCookieFilter = mockLoginFlow(MANAGE_SUB); - super.stubForGetProvider(EntityType.saml20_idp, "7", Environment.PROD); + super.stubForGetProvider(EntityType.saml20_idp, "7"); super.stubForGetChangeRequests(getChangeRequests()); User user = given() diff --git a/server/src/test/java/access/manage/ConnectionProviderConverterTest.java b/server/src/test/java/access/manage/ConnectionProviderConverterTest.java index e9f78888..7dae6ae0 100644 --- a/server/src/test/java/access/manage/ConnectionProviderConverterTest.java +++ b/server/src/test/java/access/manage/ConnectionProviderConverterTest.java @@ -43,7 +43,7 @@ void deduceChangeRequests() { Optional changeRequestOptional = connectionProviderConverter.deduceChangeRequests(connection, provider); assertTrue(changeRequestOptional.isPresent()); ChangeRequest changeRequest = changeRequestOptional.get(); - assertEquals(18, changeRequest.getPathUpdates().size()); + assertEquals(19, changeRequest.getPathUpdates().size()); } @SneakyThrows diff --git a/server/src/test/java/access/manage/PolicyAccessRightsTest.java b/server/src/test/java/access/manage/PolicyAccessRightsTest.java index 7d3eb7ff..2a87d779 100644 --- a/server/src/test/java/access/manage/PolicyAccessRightsTest.java +++ b/server/src/test/java/access/manage/PolicyAccessRightsTest.java @@ -2,7 +2,6 @@ import access.exception.UserRestrictionException; import access.model.EntityType; -import access.model.Environment; import access.model.Organization; import access.model.User; import org.jspecify.annotations.NonNull; @@ -34,7 +33,7 @@ void confirmPolicyAccess() { Organization organization = getOrganization(); - when(manage.providerByManageIdentifier(EntityType.saml20_idp, organization.getManageIdentifier(), Environment.PROD)) + when(manage.providerByManageIdentifier(EntityType.saml20_idp, organization.getManageIdentifier())) .thenReturn(this.identityProvider()); //The IdP of the Policy is not the same as the IdP of the User @@ -47,7 +46,7 @@ void confirmPolicyAccess() { policyDefinition.setIdentityProviderIds(List.of(new PolicyProvider(user.getAuthenticatingAuthority()))); policyDefinition.setServiceProviderIds(List.of(new PolicyProvider(policySPIdentifier))); - when(manage.providerByManageIdentifier(EntityType.saml20_idp, organization.getManageIdentifier(),Environment.PROD)) + when(manage.providerByManageIdentifier(EntityType.saml20_idp, organization.getManageIdentifier())) .thenReturn(this.identityProvider(policySPIdentifier)); policyAccessRights.confirmPolicyAccess(user, policyDefinition, manage, organization); } diff --git a/server/src/test/java/access/manage/RemoteManageTest.java b/server/src/test/java/access/manage/RemoteManageTest.java index a78d6b63..dd2346ab 100644 --- a/server/src/test/java/access/manage/RemoteManageTest.java +++ b/server/src/test/java/access/manage/RemoteManageTest.java @@ -3,7 +3,6 @@ import access.AbstractTest; import access.model.Connection; import access.model.EntityType; -import access.model.Environment; import access.model.State; import com.fasterxml.jackson.core.JsonProcessingException; import lombok.SneakyThrows; @@ -32,12 +31,12 @@ protected boolean seedDatabase() { @Test void providers() throws JsonProcessingException { - List> serviceProviders = localManage.providers(Environment.TEST, EntityType.saml20_sp); + List> serviceProviders = localManage.providers(EntityType.saml20_sp); String body = objectMapper.writeValueAsString(serviceProviders); stubFor(post(urlPathMatching("/manage/api/internal/search/saml20_sp")).willReturn(aResponse() .withHeader("Content-Type", "application/json") .withBody(body))); - List> remoteServiceProviders = manage.providers(Environment.TEST, EntityType.saml20_sp); + List> remoteServiceProviders = manage.providers(EntityType.saml20_sp); assertEquals(4, remoteServiceProviders.size()); } @@ -78,14 +77,14 @@ void providerByConnectionExceptionHandling() throws JsonProcessingException { @Test void identityProvidersLight() throws JsonProcessingException { - List> identityProviders = localManage.providers(Environment.TEST, EntityType.saml20_idp); + List> identityProviders = localManage.providers(EntityType.saml20_idp); String body = objectMapper.writeValueAsString(identityProviders); stubFor(post(urlPathMatching("/manage/api/internal/search/saml20_idp")).willReturn(aResponse() .withHeader("Content-Type", "application/json") .withBody(body))); - List> remoteIdentityProviders = manage.identityProvidersLight(Environment.TEST); + List> remoteIdentityProviders = manage.identityProvidersLight(); assertEquals(3, remoteIdentityProviders.size()); } diff --git a/server/src/test/java/access/stats/StatisticsMockTest.java b/server/src/test/java/access/stats/StatisticsMockTest.java index b28f027b..b14df96f 100644 --- a/server/src/test/java/access/stats/StatisticsMockTest.java +++ b/server/src/test/java/access/stats/StatisticsMockTest.java @@ -13,7 +13,7 @@ class StatisticsMockTest { private final ObjectMapper objectMapper = new ObjectMapper(); - private final StatisticsMock statistics = new StatisticsMock(new LocalManage(new ConnectionProviderConverter(objectMapper, State.testaccepted, State.prodaccepted), + private final StatisticsMock statistics = new StatisticsMock(new LocalManage(new ConnectionProviderConverter(objectMapper, State.testaccepted), objectMapper, "classpath:/manage")); @Test From a5f518c53f941b78a488fc5b087397b0a2cec5cb Mon Sep 17 00:00:00 2001 From: Okke Harsta Date: Sat, 11 Apr 2026 15:40:17 +0200 Subject: [PATCH 2/4] Eslint fix --- .gitignore | 3 ++- client/src/pages/Connection.jsx | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 80987ae1..8bd91e2e 100644 --- a/.gitignore +++ b/.gitignore @@ -50,4 +50,5 @@ jira.yml spieldata PlayGroundTest.java LOCAL_USERS.md -.opencode \ No newline at end of file +.opencode +security.MD diff --git a/client/src/pages/Connection.jsx b/client/src/pages/Connection.jsx index e5880dcb..c7877966 100644 --- a/client/src/pages/Connection.jsx +++ b/client/src/pages/Connection.jsx @@ -231,9 +231,7 @@ export const Connection = () => {
({ name: name, - disabled: - (name === "application" && false) || //!testConnectionComplete) || - (name === "contract" && false)//!productionConnectionComplete) + disabled: false }))} application={application} currentTab={currentTab} From fc2141001500e342a739cc623b3a23144fbb1e50 Mon Sep 17 00:00:00 2001 From: Okke Harsta Date: Mon, 13 Apr 2026 16:25:18 +0200 Subject: [PATCH 3/4] WIP for no prod and test --- .../ApplicationConnectionHeader.jsx | 13 +++++----- client/src/connection/ConnectionInstance.jsx | 16 ++++++++++--- client/src/connection/Overview.jsx | 24 ++++++------------- client/src/locale/en.js | 20 ++++++++-------- client/src/pages/Connection.jsx | 6 ++--- client/src/utils/Manage.js | 4 ++++ .../main/java/access/model/Connection.java | 2 +- server/src/main/resources/application.yml | 2 +- 8 files changed, 46 insertions(+), 41 deletions(-) diff --git a/client/src/components/ApplicationConnectionHeader.jsx b/client/src/components/ApplicationConnectionHeader.jsx index 021f842a..82ba77c0 100644 --- a/client/src/components/ApplicationConnectionHeader.jsx +++ b/client/src/components/ApplicationConnectionHeader.jsx @@ -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({}); @@ -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); + }) } } diff --git a/client/src/connection/ConnectionInstance.jsx b/client/src/connection/ConnectionInstance.jsx index 6807fd4f..cdb039aa 100644 --- a/client/src/connection/ConnectionInstance.jsx +++ b/client/src/connection/ConnectionInstance.jsx @@ -71,6 +71,7 @@ const sections = { technical: "technical", informationProfile: "informationProfile", testIdP: "testIdP", + visibility: "visibility", overview: "overview" } @@ -177,6 +178,9 @@ export const ConnectionInstance = ({ case sections.testIdP: { return !connection.id || (!finished || !testIdPValid()); } + case sections.visibility: { + return !connection.id; + } case sections.pendingChanges: { return false; } @@ -244,7 +248,7 @@ export const ConnectionInstance = ({ } const testIdPValid = () => { - return isProduction || !isEmpty(connection.allowedEntities); + return connection.status === CONNECTION_STATUSES.PROD_READY; } const changeSection = sectionName => { @@ -1078,7 +1082,10 @@ export const ConnectionInstance = ({ return renderInformationProfileSection(); } case sections.testIdP: { - return isProduction ? renderVisibilitySection() : renderTestIdPSection(); + return renderTestIdPSection(); + } + case sections.visibility: { + return renderVisibilitySection(); } case sections.overview: { return isOidc ? renderOIDCOverview() : renderSAMLOverview(); @@ -1113,6 +1120,9 @@ export const ConnectionInstance = ({ } return !testIdPValid(); } + case sections.visibility: { + return true; + } case sections.pendingChanges: { return false; } @@ -1222,7 +1232,7 @@ export const ConnectionInstance = ({ return ( <>
-

{I18n.t(`connection.${isComplete ? "existing" : "new"}Connection${isProduction ? "Prod" : ""}`, {name: connection.name})}

+

{I18n.t(`connection.${isComplete ? "existing" : "new"}Connection`, {name: connection.name})}

{(isProduction && application.signedContract && (connection.status === CONNECTION_STATUSES.COMPLETE || connection.status === CONNECTION_STATUSES.IN_PROGRESS)) &&
) diff --git a/client/src/locale/en.js b/client/src/locale/en.js index e8d9c124..db807b75 100644 --- a/client/src/locale/en.js +++ b/client/src/locale/en.js @@ -302,15 +302,15 @@ const en = { change_requests: "Change request", contract: "Contract", appteam: "App team", - welcome: "Welcome {{user}}. {{name}} is not yet connected to SURF Access. Start by connecting to our test environment.", + welcome: "Welcome {{user}}. {{name}} is not yet connected to SURF Access. Start by creating a connection.", testSection: "Test", teamSection: "Team", duplicatedName: "A connection with name {{name}} already exists for this Application.", duplicateEntityID: "A connection with entityID {{entityID}} already exists", test: { - name: "Test", - connections: "Connections to our test environment", - info: "Test whether federated login works via our test environment.", + name: "Connections", + connections: "Connections not activated for production yet", + info: "Test whether federated login works.", }, inUseWarning: "All the members of the following institution(s) will lose access to {{name}}:", inUseWarningOrg: "All of the members of the following institution(s) will lose access to all of the applications of this organisation:", @@ -326,21 +326,21 @@ const en = { members: "Manage team members", }, production: { - name: "Production", - connections: "Connections to the production environment", + name: "Connections", + connections: "All connections for {{app}}", catalogue: "App details for the SURF Access catalog", access: "Access & visibility", contract: "Contract", - disclaimer: "A connection to the SURF Access production environment requires approval from the SURF Access team. All of the above information is mandatory.", + disclaimer: "To activate a connection for production you will need approval from the SURF Access team. All of the above information is mandatory.", }, productionConnectionHint: "Connect to our production environment. To activate the application, all additional information must be provided.", applicationInformationHint: "Before a connection to production can be activated, all additional information must be added and the contract must be signed.", productionActivationHint: "Request activation for {{name}}.", productionActivationAction: "Do it now", productActivationPending: "The request for activation of your production connection has been received. SURF will contact you within three business days.", - newConnection: "New connection to the test environment", - existingConnection: "Edit test connection {{name}}", - newConnectionProd: "New connection to the production environment", + newConnection: "New connection", + existingConnection: "Edit connection {{name}}", + newConnectionProd: "New connection", existingConnectionProd: "Edit connection {{name}}", copyConnection: "Copy from other connection", technical: "Technical details", diff --git a/client/src/pages/Connection.jsx b/client/src/pages/Connection.jsx index c7877966..9e98443a 100644 --- a/client/src/pages/Connection.jsx +++ b/client/src/pages/Connection.jsx @@ -8,7 +8,7 @@ import {Overview} from "../connection/Overview.jsx"; import {ConnectionInstance} from "../connection/ConnectionInstance.jsx"; import {getApplicationById, getIdentityProviders} from "../api/index.js"; import {Loader} from "@surfnet/sds"; -import {APPLICATION_STATUSES, CONNECTION_STATUSES, PROTOCOLS} from "../utils/Manage.js"; +import {APPLICATION_STATUSES, CONNECTION_STATES, CONNECTION_STATUSES, PROTOCOLS} from "../utils/Manage.js"; import {AppInformation} from "../connection/AppInformation.jsx"; import { contactSectionValid, @@ -186,10 +186,9 @@ export const Connection = () => { setTab={changeTab} profileOptions={profileOptions} identityProviders={identityProviders} - isProduction={connection?.status === CONNECTION_STATUSES.PROD_READY} setDirty={setDirty} + isProduction={connection?.state === CONNECTION_STATES.prodaccepted} connectionId={connectionId} - /> } case "application": { @@ -237,6 +236,7 @@ export const Connection = () => { currentTab={currentTab} setLoading={setLoading} user={user} + currentOrganization={currentOrganization} setTab={changeTab}/> {renderCurrentTab()}
diff --git a/client/src/utils/Manage.js b/client/src/utils/Manage.js index 057da832..8f5b6ff2 100644 --- a/client/src/utils/Manage.js +++ b/client/src/utils/Manage.js @@ -52,6 +52,10 @@ export const PROTOCOLS = { OIDC10_RP: "oidc10_rp", SAML20_SP: "saml20_sp" } +export const CONNECTION_STATES = { + testaccepted: "testaccepted", prodaccepted: "prodaccepted" +} + export const CONNECTION_STATUSES = { OPEN: "OPEN", IN_PROGRESS: "IN_PROGRESS", COMPLETE: "COMPLETE", PENDING_PROD: "PENDING_PROD", PROD_READY: "PROD_READY" } diff --git a/server/src/main/java/access/model/Connection.java b/server/src/main/java/access/model/Connection.java index 6876804d..e8e2c64b 100644 --- a/server/src/main/java/access/model/Connection.java +++ b/server/src/main/java/access/model/Connection.java @@ -65,7 +65,7 @@ public class Connection implements NameHolder { @Enumerated(EnumType.STRING) @Column @NotNull - private State state = State.prodaccepted; + private State state = State.testaccepted; @Enumerated(EnumType.STRING) @Column diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml index 42778440..fed7101b 100644 --- a/server/src/main/resources/application.yml +++ b/server/src/main/resources/application.yml @@ -163,7 +163,7 @@ manage: # url: "http://localhost:8081" user: openconextaccess password: secret - defaultState: prodaccepted + defaultState: testaccepted # If manage is disabled (e.g. enabled: False) the staticManageDirectory is the directory where the {metadata_type}.json files # are located. This can also be an absolute file path, e.g. file:///opt/openconext/invite/manage staticManageDirectory: classpath:/manage From e6bb11707ee674e25c3ae94a87ffba6518196795 Mon Sep 17 00:00:00 2001 From: Okke Harsta Date: Tue, 14 Apr 2026 10:44:19 +0200 Subject: [PATCH 4/4] Forced update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 218a7e81..a07ce670 100644 --- a/README.md +++ b/README.md @@ -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 +See . ### [Local endpoints](#local-endpoints)