package org.multibit.mbm.resources.role;
import com.google.common.base.Optional;
import com.yammer.dropwizard.jersey.caching.CacheControl;
import com.yammer.metrics.annotation.Timed;
import org.multibit.mbm.api.hal.HalMediaType;
import org.multibit.mbm.api.request.AdminDeleteEntityRequest;
import org.multibit.mbm.api.request.role.AdminCreateRoleRequest;
import org.multibit.mbm.api.request.role.AdminUpdateRoleRequest;
import org.multibit.mbm.api.response.hal.role.AdminRoleBridge;
import org.multibit.mbm.api.response.hal.role.AdminRoleCollectionBridge;
import org.multibit.mbm.auth.annotation.RestrictedTo;
import org.multibit.mbm.db.dao.RoleDao;
import org.multibit.mbm.auth.Authority;
import org.multibit.mbm.core.model.Role;
import org.multibit.mbm.core.model.RoleBuilder;
import org.multibit.mbm.core.model.User;
import org.multibit.mbm.resources.BaseResource;
import org.multibit.mbm.resources.ResourceAsserts;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.ws.rs.*;
import javax.ws.rs.core.Response;
import java.net.URI;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* <p>Resource to provide the following to application:</p>
* <ul>
* <li>Provision of REST endpoints to manage CRUD operations by an administrator against a collection of {@link org.multibit.mbm.core.model.User} entities</li>
* </ul>
*
* @since 0.0.1
*/
@Component
@Path("/admin/role")
@Produces({HalMediaType.APPLICATION_HAL_JSON, HalMediaType.APPLICATION_HAL_XML})
public class AdminRoleResource extends BaseResource {
@Resource(name = "hibernateRoleDao")
RoleDao roleDao;
/**
* Create a new Role from the given mandatory fields
*
* @param adminUser A user with administrator rights
*
* @return A response containing the minimum details of the created entity
*/
@POST
@Timed
public Response create(
@RestrictedTo({Authority.ROLE_ADMIN})
User adminUser,
AdminCreateRoleRequest createRoleRequest) {
// Build a role from the given request information
Role role = RoleBuilder.newInstance()
.withName(createRoleRequest.getName())
.withDescription(createRoleRequest.getDescription())
.build();
// Perform basic verification
Optional<Role> verificationRole = roleDao.getByName(role.getName());
ResourceAsserts.assertNotConflicted(verificationRole,"role");
// Persist the role
Role persistentRole = roleDao.saveOrUpdate(role);
// Provide a representation to the client
AdminRoleBridge bridge = new AdminRoleBridge(uriInfo, Optional.of(adminUser));
URI location = uriInfo.getAbsolutePathBuilder().path(persistentRole.getId().toString()).build();
return created(bridge, persistentRole, location);
}
/**
* Provide a paged response of all roles in the system
*
* @param adminUser A user with administrator rights
* @param rawPageSize The unvalidated page size
* @param rawPageNumber The unvalidated page number
*
* @return A response containing a paged list of all roles
*/
@GET
@Timed
@CacheControl(maxAge = 6, maxAgeUnit = TimeUnit.HOURS)
public Response retrieveAllByPage(
@RestrictedTo({Authority.ROLE_ADMIN})
User adminUser,
@QueryParam("ps") Optional<String> rawPageSize,
@QueryParam("pn") Optional<String> rawPageNumber) {
// Validation
int pageSize = Integer.valueOf(rawPageSize.get());
int pageNumber = Integer.valueOf(rawPageNumber.get());
List<Role> roles = roleDao.getAllByPage(pageSize, pageNumber);
// Provide a representation to the client
AdminRoleCollectionBridge bridge = new AdminRoleCollectionBridge(uriInfo, Optional.of(adminUser));
return ok(bridge, roles);
}
/**
* Update an existing Role with the populated fields
*
* @param adminUser A user with administrator rights
*
* @return A response containing the full details of the updated entity
*/
@PUT
@Timed
@Path("/{roleId}")
public Response update(
@RestrictedTo({Authority.ROLE_ADMIN})
User adminUser,
@PathParam("roleId") Long roleId,
AdminUpdateRoleRequest updateRoleRequest) {
// Retrieve the role
Optional<Role> role = roleDao.getById(roleId);
ResourceAsserts.assertPresent(role, "role");
// Verify and apply any changes to the Role
Role persistentRole = role.get();
persistentRole.setName(updateRoleRequest.getName());
persistentRole.setDescription(updateRoleRequest.getDescription());
// TODO Re-instate this (needs an update to the request)
// for (String authorityName : updateRoleRequest.getAuthorities()) {
// try {
// Authority authority = Authority.valueOf(authorityName.toUpperCase());
// persistentRole.getAuthorities().add(authority);
// } catch (IllegalArgumentException e) {
// throw new WebApplicationException(Response.Status.BAD_REQUEST);
// }
// }
// Persist the updated role
persistentRole = roleDao.saveOrUpdate(role.get());
// Provide a representation to the client
AdminRoleBridge bridge = new AdminRoleBridge(uriInfo, Optional.of(adminUser));
return ok(bridge, persistentRole);
}
/**
* Delete an existing Role (usually meaning set flag to deleted)
*
* @param adminUser A user with administrator rights
*
* @return A response containing the full details of the updated entity
*/
@DELETE
@Timed
@Path("/{roleId}")
public Response delete(
@RestrictedTo({Authority.ROLE_ADMIN})
User adminUser,
@PathParam("roleId") Long roleId,
AdminDeleteEntityRequest deleteEntityRequest) {
// Retrieve the role
Optional<Role> role = roleDao.getById(roleId);
ResourceAsserts.assertPresent(role,"role");
// Verify and apply any changes to the Role
Role persistentRole = role.get();
persistentRole.setDeleted(true);
persistentRole.setReasonForDelete(deleteEntityRequest.getReason());
// Persist the updated role
persistentRole = roleDao.saveOrUpdate(role.get());
// Provide a representation to the client
AdminRoleBridge bridge = new AdminRoleBridge(uriInfo, Optional.of(adminUser));
return ok(bridge, persistentRole);
}
public void setRoleDao(RoleDao roleDao) {
this.roleDao = roleDao;
}
}