/* license-start
*
* Copyright (C) 2008 - 2013 Crispico, <http://www.crispico.com/>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details, at <http://www.gnu.org/licenses/>.
*
* Contributors:
* Crispico - Initial API and implementation
*
* license-end
*/
package org.flowerplatform.web.security.service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.flowerplatform.communication.CommunicationPlugin;
import org.flowerplatform.communication.service.ServiceInvocationContext;
import org.flowerplatform.web.database.DatabaseOperation;
import org.flowerplatform.web.database.DatabaseOperationWrapper;
import org.flowerplatform.web.entity.Group;
import org.flowerplatform.web.entity.Organization;
import org.flowerplatform.web.entity.PermissionEntity;
import org.flowerplatform.web.entity.dto.NamedDto;
import org.flowerplatform.web.security.dto.GroupAdminUIDto;
import org.flowerplatform.web.security.dto.OrganizationAdminUIDto;
import org.flowerplatform.web.security.sandbox.SecurityEntityAdaptor;
import org.flowerplatform.web.security.sandbox.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Service used to make CRUD operations on <code>Group</code> entity.
*
* @author Cristi
* @author Cristina
* @author Mariana
*
*
*/
public class GroupService extends ServiceObservable {
public static final String SERVICE_ID = "groupService";
private static final Logger logger = LoggerFactory.getLogger(GroupService.class);
public static GroupService getInstance() {
return (GroupService) CommunicationPlugin.getInstance().getServiceRegistry().getService(SERVICE_ID);
}
/**
* Converts a {@link Group} to {@link GroupAdminUIDto}.
*
* @see #findAllAsAdminUIDto()
* @see #findByIdAsAdminUIDto(long)
*
*/
private GroupAdminUIDto convertGroupToGroupAdminUIDto(Group group) {
GroupAdminUIDto dto = new GroupAdminUIDto();
dto.setId(group.getId());
dto.setName(group.getName());
if (group.getOrganization() != null) {
dto.setOrganization(new NamedDto(group.getOrganization().getId(), group.getOrganization().getName()));
dto.setOrganizationLabel(group.getOrganization().getLabel());
} else {
dto.setOrganizationLabel(""); // this is to avoid problems on flex
}
return dto;
}
/**
* Finds the {@link Group group} given by its id and returns a {@link GroupAdminUIDto}.
*
*/
public GroupAdminUIDto findByIdAsAdminUIDto(final long id) {
logger.debug("Find group with id = {}", id);
DatabaseOperationWrapper wrapper = new DatabaseOperationWrapper(new DatabaseOperation() {
@Override
public void run() {
Group group = wrapper.find(Group.class, id);
if (group == null)
throw new RuntimeException(String.format("Group with id=%s was not found in the DB.", id));
try {
SecurityUtils.checkAdminSecurityEntitiesPermission(PermissionEntity.GROUP_PREFIX + group.getName());
} catch (SecurityException e) {
throw new RuntimeException(String.format("Group with id=%s is not available.", id));
}
wrapper.setOperationResult(convertGroupToGroupAdminUIDto(group));
}
});
return (GroupAdminUIDto) wrapper.getOperationResult();
}
/**
* Finds all {@link Group}s and returns a list of their corresponding {@link GroupAdminUIDto}.
*
*/
public List<GroupAdminUIDto> findAllAsAdminUIDto() {
logger.debug("Find all groups");
final List<GroupAdminUIDto> list = new ArrayList<GroupAdminUIDto>();
new DatabaseOperationWrapper(new DatabaseOperation() {
@Override
public void run() {
for (Group group : wrapper.findAll(Group.class)) {
try {
SecurityUtils.checkAdminSecurityEntitiesPermission(PermissionEntity.GROUP_PREFIX + group.getName());
} catch (SecurityException e) {
// we don't have permissions
continue;
}
list.add(convertGroupToGroupAdminUIDto(group));
}
}
});
return list;
}
/**
* Finds all {@link Group}s and returns a list of their corresponding {@link NamedDto}.
*
* <p>
* Used for listboxes.
*
*
*/
public List<NamedDto> findAllAsNamedDto(final List<OrganizationAdminUIDto> filter) {
final List<NamedDto> list = new ArrayList<NamedDto>();
new DatabaseOperationWrapper(new DatabaseOperation() {
@Override
public void run() {
for (Group group : wrapper.findAll(Group.class)) {
try {
SecurityUtils.checkAdminSecurityEntitiesPermission(PermissionEntity.GROUP_PREFIX + group.getName());
} catch (SecurityException e) {
// we don't have permissions
continue;
}
// return only groups without organizations or in the organizations in the filter list
if (group.getOrganization() != null) {
for (OrganizationAdminUIDto organization : filter) {
if (organization.getId() == group.getOrganization().getId()) {
list.add(new NamedDto(group.getId(), group.getName()));
break;
}
}
} else {
list.add(new NamedDto(group.getId(), group.getName()));
}
}
}
});
return list;
}
/**
* Creates/Updates the {@link Group} based on {@link GroupAdminUIDto} stored information.
*
*/
public String mergeAdminUIDto(ServiceInvocationContext context, final GroupAdminUIDto dto) {
logger.debug("Merge group = {}", dto.getName());
Group initialGroup = (Group) new DatabaseOperationWrapper(new DatabaseOperation() {
@Override
public void run() {
wrapper.setOperationResult(wrapper.find(Group.class, dto.getId()));
}
}).getOperationResult();
DatabaseOperationWrapper wrapper = new DatabaseOperationWrapper(new DatabaseOperation() {
@Override
public void run() {
Group group = wrapper.mergeDto(Group.class, dto);
// check initial organization and new organization separately
// reason: if the user has permissions over only one of them, the check will go through
// and then the user can either change the organization to one where the user does not have permissions,
// or he can change a group of another organization
// check initial organization, if this is an existing group
String ownerEntities = SecurityEntityAdaptor.toCsvString(group.getOrganization(), null);
if (group.getId() != 0) {
if (group.getOrganization() == null) {
ownerEntities = PermissionEntity.ANY_ENTITY;
}
if (ownerEntities.trim().equals("")) {
ownerEntities = PermissionEntity.ANY_ENTITY;
}
SecurityUtils.checkAdminSecurityEntitiesPermission(ownerEntities);
}
// check new organization
ownerEntities = SecurityEntityAdaptor.toCsvString(null, dto.getOrganization());
if (dto.getOrganization() == null) {
ownerEntities = PermissionEntity.ANY_ENTITY;
}
if (ownerEntities.trim().equals("")) {
ownerEntities = PermissionEntity.ANY_ENTITY;
}
SecurityUtils.checkAdminSecurityEntitiesPermission(ownerEntities);
// check if there is already a group with the same name
List<Group> groupsWithSameName = wrapper.findByField(Group.class, "name", dto.getName());
if (dto.getId() == 0 && groupsWithSameName != null && groupsWithSameName.size() > 0) {
wrapper.setOperationResult("There is already a group with the same name!");
return;
}
group = (Group) wrapper.merge(group);
// set organization
Organization org = group.getOrganization();
if (dto.getOrganization() != null) {
org = wrapper.find(Organization.class, dto.getOrganization().getId());
group.setOrganization(org);
} else {
group.setOrganization(null);
}
}
});
Group newGroup = (Group) new DatabaseOperationWrapper(new DatabaseOperation() {
@Override
public void run() {
wrapper.setOperationResult(wrapper.find(Group.class, dto.getId()));
}
}).getOperationResult();
observable.notifyObservers(Arrays.asList(UPDATE, initialGroup, newGroup));
return (String) wrapper.getOperationResult();
}
/**
* Deletes all {@link Group}s based on the list of their ids.
*
*/
public void delete(final List<Integer> ids) {
for (final Integer id : ids) {
DatabaseOperationWrapper wrapper = new DatabaseOperationWrapper(new DatabaseOperation() {
@Override
public void run() {
Group group = wrapper.find(Group.class, Long.valueOf(id));
logger.debug("Delete {}", group);
String owners;
if (group.getOrganization() == null) {
owners = PermissionEntity.ANY_ENTITY;
} else {
owners = SecurityEntityAdaptor.toCsvString(group.getOrganization(), null);
}
SecurityUtils.checkAdminSecurityEntitiesPermission(owners);
// update organization list of groups
if (group.getOrganization() != null) {
group.getOrganization().getGroups().remove(group);
}
// all GroupUsers will be deleted automatically
wrapper.delete(group);
wrapper.setOperationResult(group);
}
});
observable.notifyObservers(Arrays.asList(DELETE, wrapper.getOperationResult()));
}
}
}