Skip to content

Commit

Permalink
chore: include hotfix-16963 (#26134)
Browse files Browse the repository at this point in the history
  • Loading branch information
erickgonzalez committed Sep 15, 2023
1 parent 7180f12 commit dcd24f3
Showing 1 changed file with 145 additions and 136 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.dotmarketing.business;

import static com.dotcms.content.elasticsearch.business.ESIndexAPI.INDEX_OPERATIONS_TIMEOUT_IN_MS;
import static com.dotcms.exception.ExceptionUtil.bubbleUpException;

import com.dotcms.business.CloseDBIfOpened;
import com.dotcms.business.WrapInTransaction;
import com.dotcms.concurrent.DotConcurrentFactory;
import com.dotcms.concurrent.lock.IdentifierStripedLock;
Expand All @@ -13,9 +13,7 @@
import com.dotcms.contenttype.model.type.ContentType;
import com.dotcms.contenttype.transform.contenttype.StructureTransformer;
import com.dotcms.rendering.velocity.viewtools.navigation.NavResult;

import com.dotcms.system.SimpleMapAppContext;
import com.dotcms.util.ReturnableDelegate;
import com.dotmarketing.beans.Host;
import com.dotmarketing.beans.Identifier;
import com.dotmarketing.beans.Inode;
Expand Down Expand Up @@ -57,8 +55,8 @@
import com.dotmarketing.util.InodeUtils;
import com.dotmarketing.util.Logger;
import com.dotmarketing.util.UtilMethods;

import com.liferay.portal.model.User;
import io.vavr.control.Try;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
Expand All @@ -68,6 +66,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.elasticsearch.action.bulk.BulkRequestBuilder;

/**
Expand Down Expand Up @@ -949,13 +948,8 @@ protected Permission getPermission(String x) {

@Override
protected List<Permission> getInheritablePermissions(Permissionable permissionable, String type) throws DotDataException {
List<Permission> permissions = getInheritablePermissions(permissionable, true);
List<Permission> toReturn = new ArrayList<Permission>();
for(Permission p : permissions) {
if(p.getType().equals(type))
toReturn.add(p);
}
return toReturn;
final List<Permission> permissions = getInheritablePermissions(permissionable, true);
return permissions.stream().filter(permission -> permission.getType().equals(type)).collect(Collectors.toList());
}

@Override
Expand Down Expand Up @@ -1007,50 +1001,24 @@ protected List<Permission> getPermissions(Permissionable permissionable, boolean
}

@Override
protected List<Permission> getPermissions(Permissionable permissionable, boolean bitPermissions, boolean onlyIndividualPermissions, boolean forceLoadFromDB) throws DotDataException {

protected List<Permission> getPermissions(Permissionable permissionable, boolean bitPermissions,
boolean onlyIndividualPermissions, boolean forceLoadFromDB) throws DotDataException {

if (!InodeUtils.isSet(permissionable.getPermissionId())) {
return new ArrayList<>();
return new ArrayList<>();
}

List<Permission> bitPermissionsList = null;

if(!forceLoadFromDB) {
bitPermissionsList = permissionCache
.getPermissionsFromCache(permissionable.getPermissionId());
}

//No permissions in cache have to look for individual permissions or inherited permissions
if (bitPermissionsList == null) {
try {
bitPermissionsList = lockManager
.tryLock(LOCK_PREFIX + permissionable.getPermissionId(),
() -> {
List<Permission> permissionsList = null;
if (!forceLoadFromDB) {
permissionsList = permissionCache.getPermissionsFromCache(permissionable.getPermissionId());
}
//Checking individual permissions
if (permissionsList == null) {
permissionsList = loadPermissions(permissionable);
permissionCache.addToPermissionCache(permissionable.getPermissionId(), permissionsList);
}
return permissionsList;
});
} catch (final Throwable throwable) {
if (throwable instanceof DotDataException) {
throw (DotDataException) throwable;
}
throw new DotDataException(throwable);
}
}
bitPermissionsList = filterOnlyNonInheritablePermissions(bitPermissionsList, permissionable.getPermissionId());
bitPermissionsList = loadPermissions(permissionable, forceLoadFromDB);
bitPermissionsList = filterOnlyNonInheritablePermissions(bitPermissionsList,
permissionable.getPermissionId());

if(!bitPermissions) {
bitPermissionsList = convertToNonBitPermissions(bitPermissionsList);
}
return onlyIndividualPermissions?filterOnlyIndividualPermissions(bitPermissionsList, permissionable.getPermissionId()):bitPermissionsList;
return onlyIndividualPermissions ? filterOnlyIndividualPermissions(bitPermissionsList,
permissionable.getPermissionId()) : bitPermissionsList;
}

@Override
Expand Down Expand Up @@ -1112,7 +1080,7 @@ private void updatePermissionReferencesOnAdd(final Permissionable permissionable
ran06=false,ran07=false,ran08=false,ran09=false,ran10=false;

final List<Map<String, Object>> idsToClear = new ArrayList<>();
final List<Permission> permissions = filterOnlyInheritablePermissions(loadPermissions(permissionable), parentPermissionableId);
final List<Permission> permissions = filterOnlyInheritablePermissions(loadPermissions(permissionable, true), parentPermissionableId);
for(final Permission p : permissions) {

if (isHost || isFolder) {
Expand Down Expand Up @@ -1489,7 +1457,7 @@ private void updatePermissionReferencesOnRemove(Permissionable permissionable) t
whileLoop: while(parentPermissionable != null) {
defaultReplacement = parentPermissionable;
String parentPermissionableId = parentPermissionable.getPermissionId();
List<Permission> permissions = filterOnlyInheritablePermissions(loadPermissions(parentPermissionable), parentPermissionableId);
final List<Permission> permissions = filterOnlyInheritablePermissions(loadPermissions(parentPermissionable, true), parentPermissionableId);
for(Permission p : permissions) {
if(typesToLookFor.contains(p.getType())) {
referenceReplacement.put(p.getType(), p.getInode());
Expand Down Expand Up @@ -1634,9 +1602,7 @@ protected void assignPermissions(List<Permission> permissions, Permissionable pe
boolean updateReferencesOnAdd = false;
boolean removePermissionableReference = false;
boolean clearReferencesCache = false;

List<Permission> currentPermissions = filterAssetOnlyPermissions(loadPermissions(permissionable), permissionable.getPermissionId());

final List<Permission> currentPermissions = filterAssetOnlyPermissions(loadPermissions(permissionable, true), permissionable.getPermissionId());
for(Permission cp : currentPermissions) {
if(containsPermission(permissions, cp)) {
deletePermission(cp);
Expand Down Expand Up @@ -2161,111 +2127,154 @@ private void deletePermission(Permission p) {
}
}

@CloseDBIfOpened
@SuppressWarnings("unchecked")
private List<Permission> loadPermissions(final Permissionable permissionable, final boolean forceDB) throws DotDataException {
if(forceDB){
permissionCache.remove(permissionable.getPermissionId());
}
return loadPermissions(permissionable);
}

@CloseDBIfOpened
@SuppressWarnings("unchecked")
private List<Permission> loadPermissions(Permissionable permissionable) throws DotDataException {
private List<Permission> loadPermissions(final Permissionable permissionable) throws DotDataException {

if(permissionable == null || ! UtilMethods.isSet(permissionable.getPermissionId())){
throw new DotDataException("Invalid Permissionable passed in. permissionable:" + permissionable.getPermissionId());
final String permissionKey = Try.of(() -> permissionable.getPermissionId())
.getOrElseThrow(() -> new DotDataException("Invalid Permissionable passed in. permissionable:" + permissionable));


// Step 1. cache lookup first
List<Permission> permissionList = permissionCache.getPermissionsFromCache(permissionKey);
if (permissionList != null) {
return permissionList;
}

HibernateUtil persistenceService = new HibernateUtil(Permission.class);
persistenceService.setSQLQuery(LOAD_PERMISSION_SQL);
persistenceService.setParam(permissionable.getPermissionId());
persistenceService.setParam(permissionable.getPermissionId());
List<Permission> bitPermissionsList = (List<Permission>) persistenceService.list();
/*
* Step 2. check the permission_reference table
* In this step, we try to find our entries in the
* permission_reference table We lock to lookup, check if cache has been loaded while we have been
* waiting, and if so, use it, otherwise we query the permission_reference table
*/

for(final Permission p : bitPermissionsList) {
p.setBitPermission(true);
permissionList = Try.of(() -> lockManager.tryLock(LOCK_PREFIX + permissionKey, () -> {
List<Permission> bitPermissionsList = permissionCache.getPermissionsFromCache(permissionKey);
if (bitPermissionsList != null) {
return bitPermissionsList;
}
HibernateUtil persistenceService = new HibernateUtil(Permission.class);
persistenceService.setSQLQuery(LOAD_PERMISSION_SQL);
persistenceService.setParam(permissionable.getPermissionId());
persistenceService.setParam(permissionable.getPermissionId());
bitPermissionsList = (List<Permission>) persistenceService.list();

bitPermissionsList.forEach(p -> p.setBitPermission(true));
// adding to cache if found

permissionCache.addToPermissionCache(permissionKey, bitPermissionsList);

return bitPermissionsList;

})).getOrElseThrow(e -> new DotDataException(e));

// if we've found permissions, return'em
if (!permissionList.isEmpty()) {
return permissionList;
}
//Check permission reference
if(bitPermissionsList.isEmpty()) {

try {
bitPermissionsList = lockManager
.tryLock(LOCK_PREFIX + permissionable.getPermissionId(), () -> {

//Need to determine who this asset should inherit from
String type = permissionable.getPermissionType();
if(permissionable instanceof Host ||
(permissionable instanceof Contentlet &&
((Contentlet)permissionable).getStructure() != null &&
((Contentlet)permissionable).getStructure().getVelocityVarName() != null &&
((Contentlet)permissionable).getStructure().getVelocityVarName().equals("Host"))){
type = Host.class.getCanonicalName();
} else if ( permissionable instanceof Contentlet &&
BaseContentType.FILEASSET.getType() == ((Contentlet) permissionable).getStructure().getStructureType()) {
type = Contentlet.class.getCanonicalName();
} else if ( permissionable instanceof IHTMLPage ||
(permissionable instanceof Contentlet && BaseContentType.HTMLPAGE.getType() == ((Contentlet) permissionable).getStructure().getStructureType())) {
type = IHTMLPage.class.getCanonicalName();
}else if(permissionable instanceof Event){
type = Contentlet.class.getCanonicalName();
}else if(permissionable instanceof Identifier){
Permissionable perm = InodeFactory.getInode(permissionable.getPermissionId(), Inode.class);
Logger.error(this, "PermissionBitFactoryImpl : loadPermissions Method : was passed an identifier. This is a problem. We will get inode as a fallback but this should be reported");
if(perm!=null){
if ( perm instanceof IHTMLPage ||
(perm instanceof Contentlet && BaseContentType.HTMLPAGE.getType() == ((Contentlet) perm).getStructure().getStructureType())) {
type = IHTMLPage.class.getCanonicalName();
}else if(perm instanceof Container){
type = Container.class.getCanonicalName();
}else if(perm instanceof Folder){
type = Folder.class.getCanonicalName();
}else if(perm instanceof Link){
type = Link.class.getCanonicalName();
}else if(perm instanceof Template){
type = Template.class.getCanonicalName();
} else if (perm instanceof Structure || perm instanceof ContentType) {
type = Structure.class.getCanonicalName();
}else if(perm instanceof Contentlet || perm instanceof Event){
type = Contentlet.class.getCanonicalName();
}
}
}
/*
* Step 3. Recursive calls to find our "parent permissionable"
* If we don't have any permissions in
* cache or entries in the permission_reference table, we need to find our "parent permissionable"
* and store that in the permission_reference table for a faster lookup in Step 2.
*/

if(permissionable instanceof Template && UtilMethods.isSet(((Template) permissionable).isDrawed()) && ((Template) permissionable).isDrawed()) {
type = TemplateLayout.class.getCanonicalName();
}
final String type = resolvePermissionType(permissionable);

if(permissionable instanceof NavResult) {
type = ((NavResult)permissionable).getEnclosingPermissionClassName();
}
Permissionable parentPermissionable = permissionable.getParentPermissionable();

Permissionable parentPermissionable = permissionable.getParentPermissionable();
Permissionable newReference = null;
List<Permission> inheritedPermissions = new ArrayList<Permission>();
while(parentPermissionable != null) {
newReference = parentPermissionable;
inheritedPermissions = getInheritablePermissions(parentPermissionable, type);
if(inheritedPermissions.size() > 0) {
break;
}
parentPermissionable = parentPermissionable.getParentPermissionable();
}
HostAPI hostAPI = APILocator.getHostAPI();
if(newReference == null)
newReference = hostAPI.findSystemHost();
while (parentPermissionable != null) {
permissionList = getInheritablePermissions(parentPermissionable, type);
if (!permissionList.isEmpty() || Host.SYSTEM_HOST.equals(parentPermissionable.getPermissionId())) {
break;
}
parentPermissionable = parentPermissionable.getParentPermissionable();
}

deleteInsertPermission(permissionable, type, newReference);
final Permissionable finalNewReference = (parentPermissionable == null) ? APILocator.systemHost() : parentPermissionable;

return inheritedPermissions;
/*
* Step 4. Upsert into the permission_reference table
* We have found our "parent permissionable", now
* we have to lock again in order to UPSERT our parent permissionable in the permission_reference
* table
*/

});
} catch (final Throwable throwable) {
if (throwable instanceof DotDataException) {
throw (DotDataException) throwable;
}
throw new DotDataException(throwable);
}
Try.run(() -> lockManager.tryLock(LOCK_PREFIX + permissionKey, () -> {
deleteInsertPermission(permissionable, type, finalNewReference);
})).onFailure(e -> {
throw new DotRuntimeException(e);
});
Logger.info(this.getClass(), "permission inherited: " + Try.of(()->type.substring(type.lastIndexOf(".")+1, type.length())).getOrElse(type) + " : " + permissionKey + " -> " +finalNewReference);

permissionCache.addToPermissionCache(permissionKey, permissionList);
return permissionList;

}

private String resolvePermissionType(final Permissionable permissionable) {
// Need to determine who this asset should inherit from
String type = permissionable.getPermissionType();
if (permissionable instanceof Host || (permissionable instanceof Contentlet && ((Contentlet) permissionable).getStructure() != null
&& ((Contentlet) permissionable).getStructure().getVelocityVarName() != null
&& ((Contentlet) permissionable).getStructure().getVelocityVarName().equals("Host"))) {
type = Host.class.getCanonicalName();
} else if (permissionable instanceof Contentlet
&& BaseContentType.FILEASSET.getType() == ((Contentlet) permissionable).getStructure().getStructureType()) {
type = Contentlet.class.getCanonicalName();
} else if (permissionable instanceof IHTMLPage || (permissionable instanceof Contentlet
&& BaseContentType.HTMLPAGE.getType() == ((Contentlet) permissionable).getStructure().getStructureType())) {
type = IHTMLPage.class.getCanonicalName();
} else if (permissionable instanceof Event) {
type = Contentlet.class.getCanonicalName();
} else if (permissionable instanceof Identifier) {
Permissionable perm = InodeFactory.getInode(permissionable.getPermissionId(), Inode.class);
Logger.error(this,
"PermissionBitFactoryImpl : loadPermissions Method : was passed an identifier. This is a problem. We will get inode as a fallback but this should be reported");
if (perm != null) {
if (perm instanceof IHTMLPage || (perm instanceof Contentlet
&& BaseContentType.HTMLPAGE.getType() == ((Contentlet) perm).getStructure().getStructureType())) {
type = IHTMLPage.class.getCanonicalName();
} else if (perm instanceof Container) {
type = Container.class.getCanonicalName();
} else if (perm instanceof Folder) {
type = Folder.class.getCanonicalName();
} else if (perm instanceof Link) {
type = Link.class.getCanonicalName();
} else if (perm instanceof Template) {
type = Template.class.getCanonicalName();
} else if (perm instanceof Structure || perm instanceof ContentType) {
type = Structure.class.getCanonicalName();
} else if (perm instanceof Contentlet || perm instanceof Event) {
type = Contentlet.class.getCanonicalName();
}
}
}

return bitPermissionsList;
if (permissionable instanceof Template && UtilMethods.isSet(((Template) permissionable).isDrawed())
&& ((Template) permissionable).isDrawed()) {
type = TemplateLayout.class.getCanonicalName();
}

if (permissionable instanceof NavResult) {
type = ((NavResult) permissionable).getEnclosingPermissionClassName();
}
return type;
}




protected static final String PERMISSION_REFERENCE = "permission_reference";
protected static final String ASSET_ID = "asset_id";
protected static final String REFERENCE_ID = "reference_id";
Expand Down Expand Up @@ -2394,7 +2403,7 @@ List<Permission> getPermissionsByRole(Role role, boolean onlyFoldersAndHosts, bo


StringBuilder query = new StringBuilder();
query.append("select {permission.*} from permission ");
query.append("select distinct {permission.*} from permission ");
if(onlyFoldersAndHosts) {
query.append(" join contentlet on (contentlet.identifier=permission.inode_id and structure_inode=?) ")
.append(" where permission.roleid =? ")
Expand Down Expand Up @@ -3801,4 +3810,4 @@ public String getInsertTemplateReferencesToAHostSQL() {
}
}

}
}

0 comments on commit dcd24f3

Please sign in to comment.