Omfattande tillägg kring rollhantering

git-svn-id: svn://svn.dsv.su.se/scipro/scipro/trunk@12 73ecded7-942e-4092-bab0-0e58ef0ee984
This commit is contained in:
mpeters 2011-01-26 15:56:34 +00:00
parent 3045a60dcb
commit 4d44d38026
16 changed files with 494 additions and 50 deletions

@ -17,6 +17,7 @@ import org.apache.wicket.protocol.http.WebRequest;
import org.apache.wicket.protocol.http.WebSession;
import org.apache.wicket.spring.injection.annot.SpringBean;
import se.su.dsv.scipro.data.dao.interfaces.RoleDao;
import se.su.dsv.scipro.data.dao.interfaces.UserDao;
import se.su.dsv.scipro.data.dataobjects.User;
import se.su.dsv.scipro.security.auth.Authenticator;
@ -39,7 +40,8 @@ public class SciProSession extends WebSession {
@SpringBean
private UserDao userDao;
@SpringBean
private RoleDao roleDao;
private List<Role> roles = new ArrayList<Role>();
private User user = null;
@ -56,7 +58,7 @@ public class SciProSession extends WebSession {
this.setLocale(Locale.ENGLISH);
else if(cookie.getValue().equals("sv"))
this.setLocale(new Locale("sv","SE"));
}
}
}
@ -130,24 +132,24 @@ public class SciProSession extends WebSession {
* Here we switch the logged in user to be that of the person chosen be the logged in admin
*/
if(userDao.isAdmin(user) && loggedInAsUsername != null){
if(roleDao.isSysadmin(user) && loggedInAsUsername != null){
this.user = userDao.getUserByUsername(loggedInAsUsername);
if( user == null)
throw new NullPointerException("No user with this username found in the database, despite successful authentication");
}
if(userDao.isStudent(user)){
if(roleDao.isStudent(user)){
roles.add(new Student());
}
if(userDao.isExternal(user)){
if(roleDao.isExternal(user)){
roles.add(new External());
}
if(userDao.isEmployee(user)){
if(roleDao.isEmployee(user)){
roles.add(new Employee());
}
if(userDao.isAdmin(user)){
if(roleDao.isAdmin(user)){
roles.add(new Admin());
}
if(userDao.isSysadmin(user)){
if(roleDao.isSysadmin(user)){
roles.add(new SysAdmin());
}

@ -1,10 +1,14 @@
package se.su.dsv.scipro.basepages;
import org.apache.wicket.Component;
import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.CSSPackageResource;
import org.apache.wicket.markup.html.WebPage;
import se.su.dsv.scipro.security.auth.Authorization;
import se.su.dsv.scipro.security.auth.ComponentSecurity;
import se.su.dsv.scipro.security.auth.MetaDataActionStrategy;
import se.su.dsv.scipro.security.auth.SecurityFailAction;
import se.su.dsv.scipro.security.auth.roles.Roles;
@Authorization(requiresLoggedInUser = true, authorizedRoles = {Roles.STUDENT, Roles.ADMIN, Roles.EMPLOYEE, Roles.EXTERNAL, Roles.SYSADMIN})
@ -33,5 +37,37 @@ public abstract class BasePage extends WebPage {
//add(CSSPackageResource.getHeaderContribution("styles/" + GLOBAL_CSS + CSS_SUFFIX));
add(CSSPackageResource.getHeaderContribution("styles/" + css + CSS_SUFFIX));
}
/**
* Convenience method to authorize actions RENDER and ENABLE on a component based on user roles.
*/
public void authorize(Component component, Roles role){
MetaDataActionStrategy.authorize(component, role);
}
/**
* Convenience method to authorize actions RENDER and ENABLE on a component based on user roles.
*/
public void authorize(Component component, Roles[] roles){
MetaDataActionStrategy.authorize(component, roles);
}
/**
* Convenience method to authorize actions RENDER and ENABLE on a component based on user roles.
* removeOnFail = true means the component won't be rendered at all if authorization fails.
* removeOnFail = false means the component will be rendered in a disabled state if authorization fails.
*/
public void authorize(Component component, Roles role, boolean removeOnFail){
MetaDataActionStrategy.authorize(component, role, removeOnFail);
}
/**
* Convenience method to authorize actions RENDER and ENABLE on a component based on user roles.
* removeOnFail = true means the component won't be rendered at all if authorization fails.
* removeOnFail = false means the component will be rendered in a disabled state if authorization fails.
*/
public void authorize(Component component, Roles[] roles, boolean removeOnFail){
MetaDataActionStrategy.authorize(component, roles, removeOnFail);
}
}

@ -0,0 +1,18 @@
package se.su.dsv.scipro.data.dao.interfaces;
import se.su.dsv.scipro.data.dataobjects.Role;
import se.su.dsv.scipro.data.dataobjects.User;
public interface RoleDao extends LazyDeleteDao<Role> {
public boolean isStudent(final User user);
public boolean isExternal(final User user);
public boolean isEmployee(final User user);
public boolean isAdmin(final User user);
public boolean isSysadmin(final User user);
}

@ -10,14 +10,4 @@ public interface UserDao extends LazyDeleteDao<User> {
public User getUserByEmail(final String emailAddress);
public boolean isStudent(final User user);
public boolean isExternal(final User user);
public boolean isEmployee(final User user);
public boolean isAdmin(final User user);
public boolean isSysadmin(final User user);
}

@ -0,0 +1,95 @@
package se.su.dsv.scipro.data.dao.jpa;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceException;
import javax.persistence.TypedQuery;
import org.springframework.orm.jpa.JpaCallback;
import org.springframework.transaction.annotation.Transactional;
import se.su.dsv.scipro.data.dao.interfaces.RoleDao;
import se.su.dsv.scipro.data.dataobjects.Role;
import se.su.dsv.scipro.data.dataobjects.User;
public class RoleDaoJPAImp extends LazyDeleteAbstractDaoJPAImpl<Role> implements
RoleDao {
public RoleDaoJPAImp() {
super(Role.class);
}
@Transactional
public boolean isStudent(final User user) {
return getJpaTemplate().execute(new JpaCallback<Boolean>() {
public Boolean doInJpa(EntityManager em)
throws PersistenceException {
TypedQuery<Role> query = em.createQuery("SELECT s FROM Student s WHERE s.user = :user AND s.deleted = false", Role.class);
query.setParameter("user", user);
try{
query.getSingleResult();
return true;
} catch (NoResultException e) {
return false;
}
}
});
}
@Transactional
public boolean isExternal(final User user) {
return false; //Not implemented
}
@Transactional
public boolean isEmployee(final User user) {
return getJpaTemplate().execute(new JpaCallback<Boolean>() {
public Boolean doInJpa(EntityManager em)
throws PersistenceException {
TypedQuery<Role> query = em.createQuery("SELECT e FROM Employee e WHERE e.user = :user AND e.deleted = false", Role.class);
query.setParameter("user", user);
try{
query.getSingleResult();
return true;
} catch (NoResultException e) {
return false;
}
}
});
}
@Transactional
public boolean isAdmin(final User user) {
return getJpaTemplate().execute(new JpaCallback<Boolean>() {
public Boolean doInJpa(EntityManager em)
throws PersistenceException {
TypedQuery<Role> query = em.createQuery("SELECT a FROM Admin a WHERE a.user = :user AND a.deleted = false", Role.class);
query.setParameter("user", user);
try{
query.getSingleResult();
return true;
} catch (NoResultException e) {
return false;
}
}
});
}
@Transactional
public boolean isSysadmin(final User user) {
return getJpaTemplate().execute(new JpaCallback<Boolean>() {
public Boolean doInJpa(EntityManager em)
throws PersistenceException {
TypedQuery<Role> query = em.createQuery("SELECT sa FROM SysAdmin sa WHERE sa.user = :user AND sa.deleted = false", Role.class);
query.setParameter("user", user);
try{
query.getSingleResult();
return true;
} catch (NoResultException e) {
return false;
}
}
});
}
}

@ -67,29 +67,4 @@ public class UserDaoJPAImp extends LazyDeleteAbstractDaoJPAImpl<User> implements
});
}
public boolean isStudent(final User user) {
// TODO Auto-generated method stub
return true;
}
public boolean isExternal(final User user) {
// TODO Auto-generated method stub
return false;
}
public boolean isEmployee(final User user) {
// TODO Auto-generated method stub
return false;
}
public boolean isAdmin(final User user) {
// TODO Auto-generated method stub
return false;
}
public boolean isSysadmin(final User user) {
// TODO Auto-generated method stub
return false;
}
}

@ -0,0 +1,20 @@
package se.su.dsv.scipro.data.dataobjects;
import javax.persistence.Cacheable;
import javax.persistence.Entity;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
/**
* @author Martin Peters - mpeters@se.su.dsv
*
*/
@Entity
@Cacheable(true)
@Cache(usage= CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) //Hibernate specific
public class Admin extends Role {
private static final long serialVersionUID = -2570983581219033271L;
}

@ -0,0 +1,20 @@
package se.su.dsv.scipro.data.dataobjects;
import javax.persistence.Cacheable;
import javax.persistence.Entity;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
/**
* @author Martin Peters - mpeters@se.su.dsv
*
*/
@Entity
@Cacheable(true)
@Cache(usage= CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) //Hibernate specific
public class Employee extends Role {
private static final long serialVersionUID = -2570983581219033271L;
}

@ -0,0 +1,96 @@
package se.su.dsv.scipro.data.dataobjects;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
@Entity
@DiscriminatorColumn(name = "rolename", discriminatorType = DiscriminatorType.STRING, length = 8)
@Table(name="role", uniqueConstraints={@UniqueConstraint(columnNames={"user_id","rolename"}, name = "role_is_unique")})
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public abstract class Role extends LazyDeletableDomainObject {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private Long id;
@ManyToOne(optional=false)
protected User user;
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return the id
*/
public Long getId() {
return id;
}
/**
* @param user the user to set
*/
public void setUser(User user) {
this.user = user;
}
/**
* @return the user
*/
public User getUser() {
return user;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((user == null) ? 0 : user.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Role other = (Role) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (user == null) {
if (other.user != null)
return false;
} else if (!user.equals(other.user))
return false;
return true;
}
@Override
public String toString() {
String tmp = user.getFirstName() + " " + user.getLastName();
if(user.getEmailAddress() != null)
tmp = tmp + " (" + user.getEmailAddress() + ")";
return tmp;
}
}

@ -0,0 +1,21 @@
package se.su.dsv.scipro.data.dataobjects;
import javax.persistence.Cacheable;
import javax.persistence.Entity;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
/**
* @author Martin Peters - mpeters@se.su.dsv
*
*/
@Entity
@Cacheable(true)
@Cache(usage= CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) //Hibernate specific
public class Student extends Role {
private static final long serialVersionUID = 6274323425191904206L;
}

@ -0,0 +1,21 @@
package se.su.dsv.scipro.data.dataobjects;
import javax.persistence.Cacheable;
import javax.persistence.Entity;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
/**
* @author Martin Peters - mpeters@se.su.dsv
*
*/
@Entity
@Cacheable(true)
@Cache(usage= CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) //Hibernate specific
public class SysAdmin extends Role {
private static final long serialVersionUID = -2570983581219033271L;
}

@ -4,6 +4,7 @@ import java.util.HashSet;
import java.util.Set;
import javax.persistence.Cacheable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
@ -40,6 +41,19 @@ public class User extends LazyDeletableDomainObject {
@OneToMany(mappedBy="user")
private Set<Username> usernames = new HashSet<Username>();
@OneToMany(mappedBy="user")
private Set<Role> roles = new HashSet<Role>();
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
public Set<Role> getRoles() {
//Return a copy of the set so no roles can be added into the real collection
return new HashSet<Role>(roles);
}
public Long getId() {
return id;
}

@ -6,7 +6,6 @@ import org.apache.wicket.PageParameters;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
@ -17,15 +16,18 @@ import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import se.su.dsv.scipro.basepages.BasePage;
import se.su.dsv.scipro.basepages.PublicPage;
import se.su.dsv.scipro.data.dao.interfaces.EventDao;
import se.su.dsv.scipro.data.dao.interfaces.RoleDao;
import se.su.dsv.scipro.data.dao.interfaces.UserDao;
import se.su.dsv.scipro.data.dataobjects.Admin;
import se.su.dsv.scipro.data.dataobjects.Event;
import se.su.dsv.scipro.security.auth.Authorization;
import se.su.dsv.scipro.security.auth.Authorization.ON_AUTH_FAIL;
import se.su.dsv.scipro.data.dataobjects.Student;
import se.su.dsv.scipro.data.dataobjects.User;
import se.su.dsv.scipro.security.auth.ComponentSecurity;
import se.su.dsv.scipro.security.auth.MetaDataActionStrategy;
import se.su.dsv.scipro.security.auth.SecurityFailAction;
import se.su.dsv.scipro.security.auth.roles.Roles;
import se.su.dsv.scipro.security.auth.roles.Student;
/**
* @author Richard Wilkinson - richard.wilkinson@jweekend.com
*
@ -34,11 +36,16 @@ public class EventPage extends BasePage {
@SpringBean
private EventDao eventDao;
@SpringBean
private RoleDao roleDao;
@SpringBean
private UserDao userDao;
Form<Event> eventForm;
public EventPage(final PageParameters pp)
{
eventForm = new Form<Event>("eventForm", new CompoundPropertyModel<Event>(new Event()));
eventForm.add(new TextField<String>("title").setRequired(true));
eventForm.add(new TextField<String>("location").setRequired(true));

@ -58,4 +58,50 @@ public class MetaDataActionStrategy implements IAuthorizationStrategy {
return true;
}
/*
* Convenience methods for component-based action authorization
*/
/**
* Convenience method to authorize actions RENDER and ENABLE on a component based on user roles.
*/
public static void authorize(Component component, Roles role){
ComponentSecurity cs = new ComponentSecurity(role, SecurityFailAction.REMOVE);
component.setMetaData(MetaDataActionStrategy.AUTHORIZED_ROLES, cs );
}
/**
* Convenience method to authorize actions RENDER and ENABLE on a component based on user roles.
*/
public static void authorize(Component component, Roles[] roles){
ComponentSecurity cs = new ComponentSecurity(roles, SecurityFailAction.REMOVE);
component.setMetaData(MetaDataActionStrategy.AUTHORIZED_ROLES, cs );
}
/**
* Convenience method to authorize actions RENDER and ENABLE on a component based on user roles.
* removeOnFail = true means the component won't be rendered at all if authorization fails.
* removeOnFail = false means the component will be rendered in a disabled state if authorization fails.
*/
public static void authorize(Component component, Roles role, boolean removeOnFail){
ComponentSecurity cs;
if(removeOnFail)
cs = new ComponentSecurity(role, SecurityFailAction.REMOVE);
else
cs = new ComponentSecurity(role, SecurityFailAction.DISABLE);
component.setMetaData(MetaDataActionStrategy.AUTHORIZED_ROLES, cs );
}
/**
* Convenience method to authorize actions RENDER and ENABLE on a component based on user roles.
* removeOnFail = true means the component won't be rendered at all if authorization fails.
* removeOnFail = false means the component will be rendered in a disabled state if authorization fails.
*/
public static void authorize(Component component, Roles[] roles, boolean removeOnFail){
ComponentSecurity cs;
if(removeOnFail)
cs = new ComponentSecurity(roles, SecurityFailAction.REMOVE);
else
cs = new ComponentSecurity(roles, SecurityFailAction.DISABLE);
component.setMetaData(MetaDataActionStrategy.AUTHORIZED_ROLES, cs );
}
}

@ -1,6 +1,7 @@
package se.su.dsv.scipro.security.auth;
import org.apache.wicket.Component;
import org.apache.wicket.RequestCycle;
import org.apache.wicket.RestartResponseAtInterceptPageException;
import org.apache.wicket.authorization.Action;
import org.apache.wicket.authorization.IAuthorizationStrategy;
@ -66,12 +67,12 @@ public class RoleBasedAuthorizationStrategy implements IAuthorizationStrategy {
}//There was an annotation present
//TODO: Remove this println
System.out.println("RoleBasedAuthorisationStrategy says authorized: "+ok+" for action "+action.getName()+" on component "+component.getClass());
//System.out.println("RoleBasedAuthorisationStrategy says authorized: "+ok+" for action "+action.getName()+" on component "+component.getClass());
return ok;
}
public <T extends Component> boolean isInstantiationAuthorized(Class<T> componentClass) {
public <T extends Component> boolean isInstantiationAuthorized(Class<T> componentClass) {
//Not annotated classes aren't checked further
Authorization annotation = (Authorization) componentClass.getAnnotation(Authorization.class);
if (annotation != null) {

@ -0,0 +1,82 @@
package se.su.dsv.scipro.security.auth;
/*
import org.opensaml.saml2.core.Attribute;
import org.opensaml.xml.XMLObject;
import org.opensaml.xml.schema.XSString;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.saml.SAMLCredential;
import org.springframework.security.saml.userdetails.SAMLUserDetailsService;
import se.su.dsv.daisy.model.authorisation.LoginCredentials;
import se.su.dsv.daisy.security.authorization.Permission;
import se.su.dsv.daisy.service.AuthorizationService;
import se.su.dsv.daisy.service.LoginCredentialsService;
*/
import javax.annotation.Resource;
import java.util.HashSet;
/**
* Created by IntelliJ IDEA.
* User: herder
* Date: 2010-jun-14
* Time: 16:41:13
*/
public abstract class SciProSAMLUserDetailsService {//implements SAMLUserDetailsService {
private String principalNameKey;
/*
@Resource
private LoginCredentialsService service;
@Resource
private AuthorizationService authorizationService;
public void setPrincipalNameKey(String uidKey) {
this.principalNameKey = uidKey;
}
@Override
public UserDetails loadUserBySAML(SAMLCredential credential) throws UsernameNotFoundException {
System.out.println("SAMLLOADUSERCALLED");
Attribute attribute = credential.getAttributeByName(principalNameKey);
for (XMLObject xmlObject : attribute.getAttributeValues()) {
if (xmlObject instanceof XSString) {
XSString xsString = (XSString) xmlObject;
System.out.println(xsString);
String[] strings = xsString.getValue().split("@");
if (strings.length >= 2) {
final String username = strings[0];
final String realm = strings[1];
LoginCredentials loginCredentials = service.getLoginCredentials(username, realm);
if (loginCredentials != null) {
final HashSet<GrantedAuthority> hashSet = new HashSet<GrantedAuthority>();
if (authorizationService.isAuthorized(loginCredentials.getId(), null, Permission.SYSADMIN)) {
hashSet.add(new GrantedAuthority() {
@Override
public String getAuthority() {
return "ROLE_ADMIN";
}
});
}
hashSet.add(new GrantedAuthority() {
@Override
public String getAuthority() {
return "ROLE_USER";
}
});
return new DaisyUser(loginCredentials.getPerson().getId(), loginCredentials.getUsername(), loginCredentials.getUsername(), loginCredentials.isEnabled(), false, !loginCredentials.isExpired(), !loginCredentials.isLocked(), hashSet);
}
return new UnknownUser(username, "****", false, true, true, false, new HashSet<GrantedAuthority>());
}
}
}
throw new UsernameNotFoundException("User not found: " + attribute.getAttributeValues());
}
*/
}