package eu.europeana.cloud.service.mcs.rest;
import com.qmino.miredot.annotations.ReturnType;
import eu.europeana.cloud.common.model.Representation;
import eu.europeana.cloud.service.aas.authentication.SpringUserUtils;
import eu.europeana.cloud.service.mcs.RecordService;
import eu.europeana.cloud.service.mcs.exception.*;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.domain.PrincipalSid;
import org.springframework.security.acls.model.MutableAcl;
import org.springframework.security.acls.model.MutableAclService;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.stereotype.Component;
import static eu.europeana.cloud.common.web.ParamConstants.*;
/**
* Resource to manage representation versions.
*/
@Path("/records/{" + P_CLOUDID + "}/representations/{" + P_REPRESENTATIONNAME + "}/versions/{" + P_VER + "}")
@Component
@Scope("request")
public class RepresentationVersionResource {
@Autowired
private RecordService recordService;
@Autowired
private MutableAclService mutableAclService;
private final String REPRESENTATION_CLASS_NAME = Representation.class.getName();
/**
* Returns representation in a specified version.
* <strong>Read permissions required.</strong>
*
* @param globalId cloud id of the record which contains the representation(required).
* @param schema name of the representation(required).
* @param version a specific version of the representation(required).
* @return representation in requested version
* @throws RepresentationNotExistsException representation does not exist in the
* specified version.
* @summary get representation by version
*/
@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@PreAuthorize("hasPermission(#globalId.concat('/').concat(#schema).concat('/').concat(#version),"
+ " 'eu.europeana.cloud.common.model.Representation', read)")
@ReturnType("eu.europeana.cloud.common.model.Representation")
public Representation getRepresentationVersion(@Context UriInfo uriInfo,
@PathParam(P_VER) String version,
@PathParam(P_REPRESENTATIONNAME) String schema,
@PathParam(P_CLOUDID) String globalId)
throws RepresentationNotExistsException {
Representation rep = recordService.getRepresentation(globalId, schema, version);
prepare(uriInfo, rep);
return rep;
}
/**
* Deletes representation version.
* <strong>Delete permissions required.</strong>
*
* @param globalId cloud id of the record which contains the representation version (required).
* @param schema name of the representation(required).
* @param version a specific version of the representation(required).
* @throws RepresentationNotExistsException representation does not exist in
* specified version.
* @throws CannotModifyPersistentRepresentationException representation in
* specified version is persistent and as such cannot be removed.
*/
@DELETE
@PreAuthorize("hasPermission(#globalId.concat('/').concat(#schema).concat('/').concat(#version), 'eu.europeana.cloud.common.model.Representation', delete)")
public void deleteRepresentation(@PathParam(P_VER) String version,
@PathParam(P_REPRESENTATIONNAME) String schema,
@PathParam(P_CLOUDID) String globalId)
throws RepresentationNotExistsException, CannotModifyPersistentRepresentationException {
recordService.deleteRepresentation(globalId, schema, version);
// let's delete the permissions as well
ObjectIdentity dataSetIdentity = new ObjectIdentityImpl(REPRESENTATION_CLASS_NAME,
globalId + "/" + schema + "/" + version);
mutableAclService.deleteAcl(dataSetIdentity, false);
}
/**
* Persists temporary representation.
* <p/>
* <strong>Write permissions required.</strong>
*
* @param globalId cloud id of the record which contains the representation version(required).
* @param schema name of the representation(required).
* @param version a specific version of the representation(required).
* @return URI to the persisted representation in content-location.
* @throws RepresentationNotExistsException representation does not exist in
* specified version.
* @throws CannotModifyPersistentRepresentationException representation
* version is already persistent.
* @throws CannotPersistEmptyRepresentationException representation version
* has no file attached and as such cannot be made persistent.
* @statuscode 201 representation is made persistent.
*/
@POST
@Path("/persist")
@PreAuthorize("hasPermission(#globalId.concat('/').concat(#schema).concat('/').concat(#version),"
+ " 'eu.europeana.cloud.common.model.Representation', write)")
public Response persistRepresentation(@Context UriInfo uriInfo,
@PathParam(P_VER) String version,
@PathParam(P_REPRESENTATIONNAME) String schema,
@PathParam(P_CLOUDID) String globalId)
throws RepresentationNotExistsException, CannotModifyPersistentRepresentationException,
CannotPersistEmptyRepresentationException {
Representation persistentVersion = recordService.persistRepresentation(globalId, schema, version);
prepare(uriInfo, persistentVersion);
return Response.created(persistentVersion.getUri()).build();
}
/**
* Copies all information with all files and their contents from one
* representation version to a new temporary one.
* <strong>Read permissions required.</strong>
*
* @param globalId cloud id of the record which contains the representation version
* @param schema name of the representation
* @param version a specific version of the representation
* @return URI to the created representation in content-location.
* @throws RepresentationNotExistsException representation does not exist in
* specified version.
* @summary copy information including file contents from one representation version to another
* @statuscode 201 representation has been copied to a new one.
*/
@POST
@Path("/copy")
@PreAuthorize("hasPermission(#globalId.concat('/').concat(#schema).concat('/').concat(#version),"
+ " 'eu.europeana.cloud.common.model.Representation', read)")
public Response copyRepresentation(@Context UriInfo uriInfo,
@PathParam(P_VER) String version,
@PathParam(P_REPRESENTATIONNAME) String schema,
@PathParam(P_CLOUDID) String globalId)
throws RepresentationNotExistsException {
Representation copiedRep = recordService.copyRepresentation(globalId, schema, version);
prepare(uriInfo, copiedRep);
String copiedReprOwner = SpringUserUtils.getUsername();
if (copiedReprOwner != null) {
ObjectIdentity versionIdentity = new ObjectIdentityImpl(REPRESENTATION_CLASS_NAME,
globalId + "/" + schema + "/" + copiedRep.getVersion());
MutableAcl versionAcl = mutableAclService.createAcl(versionIdentity);
versionAcl.insertAce(0, BasePermission.READ, new PrincipalSid(copiedReprOwner), true);
versionAcl.insertAce(1, BasePermission.WRITE, new PrincipalSid(copiedReprOwner), true);
versionAcl.insertAce(2, BasePermission.DELETE, new PrincipalSid(copiedReprOwner), true);
versionAcl.insertAce(3, BasePermission.ADMINISTRATION, new PrincipalSid(copiedReprOwner),
true);
mutableAclService.updateAcl(versionAcl);
}
return Response.created(copiedRep.getUri()).build();
}
private void prepare(UriInfo uriInfo, Representation representationVersion) {
EnrichUriUtil.enrich(uriInfo, representationVersion);
}
}