/*******************************************************************************
* Copyright (c) 2015 MEDEVIT.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* MEDEVIT <office@medevit.at> - initial API and implementation
******************************************************************************/
package ch.elexis.admin;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.elexis.core.constants.StringConstants;
import ch.elexis.core.data.events.ElexisEventDispatcher;
import ch.elexis.core.jdt.NonNull;
import ch.elexis.core.jdt.Nullable;
import ch.elexis.data.PersistentObject;
import ch.elexis.data.Role;
import ch.elexis.data.User;
import ch.rgw.tools.JdbcLink;
import ch.rgw.tools.JdbcLink.Stm;
/**
* @since 3.1
*/
public class RoleBasedAccessControl extends AbstractAccessControl {
private static Logger log = LoggerFactory.getLogger(RoleBasedAccessControl.class);
public static final String QUERY_RIGHT_FOR_USER =
"SELECT COUNT(*) FROM RIGHTS_PER_USER WHERE USER_ID LIKE %s AND (";
public static final String QUERY_RIGHT_FOR_ROLE =
"SELECT COUNT(*) FROM RIGHTS_PER_ROLE WHERE ROLE_ID LIKE %s AND (";
/**
* Query if user has the the provided right. Considers the entire rights chain, that is, if user
* u has the parent right of a given ACE the right is granted.
*
* @param u
* the {@link User}
* @param ace
* the {@link ACE}
* @return <code>true</code> if {@link User} u is granted the provided {@link ACE} ace
*/
protected static boolean queryRightForUser(@NonNull User u, @NonNull ACE ace){
return queryRight(QUERY_RIGHT_FOR_USER, u.getWrappedId(), ace);
}
protected static boolean queryRightForRole(Role r, ACE ace){
return queryRight(QUERY_RIGHT_FOR_ROLE, r.getWrappedId(), ace);
}
private static boolean queryRight(String qs, String objId, ACE ace){
// TODO cache?
String queryString = String.format(qs, objId);
StringBuilder sb = new StringBuilder(queryString);
List<ACE> parentACEs = ace.getParentChainIncludingSelf();
for (int i = 0; i < parentACEs.size(); i++) {
ACE a = parentACEs.get(i);
if (i > 0) {
sb.append(" OR ");
}
sb.append(" RIGHT_ID = " + JdbcLink.wrap(a.getUniqueHashFromACE()));
}
sb.append(StringConstants.CLOSEBRACKET + StringConstants.SEMICOLON);
Stm stm = PersistentObject.getConnection().getStatement();
boolean ret = false;
try {
ResultSet result = stm.query(sb.toString());
boolean step = result.next();
if (!step) {
return ret;
}
int counts = result.getInt(1);
ret = (counts > 0);
} catch (SQLException e) {
log.error("Error querying access right ", e);
} finally {
PersistentObject.getConnection().releaseStatement(stm);
}
return ret;
}
/**
* convenience method calling {@link #request(User, ACE)}
*
* @param ace
* @return
* @see #request(User, ACE)
*/
public boolean request(@Nullable ACE ace){
return request((User) null, ace);
}
@Override
public boolean request(String canonicalName){
if (canonicalName == null || canonicalName.length() < 1)
return false;
return request(ACE.getACEByCanonicalName(canonicalName));
}
/**
*
* @param user
* if <code>null</code> the user stored in the context is applied
* @param ace
* if <code>null</code> always returns <code>false</code>
* @return <code>true</code> if access granted
*/
public boolean request(@Nullable User user, @Nullable ACE ace){
if (ace == null)
return false;
if (user == null) {
user = (User) ElexisEventDispatcher.getSelected(User.class);
if (user == null) {
return false;
}
}
if (user.isAdministrator())
return true;
return RoleBasedAccessControl.queryRightForUser(user, ace);
}
/**
*
* @param r
* @param ace
* @return
*/
public boolean request(@NonNull Role r, @Nullable ACE ace){
if (ace == null)
return false;
return RoleBasedAccessControl.queryRightForRole(r, ace);
}
@Override
public void grant(Role r, ACE ace){
r.grantAccessRight(ace);
}
@Override
public void revoke(Role r, ACE ace){
r.revokeAccessRight(ace);
}
@Override
public void grant(String id, ACE ace){
Role r = Role.load(id);
grant(r, ace);
}
}