Re-merging shibIntegration branch after additional development:
Unit tests(needs some refactoring), added a status page for server-side parameters(may be moved/hidden soon), some minor refactoring, etc
This commit is contained in:
commit
b4930e436a
.gitignore
src
main
java/se/su/dsv/scipro
ApplicationSettings.javaSciProApplication.javaSciProSession.java
admin/pages
AbstractAdminSettingsPage.java
settings
security/auth
util
resources
test/java/se/su/dsv/scipro
security/auth
util
wicket
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
\.settings/
|
\.settings/
|
||||||
\.project
|
\.project
|
||||||
\.classpath
|
\.classpath
|
||||||
|
\target/**/*
|
||||||
|
\target/*
|
||||||
|
@ -11,6 +11,7 @@ public class ApplicationSettings {
|
|||||||
|
|
||||||
private boolean enableRemoteUserLookup;
|
private boolean enableRemoteUserLookup;
|
||||||
private String remoteLookupUrl;
|
private String remoteLookupUrl;
|
||||||
|
private boolean acceptExternalAuthentication;
|
||||||
|
|
||||||
public boolean isEnableRemoteUserLookup() {
|
public boolean isEnableRemoteUserLookup() {
|
||||||
return enableRemoteUserLookup;
|
return enableRemoteUserLookup;
|
||||||
@ -28,4 +29,12 @@ public class ApplicationSettings {
|
|||||||
return remoteLookupUrl;
|
return remoteLookupUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAcceptExternalAuthentication(){
|
||||||
|
return acceptExternalAuthentication;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAcceptExternalAuthentication(boolean pAcceptExternalAuthentication){
|
||||||
|
acceptExternalAuthentication = pAcceptExternalAuthentication;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ import se.su.dsv.scipro.admin.pages.settings.AdminFinalSeminarSettingsPage;
|
|||||||
import se.su.dsv.scipro.admin.pages.settings.AdminFinalSeminarSettingsPerProjectClassPage;
|
import se.su.dsv.scipro.admin.pages.settings.AdminFinalSeminarSettingsPerProjectClassPage;
|
||||||
import se.su.dsv.scipro.admin.pages.settings.AdminGeneralSettingsPage;
|
import se.su.dsv.scipro.admin.pages.settings.AdminGeneralSettingsPage;
|
||||||
import se.su.dsv.scipro.admin.pages.settings.AdminPeerSettingsPage;
|
import se.su.dsv.scipro.admin.pages.settings.AdminPeerSettingsPage;
|
||||||
|
import se.su.dsv.scipro.admin.pages.settings.AdminServerEnvironmentSettingsPage;
|
||||||
import se.su.dsv.scipro.basepages.DemoPage;
|
import se.su.dsv.scipro.basepages.DemoPage;
|
||||||
import se.su.dsv.scipro.basepages.errorpages.AccessDeniedPage;
|
import se.su.dsv.scipro.basepages.errorpages.AccessDeniedPage;
|
||||||
import se.su.dsv.scipro.basepages.errorpages.NotFoundPage;
|
import se.su.dsv.scipro.basepages.errorpages.NotFoundPage;
|
||||||
@ -104,9 +105,8 @@ public class SciProApplication extends RepositoryApplication implements IThemabl
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Logger instance.
|
* Logger instance.
|
||||||
* @TODO Inject
|
|
||||||
*/
|
*/
|
||||||
private Logger logger = Logger.getLogger(this.getClass());
|
private Logger logger = Logger.getLogger(SciProApplication.class);
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
@ -191,6 +191,7 @@ public class SciProApplication extends RepositoryApplication implements IThemabl
|
|||||||
mountBookmarkablePage("admin/files", SysAdminFilePage.class);
|
mountBookmarkablePage("admin/files", SysAdminFilePage.class);
|
||||||
mountBookmarkablePage("admin/allfinalseminars", AdminFinalSeminarPage.class);
|
mountBookmarkablePage("admin/allfinalseminars", AdminFinalSeminarPage.class);
|
||||||
mountBookmarkablePage("admin/settings", AdminGeneralSettingsPage.class);
|
mountBookmarkablePage("admin/settings", AdminGeneralSettingsPage.class);
|
||||||
|
mountBookmarkablePage("admin/settings/serverenvironment", AdminServerEnvironmentSettingsPage.class);
|
||||||
mountBookmarkablePage("admin/settings/finalseminargeneralsettings", AdminFinalSeminarSettingsPage.class);
|
mountBookmarkablePage("admin/settings/finalseminargeneralsettings", AdminFinalSeminarSettingsPage.class);
|
||||||
mountBookmarkablePage("admin/settings/finalseminarprojectlevel", AdminFinalSeminarSettingsPerProjectClassPage.class);
|
mountBookmarkablePage("admin/settings/finalseminarprojectlevel", AdminFinalSeminarSettingsPerProjectClassPage.class);
|
||||||
mountBookmarkablePage("admin/settings/peer", AdminPeerSettingsPage.class);
|
mountBookmarkablePage("admin/settings/peer", AdminPeerSettingsPage.class);
|
||||||
@ -310,7 +311,7 @@ public class SciProApplication extends RepositoryApplication implements IThemabl
|
|||||||
public WebRequest newWebRequest(final HttpServletRequest request){
|
public WebRequest newWebRequest(final HttpServletRequest request){
|
||||||
final WebRequest webRequest = super.newWebRequest(request);
|
final WebRequest webRequest = super.newWebRequest(request);
|
||||||
if(attemptExternalAuthentication(webRequest)){
|
if(attemptExternalAuthentication(webRequest)){
|
||||||
logger.debug("External authentication used");
|
logger.debug("External authentication used successfully");
|
||||||
}
|
}
|
||||||
return webRequest;
|
return webRequest;
|
||||||
}
|
}
|
||||||
@ -331,19 +332,19 @@ public class SciProApplication extends RepositoryApplication implements IThemabl
|
|||||||
if(session != null){
|
if(session != null){
|
||||||
if(session.isLoggedIn()){
|
if(session.isLoggedIn()){
|
||||||
if(!helper.isRemoteUserValid(session.getUser())){//This check may not be needed and may hinder performance, but better safe than sorry for now.
|
if(!helper.isRemoteUserValid(session.getUser())){//This check may not be needed and may hinder performance, but better safe than sorry for now.
|
||||||
logger.warn("User is logged in, but conflicting info is supplied via external authentication protocols.");
|
logger.debug("User is logged in as '"+session.getUser().getEmailAddress()+"', but conflicting info ('"+helper.getExternalAuthRemoteUser()+"') is supplied via external authentication protocols.");
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
//logger.info("Attempting sign in with external auth data");
|
//logger.info("Attempting sign in with external auth data");
|
||||||
if(!helper.signIn(session)){
|
if(!helper.signIn(session)){
|
||||||
logger.error("User passes external authentication but cannot be signed in.");
|
logger.error("User '"+helper.getExternalAuthRemoteUser()+"' passes external authentication but cannot be signed in.");
|
||||||
}else{
|
}else{
|
||||||
logger.debug("Signed in user '"+helper.getExternalAuthRemoteUser()+"' via external authentication");
|
logger.debug("Signed in user '"+helper.getExternalAuthRemoteUser()+"' via external authentication");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
throw new IllegalStateException("External authentication was attempted, but no session was available.");
|
throw new IllegalStateException("External authentication was attempted, but no session was available for sign in.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -207,7 +207,9 @@ public class SciProSession extends WebSession {
|
|||||||
* @return true if the switch was successful, else false.
|
* @return true if the switch was successful, else false.
|
||||||
*/
|
*/
|
||||||
public boolean switchAuthenticatedUser(final String suUser, final String suRealm){
|
public boolean switchAuthenticatedUser(final String suUser, final String suRealm){
|
||||||
logger.info("Currently logged in user: '"+user.getEmailAddress()+"' attempting switch to '"+suUser+"'");
|
if(!isLoggedIn() || user == null)//Terminate early
|
||||||
|
return false;
|
||||||
|
logger.info("Currently logged in user: '"+user.getEmailAddress()+"' attempting switch to '"+suUser+"@"+suRealm+"'");
|
||||||
if(suUser != null && roleDao.isSysadmin(user)){
|
if(suUser != null && roleDao.isSysadmin(user)){
|
||||||
iRoles.clear();
|
iRoles.clear();
|
||||||
return signInAuthenticatedUser(suUser, suRealm);
|
return signInAuthenticatedUser(suUser, suRealm);
|
||||||
|
@ -10,6 +10,7 @@ import se.su.dsv.scipro.admin.pages.settings.AdminFinalSeminarSettingsPage;
|
|||||||
import se.su.dsv.scipro.admin.pages.settings.AdminFinalSeminarSettingsPerProjectClassPage;
|
import se.su.dsv.scipro.admin.pages.settings.AdminFinalSeminarSettingsPerProjectClassPage;
|
||||||
import se.su.dsv.scipro.admin.pages.settings.AdminGeneralSettingsPage;
|
import se.su.dsv.scipro.admin.pages.settings.AdminGeneralSettingsPage;
|
||||||
import se.su.dsv.scipro.admin.pages.settings.AdminPeerSettingsPage;
|
import se.su.dsv.scipro.admin.pages.settings.AdminPeerSettingsPage;
|
||||||
|
import se.su.dsv.scipro.admin.pages.settings.AdminServerEnvironmentSettingsPage;
|
||||||
import se.su.dsv.scipro.components.AbstractMenuPanel;
|
import se.su.dsv.scipro.components.AbstractMenuPanel;
|
||||||
import se.su.dsv.scipro.icons.ImageIcon;
|
import se.su.dsv.scipro.icons.ImageIcon;
|
||||||
import se.su.dsv.scipro.security.auth.Authorization;
|
import se.su.dsv.scipro.security.auth.Authorization;
|
||||||
@ -29,6 +30,7 @@ public abstract class AbstractAdminSettingsPage extends AbstractAdminPage {
|
|||||||
protected List<MenuItem> getItemList() {
|
protected List<MenuItem> getItemList() {
|
||||||
final List<MenuItem> items = new ArrayList<MenuItem>();
|
final List<MenuItem> items = new ArrayList<MenuItem>();
|
||||||
items.add(new MenuItem("General settings", AdminGeneralSettingsPage.class));
|
items.add(new MenuItem("General settings", AdminGeneralSettingsPage.class));
|
||||||
|
items.add(new MenuItem("Server Environment", AdminServerEnvironmentSettingsPage.class));
|
||||||
items.add(new MenuItem("Final seminar general settings", AdminFinalSeminarSettingsPage.class));
|
items.add(new MenuItem("Final seminar general settings", AdminFinalSeminarSettingsPage.class));
|
||||||
items.add(new MenuItem("Final seminar project level settings", AdminFinalSeminarSettingsPerProjectClassPage.class));
|
items.add(new MenuItem("Final seminar project level settings", AdminFinalSeminarSettingsPerProjectClassPage.class));
|
||||||
items.add(new MenuItem("Peer settings", AdminPeerSettingsPage.class /*,ImageIcon.ICON_SETTINGS */));
|
items.add(new MenuItem("Peer settings", AdminPeerSettingsPage.class /*,ImageIcon.ICON_SETTINGS */));
|
||||||
|
17
src/main/java/se/su/dsv/scipro/admin/pages/settings/AdminServerEnvironmentSettingsPage.html
Normal file
17
src/main/java/se/su/dsv/scipro/admin/pages/settings/AdminServerEnvironmentSettingsPage.html
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html
|
||||||
|
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
|
||||||
|
<body>
|
||||||
|
<wicket:extend>
|
||||||
|
<h3 class="section">Server/Request environment</h3>
|
||||||
|
<div style="overflow:auto;height:50%;">
|
||||||
|
<ul>
|
||||||
|
<li wicket:id="requestAttributes">
|
||||||
|
<span wicket:id="name">[name]</span>:
|
||||||
|
<span wicket:id="value">[value]</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</wicket:extend>
|
||||||
|
</body>
|
||||||
|
</html>
|
49
src/main/java/se/su/dsv/scipro/admin/pages/settings/AdminServerEnvironmentSettingsPage.java
Normal file
49
src/main/java/se/su/dsv/scipro/admin/pages/settings/AdminServerEnvironmentSettingsPage.java
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package se.su.dsv.scipro.admin.pages.settings;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.wicket.PageParameters;
|
||||||
|
import org.apache.wicket.markup.html.basic.Label;
|
||||||
|
import org.apache.wicket.markup.html.list.ListItem;
|
||||||
|
import org.apache.wicket.markup.html.list.ListView;
|
||||||
|
|
||||||
|
import se.su.dsv.scipro.admin.pages.AbstractAdminSettingsPage;
|
||||||
|
import se.su.dsv.scipro.util.KeyValuePair;
|
||||||
|
|
||||||
|
public class AdminServerEnvironmentSettingsPage extends AbstractAdminSettingsPage {
|
||||||
|
public AdminServerEnvironmentSettingsPage(final PageParameters pp) {
|
||||||
|
super(pp);
|
||||||
|
add(new ListView<KeyValuePair<String>>("requestAttributes",getRequestAttributes()){
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
@Override
|
||||||
|
protected void populateItem(ListItem<KeyValuePair<String>> item){
|
||||||
|
KeyValuePair<String> pair = item.getModelObject();
|
||||||
|
item.add(new Label("name",pair.getKey()));
|
||||||
|
item.add(new Label("value","'"+pair.getValue()+"'"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private List<KeyValuePair<String>> getRequestAttributes(){
|
||||||
|
final HttpServletRequest rawRequest = getWebRequestCycle().getWebRequest().getHttpServletRequest();
|
||||||
|
List<KeyValuePair<String>> list = new ArrayList<KeyValuePair<String>>();
|
||||||
|
list.add(new KeyValuePair<String>("[CALL] getRemoteUser",rawRequest.getRemoteUser()));
|
||||||
|
list.add(new KeyValuePair<String>("[CALL] getAuthType",rawRequest.getAuthType()));
|
||||||
|
@SuppressWarnings("rawtypes") Enumeration attributes = rawRequest.getAttributeNames();
|
||||||
|
while(attributes.hasMoreElements()){
|
||||||
|
final String key = (String)attributes.nextElement();
|
||||||
|
final String value = rawRequest.getAttribute(key).toString();
|
||||||
|
list.add(new KeyValuePair<String>("[ATTR] "+key,value));
|
||||||
|
}
|
||||||
|
Map<String,String> envs = System.getenv();
|
||||||
|
for(String key : envs.keySet()){
|
||||||
|
list.add(new KeyValuePair<String>("[ENV] "+key,envs.get(key)));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,5 @@
|
|||||||
package se.su.dsv.scipro.security.auth;
|
package se.su.dsv.scipro.security.auth;
|
||||||
|
|
||||||
import java.security.Policy.Parameters;
|
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -8,7 +7,10 @@ import java.util.Set;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
import org.apache.wicket.injection.web.InjectorHolder;
|
||||||
|
import org.apache.wicket.spring.injection.annot.SpringBean;
|
||||||
|
|
||||||
|
import se.su.dsv.scipro.ApplicationSettings;
|
||||||
import se.su.dsv.scipro.SciProSession;
|
import se.su.dsv.scipro.SciProSession;
|
||||||
import se.su.dsv.scipro.data.dataobjects.User;
|
import se.su.dsv.scipro.data.dataobjects.User;
|
||||||
import se.su.dsv.scipro.data.dataobjects.Username;
|
import se.su.dsv.scipro.data.dataobjects.Username;
|
||||||
@ -30,18 +32,24 @@ public final class ExternalAuthenticationRequestHelper{
|
|||||||
//Wrapped request
|
//Wrapped request
|
||||||
private final HttpServletRequest req;
|
private final HttpServletRequest req;
|
||||||
//remote user attribute
|
//remote user attribute
|
||||||
private String remoteUser;
|
private String remoteUser=null;
|
||||||
//if remote user is on the username@realm form, this attribute holds the username
|
//if remote user is on the username@realm form, this attribute holds the username
|
||||||
private String remoteUserId;
|
private String remoteUserId=null;
|
||||||
//if remote user is on the username@realm form, this attribute holds the realm
|
//if remote user is on the username@realm form, this attribute holds the realm
|
||||||
private String remoteUserRealm;
|
private String remoteUserRealm=null;
|
||||||
//logger instance
|
//logger instance
|
||||||
private Logger logger = Logger.getLogger(this.getClass());
|
private Logger logger = Logger.getLogger(this.getClass());
|
||||||
|
@SpringBean
|
||||||
|
private ApplicationSettings appSettings;
|
||||||
/**
|
/**
|
||||||
* Construct a utility wrapper from a servlet request.
|
* Construct a utility wrapper from a servlet request.
|
||||||
|
* Throws IllegalStateException if the request is null.
|
||||||
* @param request
|
* @param request
|
||||||
*/
|
*/
|
||||||
public ExternalAuthenticationRequestHelper(final HttpServletRequest request){
|
public ExternalAuthenticationRequestHelper(final HttpServletRequest request) throws IllegalStateException{
|
||||||
|
if(request==null)
|
||||||
|
throw new IllegalStateException("Request is null, this is considered illegal.");
|
||||||
|
InjectorHolder.getInjector().inject(this);
|
||||||
req = request;
|
req = request;
|
||||||
formatUserString();
|
formatUserString();
|
||||||
}
|
}
|
||||||
@ -54,7 +62,7 @@ public final class ExternalAuthenticationRequestHelper{
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Exposed query method.
|
* Exposed query method.
|
||||||
* @return If remote user is on the username@realm form, this attribute holds the userid, else getExternalAuthRemoteUser().
|
* @return If remote user is on the username@realm form, this attribute holds the username, else getExternalAuthRemoteUser().
|
||||||
*/
|
*/
|
||||||
public String getExternalAuthRemoteUserId(){
|
public String getExternalAuthRemoteUserId(){
|
||||||
return remoteUserId;
|
return remoteUserId;
|
||||||
@ -70,7 +78,7 @@ public final class ExternalAuthenticationRequestHelper{
|
|||||||
* Internal query method
|
* Internal query method
|
||||||
*/
|
*/
|
||||||
private boolean isExternalAuthInfoOnRequest(){
|
private boolean isExternalAuthInfoOnRequest(){
|
||||||
return (req.getRemoteUser()!=null);
|
return (remoteUser!=null);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Internal query method
|
* Internal query method
|
||||||
@ -83,12 +91,16 @@ public final class ExternalAuthenticationRequestHelper{
|
|||||||
* @return true if the application is configured to accept external authentication and the needed information is available on the request, else false.
|
* @return true if the application is configured to accept external authentication and the needed information is available on the request, else false.
|
||||||
*/
|
*/
|
||||||
public boolean isExternalAuthSupported(){
|
public boolean isExternalAuthSupported(){
|
||||||
return (true && isExternalAuthInfoOnRequest());
|
if(appSettings.isAcceptExternalAuthentication() && !isExternalAuthInfoOnRequest())
|
||||||
|
logger.warn("External authentication support is ON, but REMOTE_USER is not populated");
|
||||||
|
if(!appSettings.isAcceptExternalAuthentication() && isExternalAuthInfoOnRequest())
|
||||||
|
logger.warn("External authentication support is OFF, but REMOTE_USER is populated");
|
||||||
|
return (appSettings.isAcceptExternalAuthentication() && isExternalAuthInfoOnRequest());
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Private utility method for dumping headers.
|
* Private utility method for dumping headers.
|
||||||
*/
|
*/
|
||||||
public void dumpAuthInfo(){
|
private void dumpAuthInfo(){
|
||||||
logger.debug("---Standard methods---");
|
logger.debug("---Standard methods---");
|
||||||
logger.debug("Request implementation:" + req.getClass().getName());
|
logger.debug("Request implementation:" + req.getClass().getName());
|
||||||
logger.debug("getAuthType = '" + getExternalAuthType() +"'");
|
logger.debug("getAuthType = '" + getExternalAuthType() +"'");
|
||||||
@ -165,12 +177,12 @@ public final class ExternalAuthenticationRequestHelper{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Signs the stored remote user in on the given SciProSession.
|
* Signs the stored remote user in on the supplied SciProSession.
|
||||||
* @param session
|
* @param session If null, method fails gracefully by returning false.
|
||||||
* @return true on success, else false.
|
* @return true on success, else false.
|
||||||
*/
|
*/
|
||||||
public boolean signIn(final SciProSession session){
|
public boolean signIn(final SciProSession session){
|
||||||
if(session != null){
|
if(session != null && isExternalAuthSupported()){
|
||||||
//dumpAuthInfo();
|
//dumpAuthInfo();
|
||||||
return session.signInAuthenticatedUser(getExternalAuthRemoteUserId(), getExternalAuthRemoteUserRealm());
|
return session.signInAuthenticatedUser(getExternalAuthRemoteUserId(), getExternalAuthRemoteUserRealm());
|
||||||
}
|
}
|
||||||
|
79
src/main/java/se/su/dsv/scipro/util/KeyValuePair.java
Normal file
79
src/main/java/se/su/dsv/scipro/util/KeyValuePair.java
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package se.su.dsv.scipro.util;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Small utility class for immutable (yes it's immutable and no it's never going to be otherwise) key/value pairs.
|
||||||
|
* The "value" field is parameterized, but the key is always intended to be a simple String.
|
||||||
|
* The Serializable properties of this depends on those of the parameterized type.
|
||||||
|
* Typical usage:
|
||||||
|
* <code>
|
||||||
|
* KeyValuePair<SomeType> pair = new KeyValuePair<SomeType>("thisIsAKey",someObject);
|
||||||
|
* pair.getKey();
|
||||||
|
* pair.getValue();
|
||||||
|
* </code>
|
||||||
|
* @param <V>
|
||||||
|
*/
|
||||||
|
public final class KeyValuePair<V> implements Serializable{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final String key;
|
||||||
|
private final V value;
|
||||||
|
/**
|
||||||
|
* Default and only constructor, provide key and value.
|
||||||
|
* null values are accepted for both key and value, and should be safe to use (yet nonsensical).
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
public KeyValuePair(final String key, final V value){
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Getter for wrapped key String
|
||||||
|
* @return The key
|
||||||
|
*/
|
||||||
|
public String getKey(){
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Getter for wrapped Value
|
||||||
|
* @return The value
|
||||||
|
*/
|
||||||
|
public V getValue(){
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Equals override, behaves in a logical fashion (two objects are equal if both key and value matches).
|
||||||
|
* Null values are accounted for, ie: two objects with null key+value are considered equal.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o){
|
||||||
|
if(o==this)
|
||||||
|
return true;
|
||||||
|
if(!(o instanceof KeyValuePair))
|
||||||
|
return false;
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final KeyValuePair<V> other = (KeyValuePair<V>)o;
|
||||||
|
return ((key==null?other.key==null:key.equals(other.key)) &&
|
||||||
|
(value==null?other.value==null:value.equals(other.value)));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Hash-code override, uses both components in a standard fashion.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode(){
|
||||||
|
final int w = 31;
|
||||||
|
int result = 17;//Why hello there Mr Bloch, how are we feeling today ?
|
||||||
|
result = w * result + (key==null?0:key.hashCode());
|
||||||
|
result = w * result + (value==null?0:value.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Standard override, return String format not exposed and subject to change.
|
||||||
|
* Any parsing of this representation is strongly advised against and done at your own risk.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return ("{"+key+":"+value+"}");
|
||||||
|
}
|
||||||
|
}
|
@ -83,6 +83,8 @@
|
|||||||
<property name="enableRemoteUserLookup" value="true"></property>
|
<property name="enableRemoteUserLookup" value="true"></property>
|
||||||
<!-- This property points to the location of the daisy json search -->
|
<!-- This property points to the location of the daisy json search -->
|
||||||
<property name="remoteLookupUrl" value="https://thesis.dsv.su.se/match/json" />
|
<property name="remoteLookupUrl" value="https://thesis.dsv.su.se/match/json" />
|
||||||
|
<!-- External auth support (via J2EE standard mechanism REMOTE_USER), if true: other authentication mechanics will be bypassed.-->
|
||||||
|
<property name="acceptExternalAuthentication" value="true"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- Defines the class used for lookup in username against a remote server NOW AUTOWIRED AND DEPRECATED, NOT MAINTAINED-->
|
<!-- Defines the class used for lookup in username against a remote server NOW AUTOWIRED AND DEPRECATED, NOT MAINTAINED-->
|
||||||
|
@ -0,0 +1,192 @@
|
|||||||
|
package se.su.dsv.scipro.security.auth;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequestWrapper;
|
||||||
|
|
||||||
|
import org.apache.wicket.protocol.http.HttpSessionStore;
|
||||||
|
import org.apache.wicket.session.ISessionStore;
|
||||||
|
import org.apache.wicket.spring.injection.annot.SpringComponentInjector;
|
||||||
|
import org.apache.wicket.spring.test.ApplicationContextMock;
|
||||||
|
import org.apache.wicket.util.tester.WicketTester;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.invocation.InvocationOnMock;
|
||||||
|
import org.mockito.stubbing.Answer;
|
||||||
|
import org.springframework.orm.jpa.LocalEntityManagerFactoryBean;
|
||||||
|
|
||||||
|
import se.su.dsv.scipro.ApplicationSettings;
|
||||||
|
import se.su.dsv.scipro.SciProApplication;
|
||||||
|
import se.su.dsv.scipro.SciProSession;
|
||||||
|
import se.su.dsv.scipro.data.dao.interfaces.ProjectDao;
|
||||||
|
import se.su.dsv.scipro.data.dao.interfaces.RoleDao;
|
||||||
|
import se.su.dsv.scipro.data.dao.interfaces.StringResourceDao;
|
||||||
|
import se.su.dsv.scipro.data.dao.interfaces.UserDao;
|
||||||
|
import se.su.dsv.scipro.data.dao.interfaces.UserSettingsDao;
|
||||||
|
import se.su.dsv.scipro.data.dataobjects.Role;
|
||||||
|
import se.su.dsv.scipro.data.dataobjects.Student;
|
||||||
|
import se.su.dsv.scipro.data.dataobjects.SysAdmin;
|
||||||
|
import se.su.dsv.scipro.data.dataobjects.User;
|
||||||
|
import se.su.dsv.scipro.data.dataobjects.Username;
|
||||||
|
import se.su.dsv.scipro.json.IUserLookup;
|
||||||
|
import se.su.dsv.scipro.repository.util.RepositoryManager;
|
||||||
|
|
||||||
|
public class TestAuthRoutines {
|
||||||
|
private SciProSession session;
|
||||||
|
private WicketTester wt;
|
||||||
|
private User user;
|
||||||
|
private Role sysAdm;
|
||||||
|
private IUserLookup fixedLookup;
|
||||||
|
private ApplicationSettings appSettings;
|
||||||
|
@Before
|
||||||
|
public void init(){
|
||||||
|
final ApplicationContextMock ac = new ApplicationContextMock();
|
||||||
|
//Create mock object in need of config
|
||||||
|
appSettings = new ApplicationSettings();
|
||||||
|
appSettings.setAcceptExternalAuthentication(true);
|
||||||
|
//Fake a lookup mechanism
|
||||||
|
fixedLookup = new IUserLookup(){
|
||||||
|
@Override
|
||||||
|
public User lookup(String username) throws Exception{
|
||||||
|
if(username.equals("kalle-kula"))
|
||||||
|
return user;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//Create mock user and associated data
|
||||||
|
user = new User();
|
||||||
|
user.setDateCreated(new Date());
|
||||||
|
user.setEmailAddress("kalle-kula@dsv.su.se");
|
||||||
|
user.setFirstName("Kalle");
|
||||||
|
user.setLastName("Kula");
|
||||||
|
user.setIdentifier(new Long(666));
|
||||||
|
user.setLastModified(new Date());
|
||||||
|
Set<Role> roles = new HashSet<Role>();
|
||||||
|
//Faked student
|
||||||
|
Role role = new Student();
|
||||||
|
role.setId(new Long(555));
|
||||||
|
role.setUser(user);
|
||||||
|
roles.add(new Student());
|
||||||
|
user.setRoles(roles);
|
||||||
|
//Faked sysadm, added later
|
||||||
|
sysAdm = new SysAdmin();
|
||||||
|
sysAdm.setId(new Long(444));
|
||||||
|
Set<Username> usernames = new HashSet<Username>();
|
||||||
|
Username username = new Username();
|
||||||
|
username.setUserName("kalle-kula");
|
||||||
|
username.setRealm("DSV.SU.SE");
|
||||||
|
usernames.add(username);
|
||||||
|
user.setUserNames(usernames);
|
||||||
|
//Put stuff on bean context
|
||||||
|
ac.putBean("entityManagerFactory",Mockito.mock(LocalEntityManagerFactoryBean.class));
|
||||||
|
ac.putBean("repositoryManager",Mockito.mock(RepositoryManager.class));
|
||||||
|
ac.putBean("applicationSettings",appSettings);
|
||||||
|
ac.putBean("userDao",Mockito.mock(UserDao.class));
|
||||||
|
ac.putBean("stringResourceDao",Mockito.mock(StringResourceDao.class));
|
||||||
|
RoleDao mockedRoleDao = Mockito.mock(RoleDao.class);
|
||||||
|
Mockito.when(mockedRoleDao.isSysadmin(user)).thenAnswer(new Answer<Boolean>() {
|
||||||
|
@Override
|
||||||
|
public Boolean answer(InvocationOnMock invocation) throws Throwable {
|
||||||
|
return user.getRoles().contains(sysAdm);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ac.putBean("roleDao",mockedRoleDao);
|
||||||
|
ac.putBean("projectDao",Mockito.mock(ProjectDao.class));
|
||||||
|
ac.putBean("userSettingsDao",Mockito.mock(UserSettingsDao.class));
|
||||||
|
ac.putBean("userFullLookup",fixedLookup);
|
||||||
|
//Create tester
|
||||||
|
wt = new WicketTester(new SciProApplication(){
|
||||||
|
@Override
|
||||||
|
protected ISessionStore newSessionStore(){
|
||||||
|
return new HttpSessionStore(this);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected SpringComponentInjector getSpringInjector() {
|
||||||
|
return new SpringComponentInjector(this, ac, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
wt.setupRequestAndResponse();
|
||||||
|
session = (SciProSession)wt.getWicketSession();
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testAuthenticationHelper() throws IllegalStateException {
|
||||||
|
//Try with faulty request
|
||||||
|
ExternalAuthenticationRequestHelper helper = new ExternalAuthenticationRequestHelper(wt.getServletRequest());
|
||||||
|
Assert.assertFalse(helper.isExternalAuthSupported());
|
||||||
|
Assert.assertTrue(helper.getExternalAuthRemoteUser()==null);
|
||||||
|
Assert.assertTrue(helper.getExternalAuthRemoteUserId()==null);
|
||||||
|
Assert.assertTrue(helper.getExternalAuthRemoteUserRealm().equals("DSV.SU.SE"));
|
||||||
|
Assert.assertFalse(helper.isRemoteUserValid(user));
|
||||||
|
Assert.assertFalse(helper.signIn(null));
|
||||||
|
//Try with conforming request
|
||||||
|
helper = new ExternalAuthenticationRequestHelper(new HttpServletRequestWrapper(wt.getServletRequest()){
|
||||||
|
@Override
|
||||||
|
public String getRemoteUser(){
|
||||||
|
return "kalle-kula@dsv.su.se";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Assert.assertTrue(helper.isExternalAuthSupported());
|
||||||
|
Assert.assertTrue(helper.getExternalAuthRemoteUser().equals("kalle-kula@dsv.su.se"));
|
||||||
|
Assert.assertTrue(helper.getExternalAuthRemoteUserId().equals("kalle-kula"));
|
||||||
|
Assert.assertTrue(helper.getExternalAuthRemoteUserRealm().equals("DSV.SU.SE"));
|
||||||
|
Assert.assertTrue(helper.isRemoteUserValid(user));
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testTurnOffViaSettings(){
|
||||||
|
appSettings.setAcceptExternalAuthentication(false);
|
||||||
|
ExternalAuthenticationRequestHelper helper = new ExternalAuthenticationRequestHelper(wt.getServletRequest());
|
||||||
|
Assert.assertFalse(helper.isExternalAuthSupported());
|
||||||
|
}
|
||||||
|
@Test(expected=IllegalStateException.class)
|
||||||
|
public void testNullRequest(){
|
||||||
|
//At this point, an exception should be thrown
|
||||||
|
new ExternalAuthenticationRequestHelper(null);
|
||||||
|
}
|
||||||
|
@Test(expected=NullPointerException.class)
|
||||||
|
public void testSessionSignInAndSu(){
|
||||||
|
ExternalAuthenticationRequestHelper helper = new ExternalAuthenticationRequestHelper(new HttpServletRequestWrapper(wt.getServletRequest()){
|
||||||
|
@Override
|
||||||
|
public String getRemoteUser(){
|
||||||
|
return "kalle-kula@dsv.su.se";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Assert.assertTrue(helper.isExternalAuthSupported());
|
||||||
|
Assert.assertTrue(helper.signIn(session));
|
||||||
|
Assert.assertTrue(helper.isRemoteUserValid(user));
|
||||||
|
Assert.assertTrue(session.isLoggedIn());
|
||||||
|
Assert.assertTrue(session.getUser().getIdentifier().equals(user.getIdentifier()));
|
||||||
|
//User not authorized to switch, this should fail
|
||||||
|
Assert.assertFalse(session.switchAuthenticatedUser("kalle-kula", "dsv.su.se"));
|
||||||
|
//Change his roles and try again
|
||||||
|
Set<Role> roles = user.getRoles();
|
||||||
|
sysAdm.setUser(user);
|
||||||
|
roles.add(sysAdm);
|
||||||
|
user.setRoles(roles);
|
||||||
|
Assert.assertTrue(session.switchAuthenticatedUser("kalle-kula", "dsv.su.se"));
|
||||||
|
Assert.assertTrue(session.getUser().getIdentifier().equals(user.getIdentifier()));
|
||||||
|
//This should fail with an exception, there is no such user
|
||||||
|
session.switchAuthenticatedUser("somebody","somewhere.se");
|
||||||
|
}
|
||||||
|
@Test(expected=NullPointerException.class)
|
||||||
|
public void testFailedAuthenticatedSignIn(){
|
||||||
|
ExternalAuthenticationRequestHelper helper = new ExternalAuthenticationRequestHelper(new HttpServletRequestWrapper(wt.getServletRequest()){
|
||||||
|
@Override
|
||||||
|
public String getRemoteUser(){
|
||||||
|
return "some-dude@ki.se";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//This should throw exceptions, not sure about this interface (throwing exceptions when authentication passes but no user can be located).
|
||||||
|
helper.signIn(session);
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testFailedSwitchAuthentitedUser(){
|
||||||
|
Assert.assertFalse(session.isLoggedIn());
|
||||||
|
Assert.assertFalse(session.switchAuthenticatedUser("some-dude-who-is-not-real","someplace.se"));
|
||||||
|
Assert.assertFalse(session.switchAuthenticatedUser("some-dude","someplace.se"));
|
||||||
|
}
|
||||||
|
}
|
22
src/test/java/se/su/dsv/scipro/util/TestKeyValuePair.java
Normal file
22
src/test/java/se/su/dsv/scipro/util/TestKeyValuePair.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package se.su.dsv.scipro.util;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TestKeyValuePair {
|
||||||
|
@Test
|
||||||
|
public void testEqualsOperations() {
|
||||||
|
KeyValuePair<String> kvpOne = new KeyValuePair<String>("key","value");
|
||||||
|
KeyValuePair<String> kvpTwo = new KeyValuePair<String>("key","value");
|
||||||
|
KeyValuePair<String> kvpThree = new KeyValuePair<String>("key3","value");
|
||||||
|
KeyValuePair<String> kvpFour = new KeyValuePair<String>(null,null);
|
||||||
|
KeyValuePair<TestKeyValuePair> kvpFive = new KeyValuePair<TestKeyValuePair>("key",this);
|
||||||
|
|
||||||
|
Assert.assertTrue(kvpOne.equals(kvpOne));
|
||||||
|
Assert.assertTrue(kvpFour.equals(kvpFour));
|
||||||
|
Assert.assertTrue(kvpOne.equals(kvpTwo) && kvpTwo.equals(kvpOne));
|
||||||
|
Assert.assertFalse(kvpOne.equals(kvpThree) && kvpThree.equals(kvpOne));
|
||||||
|
Assert.assertFalse(kvpFour.equals(kvpThree) && kvpThree.equals(kvpFour));
|
||||||
|
Assert.assertFalse(kvpOne.equals(kvpFive) && kvpFive.equals(kvpOne));
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,7 @@ import org.mockito.stubbing.Answer;
|
|||||||
import org.springframework.orm.jpa.EntityManagerFactoryInfo;
|
import org.springframework.orm.jpa.EntityManagerFactoryInfo;
|
||||||
import org.springframework.orm.jpa.LocalEntityManagerFactoryBean;
|
import org.springframework.orm.jpa.LocalEntityManagerFactoryBean;
|
||||||
|
|
||||||
|
import se.su.dsv.scipro.ApplicationSettings;
|
||||||
import se.su.dsv.scipro.SciProApplication;
|
import se.su.dsv.scipro.SciProApplication;
|
||||||
import se.su.dsv.scipro.data.controllers.FinalSeminarUploadController;
|
import se.su.dsv.scipro.data.controllers.FinalSeminarUploadController;
|
||||||
import se.su.dsv.scipro.data.dao.interfaces.BoardMessageDao;
|
import se.su.dsv.scipro.data.dao.interfaces.BoardMessageDao;
|
||||||
@ -95,6 +96,7 @@ public class BaseWicketTest {
|
|||||||
@Mock GroupEventDao groupEventDao;
|
@Mock GroupEventDao groupEventDao;
|
||||||
@Mock HandInActivityDao handInActivityDao;
|
@Mock HandInActivityDao handInActivityDao;
|
||||||
@Mock ScheduleTemplateDao scheduleTemplateDao;
|
@Mock ScheduleTemplateDao scheduleTemplateDao;
|
||||||
|
@Mock ApplicationSettings applicationSettings;
|
||||||
|
|
||||||
@Mock RepositoryManager repositoryManager;
|
@Mock RepositoryManager repositoryManager;
|
||||||
@Mock StringResourceDao stringResourceDao;
|
@Mock StringResourceDao stringResourceDao;
|
||||||
|
@ -8,6 +8,7 @@ import org.mockito.Mockito;
|
|||||||
import se.su.dsv.scipro.HomePage;
|
import se.su.dsv.scipro.HomePage;
|
||||||
import se.su.dsv.scipro.admin.pages.AdminProjectPartnerPage;
|
import se.su.dsv.scipro.admin.pages.AdminProjectPartnerPage;
|
||||||
import se.su.dsv.scipro.admin.pages.SystemMaintenancePage;
|
import se.su.dsv.scipro.admin.pages.SystemMaintenancePage;
|
||||||
|
import se.su.dsv.scipro.admin.pages.settings.AdminServerEnvironmentSettingsPage;
|
||||||
import se.su.dsv.scipro.data.dataobjects.GeneralSystemSettings;
|
import se.su.dsv.scipro.data.dataobjects.GeneralSystemSettings;
|
||||||
import se.su.dsv.scipro.data.dataobjects.Project;
|
import se.su.dsv.scipro.data.dataobjects.Project;
|
||||||
import se.su.dsv.scipro.data.dataobjects.ProjectClass;
|
import se.su.dsv.scipro.data.dataobjects.ProjectClass;
|
||||||
@ -178,6 +179,11 @@ public class TestWicketPages extends BaseWicketTest {
|
|||||||
public void testProjectPartnerPage() {
|
public void testProjectPartnerPage() {
|
||||||
tester.startPage(ProjectPartnerPage.class);
|
tester.startPage(ProjectPartnerPage.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAdminServerEnvironmentSettingsPage(){
|
||||||
|
tester.startPage(AdminServerEnvironmentSettingsPage.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user