diff --git a/uw-spring-security-core/src/main/java/edu/wisc/uwss/uds/IdentifiersBuilder.java b/uw-spring-security-core/src/main/java/edu/wisc/uwss/uds/IdentifiersBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..d015c2ab0f100d77cf52ebc2bb3b9553d294583a --- /dev/null +++ b/uw-spring-security-core/src/main/java/edu/wisc/uwss/uds/IdentifiersBuilder.java @@ -0,0 +1,122 @@ +package edu.wisc.uwss.uds; + +import java.util.ArrayList; +import java.util.List; + +import edu.wisc.services.uds.person.v1_1.Identifier; +import edu.wisc.services.uds.person.v1_1.Identifiers; + +/** + * Builder pattern for constructing {@link IdentifiersBuilder}. + * + * This class is not thread safe and is intended for use as a prototype. + * + * Example usage: + * <pre> + new IdentifiersBuilder() + .withNetid("bbadger") + .withPvi("UW000A000) + .toIdentifiers(); + * </pre> + * + * Will return: + * + * <pre> + <uds:Identifiers> + <uds:Identifier> + <uds:Source>UWMSNSUDS</uds:Source> + <uds:IdName>NETID</uds:IdName> + <uds:Value>bbadger</uds:Value> + </uds:Identifier> + <uds:Identifier> + <uds:Source>UWMSNSUDS</uds:Source> + <uds:IdName>PVI</uds:IdName> + <uds:Value>UW111Z000</uds:Value> + </uds:Identifier> + </uds:Identifiers> + * </pre> + * + * @author Nicholas Blair + */ +public class IdentifiersBuilder { + private final Identifiers identifiers = new Identifiers(); + public static final String EMPLID = "EMPLID"; + public static final String UWHRS = "UWHRS"; + public static final String UWMSNSUDS = "UWMSNSUDS"; + public static final String NETID = "NETID"; + public static final String PHOTOID = "PHOTOID"; + public static final String PVI = "PVI"; + /** + * + * @return the accumulated {@link Identifiers} + */ + public Identifiers toIdentifiers() { + return identifiers; + } + /** + * Add an {@link Identifier} for a NetID. + * + * @param value the NetID value + * @return this + */ + public IdentifiersBuilder withNetid(String value) { + return with(NETID, UWMSNSUDS, value); + } + /** + * Add an {@link Identifier} for a PVI. + * + * @param value the PVI value + * @return this + */ + public IdentifiersBuilder withPvi(String value) { + return with(PVI, UWMSNSUDS, value); + } + /** + * Add an {@link Identifier} for an HRS emplid. + * Note: the source on this Identifier is {@link #UWHRS}. + * + * @param value the emplid value + * @return this + */ + public IdentifiersBuilder withHrsEmplid(String value) { + return with(EMPLID, UWHRS, value); + } + /** + * Add an {@link Identifier} for a Photoid. + * + * @param value the photoid value + * @return this + */ + public IdentifiersBuilder withPhotoid(String value) { + return with(PHOTOID, UWMSNSUDS, value); + } + + /** + * Add an {@link Identifier}. + * + * @param idName {@link Identifier#getIdName()} + * @param source {@link Identifier#getSource()} + * @param value {@link Identifier#getValue()} + * @return this + */ + public IdentifiersBuilder with(String idName, String source, String value) { + identifiers.getIdentifiers().add(makeIdentifier(idName, source, value)); + return this; + } + /** + * Utility method to construct a new {@link Identifier} + * + * @param idName {@link Identifier#getIdName()} + * @param source {@link Identifier#getSource()} + * @param value {@link Identifier#getValue()} + * @return a new {@link Identifier} + */ + protected Identifier makeIdentifier(String idName, String source, String value) { + Identifier identifier = new Identifier(); + identifier.setIdName(idName); + identifier.setSource(source); + identifier.setValue(value); + return identifier; + } + +} diff --git a/uw-spring-security-core/src/main/java/edu/wisc/uwss/uds/IdentifiersFactory.java b/uw-spring-security-core/src/main/java/edu/wisc/uwss/uds/IdentifiersFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..d09a0ccf24a9377c8b0f73cf981480fab175efb1 --- /dev/null +++ b/uw-spring-security-core/src/main/java/edu/wisc/uwss/uds/IdentifiersFactory.java @@ -0,0 +1,46 @@ +package edu.wisc.uwss.uds; + +import edu.wisc.services.uds.person.v1_1.Identifiers; + +/** + * Factory interface for constructing {@link Identifiers} for use with {@link UdsPersonUserDetailsServiceImpl}. + * + * @author Nicholas Blair + */ +public interface IdentifiersFactory { + + /** + * + * @param value + * @return an {@link Identifiers} + */ + Identifiers withValue(String value); + + /** + * {@link IdentifiersFactory} that returns "PVI" {@link Identifiers}. + */ + public static class PVI implements IdentifiersFactory { + @Override + public Identifiers withValue(String value) { + return new IdentifiersBuilder().withPvi(value).toIdentifiers(); + } + } + /** + * {@link IdentifiersFactory} that returns "NetID" {@link Identifiers}. + */ + public static class NetID implements IdentifiersFactory { + @Override + public Identifiers withValue(String value) { + return new IdentifiersBuilder().withNetid(value).toIdentifiers(); + } + } + /** + * {@link IdentifiersFactory} that returns PhotoID {@link Identifiers}. + */ + public static class PhotoID implements IdentifiersFactory { + @Override + public Identifiers withValue(String value) { + return new IdentifiersBuilder().withPhotoid(value).toIdentifiers(); + } + } +} diff --git a/uw-spring-security-core/src/main/java/edu/wisc/uwss/UdsPersonUserDetailsImpl.java b/uw-spring-security-core/src/main/java/edu/wisc/uwss/uds/UdsPersonUserDetailsImpl.java similarity index 98% rename from uw-spring-security-core/src/main/java/edu/wisc/uwss/UdsPersonUserDetailsImpl.java rename to uw-spring-security-core/src/main/java/edu/wisc/uwss/uds/UdsPersonUserDetailsImpl.java index db52c8d1b1e0d6d7e79d221e45dc2d0611d6272c..2356f9f685670f1b22411e7ffc3a3d3f250c0d6a 100644 --- a/uw-spring-security-core/src/main/java/edu/wisc/uwss/UdsPersonUserDetailsImpl.java +++ b/uw-spring-security-core/src/main/java/edu/wisc/uwss/uds/UdsPersonUserDetailsImpl.java @@ -1,7 +1,7 @@ /** * */ -package edu.wisc.uwss; +package edu.wisc.uwss.uds; import java.util.Collection; import java.util.Collections; @@ -18,13 +18,12 @@ import edu.wisc.services.uds.person.v1_1.Employee; import edu.wisc.services.uds.person.v1_1.Identifier; import edu.wisc.services.uds.person.v1_1.Name; import edu.wisc.services.uds.person.v1_1.Person; +import edu.wisc.uwss.UWUserDetails; /** * {@link UWUserDetails} backed by a {@link Person}. * Most fields are computed fields, transforming equivalents from {@link Person}. * - * TODO: this class should move to the edu.wisc.uwss.uds package. - * * @author ctcudd */ public class UdsPersonUserDetailsImpl implements UWUserDetails { diff --git a/uw-spring-security-core/src/main/java/edu/wisc/uwss/uds/UdsPersonUserDetailsServiceImpl.java b/uw-spring-security-core/src/main/java/edu/wisc/uwss/uds/UdsPersonUserDetailsServiceImpl.java index ad7c6e71f761fec7577a070df0725c1f16feee5d..285c7ef64ac4844f3fabb1972a6843489113b648 100644 --- a/uw-spring-security-core/src/main/java/edu/wisc/uwss/uds/UdsPersonUserDetailsServiceImpl.java +++ b/uw-spring-security-core/src/main/java/edu/wisc/uwss/uds/UdsPersonUserDetailsServiceImpl.java @@ -12,24 +12,25 @@ import edu.wisc.services.uds.person.v1_1.Identifiers; import edu.wisc.services.uds.person.v1_1.Person; import edu.wisc.uds.UdsPersonService; import edu.wisc.uwss.UWUserDetails; -import edu.wisc.uwss.UdsPersonUserDetailsImpl; /** - * @author Collin Cudd + * Implementation of {@link UserDetailsService} backed by a {@link UdsPersonService} (required). + * + * An {@link IdentifiersFactory} can optionally be provided in order to control the "idName" and + * "source" used for the {@link Identifiers} passed to the {@link UdsPersonService}. + * The default {@link IdentifiersFactory} is to treat the value as a UW-Madison NetID. * + * @see IdentifiersFactory + * @author Collin Cudd */ public class UdsPersonUserDetailsServiceImpl implements UserDetailsService{ @Autowired UdsPersonService personService; - + @Autowired(required=false) IdentifiersFactory identifiersFactory = new IdentifiersFactory.NetID(); + @Override public UWUserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - Identifiers identifiers = new Identifiers(); - Identifier identifier = new Identifier(); - identifier.setIdName(UdsPersonUserDetailsImpl.NETID_IDNAME); - identifier.setSource(UdsPersonUserDetailsImpl.UWMSNSUDS_SOURCE); - identifier.setValue(username); - identifiers.getIdentifiers().add(identifier); + Identifiers identifiers = identifiersFactory.withValue(username); Person person = personService.getPerson(identifiers); if(person == null) { throw new UsernameNotFoundException("no person found for " + username + " via UDS Person"); diff --git a/uw-spring-security-core/src/test/java/edu/wisc/uwss/uds/IdentifiersBuilderTest.java b/uw-spring-security-core/src/test/java/edu/wisc/uwss/uds/IdentifiersBuilderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..fc4a782707a8a2b38ae1d7f8d407cccaaf2a0f3c --- /dev/null +++ b/uw-spring-security-core/src/test/java/edu/wisc/uwss/uds/IdentifiersBuilderTest.java @@ -0,0 +1,89 @@ +package edu.wisc.uwss.uds; + +import org.junit.Test; + +import edu.wisc.services.uds.person.v1_1.Identifier; +import edu.wisc.services.uds.person.v1_1.Identifiers; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +/** + * Unit tests for {@link IdentifiersBuilder}. + * + * Examples provided from uds-person-client-java: + * + <pre> + <uds:Identifier> + <uds:Source>UWHRS</uds:Source> + <uds:IdName>EMPLID</uds:IdName> + <uds:Value>00000123</uds:Value> + </uds:Identifier> + <uds:Identifier> + <uds:Source>UWMSNSUDS</uds:Source> + <uds:IdName>NETID</uds:IdName> + <uds:Value>bbadger</uds:Value> + </uds:Identifier> + <uds:Identifier> + <uds:Source>UWMSNSUDS</uds:Source> + <uds:IdName>PHOTOID</uds:IdName> + <uds:Value>90212345671</uds:Value> + </uds:Identifier> + <uds:Identifier> + <uds:Source>UWMSNSUDS</uds:Source> + <uds:IdName>PVI</uds:IdName> + <uds:Value>UW111Z000</uds:Value> + </uds:Identifier> + </pre> + * + * @author Nicholas Blair + */ +public class IdentifiersBuilderTest { + + /** + * Confirm stable behavior when no identifiers added. + */ + @Test + public void toIdentifiers_empty() { + assertEquals(new Identifiers(), new IdentifiersBuilder().toIdentifiers()); + } + /** + * Confirm behavior of withNetid. + */ + @Test + public void toIdentifiers_netid() { + Identifiers identifiers = new IdentifiersBuilder().withNetid("bbadger").toIdentifiers(); + assertFalse(identifiers.getIdentifiers().isEmpty()); + Identifier id = identifiers.getIdentifiers().get(0); + assertIdentifier(id, IdentifiersBuilder.NETID, IdentifiersBuilder.UWMSNSUDS, "bbadger"); + + } + /** + * Confirm behavior of withPvi. + */ + @Test + public void toIdentifiers_pvi() { + Identifiers identifiers = new IdentifiersBuilder().withPvi("UW111Z000").toIdentifiers(); + assertFalse(identifiers.getIdentifiers().isEmpty()); + Identifier id = identifiers.getIdentifiers().get(0); + assertIdentifier(id, IdentifiersBuilder.PVI, IdentifiersBuilder.UWMSNSUDS, "UW111Z000"); + } + + /** + * Confirm we can add multiple identifiers. + */ + @Test + public void toIdentifiers_both() { + Identifiers identifiers = new IdentifiersBuilder() + .withNetid("bbadger").withPvi("UW111Z000").toIdentifiers(); + assertFalse(identifiers.getIdentifiers().isEmpty()); + Identifier id = identifiers.getIdentifiers().get(0); + assertIdentifier(identifiers.getIdentifiers().get(0), IdentifiersBuilder.NETID, IdentifiersBuilder.UWMSNSUDS, "bbadger"); + assertIdentifier(identifiers.getIdentifiers().get(1), IdentifiersBuilder.PVI, IdentifiersBuilder.UWMSNSUDS, "UW111Z000"); + } + protected void assertIdentifier(Identifier id, String idName, String source, String value) { + assertEquals(idName, id.getIdName()); + assertEquals(source, id.getSource()); + assertEquals(value, id.getValue()); + } +} diff --git a/uw-spring-security-core/src/test/java/edu/wisc/uwss/uds/UdsPersonUserDetailsImplTest.java b/uw-spring-security-core/src/test/java/edu/wisc/uwss/uds/UdsPersonUserDetailsImplTest.java index 9a8645eb68be846bfeb85f094f28833ff724872c..56eda990296164740dab5bb39ddd66d52d179ee1 100644 --- a/uw-spring-security-core/src/test/java/edu/wisc/uwss/uds/UdsPersonUserDetailsImplTest.java +++ b/uw-spring-security-core/src/test/java/edu/wisc/uwss/uds/UdsPersonUserDetailsImplTest.java @@ -14,7 +14,6 @@ import edu.wisc.services.uds.person.v1_1.Identifier; import edu.wisc.services.uds.person.v1_1.Identifiers; import edu.wisc.services.uds.person.v1_1.Name; import edu.wisc.services.uds.person.v1_1.Person; -import edu.wisc.uwss.UdsPersonUserDetailsImpl; /** * Tests for {@link UdsPersonUserDetailsImpl}