/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <p>
*/
package org.olat.repository;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.hibernate.Hibernate;
import org.olat.admin.securitygroup.gui.IdentitiesAddEvent;
import org.olat.basesecurity.Constants;
import org.olat.basesecurity.Manager;
import org.olat.basesecurity.ManagerFactory;
import org.olat.basesecurity.SecurityGroup;
import org.olat.bookmark.BookmarkManager;
import org.olat.catalog.CatalogManager;
import org.olat.core.commons.modules.bc.FolderConfig;
import org.olat.core.commons.persistence.DBFactory;
import org.olat.core.commons.persistence.DBQuery;
import org.olat.core.commons.persistence.PersistenceHelper;
import org.olat.core.commons.persistence.async.BackgroundTaskQueueManager;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.id.Identity;
import org.olat.core.id.OLATResourceable;
import org.olat.core.id.Roles;
import org.olat.core.logging.AssertException;
import org.olat.core.logging.Tracing;
import org.olat.core.logging.activity.ActionType;
import org.olat.core.logging.activity.OlatResourceableType;
import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
import org.olat.core.util.StringHelper;
import org.olat.group.BusinessGroup;
import org.olat.group.BusinessGroupManagerImpl;
import org.olat.group.GroupLoggingAction;
import org.olat.group.context.BGContext;
import org.olat.group.context.BGContextManagerImpl;
import org.olat.repository.async.IncrementDownloadCounterBackgroundTask;
import org.olat.repository.async.IncrementLaunchCounterBackgroundTask;
import org.olat.repository.async.SetAccessBackgroundTask;
import org.olat.repository.async.SetDescriptionNameBackgroundTask;
import org.olat.repository.async.SetLastUsageBackgroundTask;
import org.olat.repository.async.SetPropertiesBackgroundTask;
import org.olat.repository.controllers.RepositoryEntryImageController;
import org.olat.repository.handlers.RepositoryHandler;
import org.olat.repository.handlers.RepositoryHandlerFactory;
import org.olat.resource.OLATResource;
import org.olat.resource.OLATResourceManager;
import org.olat.util.logging.activity.LoggingResourceable;
/**
* Initial Date: Mar 31, 2004
*
* @author Mike Stock
*
* Comment:
*
*/
public class RepositoryManager {
private static RepositoryManager INSTANCE = null;
private Manager securityManager;
private RepositoryManager() {
// private since singleteon
this.securityManager = ManagerFactory.getManager();
}
static { INSTANCE = new RepositoryManager(); }
/**
* @return Singleton.
*/
public static RepositoryManager getInstance() { return INSTANCE; }
/**
* @param initialAuthor
* @return A repository instance which has not been persisted yet.
*/
public RepositoryEntry createRepositoryEntryInstance(String initialAuthor) {
return createRepositoryEntryInstance(initialAuthor, null, null);
}
/**
* @param initialAuthor
* @param resourceName
* @param description
* @return A repository instance which has not been persisted yet, initialized with given data.
*/
public RepositoryEntry createRepositoryEntryInstance(String initialAuthor, String resourceName, String description) {
RepositoryEntry re = new RepositoryEntry();
re.setInitialAuthor(initialAuthor);
re.setResourcename(resourceName == null ? "" : resourceName);
re.setDescription(description == null ? "" : description);
re.setLastUsage(new Date());
return re;
}
/**
* @param repositoryEntryStatusCode
*/
public RepositoryEntryStatus createRepositoryEntryStatus(int repositoryEntryStatusCode) {
return new RepositoryEntryStatus(repositoryEntryStatusCode);
}
/**
* Save repo entry.
* @param re
*/
public void saveRepositoryEntry(RepositoryEntry re) {
if (re.getOwnerGroup() == null) {
throw new AssertException("try to save RepositoryEntry without owner-group! Plase initialize owner-group.");
}
re.setLastModified(new Date());
DBFactory.getInstance().saveObject(re);
}
/**
* Update repo entry.
* @param re
*/
public void updateRepositoryEntry(RepositoryEntry re) {
re.setLastModified(new Date());
DBFactory.getInstance().updateObject(re);
}
/**
* Delete repo entry.
* @param re
*/
public void deleteRepositoryEntry(RepositoryEntry re) {
re = (RepositoryEntry) DBFactory.getInstance().loadObject(re,true);
DBFactory.getInstance().deleteObject(re);
//TODO:pb:b this should be called in a RepoEntryImageManager.delete
//instead of a controller.
RepositoryEntryImageController.deleteImage(re);
}
public boolean deleteRepositoryEntryWithAllData(UserRequest ureq, WindowControl wControl,RepositoryEntry entry) {
// invoke handler delete callback
Tracing.logDebug("deleteRepositoryEntry start entry=" + entry, this.getClass());
entry = (RepositoryEntry) DBFactory.getInstance().loadObject(entry,true);
Tracing.logDebug("deleteRepositoryEntry after load entry=" + entry, this.getClass());
Tracing.logDebug("deleteRepositoryEntry after load entry.getOwnerGroup()=" + entry.getOwnerGroup(), this.getClass());
RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(entry);
OLATResource ores = entry.getOlatResource();
if (!handler.readyToDelete(ores, ureq, wControl)) return false;
// start transaction
// delete entry picture
File uploadDir = new File(FolderConfig.getCanonicalRoot() + FolderConfig.getRepositoryHome());
File picFile = new File(uploadDir, entry.getKey() + ".jpg");
if (picFile.exists()) {
picFile.delete();
}
// delete all bookmarks referencing deleted entry
BookmarkManager.getInstance().deleteAllBookmarksFor(entry);
// delete all catalog entries referencing deleted entry
CatalogManager.getInstance().resourceableDeleted(entry);
// delete the entry
entry = (RepositoryEntry) DBFactory.getInstance().loadObject(entry,true);
Tracing.logDebug("deleteRepositoryEntry after reload entry=" + entry, this.getClass());
Tracing.logDebug("deleteRepositoryEntry after reload entry.getOwnerGroup()=" + entry.getOwnerGroup(), this.getClass());
SecurityGroup ownerGroup = entry.getOwnerGroup();
deleteRepositoryEntry(entry);
if (ownerGroup != null) {
// delete secGroup
Tracing.logDebug("deleteRepositoryEntry deleteSecurityGroup ownerGroup=" + ownerGroup, this.getClass());
ManagerFactory.getManager().deleteSecurityGroup(ownerGroup);
}
// inform handler to do any cleanup work... handler must delete the
// referenced resourceable aswell.
handler.cleanupOnDelete(entry.getOlatResource(), ureq, wControl);
Tracing.logDebug("deleteRepositoryEntry Done" , this.getClass());
return true;
}
/**
* Lookup repo entry by key.
* @param the repository entry key (not the olatresourceable key)
* @return Repo entry represented by key or null if no such entry or key is null.
*/
public RepositoryEntry lookupRepositoryEntry(Long key) {
if (key == null) return null;
return (RepositoryEntry)DBFactory.getInstance().findObject(RepositoryEntry.class, key);
}
/**
* Lookup the repository entry which references the given olat resourceable.
* @param resourceable
* @param strict true: throws exception if not found, false: returns null if not found
* @return the RepositorEntry or null if strict=false
* @throws AssertException if the softkey could not be found (strict=true)
*/
public RepositoryEntry lookupRepositoryEntry(OLATResourceable resourceable, boolean strict) {
OLATResource ores = OLATResourceManager.getInstance().findResourceable(resourceable);
if (ores == null) {
if (!strict) return null;
throw new AssertException("Unable to fetch OLATResource for resourceable: " + resourceable.getResourceableTypeName() + ", " + resourceable.getResourceableId());
}
String query = "select v from org.olat.repository.RepositoryEntry v"+
" inner join fetch v.olatResource as ores"+
" where ores.key = :oreskey";
DBQuery dbQuery = DBFactory.getInstance().createQuery(query);
dbQuery.setLong("oreskey", ores.getKey().longValue());
dbQuery.setCacheable(true);
List result = dbQuery.list();
int size = result.size();
if (strict) {
if (size != 1)
throw new AssertException("Repository resourceable lookup returned zero or more than one result: " + size);
}
else { // not strict -> return null if zero entries found
if (size > 1)
throw new AssertException("Repository resourceable lookup returned more than one result: " + size);
if (size == 0) {
return null;
}
}
return (RepositoryEntry)result.get(0);
}
/**
* Lookup a repository entry by its softkey.
* @param softkey
* @param strict true: throws exception if not found, false: returns null if not found
* @return the RepositorEntry or null if strict=false
* @throws AssertException if the softkey could not be found (strict=true)
*/
public RepositoryEntry lookupRepositoryEntryBySoftkey(String softkey, boolean strict) {
String query = "select v from org.olat.repository.RepositoryEntry v" +
" inner join fetch v.olatResource as ores"+
" where v.softkey = :softkey";
DBQuery dbQuery = DBFactory.getInstance().createQuery(query);
dbQuery.setString("softkey", softkey);
dbQuery.setCacheable(true);
List result = dbQuery.list();
int size = result.size();
if (strict) {
if (size != 1)
throw new AssertException("Repository softkey lookup returned zero or more than one result: " + size+", softKey = "+softkey);
}
else { // not strict -> return null if zero entries found
if (size > 1)
throw new AssertException("Repository softkey lookup returned more than one result: " + size+", softKey = "+softkey);
if (size == 0) {
return null;
}
}
return (RepositoryEntry)result.get(0);
}
/**
* Convenience method to access the repositoryEntry displayname by the referenced OLATResourceable id.
* This only works if a repository entry has an referenced olat resourceable like a course or an content package repo entry
* @param resId
* @return the repositoryentry displayname or null if not found
*/
public String lookupDisplayNameByOLATResourceableId(Long resId) {
String query = "select v from org.olat.repository.RepositoryEntry v"+
" inner join fetch v.olatResource as ores"+
" where ores.resId = :resid";
DBQuery dbQuery = DBFactory.getInstance().createQuery(query);
dbQuery.setLong("resid", resId.longValue());
dbQuery.setCacheable(true);
List<RepositoryEntry> result = dbQuery.list();
int size = result.size();
if (size > 1) throw new AssertException("Repository lookup returned zero or more than one result: " + size);
else if (size == 0) return null;
RepositoryEntry entry = result.get(0);
return entry.getDisplayname();
}
/**
* Test a repo entry if identity is allowed to launch.
* @param ureq
* @param re
* @return True if current identity is allowed to launch the given repo entry.
*/
public boolean isAllowedToLaunch(UserRequest ureq, RepositoryEntry re) {
return isAllowedToLaunch(ureq.getIdentity(), ureq.getUserSession().getRoles(), re);
}
/**
* Test a repo entry if identity is allowed to launch.
* @param identity
* @param roles
* @param re
* @return True if current identity is allowed to launch the given repo entry.
*/
public boolean isAllowedToLaunch(Identity identity, Roles roles, RepositoryEntry re) {
if (!re.getCanLaunch()) return false; // deny if not launcheable
// allow if identity is owner
if (ManagerFactory.getManager().isIdentityPermittedOnResourceable(
identity, Constants.PERMISSION_ACCESS, re.getOwnerGroup())) return true;
// allow if access limit matches identity's role
// allow for olat administrators
if (roles.isOLATAdmin()) return true;
// allow for institutional resource manager
if (isInstitutionalRessourceManagerFor(re, identity)) return true;
// allow for authors if access granted at least for authors
if (roles.isAuthor() && re.getAccess() >= RepositoryEntry.ACC_OWNERS_AUTHORS) return true;
// allow for guests if access granted for guests
if (roles.isGuestOnly()) {
if (re.getAccess() >= RepositoryEntry.ACC_USERS_GUESTS) return true;
else return false;
}
// else allow if access granted for users
return re.getAccess() >= RepositoryEntry.ACC_USERS;
}
/**
* Increment the launch counter.
* @param re
*/
public void incrementLaunchCounter(RepositoryEntry re) {
//o_clusterOK by:cg
BackgroundTaskQueueManager.getInstance().addTask(new IncrementLaunchCounterBackgroundTask(re));
}
/**
* Increment the download counter.
* @param re
*/
public void incrementDownloadCounter(final RepositoryEntry re) {
BackgroundTaskQueueManager.getInstance().addTask(new IncrementDownloadCounterBackgroundTask(re));
}
/**
* Set last-usage date to to now for certain repository-entry.
* @param
*/
public static void setLastUsageNowFor(final RepositoryEntry re) {
if (re != null) {
BackgroundTaskQueueManager.getInstance().addTask(new SetLastUsageBackgroundTask(re));
}
}
public void setAccess(final RepositoryEntry re, int access ) {
SetAccessBackgroundTask task = new SetAccessBackgroundTask(re, access);
BackgroundTaskQueueManager.getInstance().addTask(task);
task.waitForDone();
}
public void setDescriptionAndName(final RepositoryEntry re, String displayName, String description ) {
SetDescriptionNameBackgroundTask task = new SetDescriptionNameBackgroundTask(re, displayName, description);
BackgroundTaskQueueManager.getInstance().addTask(task);
task.waitForDone();
}
public void setProperties(final RepositoryEntry re, boolean canCopy, boolean canReference, boolean canLaunch, boolean canDownload ) {
SetPropertiesBackgroundTask task = new SetPropertiesBackgroundTask(re, canCopy, canReference, canLaunch, canDownload);
BackgroundTaskQueueManager.getInstance().addTask(task);
task.waitForDone();
}
/**
* Count by type, limit by role accessability.
* @param restrictedType
* @param roles
* @return Number of repo entries
*/
public int countByTypeLimitAccess(String restrictedType, int restrictedAccess) {
StringBuilder query = new StringBuilder(400);
query.append("select count(*) from" +
" org.olat.repository.RepositoryEntry v, " +
" org.olat.resource.OLATResourceImpl res " +
" where v.olatResource = res and res.resName= :restrictedType and v.access >= :restrictedAccess ");
DBQuery dbquery = DBFactory.getInstance().createQuery(query.toString());
dbquery.setString("restrictedType", restrictedType);
dbquery.setInteger("restrictedAccess", restrictedAccess);
dbquery.setCacheable(true);
return ((Long)dbquery.list().get(0)).intValue();
}
/**
* Query by type without any other limitations
* @param restrictedType
* @param roles
* @return Results
*/
public List queryByType(String restrictedType) {
String query = "select v from" +
" org.olat.repository.RepositoryEntry v" +
" inner join fetch v.olatResource as res"+
" where res.resName= :restrictedType";
DBQuery dbquery = DBFactory.getInstance().createQuery(query);
dbquery.setString("restrictedType", restrictedType);
dbquery.setCacheable(true);
return dbquery.list();
}
/**
* Query by type, limit by ownership or role accessability.
* @param restrictedType
* @param roles
* @return Results
*/
public List queryByTypeLimitAccess(String restrictedType, Roles roles) {
StringBuilder query = new StringBuilder(400);
query.append("select distinct v from" +
" org.olat.repository.RepositoryEntry v" +
" inner join fetch v.olatResource as res"+
" where res.resName= :restrictedType and v.access >= ");
if (roles.isOLATAdmin()) query.append(RepositoryEntry.ACC_OWNERS); // treat admin special b/c admin is author as well
else {
if (roles.isAuthor()) query.append(RepositoryEntry.ACC_OWNERS_AUTHORS);
else if (roles.isGuestOnly()) query.append(RepositoryEntry.ACC_USERS_GUESTS);
else query.append(RepositoryEntry.ACC_USERS);
}
DBQuery dbquery = DBFactory.getInstance().createQuery(query.toString());
dbquery.setString("restrictedType", restrictedType);
dbquery.setCacheable(true);
return dbquery.list();
}
/**
* Query by type, limit by ownership or role accessability.
* @param restrictedType
* @param roles
* @return Results
*/
public List queryByTypeLimitAccess(String restrictedType, UserRequest ureq) {
Roles roles = ureq.getUserSession().getRoles();
String institution = "";
institution = ureq.getIdentity().getUser().getProperty("institutionalName", null);
if(!roles.isOLATAdmin() && institution != null && institution.length() > 0 && roles.isInstitutionalResourceManager()) {
StringBuilder query = new StringBuilder(400);
query.append("select distinct v from org.olat.repository.RepositoryEntry v inner join fetch v.olatResource as res"
+ ", org.olat.basesecurity.SecurityGroupMembershipImpl as sgmsi"
+ ", org.olat.basesecurity.IdentityImpl identity"
+ ", org.olat.user.UserImpl user "
+ " where sgmsi.securityGroup = v.ownerGroup"
+ " and sgmsi.identity = identity"
+ " and identity.user = user"
+" and user.properties['institutionalName']= :institutionCourseManager "
+ " and res.resName= :restrictedType and v.access = 1");
DBQuery dbquery = DBFactory.getInstance().createQuery(query.toString());
dbquery.setString("restrictedType", restrictedType);
dbquery.setString("institutionCourseManager", institution);
dbquery.setCacheable(true);
List result = dbquery.list();
result.addAll(queryByTypeLimitAccess(restrictedType, roles));
return result;
} else {
return queryByTypeLimitAccess(restrictedType, roles);
}
}
/**
* Query by ownership, optionally limit by type.
*
* @param identity
* @param limitType
* @return Results
*/
public List queryByOwner(Identity identity, String limitType) {
return queryByOwner( identity, new String[]{limitType});
}
public List queryByOwner(Identity identity, String[] limitTypes) {
if (identity == null) throw new AssertException("identity can not be null!");
StringBuffer query = new StringBuffer(400);
query.append("select v from" + " org.olat.repository.RepositoryEntry v inner join fetch v.olatResource as res,"
+ " org.olat.basesecurity.SecurityGroupMembershipImpl as sgmsi" + " where " + " v.ownerGroup = sgmsi.securityGroup and"
+ " sgmsi.identity = :identity");
if (limitTypes != null && limitTypes.length > 0) {
for (int i = 0; i < limitTypes.length; i++) {
String limitType = limitTypes[i];
if (i == 0) {
query.append(" and ( res.resName= '" + limitType + "'");
} else {
query.append(" or res.resName= '" + limitType + "'");
}
}
query.append(" )");
}
DBQuery dbquery = DBFactory.getInstance().createQuery(query.toString());
dbquery.setEntity("identity", identity);
return dbquery.list();
}
/**
* Query by initial-author
* @param restrictedType
* @param roles
* @return Results
*/
public List queryByInitialAuthor(String initialAuthor) {
String query = "select v from" +
" org.olat.repository.RepositoryEntry v" +
" where v.initialAuthor= :initialAuthor";
DBQuery dbquery = DBFactory.getInstance().createQuery(query);
dbquery.setString("initialAuthor", initialAuthor);
dbquery.setCacheable(true);
return dbquery.list();
}
/**
* Search for resources that can be referenced by an author. This is the case:
* 1) the user is the owner of the resource
* 2) the user is author and the resource is at least visible to authors (BA)
* and the resource is set to canReference
* @param identity The user initiating the query
* @param roles The current users role set
* @param resourceTypes Limit search result to this list of repo types. Can be NULL
* @param displayName Limit search to this repo title. Can be NULL
* @param author Limit search to this user (Name, firstname, loginname). Can be NULL
* @param desc Limit search to description. Can be NULL
* @return List of repository entries
*/
public List queryReferencableResourcesLimitType(Identity identity, Roles roles, List resourceTypes, String displayName, String author, String desc) {
if (identity == null) {
throw new AssertException("identity can not be null!");
}
if (!roles.isAuthor()) {
// if user has no author right he can not reference to any resource at all
return new ArrayList();
}
// cleanup some data: use null values if emtpy
if (resourceTypes != null && resourceTypes.size() == 0) resourceTypes = null;
if ( ! StringHelper.containsNonWhitespace(displayName)) displayName = null;
if ( ! StringHelper.containsNonWhitespace(author)) author = null;
if ( ! StringHelper.containsNonWhitespace(desc)) desc = null;
// Build the query
// 1) Joining tables
StringBuilder query = new StringBuilder(400);
query.append("select distinct v from");
query.append(" org.olat.repository.RepositoryEntry v inner join fetch v.olatResource as res" );
query.append(", org.olat.basesecurity.SecurityGroupMembershipImpl as sgmsi");
if (author != null) {
query.append(", org.olat.basesecurity.SecurityGroupMembershipImpl as sgmsi2");
query.append(", org.olat.basesecurity.IdentityImpl identity");
query.append(", org.olat.user.UserImpl user ");
}
// 2) where clause
query.append(" where ");
// the join of v.ownerGropu and sgmsi.securityGroup mus be outside the sgmsi.identity = :identity
// otherwhise the join is not present in the second part of the or clause and the cross product will
// be to large (does not work when more than 100 repo entries present!)
query.append(" v.ownerGroup = sgmsi.securityGroup");
// restrict on ownership or referencability flag
query.append(" and ( sgmsi.identity = :identity ");
query.append(" or ");
query.append(" (v.access >= :access and v.canReference = true) )");
// restrict on type
if (resourceTypes != null) {
query.append(" and res.resName in (:resourcetypes)");
}
// restrict on author
if (author != null) { // fuzzy author search
author = author.replace('*','%');
author = '%' + author + '%';
query.append(" and (sgmsi2.securityGroup = v.ownerGroup and "+
"sgmsi2.identity = identity and "+
"identity.user = user and "+
"(user.properties['firstName'] like :author or user.properties['lastName'] like :author or identity.name like :author))");
}
// restrict on resource name
if (displayName != null) {
displayName = displayName.replace('*','%');
displayName = '%' + displayName + '%';
query.append(" and v.displayname like :displayname");
}
// restrict on resource description
if (desc != null) {
desc = desc.replace('*','%');
desc = '%' + desc + '%';
query.append(" and v.description like :desc");
}
// create query an set query data
DBQuery dbquery = DBFactory.getInstance().createQuery(query.toString());
dbquery.setEntity("identity", identity);
dbquery.setInteger("access", RepositoryEntry.ACC_OWNERS_AUTHORS);
if (author != null) {
dbquery.setString("author", author);
}
if (displayName != null) {
dbquery.setString("displayname", displayName);
}
if (desc != null) {
dbquery.setString("desc", desc);
}
if (resourceTypes != null) {
dbquery.setParameterList("resourcetypes", resourceTypes, Hibernate.STRING);
}
return dbquery.list();
}
/**
* Query by ownership, limit by access.
*
* @param identity
* @param limitAccess
* @return Results
*/
public List queryByOwnerLimitAccess(Identity identity, int limitAccess) {
String query = "select v from" +
" org.olat.repository.RepositoryEntry v inner join fetch v.olatResource as res," +
" org.olat.basesecurity.SecurityGroupMembershipImpl as sgmsi" +
" where" +
" v.ownerGroup = sgmsi.securityGroup "+
" and sgmsi.identity = :identity and v.access >= :limitAccess";
DBQuery dbquery = DBFactory.getInstance().createQuery(query);
dbquery.setEntity("identity", identity);
dbquery.setInteger("limitAccess", limitAccess);
return dbquery.list();
}
/**
* check ownership of identiy for a resource
* @return true if the identity is member of the security group of the repository entry
*/
public boolean isOwnerOfRepositoryEntry(Identity identity, RepositoryEntry entry){
//TODO:gs:a transform into direct hibernate query
SecurityGroup ownerGroup = lookupRepositoryEntry(entry.getOlatResource(), true).getOwnerGroup();
return ManagerFactory.getManager().isIdentityInSecurityGroup(identity, ownerGroup);
}
/**
* Query repository
*
* If any input data contains "*", then it replaced by "%" (search me*er -> sql: me%er)
*
* @param displayName null -> no restriction
* @param author null -> no restriction
* @param desc null -> no restriction
* @param resourceTypes NOTE: for null -> no restriction, or a list of resourceTypeNames
* @param roles The calling user's roles
* @return Results as List containing RepositoryEntries
*/
private List runGenericANDQueryWithRolesRestriction(String displayName, String author, String desc, List resourceTypes, Roles roles) {
StringBuilder query = new StringBuilder(400);
boolean var_author = (author != null && author.length() != 0);
boolean var_displayname = (displayName != null && displayName.length() != 0);
boolean var_desc = (desc != null && desc.length() != 0);
boolean var_resourcetypes = (resourceTypes != null && resourceTypes.size() > 0);
// Use two different select prologues...
if (var_author) { // extended query for user search
query.append("select distinct v from" +
" org.olat.repository.RepositoryEntry v inner join fetch v.olatResource as res," +
" org.olat.basesecurity.SecurityGroupMembershipImpl sgmsi, " +
" org.olat.basesecurity.IdentityImpl identity," +
" org.olat.user.UserImpl user ");
} else { // simple query
query.append("select distinct v from" +
" org.olat.repository.RepositoryEntry v " +
" inner join fetch v.olatResource as res ");
}
boolean isFirstOfWhereClause = false;
query.append("where v.access != 0 "); // access == 0 means invalid repo-entry (not complete created)
if (var_author) { // fuzzy author search
author = author.replace('*','%');
author = '%' + author + '%';
if (!isFirstOfWhereClause) query.append(" and ");
query.append("sgmsi.securityGroup = v.ownerGroup and "+
"sgmsi.identity = identity and "+
"identity.user = user and "+
"(user.properties['firstName'] like :author or user.properties['lastName'] like :author or identity.name like :author)");
isFirstOfWhereClause = false;
}
if (var_displayname) {
displayName = displayName.replace('*','%');
displayName = '%' + displayName + '%';
if (!isFirstOfWhereClause) query.append(" and ");
query.append("v.displayname like :displayname");
isFirstOfWhereClause = false;
}
if (var_desc) {
desc = desc.replace('*','%');
desc = '%' + desc + '%';
if (!isFirstOfWhereClause) query.append(" and ");
query.append("v.description like :desc");
isFirstOfWhereClause = false;
}
if (var_resourcetypes) {
if (!isFirstOfWhereClause) query.append(" and ");
query.append("res.resName in (:resourcetypes)");
isFirstOfWhereClause = false;
}
// finally limit on roles, if not olat admin
if (!roles.isOLATAdmin()) {
if (!isFirstOfWhereClause) query.append(" and ");
query.append("v.access >= ");
if (roles.isAuthor()) query.append(RepositoryEntry.ACC_OWNERS_AUTHORS);
else if (roles.isGuestOnly()) query.append(RepositoryEntry.ACC_USERS_GUESTS);
else query.append(RepositoryEntry.ACC_USERS);
isFirstOfWhereClause = false;
}
DBQuery dbQuery = DBFactory.getInstance().createQuery(query.toString());
if (var_author) {
dbQuery.setString("author", author);
}
if (var_displayname) {
dbQuery.setString("displayname", displayName);
}
if (var_desc) {
dbQuery.setString("desc", desc);
}
if (var_resourcetypes) {
dbQuery.setParameterList("resourcetypes", resourceTypes, Hibernate.STRING);
}
return dbQuery.list();
}
/**
* Query repository
*
* If any input data contains "*", then it replaced by "%" (search me*er -> sql: me%er).
*
*
* @param ureq
* @param displayName null -> no restriction
* @param author null -> no restriction
* @param desc null -> no restriction
* @param resourceTypes NOTE: for null -> no restriction, or a list of resourceTypeNames
* @param roles The calling user's roles
* @param institution null -> no restriction
* @return Results as List containing RepositoryEntries
*/
public List genericANDQueryWithRolesRestriction(String displayName, String author, String desc, List resourceTypes, Roles roles, String institution) {
if (!roles.isOLATAdmin() && institution != null && institution.length() > 0 && roles.isInstitutionalResourceManager()) {
StringBuilder query = new StringBuilder(400);
if(author == null || author.length() == 0) author = "*";
boolean var_author = true;
boolean var_displayname = (displayName != null && displayName.length() != 0);
boolean var_desc = (desc != null && desc.length() != 0);
boolean var_resourcetypes = (resourceTypes != null && resourceTypes.size() > 0);
// Use two different select prologues...
if (var_author) { // extended query for user search
query.append("select distinct v from"
+ " org.olat.repository.RepositoryEntry v inner join fetch v.olatResource as res,"
+ " org.olat.basesecurity.SecurityGroupMembershipImpl sgmsi, "
+ " org.olat.basesecurity.IdentityImpl identity,"
+ " org.olat.user.UserImpl user ");
} else { // simple query
query.append("select distinct v from" + " org.olat.repository.RepositoryEntry v " + " inner join fetch v.olatResource as res ");
}
boolean isFirstOfWhereClause = false;
query.append("where v.access != 0 "); // access == 0 means invalid repo-entry (not complete created)
if (var_author) { // fuzzy author search
author = author.replace('*', '%');
author = '%' + author + '%';
if (!isFirstOfWhereClause) query.append(" and ");
query.append("sgmsi.securityGroup = v.ownerGroup and "
+ "sgmsi.identity = identity and "
+ "identity.user = user and "
+ "(user.properties['firstName'] like :author or user.properties['lastName'] like :author or identity.name like :author)");
isFirstOfWhereClause = false;
}
if (var_displayname) {
displayName = displayName.replace('*', '%');
displayName = '%' + displayName + '%';
if (!isFirstOfWhereClause) query.append(" and ");
query.append("v.displayname like :displayname");
isFirstOfWhereClause = false;
}
if (var_desc) {
desc = desc.replace('*', '%');
desc = '%' + desc + '%';
if (!isFirstOfWhereClause) query.append(" and ");
query.append("v.description like :desc");
isFirstOfWhereClause = false;
}
if (var_resourcetypes) {
if (!isFirstOfWhereClause) query.append(" and ");
query.append("res.resName in (:resourcetypes)");
isFirstOfWhereClause = false;
}
if (!isFirstOfWhereClause) query.append(" and ");
query.append("v.access = 1 and user.properties['institutionalName']= :institution ");
isFirstOfWhereClause = false;
DBQuery dbQuery = DBFactory.getInstance().createQuery(query.toString());
dbQuery.setString("institution", institution);
if (var_author) {
dbQuery.setString("author", author);
}
if (var_displayname) {
dbQuery.setString("displayname", displayName);
}
if (var_desc) {
dbQuery.setString("desc", desc);
}
if (var_resourcetypes) {
dbQuery.setParameterList("resourcetypes", resourceTypes, Hibernate.STRING);
}
List result = dbQuery.list();
result.addAll(runGenericANDQueryWithRolesRestriction(displayName, author, desc, resourceTypes, roles));
return result;
} else {
return runGenericANDQueryWithRolesRestriction(displayName, author, desc, resourceTypes, roles);
}
}
/**
* add provided list of identities as owners to the repo entry. silently ignore
* if some identities were already owners before.
* @param ureqIdentity
* @param addIdentities
* @param re
* @param userActivityLogger
*/
public void addOwners(Identity ureqIdentity, IdentitiesAddEvent iae, RepositoryEntry re) {
List<Identity> addIdentities = iae.getAddIdentities();
List<Identity> reallyAddedId = new ArrayList<Identity>();
SecurityGroup group = re.getOwnerGroup();
for (Identity identity : addIdentities) {
if (!securityManager.isIdentityInSecurityGroup(identity, re.getOwnerGroup())) {
securityManager.addIdentityToSecurityGroup(identity, re.getOwnerGroup());
reallyAddedId.add(identity);
ActionType actionType = ThreadLocalUserActivityLogger.getStickyActionType();
ThreadLocalUserActivityLogger.setStickyActionType(ActionType.admin);
try{
ThreadLocalUserActivityLogger.log(GroupLoggingAction.GROUP_OWNER_ADDED, getClass(),
LoggingResourceable.wrap(re, OlatResourceableType.genRepoEntry), LoggingResourceable.wrap(identity));
} finally {
ThreadLocalUserActivityLogger.setStickyActionType(actionType);
}
Tracing.logAudit("Idenitity(.key):" + ureqIdentity.getKey() + " added identity '" + identity.getName()
+ "' to securitygroup with key " + re.getOwnerGroup().getKey(), this.getClass());
}//else silently ignore already owner identities
}
iae.setIdentitiesAddedEvent(reallyAddedId);
}
/**
* remove list of identities as owners of given repository entry.
* @param ureqIdentity
* @param removeIdentities
* @param re
* @param logger
*/
public void removeOwners(Identity ureqIdentity, List<Identity> removeIdentities, RepositoryEntry re){
for (Identity identity : removeIdentities) {
securityManager.removeIdentityFromSecurityGroup(identity, re.getOwnerGroup());
String details = "Remove Owner from RepoEntry:"+re.getKey()+" USER:" + identity.getName();
ActionType actionType = ThreadLocalUserActivityLogger.getStickyActionType();
ThreadLocalUserActivityLogger.setStickyActionType(ActionType.admin);
try{
ThreadLocalUserActivityLogger.log(GroupLoggingAction.GROUP_OWNER_REMOVED, getClass(),
LoggingResourceable.wrap(re, OlatResourceableType.genRepoEntry), LoggingResourceable.wrap(identity));
} finally {
ThreadLocalUserActivityLogger.setStickyActionType(actionType);
}
Tracing.logAudit("Idenitity(.key):" + ureqIdentity.getKey() + " removed identity '" + identity.getName()
+ "' from securitygroup with key " + re.getOwnerGroup().getKey(), this.getClass());
}
}
/**
* has one owner of repository entry the same institution like the resource manager
* @param RepositoryEntry repositoryEntry
* @param Identity identity
*/
public boolean isInstitutionalRessourceManagerFor(RepositoryEntry repositoryEntry, Identity identity) {
if(repositoryEntry == null || repositoryEntry.getOwnerGroup() == null) return false;
Manager secMgr = ManagerFactory.getManager();
// list of owners
List<Identity> listIdentities = secMgr.getIdentitiesOfSecurityGroup(repositoryEntry.getOwnerGroup());
String currentUserInstitutionalName = identity.getUser().getProperty("institutionalName", null);
boolean isInstitutionalResourceManager = ManagerFactory.getManager().isIdentityPermittedOnResourceable(identity, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_INSTORESMANAGER);
boolean sameInstitutional = false;
String identInstitutionalName = "";
for (Identity ident : listIdentities) {
identInstitutionalName = ident.getUser().getProperty("institutionalName", null);
if ((identInstitutionalName != null) && (identInstitutionalName.equals(currentUserInstitutionalName))) {
sameInstitutional = true;
break;
}
}
return isInstitutionalResourceManager && sameInstitutional;
}
/**
* Gets all learning resources where the user is in a learning group as participant.
* @param identity
* @return list of RepositoryEntries
*/
public List<RepositoryEntry> getLearningResourcesAsStudent(Identity identity) {
List<RepositoryEntry> allRepoEntries = new ArrayList<RepositoryEntry>();
List<BusinessGroup>groupList = BusinessGroupManagerImpl.getInstance().findBusinessGroupsAttendedBy(BusinessGroup.TYPE_LEARNINGROUP, identity, null);
for (BusinessGroup group : groupList) {
BGContext bgContext = group.getGroupContext();
if (bgContext == null) continue;
List<RepositoryEntry> repoEntries = BGContextManagerImpl.getInstance().findRepositoryEntriesForBGContext(bgContext);
if (repoEntries == null || repoEntries.size() == 0) continue;
for (RepositoryEntry repositoryEntry : repoEntries) {
if ( ! PersistenceHelper.listContainsObjectByKey(allRepoEntries, repositoryEntry)) {
allRepoEntries.add(repositoryEntry);
}
}
}
return allRepoEntries;
}
/**
* Gets all learning resources where the user is coach of a learning group or
* where he is in the repo entry owner group (course administrator)
*
* @param identity
* @return list of RepositoryEntries
*/
public List<RepositoryEntry> getLearningResourcesAsTeacher(Identity identity) {
List<RepositoryEntry> allRepoEntries = new ArrayList<RepositoryEntry>();
// 1: search for all learning groups where user is coach
List<BusinessGroup>groupList = BusinessGroupManagerImpl.getInstance().findBusinessGroupsOwnedBy(BusinessGroup.TYPE_LEARNINGROUP, identity, null);
for (BusinessGroup group : groupList) {
BGContext bgContext = group.getGroupContext();
if (bgContext == null) continue;
List<RepositoryEntry> repoEntries = BGContextManagerImpl.getInstance().findRepositoryEntriesForBGContext(bgContext);
if (repoEntries.size() == 0) continue;
for (RepositoryEntry repositoryEntry : repoEntries) {
if ( ! PersistenceHelper.listContainsObjectByKey(allRepoEntries, repositoryEntry)) {
allRepoEntries.add(repositoryEntry);
}
}
}
// 2) search for all published learning resources that user owns
List<RepositoryEntry> repoEntries = RepositoryManager.getInstance().queryByOwnerLimitAccess(identity, RepositoryEntry.ACC_USERS);
for (RepositoryEntry repositoryEntry : repoEntries) {
if ( ! PersistenceHelper.listContainsObjectByKey(allRepoEntries, repositoryEntry)) {
allRepoEntries.add(repositoryEntry);
}
}
return allRepoEntries;
}
}