Commit 07ce3c22 authored by Matija Obreza's avatar Matija Obreza
Browse files

Merge branch '259-upgrade-appblocks' into 'master'

Resolve "Upgrade appblocks"

Closes #259

See merge request genesys-pgr/genesys-server!152
parents 777c00f8 5fc545d8
......@@ -58,7 +58,7 @@
<snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory>
<junit.version>4.12</junit.version>
<application.blocks.version>1.3</application.blocks.version>
<application.blocks.version>1.4-SNAPSHOT</application.blocks.version>
<commons.beanutils.version>1.9.2</commons.beanutils.version>
<commons.collections.version>3.2.1</commons.collections.version>
<commons.fileupload.version>1.3.1</commons.fileupload.version>
......
......@@ -21,6 +21,7 @@ import java.util.Arrays;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.genesys.blocks.security.service.BasicUserService;
import org.genesys2.server.model.UserRole;
import org.genesys2.server.model.impl.User;
import org.genesys2.server.service.UserService;
......@@ -80,7 +81,7 @@ public class AsAdminAspect {
public synchronized Authentication getSystemAdminAccount() {
if (SYS_ADMIN == null) {
LOG.warn("SYS_ADMIN not loaded. Loading now.");
final User sysUser = userService.getSystemUser("SYSTEM");
final User sysUser = userService.getUserByEmail(BasicUserService.SYSTEM_ADMIN);
if (sysUser == null) {
LOG.warn("Temporary SYS_ADMIN account is being used.");
......
......@@ -49,19 +49,13 @@ public class CreateAdminListener extends RunAsAdminListener {
if (userService.listUsers(new PageRequest(0, 1)).getTotalElements() == 0) {
createDefaultAccounts();
}
if (userService.getSystemUser("SYSTEM") == null) {
createAdmin("SYSTEM", "SYSTEM", null, AccountType.SYSTEM);
}
}
private void createDefaultAccounts() throws UserException, PasswordPolicyException {
createAdmin("SYSTEM", "SYSTEM", null, AccountType.SYSTEM);
createAdmin(defaultAdminEmail, "First Admin", defaultAdminPassword, AccountType.LOCAL);
}
private void createAdmin(String email, String fullName, String password, AccountType accountType) throws UserException, PasswordPolicyException {
final User user = userService.createUser(email, fullName, password, accountType);
userService.setRoles(user, Sets.newHashSet(UserRole.ADMINISTRATOR));
LOG.warn("Admin account for " + email + " has been successfully added.");
......
......@@ -19,7 +19,9 @@ package org.genesys2.server.model;
import org.springframework.security.core.GrantedAuthority;
public enum UserRole implements GrantedAuthority {
USER("User"), ADMINISTRATOR("Administrator"), VALIDATEDUSER("Validated user"), VETTEDUSER("Vetted user"), CONTENTMANAGER("Content Manager");
USER("User"), ADMINISTRATOR("Administrator"), VALIDATEDUSER("Validated user"), VETTEDUSER("Vetted user"), CONTENTMANAGER("Content Manager"),
/** Everyone role */
EVERYONE("Everyone");
String label;
......
......@@ -95,7 +95,6 @@ public class AccessionDetails {
private String donorNumb;
private Date lastModifiedDate;
private Date acqusitionDate;
private Float pdciScore;
private boolean historic;
......@@ -464,14 +463,6 @@ public class AccessionDetails {
this.lastModifiedDate = lastModifiedDate;
}
public Date getAcqusitionDate() {
return acqusitionDate;
}
public void setAcqusitionDate(Date acqusitionDate) {
this.acqusitionDate = acqusitionDate;
}
public Boolean getArt15() {
return art15;
}
......
......@@ -27,12 +27,9 @@ import org.springframework.transaction.annotation.Transactional;
@Transactional
public interface UserRepository extends JpaRepository<User, Long> {
@Query("select u from User u where u.email = ?1 and u.accountType != 'SYSTEM'")
@Query("select u from User u where lower(u.email) = lower(?1)")
User findByEmail(String email);
@Query("select u from User u where u.email = ?1 and u.accountType = 'SYSTEM'")
User findSystemUser(String username);
User findByUuid(String uuid);
@Query("select u from User u where u.email like ?1 and u.accountType != 'SYSTEM'")
......
......@@ -46,8 +46,6 @@ public interface UserService extends BasicUserService<UserRole, User> {
UserWrapper getWrappedById(long userId) throws UserException;
User getSystemUser(String string);
Page<User> listUsers(Pageable pageable);
boolean checkPasswordsMatch(String rawPassword, String encodedPassword);
......
......@@ -1113,9 +1113,7 @@ public class BatchRESTServiceImpl implements BatchRESTService {
}
}
// Add or update
for (
final AccessionAliasJson aa : aliases) {
for (final AccessionAliasJson aa : aliases) {
AccessionAlias accessionAlias = CollectionUtils.find(existingAliases, new Predicate<AccessionAlias>() {
@Override
public boolean evaluate(AccessionAlias alias) {
......
......@@ -19,6 +19,7 @@ package org.genesys2.server.service.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
......@@ -50,6 +51,7 @@ import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
......@@ -60,6 +62,8 @@ import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.google.common.collect.Sets;
@Service(value = "userService")
@Transactional(readOnly = true)
public class UserServiceImpl extends BasicUserServiceImpl<UserRole, User> implements UserService {
......@@ -86,6 +90,23 @@ public class UserServiceImpl extends BasicUserServiceImpl<UserRole, User> implem
return UserRole.USER;
}
@Override
protected JpaRepository<User, Long> getUserRepository() {
return userRepository;
}
@Override
protected User createSystemAdministrator(String username) throws UserException {
final User admin = createUser(username, "System Administrator", null, AccountType.SYSTEM);
setRoles(admin, Sets.newHashSet(UserRole.ADMINISTRATOR));
return admin;
}
@Override
public Collection<UserRole> getDefaultUserRoles() {
return Sets.newHashSet(UserRole.USER, UserRole.EVERYONE);
}
@Override
@Transactional
public User createUser(String email, String fullName, String password, AccountType accountType) throws UserException {
......@@ -274,15 +295,6 @@ public class UserServiceImpl extends BasicUserServiceImpl<UserRole, User> implem
return user;
}
@Override
public User getSystemUser(String username) {
User sysUser = userRepository.findSystemUser(username);
if (sysUser != null) {
sysUser.getRoles().size();
}
return sysUser;
}
@Override
public boolean exists(String username) {
return userRepository.findByEmail(username) != null;
......
......@@ -41,14 +41,14 @@ public class AclEditController extends BaseController {
public String permissions(ModelMap model, @PathVariable(value = "clazz") String className, @PathVariable("id") long id,
@RequestParam(value = "back", required = false) String backUrl) {
final AclObjectIdentity objectIdentity = aclService.ensureObjectIdentity(className, id);
final AclObjectIdentity objectIdentity = aclService.ensureObjectIdentity(id, className);
model.addAttribute("aclObjectIdentity", objectIdentity);
if (objectIdentity != null) {
model.addAttribute("aclPermissions", aclService.getAvailablePermissions(className));
}
model.addAttribute("aclSids", aclService.getSids(id, className));
// Map<AclSid, Map<Permission, Boolean>>
model.addAttribute("aclEntries", aclService.getPermissions(id, className));
model.addAttribute("sidPermissions", aclService.getPermissions(id, className));
model.addAttribute("backUrl", backUrl);
model.addAttribute("roles", UserRole.values());
......
......@@ -144,6 +144,23 @@ public class OAuthManagementController extends BaseController {
return oauthClient;
}
@PreAuthorize("hasAnyRole('VETTEDUSER','ADMINISTRATOR')")
@RequestMapping(value = "/save-client", method = RequestMethod.POST, params = "action-secret")
public String generateSecret(Model model, @RequestParam("id") String clientId) {
OAuthClient oauthClient = clientDetailsService.getClient(clientId);
String clientSecret = clientDetailsService.resetSecret(oauthClient);
model.addAttribute("clientSecret", clientSecret);
return clientDetailsInfo(model, clientId);
}
@PreAuthorize("hasAnyRole('VETTEDUSER','ADMINISTRATOR')")
@RequestMapping(value = "/save-client", method = RequestMethod.POST, params = "action-nosecret")
public String removeSecret(Model model, @RequestParam("id") String clientId) {
OAuthClient oauthClient = clientDetailsService.getClient(clientId);
clientDetailsService.removeSecret(oauthClient);
return clientDetailsInfo(model, clientId);
}
@PreAuthorize("hasAnyRole('VETTEDUSER','ADMINISTRATOR')")
@RequestMapping(value = "/save-client", method = RequestMethod.POST, params = { "id", "action-delete" })
public String deleteClient(Model model, @RequestParam("id") String clientId) {
......
......@@ -27,7 +27,6 @@ import org.genesys.blocks.security.service.CustomAclService;
import org.genesys2.server.model.impl.User;
import org.genesys2.server.service.UserService;
import org.genesys2.server.servlet.model.PermissionJson;
import org.genesys2.server.servlet.util.PermissionJsonUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
......@@ -55,15 +54,15 @@ public class PermissionController extends RestController {
@RequestMapping(value = "/add", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody Object addPermission(@RequestBody PermissionJson permissionJson) {
LOG.info("Adding permission {}", permissionJson);
final Map<Integer, Boolean> permissionMap = PermissionJsonUtil.createPermissionsMap(permissionJson);
final AclObjectIdentity oid = aclService.getObjectIdentity(permissionJson.getOid(), permissionJson.getClazz());
if (permissionJson.getAuthority() != null) {
final AclSid sid = aclService.getAuthoritySid(permissionJson.getAuthority());
aclService.addPermissions(permissionJson.getOid(), permissionJson.getClazz(), sid, permissionMap);
aclService.setPermissions(oid, sid, permissionJson);
} else if (permissionJson.getSid() != null) {
final AclSid sid = aclService.getSid(permissionJson.getSid());
aclService.addPermissions(permissionJson.getOid(), permissionJson.getClazz(), sid, permissionMap);
aclService.setPermissions(oid, sid, permissionJson);
}
return JSON_OK;
......@@ -71,16 +70,15 @@ public class PermissionController extends RestController {
@RequestMapping(value = "/update", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody Object updatePermissions(@RequestBody PermissionJson permissionJson) {
final Map<Integer, Boolean> permissionMap = PermissionJsonUtil.createPermissionsMap(permissionJson);
final AclObjectIdentity objectIdentity = aclService.ensureObjectIdentity(permissionJson.getClazz(), permissionJson.getOid());
final AclObjectIdentity objectIdentity = aclService.ensureObjectIdentity(permissionJson.getOid(), permissionJson.getClazz());
if (permissionJson.getAuthority() != null) {
final AclSid sid = aclService.getAuthoritySid(permissionJson.getAuthority());
aclService.updatePermissions(objectIdentity, sid, permissionMap);
aclService.setPermissions(objectIdentity, sid, permissionJson);
} else if (permissionJson.getSid() != null) {
final AclSid sid = aclService.getSid(permissionJson.getSid());
aclService.updatePermissions(objectIdentity, sid, permissionMap);
aclService.setPermissions(objectIdentity, sid, permissionJson);
}
return JSON_OK;
......@@ -98,7 +96,7 @@ public class PermissionController extends RestController {
@RequestMapping(value = "/autocomplete-oauth-client", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody Map<String, Long> acOauthClient(@RequestParam("term") String title) {
final Map<String, Long> oauthMap = new HashMap<>();
for (final OAuthClient client : clientDetailsService.autocompleteClients(title)) {
for (final OAuthClient client : clientDetailsService.autocompleteClients(title, 20)) {
oauthMap.put(client.getTitle(), client.getId());
}
return oauthMap;
......
......@@ -16,7 +16,9 @@
package org.genesys2.server.servlet.model;
public class PermissionJson {
import org.genesys.blocks.security.serialization.Permissions;
public class PermissionJson extends Permissions {
// sid
private Long sid;
private String authority;
......@@ -25,13 +27,6 @@ public class PermissionJson {
private long oid;
private String clazz;
// permissions
private boolean create;
private boolean read;
private boolean write;
private boolean delete;
private boolean manage;
@Override
public String toString() {
return "PJ oid=" + oid + " class=" + clazz + " (sid=" + sid + " OR authority=" + authority + ")";
......
......@@ -25,12 +25,18 @@ import static org.springframework.security.acls.domain.BasePermission.WRITE;
import java.util.HashMap;
import java.util.Map;
import org.genesys.blocks.security.serialization.Permissions;
import org.genesys2.server.servlet.model.PermissionJson;
public final class PermissionJsonUtil {
private PermissionJsonUtil() {
}
/**
* @deprecated Use {@link Permissions} instead.
* @param permissionJson
* @return
*/
public static Map<Integer, Boolean> createPermissionsMap(PermissionJson permissionJson) {
final Map<Integer, Boolean> permissionMap = new HashMap<>();
permissionMap.put(CREATE.getMask(), permissionJson.isCreate());
......@@ -40,5 +46,4 @@ public final class PermissionJsonUtil {
permissionMap.put(ADMINISTRATION.getMask(), permissionJson.isManage());
return permissionMap;
}
}
......@@ -16,8 +16,10 @@
package org.genesys2.spring.config;
import org.genesys.blocks.oauth.service.OAuthServiceImpl;
import org.genesys.blocks.oauth.util.AppBlocksInitializer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
......@@ -26,6 +28,7 @@ import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
......@@ -51,6 +54,12 @@ public class OAuth2ServerConfig {
return new OAuthServiceImpl();
}
// TODO Remove in 2.5
@Bean
protected AppBlocksInitializer appBlocksInitializer() {
return new AppBlocksInitializer();
}
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
......@@ -62,6 +71,7 @@ public class OAuth2ServerConfig {
@Override
public void configure(final HttpSecurity http) throws Exception {
/*@formatter:off*/
http.requestMatchers().antMatchers("/oauth/**", "/api/**").and()
// no sessions
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER).and()
......@@ -79,9 +89,9 @@ public class OAuth2ServerConfig {
.antMatcher("/api/v0/info/version").anonymous().and()
// others must be authenticated
.antMatcher("/api/**").authorizeRequests().anyRequest().authenticated()
// Ta
;
/*@formatter:on*/
}
}
......@@ -104,6 +114,9 @@ public class OAuth2ServerConfig {
@Autowired
@Qualifier("oauthService")
private ClientDetailsService clientDetailsService;
@Autowired
public PasswordEncoder passwordEncoder;
@Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
......@@ -117,7 +130,8 @@ public class OAuth2ServerConfig {
@Override
public void configure(final AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.allowFormAuthenticationForClients().checkTokenAccess("permitAll()").realm(APPLICATION_RESOURCE_ID + "/client");
oauthServer.allowFormAuthenticationForClients().checkTokenAccess("permitAll()").realm(APPLICATION_RESOURCE_ID + "/client")
.passwordEncoder(passwordEncoder); // added encoder
}
}
......@@ -129,6 +143,12 @@ public class OAuth2ServerConfig {
@Qualifier("oauthService")
private TokenStore tokenStore;
@Value("${default.oauth.accessToken.validity}")
private int accessTokenValiditySeconds;
@Value("${default.oauth.refreshToken.validity}")
private int refreshTokenValiditySeconds;
@Bean
public ApprovalStore approvalStore() throws Exception {
final TokenApprovalStore store = new TokenApprovalStore();
......@@ -142,6 +162,8 @@ public class OAuth2ServerConfig {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore);
defaultTokenServices.setSupportRefreshToken(true);
defaultTokenServices.setAccessTokenValiditySeconds(accessTokenValiditySeconds);
defaultTokenServices.setRefreshTokenValiditySeconds(refreshTokenValiditySeconds);
return defaultTokenServices;
}
}
......
......@@ -35,6 +35,8 @@ default.admin.email=admin@example.com
default.admin.password=Admin123!
default.oauthclient.clientId=
default.oauthclient.clientSecret=
default.oauth.accessToken.validity=21600
default.oauth.refreshToken.validity=604800
build.version=${project.version}
build.artifactId=${project.artifactId}
......
......@@ -1166,4 +1166,16 @@ databaseChangeLog:
oldColumnName: dsd
remarks: Dataset column
tableName: ds2value
# Upgrade to appliation-blocks:1.4-SNAPSHOT
- changeSet:
id: 1526423063000-1
author: mobreza
comment: Add lastLogin to User
changes:
- addColumn:
columns:
- column:
name: lastLogin
type: datetime(6)
tableName: user
......@@ -30,18 +30,18 @@
</thead>
<tbody>
<c:forEach items="${aclSids}" var="aclSid" varStatus="status">
<c:set var="sid" value="${jspHelper.aclSidById(aclSid.id)}" />
<c:forEach items="${sidPermissions}" var="sidPermission" varStatus="status">
<c:set var="sid" value="${jspHelper.aclSidById(sidPermission.sid.id)}" />
<tr class="${status.count % 2 == 0 ? 'even' : 'odd'}">
<input type="hidden" name="sid" class="aclSid" value="${sidPermission.sid.id}"/>
<td>
<c:out value="${sid.fullName}"/>
<c:catch><a href="<c:url value='mailto:${sid.email}' />"><c:out value="${sid.email}" /></a></c:catch>
<c:catch><c:if test="${sid.email ne null}"><a href="<c:url value='mailto:${sid.email}' />"><c:out value="${sid.email}" /></a></c:if></c:catch>
<c:catch><c:if test="${sid.title ne null}"><c:out value="${sid.title}" /></c:if></c:catch>
</td>
<input type="hidden" name="sid" class="aclSid" value="${aclSid.id}"/>
<c:forEach items="${aclPermissions}" var="aclPermission">
<td><input type="checkbox" value="1" class="check" name="permissionValue${aclPermission.mask}" id="permissionValue${aclPermission.mask}" disabled="disabled" ${aclEntries[aclSid.sid][aclPermission.mask] ? 'checked' : '' }/></td>
<td><input type="checkbox" value="1" class="check" name="permissionValue${aclPermission.mask}" id="permissionValue${aclPermission.mask}" disabled="disabled" ${sidPermission.isGranting(aclPermission.mask) ? 'checked' : '' }/></td>
</c:forEach>
<td>
......
......@@ -12,15 +12,24 @@
<a href="<c:url value="/admin/oauth-clients/add-client" />" class="close"><spring:message code="add" /></a>
</security:authorize>
<table class="accessions">
<table class="table table-striped">
<thead>
<tr>
<th class="col-xs-4">Client ID</th>
<th class="">Title &amp; Description</th>
</tr>
</thead>
<tbody>
<c:forEach items="${clientDetailsList}" var="clientDetail">
<tr>
<td>
<td class="col-xs-4">
<a href="<c:url value="/admin/oauth-clients/${clientDetail.clientId}/"/>"><c:out
value="${clientDetail.title}"/></a>
value="${clientDetail.clientId}"/></a>
</td>
<td>
<div><c:out value="${clientDetail.title}" /></div>
<div><c:out value="${clientDetail.description}" /></div>
</td>
<td><c:out value="${clientDetail.clientId}" /></td>
</tr>
</c:forEach>
</tbody>
......
......@@ -31,9 +31,22 @@
<label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.id"/></label>
<div class="col-lg-9 col-md-8"><c:out value="${clientDetails.clientId}" /></div>
</div>
<div class="row">
<%-- <div class="row">
<label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.secret"/></label>
<div class="col-lg-9 col-md-8"><c:out value="${clientDetails.clientSecret}" /></div>
</div> --%>
<div class="row">
<label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.secret"/></label>
<div class="col-lg-9 col-md-8">
<c:choose>
<c:when test="${clientDetails.clientSecret ne null}">Encrypted</c:when>
<c:when test="${clientDetails.clientSecret eq null}">No secret</c:when>
</c:choose>
<gui:alert type="info" display="${clientSecret ne null}">
This is the only time we display the secret. It's your responsibility from here on!
<div style="font-weight: bold"><c:out value="${clientSecret}" /></div>
</gui:alert>
</div>
</div>
<!-- Extras -->
......@@ -66,6 +79,20 @@
<div class="col-lg-9 col-md-8"><c:out value="${clientDetails.autoApproveScopes}" /></div>
</div>
<security:authorize access="hasRole('ADMINISTRATOR') or hasPermission(#clientDetails, 'ADMINISTRATION')">
<form method="post" action="<c:url value='/admin/oauth-clients/save-client' />">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<input type="hidden" name="id" value="${clientDetails.clientId}"/>
<div class="form-group">
<div class="col-lg-offset-3 col-lg-9">
<button class="btn btn-default" type="submit" name="action-secret" value="1">New Client Secret</button>
<button class="btn btn-default" type="submit" name="action-nosecret" value="1">No Secret</button>
<a class="btn btn-default" href="<c:url value='/admin/oauth-clients/' />"><spring:message code="cancel"/></a>
</div>
</div>
</form>
</security:authorize>
<security:authorize access="hasRole('ADMINISTRATOR')">
<h3><spring:message code="client.details.token.list"/></h3>
......
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