Commit b1594cf8 authored by Matija Obreza's avatar Matija Obreza
Browse files

User service exceptions from Genesys

parent 744d298e
/*
* Copyright 2017 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.genesys.blocks.security;
public class NoUserFoundException extends UserException {
private static final long serialVersionUID = -3218537334751840421L;
public NoUserFoundException() {
}
public NoUserFoundException(String message) {
super(message);
}
public NoUserFoundException(String message, Throwable cause) {
super(message, cause);
}
public NoUserFoundException(Throwable cause) {
super(cause);
}
public NoUserFoundException(long modelId) {
this.modelId = modelId;
}
public NoUserFoundException(Throwable cause, long modelId) {
super(cause);
this.modelId = modelId;
}
private long modelId;
public long getModelId() {
return modelId;
}
}
/*
* Copyright 2017 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.genesys.blocks.security;
public class NotUniqueUserException extends UserException {
private static final long serialVersionUID = -3260458819774485495L;
public NotUniqueUserException() {
}
public NotUniqueUserException(String message) {
super(message);
}
public NotUniqueUserException(String message, Throwable cause) {
super(message, cause);
}
public NotUniqueUserException(Throwable cause) {
super(cause);
}
public NotUniqueUserException(Throwable cause, String email) {
super(cause);
this.email = email;
}
private String email;
public String getEmail() {
return email;
}
}
/*
* Copyright 2017 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.genesys.blocks.security;
import org.genesys.blocks.security.model.BasicUser;
......
/*
* Copyright 2017 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.genesys.blocks.security;
public class UserException extends Exception {
private static final long serialVersionUID = -5046893564893762245L;
public UserException() {
super();
}
public UserException(String message) {
super(message);
}
public UserException(String message, Throwable cause) {
super(message, cause);
}
public UserException(Throwable cause) {
super(cause);
}
}
/*
* Copyright 2017 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.genesys.blocks.security.component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.acls.domain.AuditLogger;
import org.springframework.security.acls.model.AccessControlEntry;
import org.springframework.security.acls.model.AuditableAccessControlEntry;
import org.springframework.util.Assert;
public class Slf4jLogAuditLogger implements AuditLogger {
private static final Logger LOG = LoggerFactory.getLogger(Slf4jLogAuditLogger.class);
@Override
public void logIfNeeded(boolean granted, AccessControlEntry ace) {
Assert.notNull(ace, "AccessControlEntry required");
if (ace instanceof AuditableAccessControlEntry) {
final AuditableAccessControlEntry auditableAce = (AuditableAccessControlEntry) ace;
if (granted && auditableAce.isAuditSuccess()) {
LOG.debug("GRANTED due to ACE: " + ace);
} else if (!granted && auditableAce.isAuditFailure()) {
LOG.debug("DENIED due to ACE: " + ace);
}
}
}
}
......@@ -97,7 +97,6 @@ public abstract class BasicUser<R extends GrantedAuthority> extends AuditedVersi
@Column(length = 20)
private AccountType accountType = AccountType.LOCAL;
public String getEmail() {
return email;
}
......@@ -191,6 +190,11 @@ public abstract class BasicUser<R extends GrantedAuthority> extends AuditedVersi
return lockedUntil == null || !lockedUntil.after(new Date());
}
@JsonView(JsonViews.Protected.class)
public boolean isAccountLocked() {
return !isAccountNonLocked();
}
@Override
@JsonView(JsonViews.Protected.class)
public boolean isCredentialsNonExpired() {
......
......@@ -17,9 +17,13 @@ package org.genesys.blocks.security.service;
import java.util.Set;
import org.genesys.blocks.security.NoUserFoundException;
import org.genesys.blocks.security.NotUniqueUserException;
import org.genesys.blocks.security.model.BasicUser;
import org.genesys.blocks.security.service.PasswordPolicy.PasswordPolicyException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
public interface BasicUserService<R extends GrantedAuthority, T extends BasicUser<R>> extends UserDetailsService {
......@@ -29,7 +33,7 @@ public interface BasicUserService<R extends GrantedAuthority, T extends BasicUse
* @param id
* @return the user or <code>null</code>
*/
T getUser(long id);
T getUser(long id) throws NoUserFoundException;
/**
* Get User by email
......@@ -37,7 +41,7 @@ public interface BasicUserService<R extends GrantedAuthority, T extends BasicUse
* @param email
* @return the user
*/
T getUserByEmail(String email);
T getUserByEmail(String email) throws UsernameNotFoundException;
/**
* Create a new user account
......@@ -48,7 +52,7 @@ public interface BasicUserService<R extends GrantedAuthority, T extends BasicUse
* @param accountType TODO
* @return the new user
*/
T createUser(String email, String fullName, String password, BasicUser.AccountType accountType);
T createUser(String email, String fullName, String password, BasicUser.AccountType accountType) throws NotUniqueUserException, PasswordPolicyException;
/**
* Grant specified roles to user. The {@link UserRole#USER} will be added if missing.
......@@ -67,16 +71,17 @@ public interface BasicUserService<R extends GrantedAuthority, T extends BasicUse
* @param fullName new fullName
* @return
*/
T updateUser(T user, String email, String fullName);
T updateUser(T user, String email, String fullName) throws NotUniqueUserException;
/**
* Change password
*
* @param user the user
* @param password new password
* @throws PasswordPolicyException
* @return
*/
T changePassword(T user, String password);
T changePassword(T user, String password) throws PasswordPolicyException;
/**
* Try to delete user.
......@@ -90,9 +95,10 @@ public interface BasicUserService<R extends GrantedAuthority, T extends BasicUse
*
* @param userID User ID
* @param locked Is account locked
* @throws NoUserFoundException
*/
void setAccountLockLocal(long userId, boolean locked);
void setAccountLockLocal(long userId, boolean locked) throws NoUserFoundException;
void setAccountLock(long userId, boolean locked);
void setAccountLock(long userId, boolean locked) throws NoUserFoundException;
}
......@@ -15,6 +15,8 @@
*/
package org.genesys.blocks.security.service;
import org.genesys.blocks.security.UserException;
/**
* Password policy interface
*/
......@@ -31,7 +33,7 @@ public interface PasswordPolicy {
/**
* Thrown when password is not okay
*/
public static final class PasswordPolicyException extends Exception {
public static final class PasswordPolicyException extends UserException {
private static final long serialVersionUID = -4692900263383479542L;
public PasswordPolicyException(String message) {
......
......@@ -18,8 +18,12 @@ package org.genesys.blocks.security.service.impl;
import java.util.Date;
import java.util.Set;
import org.genesys.blocks.security.NoUserFoundException;
import org.genesys.blocks.security.model.BasicUser;
import org.genesys.blocks.security.model.BasicUser.AccountType;
import org.genesys.blocks.security.service.BasicUserService;
import org.genesys.blocks.security.service.PasswordPolicy;
import org.genesys.blocks.security.service.PasswordPolicy.PasswordPolicyException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -28,6 +32,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
......@@ -36,14 +41,20 @@ public abstract class BasicUserServiceImpl<R extends GrantedAuthority, T extends
public static final Logger LOG = LoggerFactory.getLogger(BasicUserServiceImpl.class);
/// A non-password used for system and Google accounts
private static final String THIS_IS_NOT_A_PASSWORD = "THIS-IS-NOT-A-PASSWORD";
private long accountLockoutTime = 5 * 60 * 1000;
@Autowired
private JpaRepository<T, Long> userRepository;
@Autowired
PasswordEncoder passwordEncoder;
@Autowired(required = false)
protected final PasswordEncoder passwordEncoder = NoOpPasswordEncoder.getInstance();
@Autowired(required = false)
private PasswordPolicy passwordPolicy;
public void setAccountLockoutTime(long accountLockoutTime) {
this.accountLockoutTime = accountLockoutTime;
}
......@@ -54,8 +65,12 @@ public abstract class BasicUserServiceImpl<R extends GrantedAuthority, T extends
}
@Override
public T getUser(long id) {
return userRepository.findOne(id);
public T getUser(long id) throws NoUserFoundException {
T user = userRepository.findOne(id);
if (user == null) {
throw new NoUserFoundException(id);
}
return user;
}
@Override
......@@ -92,22 +107,30 @@ public abstract class BasicUserServiceImpl<R extends GrantedAuthority, T extends
@Override
@Transactional
public T changePassword(final T user, final String password) {
public T changePassword(final T user, final String password) throws PasswordPolicyException {
setPassword(user, password);
return userRepository.save(user);
}
private void setPassword(final T user, final String password) {
user.setPassword(password == null ? null : passwordEncoder.encode(password));
protected void setPassword(final T user, final String password) throws PasswordPolicyException {
if (user.getAccountType() == AccountType.LOCAL) {
if (passwordPolicy != null) {
passwordPolicy.assureGoodPassword(password);
}
user.setPassword(password == null ? null : passwordEncoder.encode(password));
} else {
user.setPassword(THIS_IS_NOT_A_PASSWORD);
}
}
/**
* For internal use only.
*
* @throws NoUserFoundException
*/
@Override
@Transactional
public void setAccountLockLocal(long userId, boolean locked) {
public void setAccountLockLocal(long userId, boolean locked) throws NoUserFoundException {
final T user = getUser(userId);
if (locked) {
// Lock for account until some time
......@@ -123,7 +146,7 @@ public abstract class BasicUserServiceImpl<R extends GrantedAuthority, T extends
@Override
@Transactional
@PreAuthorize("hasRole('ADMINISTRATOR')")
public void setAccountLock(long userId, boolean locked) {
public void setAccountLock(long userId, boolean locked) throws NoUserFoundException {
setAccountLockLocal(userId, locked);
}
......
Supports Markdown
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