From 002234c4324d8ba7037945c52a3c0a3804989896 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Thu, 26 Sep 2024 15:18:00 -0700 Subject: [PATCH] NOJIRA - handling migration of values for existing bundles --- .../MigrationTasksContextLoadedListener.java | 35 ++++ .../admin/ui/domain/AttributeBundle.java | 4 +- .../repository/AttributeBundleRepository.java | 13 ++ testbed/postgres/conf/application.yml | 192 +++++++++++++++--- 4 files changed, 211 insertions(+), 33 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/MigrationTasksContextLoadedListener.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/MigrationTasksContextLoadedListener.java index 5adb815cc..427a83759 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/MigrationTasksContextLoadedListener.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/MigrationTasksContextLoadedListener.java @@ -1,5 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.configuration; +import edu.internet2.tier.shibboleth.admin.ui.domain.BundleableAttributeType; +import edu.internet2.tier.shibboleth.admin.ui.repository.AttributeBundleRepository; import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository; import edu.internet2.tier.shibboleth.admin.ui.security.model.Group; import edu.internet2.tier.shibboleth.admin.ui.security.model.Ownership; @@ -13,11 +15,19 @@ import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; +import java.util.HashSet; +import java.util.Set; + /** * After the context loads, do any needed migration tasks */ @Component public class MigrationTasksContextLoadedListener implements ApplicationListener { + private static boolean attrBundleMigrated = false; + + @Autowired + private AttributeBundleRepository attributeBundleRepository; + @Autowired private EntityDescriptorRepository entityDescriptorRepository; @@ -36,8 +46,14 @@ public class MigrationTasksContextLoadedListener implements ApplicationListener< @Override public void onApplicationEvent(ContextRefreshedEvent event) { doshibui_1740_migration(); // do first + if (!attrBundleMigrated) { + doAttributeBundleMigration(); + } } + /** + * This was a long time ago - don't think we need this anymore... + */ @Transactional void doshibui_1740_migration() { groupService.ensureAdminGroupExists(); // do first @@ -62,4 +78,23 @@ void doshibui_1740_migration() { } }); } + + @Transactional + void doAttributeBundleMigration() { + attributeBundleRepository.migrateData(); + attributeBundleRepository.findAll().forEach(attrBundleEntry -> { + try { + Set names = new HashSet(); + attrBundleEntry.getAttributes().forEach(value -> { + names.add(BundleableAttributeType.values()[Integer.parseInt(value)].label()); + }); + attrBundleEntry.setAttributes(names); + attributeBundleRepository.save(attrBundleEntry); + } + catch (NumberFormatException ignore) { + } + }); + attrBundleMigrated = true; + attributeBundleRepository.clearMigratedValues(); + } } \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeBundle.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeBundle.java index 0b11b8f21..88748fca2 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeBundle.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeBundle.java @@ -13,9 +13,9 @@ @Entity(name = "attribute_bundle_definition") @Data public class AttributeBundle { - @Column(nullable = false) + @Column(name="attribute_names", nullable = false) @ElementCollection - Set attributes = new HashSet<>(); + Set attributes = new HashSet<>(); @Column(name = "name", nullable = true) String name; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/AttributeBundleRepository.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/AttributeBundleRepository.java index 0c9bc2aed..f360bde54 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/AttributeBundleRepository.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/AttributeBundleRepository.java @@ -2,6 +2,9 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.AttributeBundle; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Optional; @@ -15,4 +18,14 @@ public interface AttributeBundleRepository extends JpaRepository findByResourceId(String resourceId); AttributeBundle save(AttributeBundle target); + + @Query(value = "INSERT INTO attribute_bundle_definition_attribute_names SELECT * FROM attribute_bundle_definition_attributes", nativeQuery = true) + @Modifying + @Transactional + void migrateData(); + + @Query(value = "DELETE FROM attribute_bundle_definition_attributes", nativeQuery = true) + @Modifying + @Transactional + void clearMigratedValues(); } \ No newline at end of file diff --git a/testbed/postgres/conf/application.yml b/testbed/postgres/conf/application.yml index b13a2ac74..c601bece1 100644 --- a/testbed/postgres/conf/application.yml +++ b/testbed/postgres/conf/application.yml @@ -50,7 +50,145 @@ custom: displayName: label.attribute-eduPersonUniqueId - name: employeeNumber displayName: label.attribute-employeeNumber - # Custom attributes + # Custom attributes + - name: SANSmail + displayName: SANSmail + - name: displayName + displayName: displayName + - name: sn + displayName: sn + - name: mail-attr + displayName: mail-attr + - name: email + displayName: email + - name: homePhone + displayName: homePhone + - name: homePostalAddress + displayName: homePostalAddress + - name: mobileNumber + displayName: mobileNumber + - name: pagerNumber + displayName: pagerNumber + - name: commonName + displayName: commonName + - name: locality + displayName: locality + - name: stateProvince + displayName: stateProvince + - name: street + displayName: street + - name: organizationName + displayName: organizationName + - name: organizationalUnit + displayName: organizationalUnit + - name: title + displayName: title + - name: postalAddress + displayName: postalAddress + - name: postalCode + displayName: postalCode + - name: telephoneNumber + displayName: telephoneNumber + - name: initials + displayName: initials + - name: muohioeduAffiliationCode + displayName: muohioeduAffiliationCode + - name: eppnMUOhio + displayName: eppnMUOhio + - name: muohioeduLocationCode + displayName: muohioeduLocationCode + - name: muohioeduPrimaryLocation + displayName: muohioeduPrimaryLocation + - name: buildingName + displayName: buildingName + - name: muohioeduDepartment + displayName: muohioeduDepartment + - name: muohioeduDepartmentCode + displayName: muohioeduDepartmentCode + - name: muohioeduDivisionCode + displayName: muohioeduDivisionCode + - name: muohioeduDivision + displayName: muohioeduDivision + - name: muohioeduCampusTelephoneNumber + displayName: muohioeduCampusTelephoneNumber + - name: eduCourseOffering + displayName: eduCourseOffering + - name: isMemberOf + displayName: isMemberOf + - name: group + displayName: group + - name: studentType + displayName: studentType + - name: campus_fyindicator + displayName: campus_fyindicator + - name: upperUID + displayName: upperUID + - name: sciquestRole + displayName: sciquestRole + - name: awsRoles + displayName: awsRoles + - name: nyansaRole + displayName: nyansaRole + - name: awsRoleSessionName + displayName: awsRoleSessionName + - name: awsSessionDuration + displayName: awsSessionDuration + - name: muohioeduMiddleName + displayName: muohioeduMiddleName + - name: BannerID + displayName: BannerID + - name: trimmedBannerID + displayName: trimmedBannerID + - name: SAML_SUBJECT + displayName: SAML_SUBJECT + - name: OPEID + displayName: OPEID + - name: stream2Role + displayName: stream2Role + - name: muohioeduPersonPrimaryAffiliation + displayName: muohioeduPersonPrimaryAffiliation + - name: muohioeduPrimaryAffiliationCode + displayName: muohioeduPrimaryAffiliationCode + - name: User.FirstName + displayName: User.FirstName + - name: User.LastName + displayName: User.LastName + - name: User.Country + displayName: User.Country + - name: eppnMUOhioScripted + displayName: eppnMUOhioScripted + - name: Gallup.Country + displayName: Gallup.Country + - name: Gallup.SANSmail + displayName: Gallup.SANSmail + - name: Gallup.nameIdentifier + displayName: Gallup.nameIdentifier + - name: Gallup.PPID + displayName: Gallup.PPID + - name: Gallup.Surname + displayName: Gallup.Surname + - name: Gallup.GivenName + displayName: Gallup.GivenName + + + # The following contains a map of relying party overrides. + # The structure of an entry is as follows: + # - name: The name of the entry. used to uniquely identify this entry. + # displayName: This will normally be the label used when displaying this override in the UI + # displayType: The type to use when displaying this option + # helpText: This is the help-icon hover-over text + # defaultValues: One or more values to be displayed as default options in the UI + # persistType: Optional. If it is necessary to persist something different than the override's display type, + # set that type here. For example, display a boolean, but persist a string. + # persistValue: Required only when persistType is used. Defines the value to be persisted. + # attributeName: This is the name of the attribute to be used in the xml. This is assumed to be a URI. + # attributeFriendlyName: This is the friendly name associated with the above attributeName. + # + # It is imperative when defining these that the displayType and persistType are known types. + # Typos or unsupported values here will result in that override being skipped! + # Supported types are as follows: boolean, integer, string, set, list + # Note that persistType doesn't have to match displayType. However, the only unmatching combination currently + # supported is a displayType of boolean and persistType of string. overrides: # Default overrides - name: signAssertion @@ -81,6 +219,7 @@ custom: persistValue: shibboleth.SecurityConfiguration.SHA1 attributeName: http://shibboleth.net/ns/profiles/securityConfiguration attributeFriendlyName: securityConfiguration + protocol: saml,oidc - name: ignoreAuthenticationMethod displayName: label.ignore-any-sp-requested-authentication-method displayType: boolean @@ -89,6 +228,7 @@ custom: persistValue: 0x1 attributeName: http://shibboleth.net/ns/profiles/disallowedFeatures attributeFriendlyName: disallowedFeatures + protocol: saml,oidc - name: omitNotBefore displayName: label.omit-not-before-condition displayType: boolean @@ -123,6 +263,7 @@ custom: - urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport attributeName: http://shibboleth.net/ns/profiles/defaultAuthenticationMethods attributeFriendlyName: defaultAuthenticationMethods + protocol: saml,oidc - name: forceAuthn displayName: label.force-authn displayType: boolean @@ -135,13 +276,17 @@ custom: helpText: tooltip.ignore-request-signatures attributeName: http://shibboleth.net/ns/profiles/ignoreRequestSignatures attributeFriendlyName: ignoreRequestSignatures - - name: disallowedFeatures - attributeFriendlyName: disallowedFeatures - displayName: label.disallowedFeatures - helpText: tooltip.disallowedFeatures - displayType: string - attributeName: http://shibboleth.net/ns/profiles/disallowedFeatures - protocol: oidc + - name: postAuthenticationFlows + attributeFriendlyName: postAuthenticationFlows + displayName: label.postAuthenticationFlows + helpText: tooltip.postAuthenticationFlows + displayType: selection_list + defaultValues: + - attribute-release + - expiring-password + - terms-of-use + attributeName: http://shibboleth.net/ns/profiles/postAuthenticationFlows" + protocol: saml,oidc - name: inboundInterceptorFlows attributeFriendlyName: inboundInterceptorFlows displayName: label.inboundInterceptorFlows @@ -156,14 +301,6 @@ custom: displayType: string attributeName: http://shibboleth.net/ns/profiles/outboundInterceptorFlows protocol: oidc - - name: securityConfiguration - attributeFriendlyName: securityConfiguration - displayName: label.securityConfiguration - helpText: tooltip.securityConfiguration - displayType: string - defaultValue: shibboleth.DefaultSecurityConfiguration - attributeName: http://shibboleth.net/ns/profiles/securityConfiguration - protocol: oidc - name: tokenEndpointAuthMethods attributeFriendlyName: tokenEndpointAuthMethods displayName: label.tokenEndpointAuthMethods @@ -172,20 +309,13 @@ custom: defaultValue: client_secret_basic, client_secret_post, client_secret_jwt, private_key_jwt attributeName: http://shibboleth.net/ns/profiles/tokenEndpointAuthMethods protocol: oidc - - name: defaultAuthenticationMethods - attributeFriendlyName: defaultAuthenticationMethods - displayName: label.defaultAuthenticationMethods - helpText: tooltip.defaultAuthenticationMethods - displayType: string - attributeName: http://shibboleth.net/ns/profiles/defaultAuthenticationMethods - protocol: oidc - - name: postAuthenticationFlows - attributeFriendlyName: postAuthenticationFlows - displayName: label.postAuthenticationFlows - helpText: tooltip.postAuthenticationFlows - displayType: string - attributeName: http://shibboleth.net/ns/profiles/postAuthenticationFlows - protocol: oidc + # - name: postAuthenticationFlows + # attributeFriendlyName: postAuthenticationFlows + # displayName: label.postAuthenticationFlows + # helpText: tooltip.postAuthenticationFlows + # displayType: string + # attributeName: http://shibboleth.net/ns/profiles/postAuthenticationFlows + # protocol: oidc - name: proxyCount attributeFriendlyName: proxyCount displayName: label.proxyCount @@ -379,7 +509,7 @@ custom: - name: IDTokenLifetimeBrowser attributeFriendlyName: IDTokenLifetimeBrowser displayName: label.IDTokenLifetime.browser - helpText: tooltip.IDTokenLifetime.broswer + helpText: tooltip.IDTokenLifetime.browser displayType: string defaultValue: PT1H attributeName: http://shibboleth.net/ns/profiles/oidc/sso/browser/IDTokenLifetime