mirror of
https://gitee.com/jmix/cuba.git
synced 2024-12-02 19:27:57 +08:00
Check attribute permissions on Middleware. #PL-6092
This commit is contained in:
parent
73f5ee4db5
commit
c56f50a10c
@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2015 Haulmont. All rights reserved.
|
||||
* Use is subject to license terms, see http://www.cuba-platform.com/license for details.
|
||||
*/
|
||||
|
||||
package com.haulmont.cuba.core.app;
|
||||
|
||||
import com.haulmont.bali.util.Preconditions;
|
||||
import com.haulmont.chile.core.model.MetaClass;
|
||||
import com.haulmont.chile.core.model.MetaProperty;
|
||||
import com.haulmont.cuba.core.PersistenceSecurity;
|
||||
import com.haulmont.cuba.core.entity.BaseGenericIdEntity;
|
||||
import com.haulmont.cuba.core.entity.Entity;
|
||||
import com.haulmont.cuba.core.global.*;
|
||||
import com.haulmont.cuba.core.sys.persistence.CubaEntityFetchGroup;
|
||||
import org.eclipse.persistence.queries.FetchGroup;
|
||||
import org.eclipse.persistence.queries.FetchGroupTracker;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Supports enforcing entity attribute permissions on Middleware.
|
||||
*
|
||||
* @author Konstantin Krivopustov
|
||||
* @version $Id$
|
||||
*/
|
||||
@Component(AttributeSecuritySupport.NAME)
|
||||
public class AttributeSecuritySupport {
|
||||
|
||||
public static final String NAME = "cuba_AttributeSecuritySupport";
|
||||
|
||||
@Inject
|
||||
protected Metadata metadata;
|
||||
|
||||
@Inject
|
||||
protected MetadataTools metadataTools;
|
||||
|
||||
@Inject
|
||||
protected PersistenceSecurity security;
|
||||
|
||||
@Inject
|
||||
protected ServerConfig config;
|
||||
|
||||
/**
|
||||
* Removes restricted attributes from a view.
|
||||
*
|
||||
* @param view source view
|
||||
* @return restricted view
|
||||
*/
|
||||
public View createRestrictedView(View view) {
|
||||
if (!config.getEntityAttributePermissionChecking()) {
|
||||
return view;
|
||||
}
|
||||
Preconditions.checkNotNullArgument(view, "view is null");
|
||||
|
||||
View restrictedView = new View(view.getEntityClass());
|
||||
copyViewConsideringPermissions(view, restrictedView);
|
||||
return restrictedView;
|
||||
}
|
||||
|
||||
private void copyViewConsideringPermissions(View srcView, View dstView) {
|
||||
MetaClass metaClass = metadata.getClassNN(srcView.getEntityClass());
|
||||
for (ViewProperty property : srcView.getProperties()) {
|
||||
if (security.isEntityAttrReadPermitted(metaClass, property.getName())) {
|
||||
View viewCopy = null;
|
||||
if (property.getView() != null) {
|
||||
viewCopy = new View(property.getView().getEntityClass(), property.getView().getName() + "(restricted)");
|
||||
copyViewConsideringPermissions(property.getView(), viewCopy);
|
||||
}
|
||||
dstView.addProperty(property.getName(), viewCopy, property.getFetchMode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called after loading an entity from the database.
|
||||
*
|
||||
* @param entity just loaded detached entity
|
||||
*/
|
||||
public void afterLoad(Entity entity) {
|
||||
if (!config.getEntityAttributePermissionChecking()) {
|
||||
return;
|
||||
}
|
||||
if (entity != null) {
|
||||
metadataTools.traverseAttributes(entity, new FillingInaccessibleAttributesVisitor());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called after loading a list of entities from the database.
|
||||
*
|
||||
* @param entities list of just loaded detached entities
|
||||
*/
|
||||
public void afterLoad(Collection<? extends Entity> entities) {
|
||||
if (!config.getEntityAttributePermissionChecking()) {
|
||||
return;
|
||||
}
|
||||
Preconditions.checkNotNullArgument(entities, "entities list is null");
|
||||
|
||||
for (Entity entity : entities) {
|
||||
afterLoad(entity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called before persisting a new entity.
|
||||
*
|
||||
* @param entity new entity
|
||||
*/
|
||||
public void beforePersist(Entity entity) {
|
||||
if (!config.getEntityAttributePermissionChecking()) {
|
||||
return;
|
||||
}
|
||||
metadata.getTools().traverseAttributes(entity, new ClearReadOnlyAttributesVisitor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called before merging an entity.
|
||||
*
|
||||
* @param entity detached entity
|
||||
*/
|
||||
public void beforeMerge(Entity entity) {
|
||||
if (!config.getEntityAttributePermissionChecking()) {
|
||||
return;
|
||||
}
|
||||
MetaClass metaClass = metadata.getClassNN(entity.getClass());
|
||||
FetchGroup fetchGroup = ((FetchGroupTracker) entity)._persistence_getFetchGroup();
|
||||
if (fetchGroup != null) {
|
||||
List<String> attributesToRemove = new ArrayList<>();
|
||||
for (String attrName : fetchGroup.getAttributeNames()) {
|
||||
String[] parts = attrName.split("\\.");
|
||||
MetaClass tmpMetaClass = metaClass;
|
||||
for (String part : parts) {
|
||||
if (!security.isEntityAttrUpdatePermitted(tmpMetaClass, part)) {
|
||||
attributesToRemove.add(attrName);
|
||||
break;
|
||||
}
|
||||
MetaProperty metaProperty = tmpMetaClass.getPropertyNN(part);
|
||||
if (metaProperty.getRange().isClass()) {
|
||||
tmpMetaClass = metaProperty.getRange().asClass();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!attributesToRemove.isEmpty()) {
|
||||
List<String> attributeNames = new ArrayList<>(fetchGroup.getAttributeNames());
|
||||
attributeNames.removeAll(attributesToRemove);
|
||||
((FetchGroupTracker) entity)._persistence_setFetchGroup(new CubaEntityFetchGroup(attributeNames));
|
||||
}
|
||||
} else {
|
||||
List<String> attributeNames = new ArrayList<>();
|
||||
for (MetaProperty metaProperty : metaClass.getProperties()) {
|
||||
if (security.isEntityAttrUpdatePermitted(metaClass, metaProperty.getName())) {
|
||||
attributeNames.add(metaProperty.getName());
|
||||
}
|
||||
}
|
||||
((FetchGroupTracker) entity)._persistence_setFetchGroup(new CubaEntityFetchGroup(attributeNames));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called after merging an entity and transaction commit.
|
||||
*
|
||||
* @param entity detached entity
|
||||
*/
|
||||
public void afterMerge(Entity entity, View view) {
|
||||
if (!config.getEntityAttributePermissionChecking()) {
|
||||
return;
|
||||
}
|
||||
if (entity != null) {
|
||||
metadataTools.traverseAttributesByView(view, entity, new ClearInaccessibleAttributesVisitor());
|
||||
}
|
||||
}
|
||||
|
||||
private void addInaccessibleAttribute(BaseGenericIdEntity entity, String property) {
|
||||
String[] attributes = entity.__inaccessibleAttributes();
|
||||
attributes = attributes == null ? new String[1] : Arrays.copyOf(attributes, attributes.length + 1);
|
||||
attributes[attributes.length - 1] = property;
|
||||
entity.__inaccessibleAttributes(attributes);
|
||||
}
|
||||
|
||||
private class FillingInaccessibleAttributesVisitor implements EntityAttributeVisitor {
|
||||
@Override
|
||||
public void visit(Entity entity, MetaProperty property) {
|
||||
MetaClass metaClass = metadata.getClassNN(entity.getClass());
|
||||
if (!security.isEntityAttrReadPermitted(metaClass, property.getName())) {
|
||||
addInaccessibleAttribute((BaseGenericIdEntity) entity, property.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ClearReadOnlyAttributesVisitor implements EntityAttributeVisitor {
|
||||
@Override
|
||||
public void visit(Entity entity, MetaProperty property) {
|
||||
MetaClass metaClass = metadata.getClassNN(entity.getClass());
|
||||
if (!security.isEntityAttrUpdatePermitted(metaClass, property.getName())) {
|
||||
entity.setValue(property.getName(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ClearInaccessibleAttributesVisitor implements EntityAttributeVisitor {
|
||||
@Override
|
||||
public void visit(Entity entity, MetaProperty property) {
|
||||
MetaClass metaClass = metadata.getClassNN(entity.getClass());
|
||||
if (!security.isEntityAttrReadPermitted(metaClass, property.getName())) {
|
||||
addInaccessibleAttribute((BaseGenericIdEntity) entity, property.getName());
|
||||
entity.setValue(property.getName(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -26,8 +26,8 @@ import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import java.util.*;
|
||||
@ -55,6 +55,9 @@ public class DataManagerBean implements DataManager {
|
||||
@Inject
|
||||
protected PersistenceSecurity security;
|
||||
|
||||
@Inject
|
||||
protected AttributeSecuritySupport attributeSecurity;
|
||||
|
||||
@Inject
|
||||
protected Persistence persistence;
|
||||
|
||||
@ -95,7 +98,7 @@ public class DataManagerBean implements DataManager {
|
||||
|
||||
com.haulmont.cuba.core.Query query = createQuery(em, context);
|
||||
//noinspection unchecked
|
||||
List<E> resultList = query.getResultList();
|
||||
List<E> resultList = executeQuery(query);
|
||||
if (!resultList.isEmpty())
|
||||
result = resultList.get(0);
|
||||
|
||||
@ -108,6 +111,8 @@ public class DataManagerBean implements DataManager {
|
||||
tx.end();
|
||||
}
|
||||
|
||||
attributeSecurity.afterLoad(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -161,6 +166,8 @@ public class DataManagerBean implements DataManager {
|
||||
tx.end();
|
||||
}
|
||||
|
||||
attributeSecurity.afterLoad(resultList);
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
@ -225,6 +232,7 @@ public class DataManagerBean implements DataManager {
|
||||
// persist new
|
||||
for (Entity entity : context.getCommitInstances()) {
|
||||
if (PersistenceHelper.isNew(entity)) {
|
||||
attributeSecurity.beforePersist(entity);
|
||||
em.persist(entity);
|
||||
res.add(entity);
|
||||
persisted.add(entity);
|
||||
@ -238,8 +246,14 @@ public class DataManagerBean implements DataManager {
|
||||
// merge detached
|
||||
for (Entity entity : context.getCommitInstances()) {
|
||||
if (PersistenceHelper.isDetached(entity)) {
|
||||
attributeSecurity.beforeMerge(entity);
|
||||
View view = context.getViews().get(entity);
|
||||
Entity merged = em.merge(entity, view);
|
||||
if (view == null) {
|
||||
view = viewRepository.getView(entity.getClass(), View.LOCAL);
|
||||
}
|
||||
View restrictedView = attributeSecurity.createRestrictedView(view);
|
||||
|
||||
Entity merged = em.merge(entity, restrictedView);
|
||||
res.add(merged);
|
||||
if (entityHasDynamicAttributes(entity)) {
|
||||
BaseGenericIdEntity originalBaseGenericIdEntity = (BaseGenericIdEntity) entity;
|
||||
@ -280,6 +294,16 @@ public class DataManagerBean implements DataManager {
|
||||
tx.end();
|
||||
}
|
||||
|
||||
for (Entity entity : res) {
|
||||
if (!persisted.contains(entity)) {
|
||||
View view = context.getViews().get(entity);
|
||||
if (view == null) {
|
||||
view = viewRepository.getView(entity.getClass(), View.LOCAL);
|
||||
}
|
||||
attributeSecurity.afterMerge(entity, view);
|
||||
}
|
||||
}
|
||||
|
||||
updateReferences(persisted, res);
|
||||
|
||||
return res;
|
||||
@ -415,10 +439,13 @@ public class DataManagerBean implements DataManager {
|
||||
}
|
||||
|
||||
if (entityLoadInfoBuilder.contains(newInstances, entity)) {
|
||||
attributeSecurity.beforePersist(entity);
|
||||
em.persist(entity);
|
||||
result.add(entity);
|
||||
} else {
|
||||
Entity e = em.merge(entity);
|
||||
attributeSecurity.beforeMerge(entity);
|
||||
View view = context.getViews().get(entity);
|
||||
Entity e = em.merge(entity, view);
|
||||
result.add(e);
|
||||
}
|
||||
}
|
||||
@ -486,16 +513,16 @@ public class DataManagerBean implements DataManager {
|
||||
query.setMaxResults(contextQuery.getMaxResults());
|
||||
}
|
||||
|
||||
if (context.getView() != null) {
|
||||
query.setView(context.getView());
|
||||
}
|
||||
View view = context.getView() != null ? context.getView() :
|
||||
viewRepository.getView(metadata.getClassNN(context.getMetaClass()), View.LOCAL);
|
||||
View restrictedView = attributeSecurity.createRestrictedView(view);
|
||||
query.setView(restrictedView);
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
protected <E extends Entity> List<E> getResultList(LoadContext<E> context, Query query, boolean ensureDistinct) {
|
||||
//noinspection unchecked
|
||||
List<E> list = query.getResultList();
|
||||
List<E> list = executeQuery(query);
|
||||
if (!ensureDistinct || list.size() == 0)
|
||||
return list;
|
||||
|
||||
@ -553,6 +580,23 @@ public class DataManagerBean implements DataManager {
|
||||
return result;
|
||||
}
|
||||
|
||||
protected <E extends Entity> List<E> executeQuery(Query query) {
|
||||
List<E> list;
|
||||
try {
|
||||
//noinspection unchecked
|
||||
list = query.getResultList();
|
||||
} catch (javax.persistence.PersistenceException e) {
|
||||
if (e.getCause() instanceof org.eclipse.persistence.exceptions.QueryException
|
||||
&& e.getMessage() != null
|
||||
&& e.getMessage().contains("Fetch group cannot be set on report query")) {
|
||||
throw new DevelopmentException("DataManager cannot execute query for single attributes");
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
protected void checkPermissions(CommitContext context) {
|
||||
Set<MetaClass> checkedCreateRights = new HashSet<>();
|
||||
Set<MetaClass> checkedUpdateRights = new HashSet<>();
|
||||
|
@ -132,4 +132,12 @@ public interface ServerConfig extends Config {
|
||||
@Property("cuba.prettyTimeProperties")
|
||||
@DefaultString("")
|
||||
String getPrettyTimeProperties();
|
||||
|
||||
/**
|
||||
* If set to false, attribute permissions are not enforced on Middleware. This is appropriate if only server-side
|
||||
* clients are used.
|
||||
*/
|
||||
@Property("cuba.entityAttributePermissionChecking")
|
||||
@DefaultBoolean(true)
|
||||
boolean getEntityAttributePermissionChecking();
|
||||
}
|
||||
|
@ -268,7 +268,10 @@ public class EntityManagerImpl implements EntityManager {
|
||||
return delegate.unwrap(Connection.class);
|
||||
}
|
||||
|
||||
private void deepCopyIgnoringNulls(Entity source, Entity dest) {
|
||||
/**
|
||||
* Copies all property values from source to dest excluding null values.
|
||||
*/
|
||||
protected void deepCopyIgnoringNulls(Entity source, Entity dest) {
|
||||
for (MetaProperty srcProperty : source.getMetaClass().getProperties()) {
|
||||
String name = srcProperty.getName();
|
||||
|
||||
|
@ -95,8 +95,12 @@ public class DataManagerTest extends CubaTestCase {
|
||||
loadContext.setQueryString("select u.group from sec$User u where u.id = :userId")
|
||||
.setParameter("userId", UUID.fromString("60885987-1b61-4247-94c7-dff348347f93"));
|
||||
|
||||
List<User> list = dataManager.loadList(loadContext);
|
||||
assertTrue(list.size() == 1);
|
||||
try {
|
||||
dataManager.loadList(loadContext);
|
||||
fail();
|
||||
} catch (DevelopmentException e) {
|
||||
assertEquals("DataManager cannot execute query for single attributes", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testLoadListCaseInsensitive() {
|
||||
|
@ -6,10 +6,13 @@
|
||||
package com.haulmont.cuba.testsupport;
|
||||
|
||||
import com.haulmont.bali.db.QueryRunner;
|
||||
import com.haulmont.chile.core.model.MetaClass;
|
||||
import com.haulmont.cuba.core.EntityManager;
|
||||
import com.haulmont.cuba.core.Persistence;
|
||||
import com.haulmont.cuba.core.entity.Entity;
|
||||
import com.haulmont.cuba.core.global.AppBeans;
|
||||
import com.haulmont.cuba.core.global.Metadata;
|
||||
import com.haulmont.cuba.core.global.MetadataTools;
|
||||
import com.haulmont.cuba.core.sys.AbstractAppContextLoader;
|
||||
import com.haulmont.cuba.core.sys.AppContext;
|
||||
import com.haulmont.cuba.core.sys.AppContextLoader;
|
||||
@ -130,12 +133,12 @@ public class TestContainer extends ExternalResource {
|
||||
return AppBeans.get(Metadata.class);
|
||||
}
|
||||
|
||||
public void deleteRecord(String table, UUID... ids) {
|
||||
public void deleteRecord(String table, Object... ids) {
|
||||
deleteRecord(table, "ID", ids);
|
||||
}
|
||||
|
||||
public void deleteRecord(String table, String primaryKeyCol, UUID... ids) {
|
||||
for (UUID id : ids) {
|
||||
public void deleteRecord(String table, String primaryKeyCol, Object... ids) {
|
||||
for (Object id : ids) {
|
||||
String sql = "delete from " + table + " where " + primaryKeyCol + " = '" + id.toString() + "'";
|
||||
QueryRunner runner = new QueryRunner(persistence().getDataSource());
|
||||
try {
|
||||
@ -146,6 +149,20 @@ public class TestContainer extends ExternalResource {
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteRecord(Entity... entities) {
|
||||
for (Entity entity : entities) {
|
||||
MetadataTools metadataTools = metadata().getTools();
|
||||
MetaClass metaClass = metadata().getClassNN(entity.getClass());
|
||||
|
||||
String table = metadataTools.getDatabaseTable(metaClass);
|
||||
String primaryKey = metadataTools.getPrimaryKeyName(metaClass);
|
||||
if (table == null || primaryKey == null)
|
||||
throw new RuntimeException("Unable to determine table or primary key name for " + entity);
|
||||
|
||||
deleteRecord(table, primaryKey, entity.getId());
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getAppPropertiesFiles() {
|
||||
return appPropertiesFiles;
|
||||
}
|
||||
|
@ -54,15 +54,18 @@ public abstract class BaseGenericIdEntity<T> extends AbstractInstance implements
|
||||
@Transient
|
||||
protected boolean __removed;
|
||||
|
||||
@Transient
|
||||
protected String[] __inaccessibleAttributes;
|
||||
|
||||
@Transient
|
||||
protected Map<String, CategoryAttributeValue> dynamicAttributes = null;
|
||||
|
||||
@Column(name = "CREATE_TS")
|
||||
protected Date createTs;
|
||||
|
||||
@Column(name = "CREATED_BY", length = LOGIN_FIELD_LEN)
|
||||
protected String createdBy;
|
||||
|
||||
@Transient
|
||||
protected Map<String, CategoryAttributeValue> dynamicAttributes = null;
|
||||
|
||||
public abstract void setId(T id);
|
||||
|
||||
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
|
||||
@ -111,6 +114,16 @@ public abstract class BaseGenericIdEntity<T> extends AbstractInstance implements
|
||||
this.__removed = removed;
|
||||
}
|
||||
|
||||
/** INTERNAL */
|
||||
public String[] __inaccessibleAttributes() {
|
||||
return __inaccessibleAttributes;
|
||||
}
|
||||
|
||||
/** INTERNAL */
|
||||
public void __inaccessibleAttributes(String[] __inaccessibleAttributes) {
|
||||
this.__inaccessibleAttributes = __inaccessibleAttributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaClass getMetaClass() {
|
||||
Metadata metadata = AppBeans.get(Metadata.NAME);
|
||||
|
@ -41,6 +41,11 @@ public class StandardEntity extends BaseUuidEntity implements Versioned, Updatab
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVersion(Integer version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getUpdateTs() {
|
||||
return updateTs;
|
||||
|
@ -12,7 +12,11 @@ package com.haulmont.cuba.core.entity;
|
||||
*/
|
||||
public interface Versioned {
|
||||
|
||||
String[] PROPERTIES = {"version"};
|
||||
|
||||
Integer getVersion();
|
||||
|
||||
/**
|
||||
* Do not set version if you are not sure - it must be null for a new entity or loaded from the database
|
||||
* for a persistent one.
|
||||
*/
|
||||
void setVersion(Integer version);
|
||||
}
|
||||
|
@ -4,6 +4,9 @@
|
||||
*/
|
||||
package com.haulmont.cuba.core.global;
|
||||
|
||||
import com.haulmont.cuba.core.entity.Entity;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@ -13,6 +16,18 @@ public class NotDetachedCommitContext extends CommitContext {
|
||||
|
||||
protected Set<String> newInstanceIds = new HashSet<>();
|
||||
|
||||
public NotDetachedCommitContext(Entity... commitInstances) {
|
||||
super(commitInstances);
|
||||
}
|
||||
|
||||
public NotDetachedCommitContext(Collection commitInstances) {
|
||||
super(commitInstances);
|
||||
}
|
||||
|
||||
public NotDetachedCommitContext(Collection commitInstances, Collection removeInstances) {
|
||||
super(commitInstances, removeInstances);
|
||||
}
|
||||
|
||||
public Set<String> getNewInstanceIds() {
|
||||
return newInstanceIds;
|
||||
}
|
||||
|
@ -118,6 +118,13 @@ public class PersistenceHelper {
|
||||
* @return true if loaded
|
||||
*/
|
||||
public static boolean isLoaded(Object entity, String property) {
|
||||
if (entity instanceof BaseGenericIdEntity
|
||||
&& ((BaseGenericIdEntity) entity).__inaccessibleAttributes() != null) {
|
||||
for (String inaccessibleAttr : ((BaseGenericIdEntity) entity).__inaccessibleAttributes()) {
|
||||
if (inaccessibleAttr.equals(property))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (entity instanceof FetchGroupTracker) {
|
||||
FetchGroup fetchGroup = ((FetchGroupTracker) entity)._persistence_getFetchGroup();
|
||||
if (fetchGroup != null)
|
||||
|
@ -5,12 +5,15 @@
|
||||
|
||||
package com.haulmont.cuba.core.sys.persistence;
|
||||
|
||||
import com.haulmont.cuba.core.entity.BaseGenericIdEntity;
|
||||
import com.haulmont.cuba.core.global.IllegalEntityStateException;
|
||||
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
|
||||
import org.eclipse.persistence.internal.queries.EntityFetchGroup;
|
||||
import org.eclipse.persistence.queries.FetchGroup;
|
||||
import org.eclipse.persistence.queries.FetchGroupTracker;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author krivopustov
|
||||
* @version $Id$
|
||||
@ -21,8 +24,20 @@ public class CubaEntityFetchGroup extends EntityFetchGroup {
|
||||
super(fetchGroup);
|
||||
}
|
||||
|
||||
public CubaEntityFetchGroup(Collection<String> attributeNames) {
|
||||
super(attributeNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onUnfetchedAttribute(FetchGroupTracker entity, String attributeName) {
|
||||
String[] inaccessible = ((BaseGenericIdEntity) entity).__inaccessibleAttributes();
|
||||
if (inaccessible != null) {
|
||||
for (String inaccessibleAttribute : inaccessible) {
|
||||
if (attributeName.equals(inaccessibleAttribute))
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (attributeName == null && entity._persistence_getSession() != null) { // occurs on merge
|
||||
return super.onUnfetchedAttribute(entity, null);
|
||||
}
|
||||
|
@ -44,6 +44,9 @@ public class UserSession implements Serializable {
|
||||
|
||||
protected Map<String, Serializable> attributes;
|
||||
|
||||
/**
|
||||
* INTERNAL
|
||||
*/
|
||||
public UserSession(UUID id, User user, Collection<Role> roles, Locale locale, boolean system) {
|
||||
this.id = id;
|
||||
this.user = user;
|
||||
@ -69,12 +72,18 @@ public class UserSession implements Serializable {
|
||||
attributes = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL
|
||||
*/
|
||||
public UserSession(UserSession src, User user, Collection<Role> roles, Locale locale) {
|
||||
this(src.id, user, roles, locale, src.system);
|
||||
this.user = src.user;
|
||||
this.substitutedUser = this.user.equals(user) ? null : user;
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL
|
||||
*/
|
||||
public UserSession(UserSession src) {
|
||||
id = src.id;
|
||||
user = src.user;
|
||||
@ -104,7 +113,7 @@ public class UserSession implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't do it
|
||||
* INTERNAL
|
||||
*/
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
@ -118,7 +127,7 @@ public class UserSession implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't do it
|
||||
* INTERNAL
|
||||
*/
|
||||
public void setSubstitutedUser(User substitutedUser) {
|
||||
this.substitutedUser = substitutedUser;
|
||||
@ -145,6 +154,9 @@ public class UserSession implements Serializable {
|
||||
return locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL
|
||||
*/
|
||||
public void setLocale(Locale locale) {
|
||||
this.locale = locale;
|
||||
}
|
||||
@ -157,6 +169,9 @@ public class UserSession implements Serializable {
|
||||
return timeZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL
|
||||
*/
|
||||
public void setTimeZone(TimeZone timeZone) {
|
||||
this.timeZone = timeZone;
|
||||
}
|
||||
@ -168,6 +183,9 @@ public class UserSession implements Serializable {
|
||||
return address;
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL
|
||||
*/
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
@ -179,14 +197,17 @@ public class UserSession implements Serializable {
|
||||
return clientInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL
|
||||
*/
|
||||
public void setClientInfo(String clientInfo) {
|
||||
this.clientInfo = clientInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used by security subsystem
|
||||
* INTERNAL
|
||||
*/
|
||||
public void addPermission(PermissionType type, String target, String extTarget, int value) {
|
||||
public void addPermission(PermissionType type, String target, @Nullable String extTarget, int value) {
|
||||
Integer currentValue = permissions[type.ordinal()].get(target);
|
||||
if (currentValue == null || currentValue < value) {
|
||||
permissions[type.ordinal()].put(target, value);
|
||||
@ -196,14 +217,14 @@ public class UserSession implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used by security subsystem
|
||||
* INTERNAL
|
||||
*/
|
||||
public void removePermission(PermissionType type, String target) {
|
||||
permissions[type.ordinal()].remove(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used by security subsystem
|
||||
* INTERNAL
|
||||
*/
|
||||
public Integer getPermissionValue(PermissionType type, String target) {
|
||||
return permissions[type.ordinal()].get(target);
|
||||
@ -286,7 +307,7 @@ public class UserSession implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used by security subsystem
|
||||
* INTERNAL
|
||||
*/
|
||||
public void addConstraint(String entityName, String joinClause, String whereClause) {
|
||||
List<String[]> list = constraints.get(entityName);
|
||||
@ -298,7 +319,7 @@ public class UserSession implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used by security subsystem
|
||||
* INTERNAL
|
||||
*/
|
||||
public List<String[]> getConstraints(String entityName) {
|
||||
List<String[]> list = constraints.get(entityName);
|
||||
|
Loading…
Reference in New Issue
Block a user