Commit 622d0999 authored by Matija Obreza's avatar Matija Obreza

ACL implemented on Team, uses pricipal.username as SID

parent e0cdbda2
......@@ -32,7 +32,7 @@
<hibernate.version>4.2.7.SP1</hibernate.version>
<hibernate.annotations.version>4.0.4.Final</hibernate.annotations.version>
<hsqldb.version>2.3.1</hsqldb.version>
<ehcache.version>2.7.0</ehcache.version>
<ehcache.version>2.7.4</ehcache.version>
<slf4j.version>1.7.5</slf4j.version>
<log4j.version>1.2.17</log4j.version>
......
......@@ -28,4 +28,9 @@ public interface TeamRepository extends JpaRepository<Team, Long> {
@Query("select t from Team t where ?1 member of t.members")
List<Team> listForUser(User user);
Team findOneByUuid(String uuid);
@Query("select t.members from Team t where t = ?1")
List<User> listMembers(Team team);
}
......@@ -23,6 +23,7 @@ import org.genesys2.server.model.impl.Team;
import org.genesys2.server.model.impl.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
public interface TeamService {
......@@ -43,7 +44,7 @@ public interface TeamService {
* @param user
* @return
*/
@PreAuthorize("hasRole('ADMINISTRATOR')")
@PreAuthorize("hasRole('ADMINISTRATOR') || hasPermission(#team, 'CREATE')")
Team addTeamMember(Team team, User user);
/**
......@@ -52,7 +53,7 @@ public interface TeamService {
* @param team
* @param user
*/
@PreAuthorize("hasRole('ADMINISTRATOR')")
@PreAuthorize("hasRole('ADMINISTRATOR') || hasPermission(#team, 'CREATE')")
Team removeTeamMember(Team team, User user);
/**
......@@ -64,7 +65,6 @@ public interface TeamService {
void removeMe(long teamId);
@PreAuthorize("hasRole('ADMINISTRATOR')")
Team addTeamInstitute(Team team, FaoInstitute institute);
......@@ -94,5 +94,10 @@ public interface TeamService {
@PreAuthorize("hasRole('ADMINISTRATOR')")
Page<Team> listTeams(Pageable pageable);
@PostAuthorize("hasRole('ADMINISTRATOR') or hasPermission(returnObject, 'READ')")
Team getTeam(String uuid);
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#team, 'READ')")
List<User> getMembers(Team team);
}
......@@ -39,11 +39,13 @@ import org.springframework.security.acls.model.Permission;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* TODO Add support for cleaning up after objects are removed
*/
@Service
@Transactional
public class AclAssignerServiceImpl implements AclAssignerService {
private static final Logger LOG = LoggerFactory.getLogger(AclAssignerServiceImpl.class);
......
......@@ -32,6 +32,7 @@ import org.genesys2.server.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
......@@ -49,8 +50,17 @@ public class TeamServiceImpl implements TeamService {
@Autowired
private UserService userService;
@Override
@PostAuthorize("hasRole('ADMINISTRATOR') or hasPermission(returnObject, 'READ')")
public Team getTeam(String uuid) {
Team team = teamRepository.findOneByUuid(uuid);
System.err.println("Loaded by uuid: " + team);
return team;
}
@Override
@Transactional(readOnly = false)
@PreAuthorize("isAuthenticated()")
public Team addTeam(String name) {
User user = getCurrentUser();
......@@ -68,7 +78,7 @@ public class TeamServiceImpl implements TeamService {
@Override
@Transactional(readOnly = false)
@PreAuthorize("hasRole('ADMINISTRATOR')")
@PreAuthorize("hasRole('ADMINISTRATOR') || hasPermission(#team, 'CREATE')")
public Team addTeamMember(Team team, User user) {
if (team.getMembers().contains(user)) {
LOG.info("User already member of this team");
......@@ -82,7 +92,7 @@ public class TeamServiceImpl implements TeamService {
}
@Override
@PreAuthorize("hasRole('ADMINISTRATOR')")
@PreAuthorize("hasRole('ADMINISTRATOR') || hasPermission(#team, 'CREATE')")
@Transactional(readOnly = false)
public Team removeTeamMember(Team team, User user) {
if (team.getMembers().remove(user)) {
......@@ -96,12 +106,14 @@ public class TeamServiceImpl implements TeamService {
@Override
@Transactional(readOnly = false)
@PreAuthorize("isAuthenticated()")
public void removeMe(long teamId) {
removeMe(teamRepository.findOne(teamId));
}
@Override
@Transactional(readOnly = false)
@PreAuthorize("isAuthenticated()")
public void removeMe(Team team) {
User user = getCurrentUser();
boolean removed = team.getMembers().remove(user);
......@@ -154,6 +166,7 @@ public class TeamServiceImpl implements TeamService {
}
@Override
@PreAuthorize("isAuthenticated()")
public List<Team> listMyTeams() {
User user = getCurrentUser();
return listUserTeams(user);
......@@ -169,4 +182,10 @@ public class TeamServiceImpl implements TeamService {
public Page<Team> listTeams(Pageable pageable) {
return teamRepository.findAll(pageable);
}
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#team, 'READ')")
public List<User> getMembers(Team team) {
return teamRepository.listMembers(team);
}
}
/**
* Copyright 2013 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
package org.genesys2.server.servlet.controller;
import org.genesys2.server.model.impl.Team;
import org.genesys2.server.service.ContentService;
import org.genesys2.server.service.InstituteService;
import org.genesys2.server.service.TeamService;
import org.genesys2.spring.ResourceNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@Scope("request")
@RequestMapping("/team")
public class TeamController extends BaseController {
@Autowired
private InstituteService instituteService;
@Autowired
private ContentService contentService;
@Autowired
private TeamService teamService;
@RequestMapping("")
@PreAuthorize("hasRole('ADMINISTRATOR')")
public String viewAll(ModelMap model, @RequestParam(value = "page", required = false, defaultValue = "1") int page) {
model.addAttribute("pagedData", teamService.listTeams(new PageRequest(page - 1, 50, new Sort("name"))));
return "/team/index";
}
@RequestMapping("/{teamUuid}")
public String viewTeam(ModelMap model, @PathVariable(value = "teamUuid") String uuid) {
Team team = teamService.getTeam(uuid);
if (team == null) {
throw new ResourceNotFoundException();
}
model.addAttribute("team", team);
model.addAttribute("teammembers", teamService.getMembers(team));
model.addAttribute("blurp", contentService.getArticle(team, "blurp", getLocale()));
return "/team/details";
}
}
......@@ -310,3 +310,7 @@ team.user-teams=User's Teams
team.create-new-team=Create a new team
team.team-name=Team name
team.leave-team=Leave team
team.team-members=Team members
team.page.profile.title=Team: {0}
team.page.list.title=All teams
......@@ -14,44 +14,22 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<!--Default cache settings-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
overflowToDisk="false"/>
<!--ACL in-memory cache-->
<cache name="sparsedata"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
overflowToDisk="false" />
<cache name="sparseentry"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
overflowToDisk="false" />
<!--CACHEABLE CACHES-->
<!--ACL in-memory cache-->
<cache name="acl"
maxElementsInMemory="0"
maxBytesLocalHeap="64M"
eternal="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
overflowToDisk="false"/>
<!--HIBERNATE L2 CACHES-->
<!--Here are specific caches for all persistence models-->
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<!--Default cache settings -->
<defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="1800" timeToLiveSeconds="3600" overflowToDisk="false" />
<!--ACL in-memory cache -->
<cache name="sparsedata" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="1800" timeToLiveSeconds="3600" overflowToDisk="false" />
<cache name="sparseentry" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="1800" timeToLiveSeconds="3600" overflowToDisk="false" />
<!--CACHEABLE CACHES -->
<!--ACL in-memory cache -->
<cache name="acl" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="1800" timeToLiveSeconds="3600" overflowToDisk="false" />
<!--HIBERNATE L2 CACHES -->
<!--Here are specific caches for all persistence models -->
</ehcache>
......@@ -14,64 +14,50 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean name="aclAuthorizationStrategy" class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
<constructor-arg index="0">
<list value-type="org.springframework.security.core.authority.SimpleGrantedAuthority">
<!--TODO review-->
<!--TODO review -->
<value>ADMINISTRATOR</value>
</list>
</constructor-arg>
</bean>
<bean name="slf4jAuditLogger" class="org.genesys2.server.security.Slf4jAuditLogger"/>
<bean name="slf4jAuditLogger" class="org.genesys2.server.security.Slf4jAuditLogger" />
<bean name="permissionGrantingStrategy" class="org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy">
<constructor-arg index="0" type="org.springframework.security.acls.domain.AuditLogger"
ref="slf4jAuditLogger"/>
<constructor-arg type="org.springframework.security.acls.domain.AuditLogger" ref="slf4jAuditLogger" />
</bean>
<bean name="aclCacheBean" factory-bean="ehCacheManager" factory-method="addCacheIfAbsent">
<constructor-arg index="0" type="java.lang.String" value="acl"/>
<constructor-arg type="java.lang.String" value="acl" />
</bean>
<bean name="aclCache" class="org.springframework.security.acls.domain.EhCacheBasedAclCache">
<constructor-arg index="0" type="net.sf.ehcache.Ehcache"
ref="aclCacheBean"/>
<constructor-arg index="1" type="org.springframework.security.acls.model.PermissionGrantingStrategy"
ref="permissionGrantingStrategy"/>
<constructor-arg index="2" type="org.springframework.security.acls.domain.AclAuthorizationStrategy"
ref="aclAuthorizationStrategy"/>
<constructor-arg type="net.sf.ehcache.Ehcache" ref="aclCacheBean" />
<constructor-arg type="org.springframework.security.acls.model.PermissionGrantingStrategy" ref="permissionGrantingStrategy" />
<constructor-arg type="org.springframework.security.acls.domain.AclAuthorizationStrategy" ref="aclAuthorizationStrategy" />
</bean>
<bean name="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
<constructor-arg index="0" type="javax.sql.DataSource"
ref="dataSource"/>
<constructor-arg index="1" type="org.springframework.security.acls.model.AclCache"
ref="aclCache"/>
<constructor-arg index="2" type="org.springframework.security.acls.domain.AclAuthorizationStrategy"
ref="aclAuthorizationStrategy"/>
<constructor-arg index="3" type="org.springframework.security.acls.model.PermissionGrantingStrategy"
ref="permissionGrantingStrategy"/>
<constructor-arg type="javax.sql.DataSource" ref="dataSource" />
<constructor-arg type="org.springframework.security.acls.model.AclCache" ref="aclCache" />
<constructor-arg type="org.springframework.security.acls.domain.AclAuthorizationStrategy" ref="aclAuthorizationStrategy" />
<constructor-arg type="org.springframework.security.acls.model.PermissionGrantingStrategy" ref="permissionGrantingStrategy" />
</bean>
<!-- FIXME Should not be using JdbcMutableAclService, but own service! -->
<bean name="aclService" class="org.springframework.security.acls.jdbc.JdbcMutableAclService">
<constructor-arg index="0" type="javax.sql.DataSource"
ref="dataSource"/>
<constructor-arg index="1" type="org.springframework.security.acls.jdbc.LookupStrategy"
ref="lookupStrategy"/>
<constructor-arg index="2" type="org.springframework.security.acls.model.AclCache"
ref="aclCache"/>
<constructor-arg type="javax.sql.DataSource" ref="dataSource" />
<constructor-arg type="org.springframework.security.acls.jdbc.LookupStrategy" ref="lookupStrategy" />
<constructor-arg type="org.springframework.security.acls.model.AclCache" ref="aclCache" />
</bean>
<bean name="permissionEvaluator" class="org.springframework.security.acls.AclPermissionEvaluator">
<constructor-arg index="0" type="org.springframework.security.acls.model.AclService"
ref="aclService"/>
<constructor-arg index="0" type="org.springframework.security.acls.model.AclService" ref="aclService" />
</bean>
</beans>
<!DOCTYPE html>
<%@include file="/WEB-INF/jsp/init.jsp"%>
<html>
<head>
<title><spring:message code="team.page.profile.title" arguments="${team.name}" argumentSeparator="||" /></title>
</head>
<body>
<h1>
<c:out value="${team.name}" />
</h1>
<h4>
<spring:message code="team.team-members" arguments="${teammembers.size()}" />
</h4>
<ul class="funny-list">
<c:forEach items="${teammembers}" var="user" varStatus="status">
<li class="${status.count % 2 == 0 ? 'even' : 'odd'}">
<c:out value="${user.name}" />
</li>
</c:forEach>
</ul>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<%@include file="/WEB-INF/jsp/init.jsp"%>
<html>
<head>
<title><spring:message code="team.page.list.title" /></title>
</head>
<body>
<h1>
<spring:message code="team.page.list.title" />
</h1>
<div class="nav-header">
<spring:message code="paged.totalElements" arguments="${pagedData.totalElements}" />
<br />
<spring:message code="paged.pageOfPages" arguments="${pagedData.number+1},${pagedData.totalPages}" />
<a class="${pagedData.number eq 0 ? 'disabled' :''}" href="?page=${pagedData.number eq 0 ? 1 : pagedData.number}"><spring:message code="pagination.previous-page" /></a> <a href="?page=${pagedData.number + 2}"><spring:message code="pagination.next-page" /></a>
</div>
<ul class="funny-list">
<c:forEach items="${pagedData.content}" var="team" varStatus="status">
<li class="clearfix ${status.count % 2 == 0 ? 'even' : 'odd'}">
<a href="<c:url value="/team/${team.uuid}" />"><c:out value="${team.name}" /></a>
</li>
</c:forEach>
</ul>
</body>
</html>
\ No newline at end of file
......@@ -49,7 +49,7 @@
<label for="team-name" class="col-lg-2 control-label"><spring:message code="team.team-name" /></label>
<div class="col-lg-3"><input type="text" name="name" id="team-name" class="span3 form-control" /></div>
<div class="col-lg-1">
<input type="submit" value="<spring:message code="create"/>" class="btn btn-primary" />
<input type="submit" value="<spring:message code="create" />" class="btn btn-primary" />
</div>
</div>
</form>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment