mirror of
https://gitee.com/jmix/cuba.git
synced 2024-11-30 18:27:56 +08:00
Security constraints added
This commit is contained in:
parent
a095a26d73
commit
e751b3c60e
@ -155,6 +155,25 @@ alter table SEC_PERMISSION add constraint SEC_PERMISSION_UNIQUE unique (ROLE_ID,
|
||||
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
|
||||
create table SEC_CONSTRAINT (
|
||||
ID varchar(36),
|
||||
CREATE_TS timestamp,
|
||||
CREATED_BY varchar(20),
|
||||
VERSION integer,
|
||||
UPDATE_TS timestamp,
|
||||
UPDATED_BY varchar(20),
|
||||
DELETE_TS timestamp,
|
||||
DELETED_BY varchar(20),
|
||||
ENTITY_NAME varchar(50),
|
||||
WHERE_CLAUSE varchar(500),
|
||||
GROUP_ID varchar(36),
|
||||
primary key (ID)
|
||||
);
|
||||
|
||||
alter table SEC_CONSTRAINT add constraint SEC_CONSTRAINT_GROUP foreign key (GROUP_ID) references SEC_GROUP;
|
||||
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
|
||||
insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, PASSWORD, NAME)
|
||||
values ('60885987-1b61-4247-94c7-dff348347f93', current_timestamp, 0, 'admin', '21232f297a57a5a743894a0e4a801fc3', 'Administrator');
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
<class>com.haulmont.cuba.security.entity.Profile</class>
|
||||
<class>com.haulmont.cuba.security.entity.ProfileRole</class>
|
||||
<class>com.haulmont.cuba.security.entity.Permission</class>
|
||||
<class>com.haulmont.cuba.security.entity.Constraint</class>
|
||||
|
||||
<properties>
|
||||
<property name="openjpa.Log" value="log4j"/>
|
||||
|
@ -22,8 +22,12 @@ public interface EntityManager
|
||||
|
||||
<T extends BaseEntity> T find(Class<T> clazz, Object key);
|
||||
|
||||
Query createQuery();
|
||||
|
||||
Query createQuery(String qlStr);
|
||||
|
||||
Query createNativeQuery();
|
||||
|
||||
Query createNativeQuery(String sql);
|
||||
|
||||
void setView(View view);
|
||||
|
@ -18,6 +18,10 @@ import java.util.Date;
|
||||
|
||||
public interface Query
|
||||
{
|
||||
String getQueryString();
|
||||
|
||||
void setQueryString(String queryString);
|
||||
|
||||
List getResultList();
|
||||
|
||||
Object getSingleResult();
|
||||
|
@ -11,8 +11,11 @@
|
||||
package com.haulmont.cuba.core;
|
||||
|
||||
import com.haulmont.cuba.security.global.UserSession;
|
||||
import com.haulmont.cuba.core.global.QueryTransformer;
|
||||
import com.haulmont.cuba.core.global.QueryTransformerFactory;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class SecurityProvider
|
||||
{
|
||||
@ -54,5 +57,35 @@ public abstract class SecurityProvider
|
||||
return (Arrays.binarySearch(session.getRoles(), role) >= 0);
|
||||
}
|
||||
|
||||
public static void applyConstraints(Query query, String entityName) {
|
||||
getInstance().__applyConstraints(query, entityName);
|
||||
}
|
||||
|
||||
protected abstract UserSession __currentUserSession();
|
||||
|
||||
protected void __applyConstraints(Query query, String entityName) {
|
||||
List<String> constraints = __currentUserSession().getConstraints(entityName);
|
||||
if (constraints.isEmpty())
|
||||
return;
|
||||
|
||||
QueryTransformer transformer = QueryTransformerFactory.createTransformer(
|
||||
query.getQueryString(), entityName);
|
||||
|
||||
for (String constraint : constraints) {
|
||||
transformer.addWhere(constraint);
|
||||
}
|
||||
query.setQueryString(transformer.getResult());
|
||||
for (String paramName : transformer.getAddedParams()) {
|
||||
setQueryParam(query, paramName);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setQueryParam(Query query, String paramName) {
|
||||
if ("currentUserLogin".equals(paramName)) {
|
||||
query.setParameter("currentUserLogin", __currentUserSession().getLogin());
|
||||
}
|
||||
else if ("currentUserId".equals(paramName)) {
|
||||
query.setParameter("currentUserId", __currentUserSession().getUserId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,11 @@ import com.haulmont.cuba.core.global.BasicInvocationContext;
|
||||
import com.haulmont.cuba.core.EntityManager;
|
||||
import com.haulmont.cuba.core.PersistenceProvider;
|
||||
import com.haulmont.cuba.core.Query;
|
||||
import com.haulmont.cuba.core.SecurityProvider;
|
||||
|
||||
import javax.ejb.Stateless;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Stateless(name = BasicWorker.JNDI_NAME)
|
||||
public class BasicWorkerBean implements BasicWorker
|
||||
@ -65,11 +67,18 @@ public class BasicWorkerBean implements BasicWorker
|
||||
|
||||
public <T extends BaseEntity> List<T> loadList(BasicInvocationContext ctx) {
|
||||
EntityManager em = PersistenceProvider.getEntityManager();
|
||||
|
||||
Query query = em.createQuery(ctx.getQueryString());
|
||||
SecurityProvider.applyConstraints(query, ctx.getMetaClass().getName());
|
||||
|
||||
for (Map.Entry<String, Object> entry : ctx.getQueryParams().entrySet()) {
|
||||
query.setParameter(entry.getKey(), entry.getValue());
|
||||
}
|
||||
if (ctx.getView() != null) {
|
||||
query.setView(ctx.getView());
|
||||
}
|
||||
List resultList = query.getResultList();
|
||||
|
||||
return resultList;
|
||||
}
|
||||
}
|
||||
|
@ -11,17 +11,20 @@
|
||||
package com.haulmont.cuba.core.global;
|
||||
|
||||
import com.haulmont.cuba.core.entity.BaseEntity;
|
||||
import com.haulmont.chile.core.model.MetaClass;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class BasicInvocationContext implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = -6533204272933592530L;
|
||||
|
||||
private Class<? extends BaseEntity> entityClass;
|
||||
|
||||
private Object id;
|
||||
|
||||
private String queryString;
|
||||
|
||||
private Map<String, Object> queryParams = new HashMap<String, Object>();
|
||||
private View view;
|
||||
|
||||
public Class<? extends BaseEntity> getEntityClass() {
|
||||
@ -33,6 +36,10 @@ public class BasicInvocationContext implements Serializable
|
||||
return this;
|
||||
}
|
||||
|
||||
public MetaClass getMetaClass() {
|
||||
return MetadataProvider.getSession().getClass(entityClass);
|
||||
}
|
||||
|
||||
public Object getId() {
|
||||
return id;
|
||||
}
|
||||
@ -51,6 +58,15 @@ public class BasicInvocationContext implements Serializable
|
||||
return this;
|
||||
}
|
||||
|
||||
public Map<String, Object> getQueryParams() {
|
||||
return queryParams;
|
||||
}
|
||||
|
||||
public BasicInvocationContext addQueryParam(String name, Object value) {
|
||||
queryParams.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public View getView() {
|
||||
return view;
|
||||
}
|
||||
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Haulmont Technology Ltd. All Rights Reserved.
|
||||
* Haulmont Technology proprietary and confidential.
|
||||
* Use is subject to license terms.
|
||||
|
||||
* Author: Konstantin Krivopustov
|
||||
* Created: 26.12.2008 10:17:29
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
package com.haulmont.cuba.core.global;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface QueryTransformer
|
||||
{
|
||||
void addWhere(String where);
|
||||
|
||||
void mergeWhere(String query);
|
||||
|
||||
void reset();
|
||||
|
||||
String getResult();
|
||||
|
||||
Set<String> getAddedParams();
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Haulmont Technology Ltd. All Rights Reserved.
|
||||
* Haulmont Technology proprietary and confidential.
|
||||
* Use is subject to license terms.
|
||||
|
||||
* Author: Konstantin Krivopustov
|
||||
* Created: 26.12.2008 10:10:03
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
package com.haulmont.cuba.core.global;
|
||||
|
||||
public class QueryTransformerFactory
|
||||
{
|
||||
public static QueryTransformer createTransformer(String query, String targetEntity) {
|
||||
return new QueryTransformerRegex(query, targetEntity);
|
||||
}
|
||||
}
|
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Haulmont Technology Ltd. All Rights Reserved.
|
||||
* Haulmont Technology proprietary and confidential.
|
||||
* Use is subject to license terms.
|
||||
|
||||
* Author: Konstantin Krivopustov
|
||||
* Created: 26.12.2008 9:53:52
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
package com.haulmont.cuba.core.global;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class QueryTransformerRegex implements QueryTransformer
|
||||
{
|
||||
public static final String ENTITY_PATTERN_REGEX = "(\\b[_A-Za-z]+\\$[A-Z][_A-Za-z]*)(\\s+as\\b)?\\s+([a-z]+[a-z0-9]*)*\\b";
|
||||
public static final Pattern ENTITY_PATTERN = Pattern.compile(ENTITY_PATTERN_REGEX, Pattern.CASE_INSENSITIVE);
|
||||
|
||||
public static final String WHERE_PATTERN_REGEX = "\\bWHERE\\b";
|
||||
public static final Pattern WHERE_PATTERN = Pattern.compile(WHERE_PATTERN_REGEX, Pattern.CASE_INSENSITIVE);
|
||||
|
||||
public static final String LAST_CLAUSE_PATTERN_REGEX = "(\\bGROUP\\s+BY\\b)|(\\bORDER\\s+BY\\b)|(\\bHAVING\\b)";
|
||||
public static final Pattern LAST_CLAUSE_PATTERN = Pattern.compile(LAST_CLAUSE_PATTERN_REGEX, Pattern.CASE_INSENSITIVE);
|
||||
|
||||
public static final String ALIAS_PATTERN_REGEX = "(^|\\s|\\()(\\w+)\\.";
|
||||
public static final Pattern ALIAS_PATTERN = Pattern.compile(ALIAS_PATTERN_REGEX, Pattern.CASE_INSENSITIVE);
|
||||
|
||||
public static final String PARAM_PATTERN_REGEX = ":([a-zA-Z_0-9]+)";
|
||||
public static final Pattern PARAM_PATTERN = Pattern.compile(PARAM_PATTERN_REGEX, Pattern.CASE_INSENSITIVE);
|
||||
|
||||
private String source;
|
||||
private String targetEntity;
|
||||
private StringBuffer buffer;
|
||||
private Set<String> addedParams;
|
||||
|
||||
QueryTransformerRegex(String source, String targetEntity) {
|
||||
this.source = source;
|
||||
this.targetEntity = targetEntity;
|
||||
buffer = new StringBuffer(source);
|
||||
addedParams = new HashSet<String>();
|
||||
}
|
||||
|
||||
public void addWhere(String where) {
|
||||
String alias = null;
|
||||
Matcher entityMatcher = ENTITY_PATTERN.matcher(buffer);
|
||||
while (entityMatcher.find()) {
|
||||
if (targetEntity.equals(entityMatcher.group(1))) {
|
||||
alias = entityMatcher.group(3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (StringUtils.isBlank(alias))
|
||||
error("No alias for target entity " + targetEntity + " found");
|
||||
|
||||
int insertPos = source.length();
|
||||
Matcher lastClauseMatcher = LAST_CLAUSE_PATTERN.matcher(buffer);
|
||||
if (lastClauseMatcher.find(entityMatcher.end()))
|
||||
insertPos = lastClauseMatcher.start() - 1;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Matcher whereMatcher = WHERE_PATTERN.matcher(buffer);
|
||||
if (whereMatcher.find(entityMatcher.end()))
|
||||
sb.append(" and ");
|
||||
else
|
||||
sb.append(" where ");
|
||||
|
||||
addReplacingAlias(sb, where, alias);
|
||||
|
||||
buffer.insert(insertPos, sb);
|
||||
|
||||
Matcher paramMatcher = PARAM_PATTERN.matcher(where);
|
||||
while (paramMatcher.find()) {
|
||||
addedParams.add(paramMatcher.group(1));
|
||||
}
|
||||
}
|
||||
|
||||
public void mergeWhere(String query) {
|
||||
int startPos = 0;
|
||||
Matcher whereMatcher = WHERE_PATTERN.matcher(query);
|
||||
if (whereMatcher.find())
|
||||
startPos = whereMatcher.end() + 1;
|
||||
|
||||
int endPos = query.length();
|
||||
Matcher lastClauseMatcher = LAST_CLAUSE_PATTERN.matcher(query);
|
||||
if (lastClauseMatcher.find())
|
||||
endPos = lastClauseMatcher.start();
|
||||
|
||||
addWhere(query.substring(startPos, endPos));
|
||||
}
|
||||
|
||||
private void addReplacingAlias(StringBuilder sb, String where, String alias) {
|
||||
Matcher matcher = ALIAS_PATTERN.matcher(where);
|
||||
int pos = 0;
|
||||
while (matcher.find()) {
|
||||
sb.append(where.substring(pos, matcher.start(2)));
|
||||
pos = matcher.end(2);
|
||||
sb.append(alias);
|
||||
}
|
||||
sb.append(where.substring(pos));
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
buffer = new StringBuffer(source);
|
||||
addedParams.clear();
|
||||
}
|
||||
|
||||
public String getResult() {
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public Set<String> getAddedParams() {
|
||||
return Collections.unmodifiableSet(addedParams);
|
||||
}
|
||||
|
||||
private void error(String message) {
|
||||
throw new RuntimeException(message + " [" + buffer.toString() + "]");
|
||||
}
|
||||
}
|
@ -34,8 +34,6 @@ public class EntityManagerImpl implements EntityManager
|
||||
void onClose();
|
||||
}
|
||||
|
||||
private Log log = LogFactory.getLog(EntityManagerImpl.class);
|
||||
|
||||
private OpenJPAEntityManager jpaEm;
|
||||
|
||||
private boolean closed;
|
||||
@ -88,14 +86,24 @@ public class EntityManagerImpl implements EntityManager
|
||||
return jpaEm.find(clazz, key);
|
||||
}
|
||||
|
||||
public Query createQuery() {
|
||||
return new QueryImpl(jpaEm, false);
|
||||
}
|
||||
|
||||
public Query createQuery(String qlStr) {
|
||||
log.trace("Creating JPQL query: " + qlStr);
|
||||
return new QueryImpl(jpaEm.createQuery(qlStr));
|
||||
QueryImpl query = new QueryImpl(jpaEm, false);
|
||||
query.setQueryString(qlStr);
|
||||
return query;
|
||||
}
|
||||
|
||||
public Query createNativeQuery() {
|
||||
return new QueryImpl(jpaEm, true);
|
||||
}
|
||||
|
||||
public Query createNativeQuery(String sql) {
|
||||
log.trace("Creating SQL query: " + sql);
|
||||
return new QueryImpl(jpaEm.createNativeQuery(sql));
|
||||
QueryImpl query = new QueryImpl(jpaEm, true);
|
||||
query.setQueryString(sql);
|
||||
return query;
|
||||
}
|
||||
|
||||
public void setView(View view) {
|
||||
|
@ -12,7 +12,6 @@ package com.haulmont.cuba.core.sys;
|
||||
|
||||
import com.haulmont.cuba.core.Query;
|
||||
import com.haulmont.cuba.core.global.View;
|
||||
import com.haulmont.cuba.core.global.ViewProperty;
|
||||
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.FlushModeType;
|
||||
@ -20,61 +19,94 @@ import java.util.List;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.openjpa.persistence.OpenJPAQuery;
|
||||
import org.apache.openjpa.persistence.FetchPlan;
|
||||
import org.apache.openjpa.persistence.OpenJPAEntityManager;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
public class QueryImpl implements Query
|
||||
{
|
||||
private OpenJPAQuery query;
|
||||
private Log log = LogFactory.getLog(QueryImpl.class);
|
||||
|
||||
public QueryImpl(OpenJPAQuery query) {
|
||||
this.query = query;
|
||||
this.query.setFlushMode(FlushModeType.COMMIT);
|
||||
private OpenJPAEntityManager em;
|
||||
private OpenJPAQuery query;
|
||||
private boolean isNative;
|
||||
private String queryString;
|
||||
|
||||
public QueryImpl(OpenJPAEntityManager entityManager, boolean isNative) {
|
||||
this.em = entityManager;
|
||||
this.isNative = isNative;
|
||||
}
|
||||
|
||||
private OpenJPAQuery getQuery() {
|
||||
if (query == null) {
|
||||
if (isNative) {
|
||||
log.trace("Creating SQL query: " + queryString);
|
||||
query = em.createNativeQuery(queryString);
|
||||
query.setFlushMode(FlushModeType.COMMIT);
|
||||
}
|
||||
else {
|
||||
log.trace("Creating JPQL query: " + queryString);
|
||||
query = em.createQuery(queryString);
|
||||
query.setFlushMode(FlushModeType.COMMIT);
|
||||
}
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
public List getResultList() {
|
||||
return query.getResultList();
|
||||
return getQuery().getResultList();
|
||||
}
|
||||
|
||||
public Object getSingleResult() {
|
||||
return query.getSingleResult();
|
||||
return getQuery().getSingleResult();
|
||||
}
|
||||
|
||||
public int executeUpdate() {
|
||||
return query.executeUpdate();
|
||||
return getQuery().executeUpdate();
|
||||
}
|
||||
|
||||
public Query setMaxResults(int maxResult) {
|
||||
query.setMaxResults(maxResult);
|
||||
getQuery().setMaxResults(maxResult);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Query setFirstResult(int startPosition) {
|
||||
query.setFirstResult(startPosition);
|
||||
getQuery().setFirstResult(startPosition);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Query setParameter(String name, Object value) {
|
||||
query.setParameter(name, value);
|
||||
getQuery().setParameter(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Query setParameter(String name, Date value, TemporalType temporalType) {
|
||||
query.setParameter(name, value, temporalType);
|
||||
getQuery().setParameter(name, value, temporalType);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Query setParameter(int position, Object value) {
|
||||
query.setParameter(position, value);
|
||||
getQuery().setParameter(position, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Query setParameter(int position, Date value, TemporalType temporalType) {
|
||||
query.setParameter(position, value, temporalType);
|
||||
getQuery().setParameter(position, value, temporalType);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Query setView(View view) {
|
||||
ViewHelper.setView(query.getFetchPlan(), view);
|
||||
ViewHelper.setView(getQuery().getFetchPlan(), view);
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getQueryString() {
|
||||
return queryString;
|
||||
}
|
||||
|
||||
public void setQueryString(String queryString) {
|
||||
if (query != null)
|
||||
throw new IllegalStateException("Unable to set query string: query is already created");
|
||||
this.queryString = queryString;
|
||||
}
|
||||
}
|
||||
|
@ -13,11 +13,10 @@ package com.haulmont.cuba.core.sys;
|
||||
import com.haulmont.cuba.core.SecurityProvider;
|
||||
import com.haulmont.cuba.security.global.UserSession;
|
||||
import com.haulmont.cuba.security.sys.UserSessionManager;
|
||||
import org.jboss.security.SecurityAssociation;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.jboss.security.SecurityAssociation;
|
||||
|
||||
public class SecurityProviderImpl extends SecurityProvider
|
||||
{
|
||||
protected UserSession __currentUserSession() {
|
||||
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Haulmont Technology Ltd. All Rights Reserved.
|
||||
* Haulmont Technology proprietary and confidential.
|
||||
* Use is subject to license terms.
|
||||
|
||||
* Author: Konstantin Krivopustov
|
||||
* Created: 25.12.2008 16:25:02
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
package com.haulmont.cuba.security.entity;
|
||||
|
||||
import com.haulmont.cuba.core.entity.StandardEntity;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
@Entity(name = "sec$Constraint")
|
||||
@Table(name = "SEC_CONSTRAINT")
|
||||
public class Constraint extends StandardEntity
|
||||
{
|
||||
private static final long serialVersionUID = -8598548105315052474L;
|
||||
|
||||
@Column(name = "ENTITY_NAME", length = 50)
|
||||
private String entityName;
|
||||
|
||||
@Column(name = "WHERE_CLAUSE", length = 500)
|
||||
private String whereClause;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "GROUP_ID")
|
||||
private Group group;
|
||||
|
||||
public String getEntityName() {
|
||||
return entityName;
|
||||
}
|
||||
|
||||
public void setEntityName(String entityName) {
|
||||
this.entityName = entityName;
|
||||
}
|
||||
|
||||
public Group getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public void setGroup(Group group) {
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
public String getWhereClause() {
|
||||
return whereClause;
|
||||
}
|
||||
|
||||
public void setWhereClause(String whereClause) {
|
||||
this.whereClause = whereClause;
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ import com.haulmont.cuba.core.entity.annotation.Listeners;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Entity(name = "sec$Group")
|
||||
@Table(name = "SEC_GROUP")
|
||||
@ -34,6 +35,9 @@ public class Group extends StandardEntity
|
||||
@OrderBy("level")
|
||||
private List<GroupHierarchy> hierarchyList;
|
||||
|
||||
@OneToMany(mappedBy = "group")
|
||||
private Set<Constraint> constraints;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@ -58,6 +62,14 @@ public class Group extends StandardEntity
|
||||
this.hierarchyList = hierarchyList;
|
||||
}
|
||||
|
||||
public Set<Constraint> getConstraints() {
|
||||
return constraints;
|
||||
}
|
||||
|
||||
public void setConstraints(Set<Constraint> constraints) {
|
||||
this.constraints = constraints;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Group{" +
|
||||
"name='" + name + '\'' +
|
||||
|
@ -20,11 +20,7 @@ public class Permission extends StandardEntity
|
||||
{
|
||||
private static final long serialVersionUID = 4188184934170706381L;
|
||||
|
||||
public static int TYPE_ACTION = 10;
|
||||
public static int TYPE_ENTITY_OP = 20;
|
||||
public static int TYPE_ENTITY_ATTR = 30;
|
||||
public static int TYPE_SPECIFIC = 40;
|
||||
|
||||
/** @see com.haulmont.cuba.security.entity.PermissionType PermissionType.getId() */
|
||||
@Column(name = "TYPE")
|
||||
private Integer type;
|
||||
|
||||
|
@ -10,6 +10,10 @@
|
||||
*/
|
||||
package com.haulmont.cuba.security.entity;
|
||||
|
||||
/**
|
||||
* Type of permission<br>
|
||||
* id - corresponding database value
|
||||
*/
|
||||
public enum PermissionType
|
||||
{
|
||||
ACTION(10),
|
||||
@ -23,10 +27,12 @@ public enum PermissionType
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/** Returns corresponding database value */
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/** Constructs type from corresponding database value */
|
||||
public static PermissionType fromId(int id) {
|
||||
for (PermissionType type : PermissionType.values()) {
|
||||
if (type.getId() == id) {
|
||||
|
@ -28,6 +28,7 @@ public class UserSession implements Serializable
|
||||
private final Locale locale;
|
||||
|
||||
private final Map<String, Integer>[] permissions;
|
||||
private final Map<String, List<String>> constraints;
|
||||
|
||||
public UserSession(User user, String[] roles, Locale locale) {
|
||||
id = UuidProvider.createUuid();
|
||||
@ -44,6 +45,8 @@ public class UserSession implements Serializable
|
||||
for (int i = 0; i < permissions.length; i++) {
|
||||
permissions[i] = new HashMap<String, Integer>();
|
||||
}
|
||||
|
||||
constraints = new HashMap<String, List<String>>();
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
@ -87,6 +90,20 @@ public class UserSession implements Serializable
|
||||
return p == null || p >= value;
|
||||
}
|
||||
|
||||
public void addConstraint(String entityName, String constraint) {
|
||||
List<String> list = constraints.get(entityName);
|
||||
if (list == null) {
|
||||
list = new ArrayList<String>();
|
||||
constraints.put(entityName, list);
|
||||
}
|
||||
list.add(constraint);
|
||||
}
|
||||
|
||||
public List<String> getConstraints(String entityName) {
|
||||
List<String> list = constraints.get(entityName);
|
||||
return list != null ? list : Collections.<String>emptyList();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "UserSession{" +
|
||||
"id=" + id +
|
||||
|
@ -13,6 +13,9 @@ package com.haulmont.cuba.security.sys;
|
||||
import com.haulmont.cuba.security.entity.*;
|
||||
import com.haulmont.cuba.security.global.UserSession;
|
||||
import com.haulmont.cuba.security.global.NoUserSessionException;
|
||||
import com.haulmont.cuba.core.PersistenceProvider;
|
||||
import com.haulmont.cuba.core.EntityManager;
|
||||
import com.haulmont.cuba.core.Query;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@ -42,6 +45,7 @@ public class UserSessionManager
|
||||
}
|
||||
UserSession session = new UserSession(user, roleNames.toArray(new String[roleNames.size()]), locale);
|
||||
compilePermissions(session, roles);
|
||||
compileConstraints(session, profile.getGroup());
|
||||
sessions.add(session);
|
||||
return session;
|
||||
}
|
||||
@ -64,6 +68,19 @@ public class UserSessionManager
|
||||
}
|
||||
}
|
||||
|
||||
private void compileConstraints(UserSession session, Group group) {
|
||||
EntityManager em = PersistenceProvider.getEntityManager();
|
||||
Query q = em.createQuery("select c from sec$GroupHierarchy h join h.parent.constraints c " +
|
||||
"where h.group = ?1");
|
||||
q.setParameter(1, group);
|
||||
List<Constraint> constraints = q.getResultList();
|
||||
List<Constraint> list = new ArrayList<Constraint>(constraints);
|
||||
list.addAll(group.getConstraints());
|
||||
for (Constraint constraint : list) {
|
||||
session.addConstraint(constraint.getEntityName(), constraint.getWhereClause());
|
||||
}
|
||||
}
|
||||
|
||||
public void removeSession(UserSession session) {
|
||||
sessions.remove(session);
|
||||
}
|
||||
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Haulmont Technology Ltd. All Rights Reserved.
|
||||
* Haulmont Technology proprietary and confidential.
|
||||
* Use is subject to license terms.
|
||||
|
||||
* Author: Konstantin Krivopustov
|
||||
* Created: 26.12.2008 12:53:07
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
package com.haulmont.cuba.core.global;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class QueryTransformerRegexTest extends TestCase
|
||||
{
|
||||
public void test() {
|
||||
QueryTransformerRegex transformer = new QueryTransformerRegex(
|
||||
"select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par",
|
||||
"sec$GroupHierarchy");
|
||||
|
||||
transformer.addWhere("a.createdBy = :par1");
|
||||
String res = transformer.getResult();
|
||||
assertEquals(
|
||||
"select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par and h.createdBy = :par1",
|
||||
res);
|
||||
|
||||
transformer = new QueryTransformerRegex(
|
||||
"select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " +
|
||||
"group by c.level order by c.level having c.level > 0",
|
||||
"sec$GroupHierarchy");
|
||||
|
||||
transformer.addWhere("a.createdBy = :par1");
|
||||
res = transformer.getResult();
|
||||
assertEquals(
|
||||
"select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " +
|
||||
"and h.createdBy = :par1 group by c.level order by c.level having c.level > 0",
|
||||
res);
|
||||
Set<String> set = transformer.getAddedParams();
|
||||
assertEquals(1, set.size());
|
||||
assertEquals("par1", set.iterator().next());
|
||||
|
||||
transformer.addWhere("(a.updatedBy = :par2 and a.groupId = :par3)");
|
||||
res = transformer.getResult();
|
||||
assertEquals(
|
||||
"select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " +
|
||||
"and h.createdBy = :par1 and (h.updatedBy = :par2 and h.groupId = :par3) group by c.level order by c.level having c.level > 0",
|
||||
res);
|
||||
set = transformer.getAddedParams();
|
||||
assertEquals(3, set.size());
|
||||
|
||||
transformer.reset();
|
||||
|
||||
transformer.mergeWhere("select gh from sec$GroupHierarchy gh where gh.version between 1 and 2");
|
||||
res = transformer.getResult();
|
||||
assertEquals(
|
||||
"select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " +
|
||||
"and h.version between 1 and 2 group by c.level order by c.level having c.level > 0",
|
||||
res);
|
||||
|
||||
}
|
||||
|
||||
public void testInvalidEntity() {
|
||||
QueryTransformerRegex transformer = new QueryTransformerRegex(
|
||||
"select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " +
|
||||
"group by c.level order by c.level having c.level > 0",
|
||||
"sec$Group");
|
||||
try {
|
||||
transformer.addWhere("a.createdBy = :par1");
|
||||
fail();
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof RuntimeException);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -11,14 +11,13 @@
|
||||
package com.haulmont.cuba.core.sys;
|
||||
|
||||
import com.haulmont.cuba.core.SecurityProvider;
|
||||
import com.haulmont.cuba.security.global.UserSession;
|
||||
import com.haulmont.cuba.security.entity.User;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.Locale;
|
||||
|
||||
import com.haulmont.cuba.security.global.UserSession;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
public class TestSecurityProvider extends SecurityProvider
|
||||
{
|
||||
protected UserSession __currentUserSession() {
|
||||
@ -29,6 +28,8 @@ public class TestSecurityProvider extends SecurityProvider
|
||||
user.setPassword(DigestUtils.md5Hex("test_admin"));
|
||||
|
||||
UserSession session = new UserSession(user, new String[]{"Administrators"}, Locale.getDefault());
|
||||
session.addConstraint("sec$Group", "a.createdBy = :currentUserLogin");
|
||||
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
143
modules/core/test/com/haulmont/cuba/security/ConstraintTest.java
Normal file
143
modules/core/test/com/haulmont/cuba/security/ConstraintTest.java
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Haulmont Technology Ltd. All Rights Reserved.
|
||||
* Haulmont Technology proprietary and confidential.
|
||||
* Use is subject to license terms.
|
||||
|
||||
* Author: Konstantin Krivopustov
|
||||
* Created: 25.12.2008 17:39:53
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
package com.haulmont.cuba.security;
|
||||
|
||||
import com.haulmont.cuba.core.*;
|
||||
import com.haulmont.cuba.core.global.BasicInvocationContext;
|
||||
import com.haulmont.cuba.core.app.BasicService;
|
||||
import com.haulmont.cuba.security.entity.Group;
|
||||
import com.haulmont.cuba.security.entity.Profile;
|
||||
import com.haulmont.cuba.security.entity.User;
|
||||
import com.haulmont.cuba.security.entity.Constraint;
|
||||
import com.haulmont.cuba.security.app.LoginWorker;
|
||||
import com.haulmont.cuba.security.global.UserSession;
|
||||
import com.haulmont.cuba.security.global.LoginException;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.Locale;
|
||||
import java.util.List;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
|
||||
public class ConstraintTest extends CubaTestCase
|
||||
{
|
||||
private static final String ADMIN_NAME = "admin";
|
||||
private static final String ADMIN_PASSW = DigestUtils.md5Hex("admin");
|
||||
private static final String PROFILE_NAME = "testProfile";
|
||||
|
||||
private UUID constraintId, parentConstraintId, groupId, parentGroupId, profileId;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
Transaction tx = Locator.createTransaction();
|
||||
try {
|
||||
EntityManager em = PersistenceProvider.getEntityManager();
|
||||
|
||||
User user = em.find(User.class, UUID.fromString("60885987-1b61-4247-94c7-dff348347f93"));
|
||||
|
||||
Group parentGroup = new Group();
|
||||
parentGroupId = parentGroup.getId();
|
||||
parentGroup.setName("testParentGroup");
|
||||
em.persist(parentGroup);
|
||||
|
||||
tx.commitRetaining();
|
||||
em = PersistenceProvider.getEntityManager();
|
||||
|
||||
Constraint parentConstraint = new Constraint();
|
||||
parentConstraintId = parentConstraint.getId();
|
||||
parentConstraint.setEntityName("core$Server");
|
||||
parentConstraint.setWhereClause("address = '127.0.0.1'");
|
||||
parentConstraint.setGroup(parentGroup);
|
||||
em.persist(parentConstraint);
|
||||
|
||||
Group group = new Group();
|
||||
groupId = group.getId();
|
||||
group.setName("testGroup");
|
||||
group.setParent(parentGroup);
|
||||
em.persist(group);
|
||||
|
||||
Constraint constraint = new Constraint();
|
||||
constraintId = constraint.getId();
|
||||
constraint.setEntityName("core$Server");
|
||||
constraint.setWhereClause("name = 'localhost'");
|
||||
constraint.setGroup(group);
|
||||
em.persist(constraint);
|
||||
|
||||
Profile profile = new Profile();
|
||||
profileId = profile.getId();
|
||||
profile.setName(PROFILE_NAME);
|
||||
profile.setUser(user);
|
||||
profile.setGroup(group);
|
||||
em.persist(profile);
|
||||
|
||||
tx.commit();
|
||||
} finally {
|
||||
tx.end();
|
||||
}
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
Transaction tx = Locator.createTransaction();
|
||||
try {
|
||||
EntityManager em = PersistenceProvider.getEntityManager();
|
||||
|
||||
Query q = em.createNativeQuery("delete from SEC_PROFILE where ID = ?");
|
||||
q.setParameter(1, profileId.toString());
|
||||
q.executeUpdate();
|
||||
|
||||
q = em.createNativeQuery("delete from SEC_CONSTRAINT where ID = ? or ID = ?");
|
||||
q.setParameter(1, parentConstraintId.toString());
|
||||
q.setParameter(2, constraintId.toString());
|
||||
q.executeUpdate();
|
||||
|
||||
q = em.createNativeQuery("delete from SEC_GROUP_HIERARCHY where GROUP_ID = ?");
|
||||
q.setParameter(1, groupId.toString());
|
||||
q.executeUpdate();
|
||||
|
||||
q = em.createNativeQuery("delete from SEC_GROUP where ID = ?");
|
||||
q.setParameter(1, groupId.toString());
|
||||
q.executeUpdate();
|
||||
|
||||
q = em.createNativeQuery("delete from SEC_GROUP_HIERARCHY where GROUP_ID = ?");
|
||||
q.setParameter(1, groupId.toString());
|
||||
q.executeUpdate();
|
||||
|
||||
q = em.createNativeQuery("delete from SEC_GROUP where ID = ?");
|
||||
q.setParameter(1, parentGroupId.toString());
|
||||
q.executeUpdate();
|
||||
|
||||
tx.commit();
|
||||
} finally {
|
||||
tx.end();
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public void test() throws LoginException {
|
||||
LoginWorker lw = Locator.lookupLocal(LoginWorker.JNDI_NAME);
|
||||
|
||||
UserSession userSession = lw.login(ADMIN_NAME, ADMIN_PASSW, PROFILE_NAME, Locale.getDefault());
|
||||
assertNotNull(userSession);
|
||||
|
||||
List<String> constraints = userSession.getConstraints("core$Server");
|
||||
assertEquals(2, constraints.size());
|
||||
|
||||
BasicService bs = Locator.lookupLocal(BasicService.JNDI_NAME);
|
||||
BasicInvocationContext ctx = new BasicInvocationContext()
|
||||
.setEntityClass(Group.class)
|
||||
.setQueryString("select g from sec$Group g where g.createTs <= :createTs")
|
||||
.addQueryParam("createTs", new Date());
|
||||
List<Group> list = bs.loadList(ctx);
|
||||
assertTrue(list.size() > 0);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user