restructured code

enhanced permission system
This commit is contained in:
2019-01-10 18:08:36 +01:00
parent b552e0b8bc
commit ecedc1872b
25 changed files with 1158 additions and 1033 deletions

View File

@ -21,6 +21,7 @@ import de.muehlencord.shared.account.business.account.entity.AccountLoginEntity;
import de.muehlencord.shared.account.business.account.entity.AccountStatus;
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
import de.muehlencord.shared.account.business.application.entity.ApplicationRoleEntity;
import de.muehlencord.shared.account.business.instance.boundary.ApplicationPermissions;
import de.muehlencord.shared.account.business.mail.boundary.MailService;
import de.muehlencord.shared.account.business.mail.entity.MailException;
import de.muehlencord.shared.account.util.AccountPU;
@ -30,6 +31,7 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.inject.Inject;
@ -63,12 +65,31 @@ public class AccountControl implements Serializable {
@AccountPU
EntityManager em;
public List<AccountEntity> getAllAccounts(boolean includeDisabled) {
List<AccountEntity> resultList;
if (includeDisabled) {
resultList = getAllAccounts();
} else {
resultList = getActiveAccounts();
}
if (SecurityUtil.checkPermission(ApplicationPermissions.ACCOUNT_LIST)) {
return resultList;
} else {
String currentUserName = SecurityUtils.getSubject().getPrincipal().toString();
return resultList.stream()
.filter(account -> account.getAccountLogin() != null)
.filter (account -> account.getUsername().equals (currentUserName))
.collect(Collectors.toList());
}
}
/**
* returns a list of active accounts
*
* @return a list of active accounts
*/
public List<AccountEntity> getActiveAccounts() {
private List<AccountEntity> getActiveAccounts() {
Query query = em.createQuery("SELECT a FROM AccountEntity a WHERE a.status <> :status", AccountEntity.class);
query.setParameter("status", AccountStatus.DISABLED.name());
return query.getResultList();
@ -79,18 +100,11 @@ public class AccountControl implements Serializable {
*
* @return a list of active accounts
*/
public List<AccountEntity> getAllAccounts() {
private List<AccountEntity> getAllAccounts() {
Query query = em.createNamedQuery("AccountEntity.findAll");
return query.getResultList();
}
public List<AccountEntity> getAccounts(boolean includeDisabled) {
if (includeDisabled) {
return getAllAccounts();
} else {
return getActiveAccounts();
}
}
public AccountEntity getAccountEntity(String userName, boolean loadRoles) {
StringBuilder queryBuilder = new StringBuilder();

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.muehlencord.shared.account.business.accountconfig.entity;
package de.muehlencord.shared.account.business.account.entity;
/**
*

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.muehlencord.shared.account.business.accountconfig.entity;
package de.muehlencord.shared.account.business.account.entity;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;

View File

@ -21,14 +21,14 @@ import de.muehlencord.shared.account.util.SecurityError;
*
* @author Joern Muehlencord <joern at muehlencord.de>
*/
public enum ApplicationServiceError implements SecurityError {
public enum ApplicationError implements SecurityError {
LISTALL_DENIED("1000", "listall_denied");
LIST_DENIED("1000", "list_denied");
private final String errorCode;
private final String messageKey;
private ApplicationServiceError(String errorCode, String messageKey) {
private ApplicationError(String errorCode, String messageKey) {
this.errorCode = errorCode;
this.messageKey = messageKey;
}

View File

@ -13,9 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.muehlencord.shared.account.business.application.boundary;
package de.muehlencord.shared.account.business.application.control;
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
import de.muehlencord.shared.account.business.instance.boundary.ApplicationPermissions;
import de.muehlencord.shared.account.util.AccountPU;
import de.muehlencord.shared.account.util.AccountSecurityException;
import de.muehlencord.shared.account.util.SecurityUtil;
@ -28,6 +29,8 @@ import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.transaction.Transactional;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -36,10 +39,10 @@ import org.slf4j.LoggerFactory;
* @author Joern Muehlencord <joern at muehlencord.de>
*/
@Stateless
public class ApplicationService implements Serializable {
public class ApplicationControl implements Serializable {
private static final long serialVersionUID = 4262608935325326191L;
private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationService.class);
private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationControl.class);
@Inject
@AccountPU
@ -50,14 +53,34 @@ public class ApplicationService implements Serializable {
}
public List<ApplicationEntity> getAllApplications() throws AccountSecurityException {
SecurityUtil.checkPermission(ApplicationPermissions.APP_LISTALL, ApplicationServiceError.LISTALL_DENIED);
List<ApplicationEntity> resultList = new ArrayList<>();
Query query = em.createNamedQuery("ApplicationEntity.findAll");
List<ApplicationEntity> resultList = query.getResultList();
if (resultList == null) {
return new ArrayList<>();
} else {
List<ApplicationEntity> queryList = query.getResultList();
if ((queryList == null) || (queryList.isEmpty())) {
return resultList;
}
Subject currentUser = SecurityUtils.getSubject();
if (currentUser == null)
return resultList;
String userName = currentUser.getPrincipal().toString();
queryList.stream().forEach(app -> {
String applicationName = app.getApplicationName(); // TODO add unique short cut to db model
applicationName = applicationName.toLowerCase();
applicationName = applicationName.replace (" ", "");
String permissionName = ApplicationPermissions.APP_LIST.getName()+":"+applicationName;
boolean userHasPermissionToListApplication = SecurityUtil.checkPermission (permissionName);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("validating if user {} has permission {} = {}", userName, permissionName, userHasPermissionToListApplication);
}
if (userHasPermissionToListApplication) {
resultList.add (app);
}
});
return resultList;
}
@Transactional

View File

@ -15,8 +15,8 @@
*/
package de.muehlencord.shared.account.business.config.boundary;
import de.muehlencord.shared.account.business.accountconfig.entity.AccountConfigurationKey;
import de.muehlencord.shared.account.business.accountconfig.entity.AccountConfigurationValue;
import de.muehlencord.shared.account.business.account.entity.AccountConfigurationKey;
import de.muehlencord.shared.account.business.account.entity.AccountConfigurationValue;
import de.muehlencord.shared.account.business.config.entity.ConfigException;
import javax.ejb.EJB;
import javax.enterprise.context.Dependent;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.muehlencord.shared.account.business.application.boundary;
package de.muehlencord.shared.account.business.instance.boundary;
import de.muehlencord.shared.account.util.Permission;
@ -23,7 +23,7 @@ import de.muehlencord.shared.account.util.Permission;
*/
public enum ApplicationPermissions implements Permission {
APP_LISTALL("application:listall", "Allows to list all avaiable applications"),
APP_LIST("application:list", "Allows to list all avaiable applications"),
APP_ADD("application:add", "Allow to add a new application"),
APP_EDIT("application:edit", "Allow to edit an application"),
APP_DELETE("application:delete", "Allow to delete an application"),
@ -34,7 +34,14 @@ public enum ApplicationPermissions implements Permission {
ROLE_EDIT("role:edit", "Allow to edit a role"),
ROLE_DELETE("role:delete", "Allow to delete a role"),
ROLE_PERMISSION_ASSIGN("role:permission:assign", "Allow to assign a permission to role"),
ROLE_PERMISSION_REVOKE("role:permission:revoke", "All ow to revoke a permission from a role");
ROLE_PERMISSION_REVOKE("role:permission:revoke", "All ow to revoke a permission from a role"),
ACCOUNT_LIST ("account:list", "Allow to list all accounts of an application"),
ACCOUNT_ADD ("account:add", "Allow to create a new account"),
ACCOUNT_EDIT ("account:edit", "Allow to edit an existing account"),
ACCOUNT_DELETE ("account:delete", "Allow to delete an existing account"),
ACCOUNT_LOGIN_ADD ("account:login:add", "Allow to add a login to an account"),
ACCOUNT_LOGIN_EDIT ("account:login:edit", "Allow to overwrite the password of an account"),
ACCOUNT_LOGIN_DELETE ("account:login:delete", "Allow to delete the login of an account");
private final String name;
private final String description;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.muehlencord.shared.account.business.application.boundary;
package de.muehlencord.shared.account.business.instance.boundary;
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
import de.muehlencord.shared.account.business.config.boundary.ConfigService;

View File

@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.muehlencord.shared.account.business.application.control;
package de.muehlencord.shared.account.business.instance.control;
import de.muehlencord.shared.account.business.application.boundary.ApplicationService;
import de.muehlencord.shared.account.business.application.control.ApplicationControl;
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
import java.io.IOException;
import java.io.InputStream;
@ -40,7 +40,7 @@ public class ApplicationController {
private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationController.class);
@EJB
ApplicationService applicationService;
ApplicationControl applicationService;
private String version;
private String buildDate;

View File

@ -16,7 +16,7 @@
package de.muehlencord.shared.account.business.mail.boundary;
import de.muehlencord.shared.account.business.mail.entity.MailTemplateException;
import de.muehlencord.shared.account.business.accountconfig.entity.AccountConfigurationKey;
import de.muehlencord.shared.account.business.account.entity.AccountConfigurationKey;
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
import de.muehlencord.shared.account.business.account.entity.AccountLoginEntity;
import de.muehlencord.shared.account.business.mail.entity.MailDatamodel;
@ -38,7 +38,7 @@ import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.muehlencord.shared.account.business.accountconfig.entity.AccountConfigurationValue;
import de.muehlencord.shared.account.business.account.entity.AccountConfigurationValue;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;

View File

@ -25,7 +25,6 @@ import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import javax.naming.NamingException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
@ -119,7 +118,10 @@ public class LoginView implements Serializable {
currentUser.logout();
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
// ensure faces session is invalidated so beans are destroyed
ec.invalidateSession();
// check if redirect shall be executed
// default setting is yes to /login.xhtml
// can be overwritten using parameters

View File

@ -46,16 +46,25 @@ public class SecurityUtil {
LOGGER.trace(encryptedPassword);
return encryptedPassword;
}
public static boolean checkPermission(Permission permission) {
return checkPermission (permission.getName());
}
public static void checkPermission(Permission permission, SecurityError error) throws AccountSecurityException {
public static boolean checkPermission(String permissionName) {
Subject currentUser = SecurityUtils.getSubject();
if ((currentUser == null) || (!currentUser.isAuthenticated())) {
throw new AccountSecurityException(error); // TODO support special error for not logged in
return false;
}
String requiredPermissions = permission.getName();
if (!currentUser.isPermitted(requiredPermissions)) {
String requiredPermissions = permissionName;
return currentUser.isPermitted(requiredPermissions);
}
public static void checkPermission(Permission permission, SecurityError error) throws AccountSecurityException {
if (!checkPermission(permission)) {
throw new AccountSecurityException(error);
}
}
}

View File

@ -13,4 +13,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
listall_denied=You are not allowed to list all applications
list_denied=You are not allowed to list any application

View File

@ -13,4 +13,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
listall_denied=Sie haben nicht die n\u00f6tige Rechte alle Applikationen aufzulisten
list_denied=Sie haben nicht die n\u00f6tige Rechte eine Applikationen aufzulisten.

View File

@ -13,4 +13,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
listall_denied=User not allowed to list all applications
list_denied=User not allowed to list any application