/**
* Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.glite.security.voms.admin.persistence.dao;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.glite.security.voms.admin.configuration.VOMSConfiguration;
import org.glite.security.voms.admin.configuration.VOMSConfigurationConstants;
import org.glite.security.voms.admin.configuration.VOMSConfigurationException;
import org.glite.security.voms.admin.error.NullArgumentException;
import org.glite.security.voms.admin.error.VOMSSyntaxException;
import org.glite.security.voms.admin.persistence.HibernateFactory;
import org.glite.security.voms.admin.persistence.error.AlreadyExistsException;
import org.glite.security.voms.admin.persistence.error.IllegalOperationException;
import org.glite.security.voms.admin.persistence.error.NoSuchAttributeException;
import org.glite.security.voms.admin.persistence.error.NoSuchGroupException;
import org.glite.security.voms.admin.persistence.error.VOMSDatabaseException;
import org.glite.security.voms.admin.persistence.model.VOMSAdmin;
import org.glite.security.voms.admin.persistence.model.VOMSGroup;
import org.glite.security.voms.admin.persistence.model.VOMSUser;
import org.glite.security.voms.admin.persistence.model.attribute.VOMSAttributeDescription;
import org.glite.security.voms.admin.persistence.model.attribute.VOMSGroupAttribute;
import org.glite.security.voms.admin.util.PathNamingScheme;
import org.hibernate.HibernateException;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.Query;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class VOMSGroupDAO {
public static final Logger log = LoggerFactory.getLogger(VOMSGroupDAO.class);
private VOMSGroupDAO() {
HibernateFactory.beginTransaction();
}
public List<VOMSGroup> getAll() {
String query = "from VOMSGroup order by name asc";
Query q = HibernateFactory.getSession()
.createQuery(query);
@SuppressWarnings("unchecked")
List<VOMSGroup> res = q.list();
return DAOUtils.filterUnvisibleGroups(res);
}
public int countMatches(String searchString) {
String sString = "%" + searchString + "%";
String cQueryString = "select count(*) from org.glite.security.voms.admin.persistence.model.VOMSGroup where name like :searchString";
Long totalMatches = (Long) HibernateFactory.getSession()
.createQuery(cQueryString)
.setString("searchString", sString)
.uniqueResult();
return totalMatches.intValue();
}
public int countGroups() {
Long count = (Long) HibernateFactory.getSession()
.createQuery(
"select count(*) from org.glite.security.voms.admin.persistence.model.VOMSGroup")
.uniqueResult();
return count.intValue();
}
public List<VOMSGroup> findAllWithoutRootGroup() {
String query = "from VOMSGroup g where g != g.parent";
Query q = HibernateFactory.getSession()
.createQuery(query);
return q.list();
}
public List<VOMSGroup> findAll() {
String query = "from org.glite.security.voms.admin.persistence.model.VOMSGroup";
Query q = HibernateFactory.getSession()
.createQuery(query);
return q.list();
}
public SearchResults getAll(int firstResult, int maxResults) {
SearchResults results = SearchResults.instance();
String query = "from org.glite.security.voms.admin.persistence.model.VOMSGroup order by name asc";
Query q = HibernateFactory.getSession()
.createQuery(query);
q.setFirstResult(firstResult);
q.setMaxResults(maxResults);
List<VOMSGroup> res = DAOUtils.filterUnvisibleGroups(q.list());
results.setCount(countGroups());
results.setFirstResult(firstResult);
results.setResultsPerPage(maxResults);
results.setResults(res);
return results;
}
public SearchResults search(String searchString, int firstResult,
int maxResults) {
if (searchString == null || searchString.equals("")
|| searchString.length() == 0)
return getAll(firstResult, maxResults);
SearchResults results = SearchResults.instance();
String sString = "%" + searchString + "%";
String queryString = "from org.glite.security.voms.admin.persistence.model.VOMSGroup where name like :searchString order by name asc";
Query q = HibernateFactory.getSession()
.createQuery(queryString)
.setString("searchString", sString);
q.setFirstResult(firstResult);
q.setMaxResults(maxResults);
List<VOMSGroup> res = DAOUtils.filterUnvisibleGroups(q.list());
results.setSearchString(searchString);
results.setResults(res);
results.setCount(countMatches(searchString));
results.setFirstResult(firstResult);
results.setResultsPerPage(maxResults);
return results;
}
public SearchResults getMembers(VOMSGroup g, int firstResult,
int maxResults) {
Set groupMembers = g.getMembers();
// int count = g.getMembers().size(); // Maybe the HQL query is more
// efficient
int count = groupMembers.size();
SearchResults results = SearchResults.instance();
String queryString = "select m.user as user from org.glite.security.voms.admin.persistence.model.VOMSMapping m where m.group = :group and m.role is null";
Query q = HibernateFactory.getSession()
.createQuery(queryString)
.setFirstResult(firstResult)
.setMaxResults(maxResults);
q.setEntity("group", g);
List res = q.list();
results.setSearchString(null);
results.setResults(res);
results.setCount(count);
results.setFirstResult(firstResult);
results.setResultsPerPage(maxResults);
return results;
}
public int countMatchingMembers(VOMSGroup g, String searchString) {
if (g == null)
throw new NullArgumentException("Cannot search members in a null group!");
String sString = "%" + searchString + "%";
String queryString = "select count(m.user) as u from VOMSMapping m join m.user.certificates as cert where "
+ "m.group = :group and m.role is null and "
+ "(cert.subjectString like :searchString "
+ "or cert.ca.subjectString like :searchString "
+ "or m.user.name like :searchString "
+ "or m.user.surname like :searchString "
+ "or m.user.emailAddress like :searchString "
+ "or m.user.institution like :searchString)";
// String queryString =
// "select count(m.user) from
// org.glite.security.voms.admin.persistence.model.VOMSMapping m where
// m.group = :group and m.role is null "+
// "and m.user.dn like :searchString";
Query q = HibernateFactory.getSession()
.createQuery(queryString)
.setString("searchString", sString);
q.setEntity("group", g);
return ((Long) q.uniqueResult()).intValue();
}
public SearchResults searchMembers(VOMSGroup g, String searchString,
int firstResult, int maxResults) {
if (g == null)
throw new NullArgumentException("Cannot search members in a null group!");
if (searchString == null || searchString.equals("")
|| searchString.length() == 0)
return getMembers(g, firstResult, maxResults);
SearchResults results = SearchResults.instance();
String sString = "%" + searchString + "%";
String queryString = "select m.user as u from VOMSMapping m join m.user.certificates as cert where "
+ "m.group = :group and m.role is null and "
+ "(cert.subjectString like :searchString "
+ "or cert.ca.subjectString like :searchString "
+ "or m.user.name like :searchString "
+ "or m.user.surname like :searchString "
+ "or m.user.emailAddress like :searchString "
+ "or m.user.institution like :searchString)";
// String queryString =
// "select m.user as user from
// org.glite.security.voms.admin.persistence.model.VOMSMapping m where
// m.group = :group and m.role is null "+
// "and (m.user.dn like :searchString or m.user.ca.subjectString like
// :searchString) order by m.user.dn asc";
Query q = HibernateFactory.getSession()
.createQuery(queryString)
.setString("searchString", sString);
q.setEntity("group", g);
q.setFirstResult(firstResult);
q.setMaxResults(maxResults);
List res = q.list();
results.setSearchString(searchString);
results.setResults(res);
results.setCount(countMatchingMembers(g, searchString));
results.setFirstResult(firstResult);
results.setResultsPerPage(maxResults);
return results;
}
public VOMSGroup findByName(String name) {
if (!PathNamingScheme.isGroup(name))
throw new VOMSSyntaxException("Syntax error in group name: " + name);
String query = "from org.glite.security.voms.admin.persistence.model.VOMSGroup as g where g.name =:groupName";
Query q = HibernateFactory.getSession()
.createQuery(query);
q.setString("groupName", name);
VOMSGroup g = (VOMSGroup) q.uniqueResult();
return g;
}
public VOMSGroup findById(Long id) {
VOMSGroup g = (VOMSGroup) HibernateFactory.getSession()
.get(VOMSGroup.class, id);
return g;
}
public VOMSGroup getVOGroup() {
VOMSConfiguration conf = VOMSConfiguration.instance();
String voName = conf.getString(VOMSConfigurationConstants.VO_NAME);
if (voName == null)
throw new VOMSConfigurationException(
VOMSConfigurationConstants.VO_NAME + "undefined in configuration!");
VOMSGroup g = findByName("/" + voName);
return g;
}
@SuppressWarnings("unchecked")
public List<VOMSGroup> getChildren(VOMSGroup parentGroup) {
String query = "from org.glite.security.voms.admin.persistence.model.VOMSGroup g where g.parent = :parentGroup and g != :parentGroup order by g.name";
Query q = HibernateFactory.getSession()
.createQuery(query);
q.setEntity("parentGroup", parentGroup);
return q.list();
}
public VOMSGroup create(String groupName) {
return create(groupName, null, null);
}
public VOMSGroup create(String groupName, String description,
Boolean isRestricted) {
if (!PathNamingScheme.isGroup(groupName))
throw new VOMSSyntaxException("Syntax error in group name: " + groupName);
if (findByName(groupName) != null)
throw new AlreadyExistsException(
"Group \"" + groupName + "\" already defined!");
String[] parentGroupChain = PathNamingScheme.getParentGroupChain(groupName);
String rootGroupName = getVOGroup().getName();
// The root group of the parent chain must be the root group defined for
// the VO
if (!parentGroupChain[0].equals(rootGroupName))
throw new IllegalArgumentException("The root group for \"" + groupName
+ "\" must match the root group of the VO (i.e., " + rootGroupName
+ ")");
String parentGroupName = PathNamingScheme.getParentGroupName(groupName);
VOMSGroup parentGroup = findByName(parentGroupName);
if (parentGroup == null)
throw new NoSuchGroupException(
"Parent group \"" + parentGroupName + "\" not defined in database!");
VOMSGroup newGroup = new VOMSGroup();
newGroup.setName(groupName);
newGroup.setParent(parentGroup);
if (description != null)
newGroup.setDescription(description);
if (isRestricted != null)
newGroup.setRestricted(isRestricted);
log.debug("Creating group \"" + newGroup + "\".");
HibernateFactory.getSession()
.save(newGroup);
return newGroup;
}
public void delete(Long id) {
VOMSGroup g = (VOMSGroup) findById(id);
if (g == null)
throw new NoSuchGroupException(
"Group with id \"" + id + "\" not defined!");
try {
delete(g);
} catch (ObjectNotFoundException e) {
throw new NoSuchGroupException(
"Group with id \"" + id + "\" not defined!");
}
}
private void uncheckedDelete(VOMSGroup g) {
if (!g.isRootGroup()) {
g.getMappings()
.clear();
g.getAttributes()
.clear();
HibernateFactory.getSession()
.delete(g);
}
}
public void deleteAll() {
Iterator groups = getAll().iterator();
while (groups.hasNext())
uncheckedDelete((VOMSGroup) groups.next());
}
public void delete(VOMSGroup g) {
if (!PathNamingScheme.isGroup(g.getName()))
throw new VOMSSyntaxException(
"Syntax error in group name for group: " + g);
if (g.isRootGroup() && g.equals(getVOGroup()))
throw new IllegalOperationException(
"VO root group \"" + g.getName() + "\" cannot be deleted!");
if (findByName(g.getName()) == null)
throw new NoSuchGroupException("Group \"" + g + "\" not defined!");
List children = getChildren(g);
if (!children.isEmpty())
throw new IllegalOperationException("The group \"" + g
+ "\" cannot be deleted since it contains subgroups. Delete subgroups first.");
log.debug("Deleting group " + g + "\".");
VOMSRoleDAO.instance()
.removeRoleAttributesForGroup(g);
g.getMappings()
.clear();
g.getAcls()
.clear();
// Delete admins and ACL permissions that are related to this group
VOMSAdminDAO adminDAO = VOMSAdminDAO.instance();
VOMSAdmin groupAdmin = adminDAO.getByFQAN(g.getName());
if (groupAdmin != null) {
ACLDAO.instance()
.deletePermissionsForAdmin(groupAdmin);
adminDAO.delete(groupAdmin);
}
HibernateFactory.getSession()
.delete(g);
HibernateFactory.getSession()
.flush();
}
public VOMSGroup createVOGroup() {
VOMSConfiguration conf = VOMSConfiguration.instance();
String voName = conf.getVOName();
if (voName == null)
throw new VOMSConfigurationException(
VOMSConfigurationConstants.VO_NAME + " undefined in configuration!");
VOMSGroup g = findByName("/" + voName);
if (g != null)
throw new VOMSDatabaseException(
"Root group already defined for vo " + voName);
g = new VOMSGroup();
g.setName("/" + voName);
g.setId(new Long(1));
try {
// The ugly transaction management code here is acceptable since
// the creation of the VO GROUP is performed only once during the
// lifetime of a VO.
HibernateFactory.getSession()
.save(g);
HibernateFactory.commitTransaction();
HibernateFactory.beginTransaction();
g.setParent(g);
HibernateFactory.getSession()
.update(g);
HibernateFactory.commitTransaction();
} catch (HibernateException e) {
throw new VOMSDatabaseException("Failed creation of VO root group!", e);
} finally {
HibernateFactory.commitTransaction();
}
return g;
}
public VOMSGroupAttribute setAttribute(VOMSGroup g, String attrName,
String attrValue) {
VOMSAttributeDescription desc = VOMSAttributeDAO.instance()
.getAttributeDescriptionByName(attrName);
if (desc == null)
throw new NoSuchAttributeException(
"Attribute '" + attrName + "' is not defined in this vo.");
VOMSGroupAttribute val = g.getAttributeByName(attrName);
if (val != null)
val.setValue(attrValue);
else {
val = VOMSGroupAttribute.instance(desc, attrValue, g);
g.addAttribute(val);
}
HibernateFactory.getSession()
.update(g);
return val;
}
public VOMSGroupAttribute createAttribute(VOMSGroup g, String attrName,
String attrDesc, String attrValue) {
if (g.getAttributeByName(attrName) != null)
throw new AlreadyExistsException("Attribute \"" + attrName
+ "\" already defined for group \"" + g + "\".");
VOMSAttributeDescription desc = VOMSAttributeDAO.instance()
.getAttributeDescriptionByName(attrName);
if (desc == null)
desc = VOMSAttributeDAO.instance()
.createAttributeDescription(attrName, attrDesc);
log.debug("Creating attribute \"(" + attrName + "," + attrValue
+ ")\" for group \"" + g + "\"");
VOMSGroupAttribute val = VOMSGroupAttribute.instance(desc, attrValue, g);
g.addAttribute(val);
return val;
}
public VOMSGroupAttribute deleteAttribute(VOMSGroup g, String attrName) {
VOMSGroupAttribute ga = g.getAttributeByName(attrName);
if (ga == null)
throw new NoSuchAttributeException("Attribute named '" + attrName
+ "' not defined for group '" + g.getName() + "'!");
deleteAttribute(g, ga);
return ga;
}
public void deleteAttribute(VOMSGroup g, VOMSGroupAttribute val) {
log.debug(
"Deleting attribute \"" + val.getName() + "\" from group \"" + g + "\"");
g.deleteAttribute(val);
}
public boolean isVOGroup(VOMSGroup g) {
return (g.equals(getVOGroup()));
}
public static VOMSGroupDAO instance() {
return new VOMSGroupDAO();
}
@SuppressWarnings("unchecked")
public List<VOMSUser> getMembers(VOMSGroup g) {
if (g == null)
throw new NullArgumentException("Cannot get members of a null group!");
String query = "select m.user from VOMSMapping m where m.group = :group and m.role is null";
return HibernateFactory.getSession()
.createQuery(query)
.setEntity("group", g)
.list();
}
@SuppressWarnings("unchecked")
public List<String> getMemberSubjectStrings(VOMSGroup g) {
if (g == null)
throw new NullArgumentException("Cannot get members of a null group!");
String query = "select distinct c.subjectString from VOMSUser u join u.certificates c join u.mappings m where u.suspended is false and c.suspended is false and m.group = :group and m.role is null";
return HibernateFactory.getSession()
.createQuery(query)
.setEntity("group", g)
.list();
}
}