From b5738f7337c2732090388fb592c45b0edbee2d1d Mon Sep 17 00:00:00 2001 From: Nicholas Blair <nicholas.blair@wisc.edu> Date: Mon, 16 May 2016 10:46:52 -0500 Subject: [PATCH] feat: add uw-frame compatible output for /profile/uw-frame --- .../edu/wisc/uwss/web/ProfileController.java | 44 +++++- .../wisc/uwss/web/uwframe/UwframeBuild.java | 113 +++++++++++++++ .../wisc/uwss/web/uwframe/UwframeSession.java | 131 ++++++++++++++++++ .../uwss/web/uwframe/UwframeBuildTest.java | 50 +++++++ .../uwss/web/uwframe/UwframeSessionTest.java | 47 +++++++ 5 files changed, 381 insertions(+), 4 deletions(-) create mode 100644 uw-spring-security-web/src/main/java/edu/wisc/uwss/web/uwframe/UwframeBuild.java create mode 100644 uw-spring-security-web/src/main/java/edu/wisc/uwss/web/uwframe/UwframeSession.java create mode 100644 uw-spring-security-web/src/test/java/edu/wisc/uwss/web/uwframe/UwframeBuildTest.java create mode 100644 uw-spring-security-web/src/test/java/edu/wisc/uwss/web/uwframe/UwframeSessionTest.java diff --git a/uw-spring-security-web/src/main/java/edu/wisc/uwss/web/ProfileController.java b/uw-spring-security-web/src/main/java/edu/wisc/uwss/web/ProfileController.java index 8ec8233..cc1295c 100644 --- a/uw-spring-security-web/src/main/java/edu/wisc/uwss/web/ProfileController.java +++ b/uw-spring-security-web/src/main/java/edu/wisc/uwss/web/ProfileController.java @@ -3,16 +3,17 @@ */ package edu.wisc.uwss.web; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.security.core.Authentication; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; +import edu.wisc.uwss.UWUserDetails; +import edu.wisc.uwss.web.uwframe.UwframeSession; + /** * {@link Controller} useful for returning the current authenticated principal. * @@ -20,7 +21,11 @@ import org.springframework.web.bind.annotation.ResponseBody; * @author Nicholas Blair */ @Controller +@RequestMapping("/profile") public class ProfileController { + @Autowired + private Environment environment; + /** * This method intentionally avoids using {@link edu.wisc.uwss.UWUserDetails} for the argument and * return type. Configurations exist that may result authentication not being required for this URL. @@ -32,4 +37,35 @@ public class ProfileController { return principal; } + /** + * This method transforms the {@link UWUserDetails} (if present) to a {@link UwframeSession}, + * Intended for use in uw-frame applications. + * + * To register this url in your uw-frame app, create the file 'src/main/webapp/js/override.js' with the following + * contents: + <pre> + define(['angular'], function(angular) { + var config = angular.module('override', []); + config + .constant('OVERRIDE', { + 'SERVICE_LOC': { + 'sessionInfo' : 'profile/uw-frame', + } + }); + return config; + }); + </pre> + * + * @param principal + * @return the current authenticated principal as a {@link UwframeSession} + */ + @RequestMapping(value="/profile/uw-frame", method=RequestMethod.GET) + public @ResponseBody Object uwFrameCompatibleProfile(@AuthenticationPrincipal Object principal) { + if(principal instanceof UWUserDetails) { + return new UwframeSession(environment, (UWUserDetails) principal); + } else { + return new UwframeSession(environment); + } + } + } diff --git a/uw-spring-security-web/src/main/java/edu/wisc/uwss/web/uwframe/UwframeBuild.java b/uw-spring-security-web/src/main/java/edu/wisc/uwss/web/uwframe/UwframeBuild.java new file mode 100644 index 0000000..4ad0eab --- /dev/null +++ b/uw-spring-security-web/src/main/java/edu/wisc/uwss/web/uwframe/UwframeBuild.java @@ -0,0 +1,113 @@ +/** + * + */ +package edu.wisc.uwss.web.uwframe; + +import org.apache.commons.lang.StringUtils; + +/** + * Bean that mimics the data model uw-frame expects for the application's build information. + * + * @author Nicholas Blair + */ +public class UwframeBuild { + + protected String buildNumber; + protected String scmBranch; + protected String projectVersion; + protected String tags; + + public UwframeBuild() { + } + /** + * + * @param buildNumber the git commitId + * @param scmBranch the git branch (can be null) + * @param projectVersion the maven project version + * @param tags the tags (can be null) + */ + public UwframeBuild(String buildNumber, String scmBranch, String projectVersion, String tags) { + this.buildNumber = buildNumber; + this.scmBranch = scmBranch; + this.projectVersion = projectVersion; + this.tags = tags; + } + /** + * @return the buildNumber + */ + public String getBuildNumber() { + return buildNumber; + } + /** + * @param buildNumber the buildNumber to set + */ + public UwframeBuild setBuildNumber(String buildNumber) { + this.buildNumber = buildNumber; + return this; + } + /** + * @return the scmBranch + */ + public String getScmBranch() { + return scmBranch; + } + /** + * @param scmBranch the scmBranch to set + */ + public UwframeBuild setScmBranch(String scmBranch) { + this.scmBranch = scmBranch; + return this; + } + /** + * @return the projectVersion + */ + public String getProjectVersion() { + return projectVersion; + } + /** + * @param projectVersion the projectVersion to set + */ + public UwframeBuild setProjectVersion(String projectVersion) { + this.projectVersion = projectVersion; + return this; + } + + /** + * @return the tags + */ + public String getTags() { + return tags; + } + /** + * @param tags the tags to set + */ + public UwframeBuild setTags(String tags) { + this.tags = tags; + return this; + } + + /** + * Returns an empty string if not all necessary fields are set. + * + * @return the fields as a single, human readable string + */ + public String toVersionString() { + if(StringUtils.isBlank(buildNumber)) { + return ""; + } + StringBuilder builder = new StringBuilder(); + builder.append("Revision "); + builder.append(buildNumber); + if(StringUtils.isNotBlank(projectVersion)) { + builder.append(" (Version "); + builder.append(projectVersion); + if (StringUtils.isBlank(tags) && StringUtils.isNotBlank(scmBranch)) { + builder.append(" from "); + builder.append(scmBranch); + builder.append(" branch"); + } + builder.append(")"); + } + return builder.toString(); + } +} diff --git a/uw-spring-security-web/src/main/java/edu/wisc/uwss/web/uwframe/UwframeSession.java b/uw-spring-security-web/src/main/java/edu/wisc/uwss/web/uwframe/UwframeSession.java new file mode 100644 index 0000000..665f5ba --- /dev/null +++ b/uw-spring-security-web/src/main/java/edu/wisc/uwss/web/uwframe/UwframeSession.java @@ -0,0 +1,131 @@ +package edu.wisc.uwss.web.uwframe; + +import org.springframework.core.env.Environment; + +import edu.wisc.uwss.UWUserDetails; + +/** + * Bean matching data model expected by <a href="https://github.com/UW-Madison-DoIT/uw-frame">uw-frame</a>. + * + * The session contains a mix of user attributes and product revision information: + * + <pre> + { + "person": { + "userName": "admin", + "sessionKey": "someRandomKey", + "serverName": "localhost", + "firstName" : "Bucky", + "lastName" : "Badger", + "displayName": "Bucky Badger", + "email" : "bucky@wisc.edu", + "version": "2.2.0" + } + } + </pre> + * + * @author Nicholas Blair + */ +public class UwframeSession { + + public static final String GIT_BRANCH = "git.branch"; + public static final String GIT_COMMIT_ID_ABBREV = "git.commit.id.abbrev"; + public static final String GIT_TAGS = "git.tags"; + public static final String PROJECT_VERSION = "projectVersion"; + + private final String username; + private final String displayName; + private final String firstName; + private final String lastName; + private final UwframeBuild build; + + /** + * Construct a "guest" session with no revision information available. + */ + public UwframeSession() { + this(null); + } + /** + * Construct a "guest" session + * + * @param environment source for revision information + */ + public UwframeSession(Environment environment) { + this(environment, "anonymousUser", "Guest", "Guest", ""); + } + /** + * Preferred constructor. + * + * @param environment + * @param userDetails + */ + public UwframeSession(Environment environment, UWUserDetails userDetails) { + this(environment, userDetails.getUsername(), userDetails.getFullName(), userDetails.getFirstName(), userDetails.getLastName()); + } + /** + * + * @param environment + * @param username + * @param displayName + * @deprecated prefer constructor UwframeSession(Environment, UWUserDetails) instead + */ + @Deprecated + public UwframeSession(Environment environment, String username, String displayName) { + this(environment, username, displayName, null, null); + } + + public UwframeSession(Environment environment, String username, String displayName, String firstName, String lastName) { + this.username = username; + this.displayName = displayName; + this.firstName = firstName; + this.lastName = lastName; + if(environment != null && environment.containsProperty(GIT_COMMIT_ID_ABBREV)) { + this.build = new UwframeBuild(environment.getProperty(GIT_COMMIT_ID_ABBREV), environment.getProperty(GIT_BRANCH), environment.getProperty(PROJECT_VERSION), environment.getProperty(GIT_TAGS)); + } else { + this.build = new UwframeBuild(); + } + } + + /** + * @return the username + */ + public String getUsername() { + return username; + } + /** + * @return always an empty String + */ + public String getSessionKey() { + return ""; + } + /** + * @return always an empty String + */ + public String getServerName() { + return ""; + } + /** + * @return the displayName + */ + public String getDisplayName() { + return displayName; + } + /** + * @return the first name + */ + public String getFirstName() { + return firstName; + } + /** + * @return the last name + */ + public String getLastName() { + return lastName; + } + /** + * @return the version + */ + public String getVersion() { + return build.toVersionString(); + } +} diff --git a/uw-spring-security-web/src/test/java/edu/wisc/uwss/web/uwframe/UwframeBuildTest.java b/uw-spring-security-web/src/test/java/edu/wisc/uwss/web/uwframe/UwframeBuildTest.java new file mode 100644 index 0000000..2532a1f --- /dev/null +++ b/uw-spring-security-web/src/test/java/edu/wisc/uwss/web/uwframe/UwframeBuildTest.java @@ -0,0 +1,50 @@ +package edu.wisc.uwss.web.uwframe; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Tests for {@link UwframeBuild} + * @author Nicholas Blair + */ +public class UwframeBuildTest { + + @Test + public void toVersionString_empty() { + assertEquals("", new UwframeBuild().toVersionString()); + } + + @Test + public void toVersionString_revisionOnly() { + assertEquals("Revision abcde1", new UwframeBuild().setBuildNumber("abcde1").toVersionString()); + } + @Test + public void toVersionString_release_withbranch() { + assertEquals("Revision abcde1 (Version 1.2.3 from release-1-2 branch)", + new UwframeBuild() + .setBuildNumber("abcde1") + .setProjectVersion("1.2.3") + .setScmBranch("release-1-2") + .toVersionString()); + } + @Test + public void toVersionString_release_withtag() { + assertEquals("Revision abcde1 (Version 1.2.3)", + new UwframeBuild() + .setBuildNumber("abcde1") + .setProjectVersion("1.2.3") + .setTags("1.2.3") + .setScmBranch("feature-branch") + .toVersionString()); + } + @Test + public void toVersionString_complete() { + assertEquals("Revision abcde1 (Version 1.2.3-SNAPSHOT from feature-branch branch)", + new UwframeBuild() + .setBuildNumber("abcde1") + .setProjectVersion("1.2.3-SNAPSHOT") + .setScmBranch("feature-branch") + .toVersionString()); + } +} diff --git a/uw-spring-security-web/src/test/java/edu/wisc/uwss/web/uwframe/UwframeSessionTest.java b/uw-spring-security-web/src/test/java/edu/wisc/uwss/web/uwframe/UwframeSessionTest.java new file mode 100644 index 0000000..7f47c7f --- /dev/null +++ b/uw-spring-security-web/src/test/java/edu/wisc/uwss/web/uwframe/UwframeSessionTest.java @@ -0,0 +1,47 @@ +package edu.wisc.uwss.web.uwframe; + +import org.junit.Test; +import org.springframework.core.env.Environment; +import org.springframework.mock.env.MockEnvironment; + +import static org.junit.Assert.assertEquals; + +/** + * Tests for {@link UwframeSession}. + * + * @author Nicholas Blair + */ +public class UwframeSessionTest { + + @Test + public void empty() { + UwframeSession session = new UwframeSession(); + assertEquals("anonymousUser", session.getUsername()); + assertEquals("Guest", session.getDisplayName()); + assertEquals("Guest", session.getFirstName()); + assertEquals("", session.getLastName()); + assertEquals("", session.getVersion()); + } + + @Test + public void with_empty_Environment() { + Environment environment = new MockEnvironment(); + UwframeSession session = new UwframeSession(environment, "jim", "James Badger", "James", "Badger"); + assertEquals("jim", session.getUsername()); + assertEquals("James Badger", session.getDisplayName()); + assertEquals("James", session.getFirstName()); + assertEquals("Badger", session.getLastName()); + assertEquals("", session.getVersion()); + } + @Test + public void with_complete_Environment() { + MockEnvironment environment = new MockEnvironment(); + environment.setProperty(UwframeSession.GIT_COMMIT_ID_ABBREV, "abcde2"); + UwframeSession session = new UwframeSession(environment, "jim", "James Badger", "James", "Badger"); + assertEquals("jim", session.getUsername()); + assertEquals("James Badger", session.getDisplayName()); + assertEquals("James", session.getFirstName()); + assertEquals("Badger", session.getLastName()); + assertEquals("Revision abcde2", session.getVersion()); + } +} -- GitLab