Commit e9f1b92d authored by Matija Obreza's avatar Matija Obreza
Browse files

Merge branch '309-api-v1-requests' into 'master'

Resolve "API v1: Requests"

Closes #309

See merge request genesys-pgr/genesys-server!202
parents f47326f6 08930e6b
......@@ -67,7 +67,7 @@ public class RequestsController extends ApiBaseController {
public @ResponseBody
Object listRequests(@RequestParam(value = "page", required = false, defaultValue = "0") int page) {
LOG.info("Listing requests");
final Page<MaterialRequest> requests = requestService.list(new PageRequest(page, PAGE_SIZE, new Sort(Direction.DESC, "createdDate")));
final Page<MaterialRequest> requests = requestService.list(null, new PageRequest(page, PAGE_SIZE, new Sort(Direction.DESC, "createdDate")));
return requests;
}
......@@ -137,7 +137,7 @@ public class RequestsController extends ApiBaseController {
Object listInstituteRequests(@PathVariable("instCode") String instCode, @RequestParam(value = "page", required = false, defaultValue = "0") int page) {
LOG.info("Listing requests for {}", instCode);
final FaoInstitute institute = instituteService.getInstitute(instCode);
final Page<MaterialSubRequest> requests = requestService.list(institute, new PageRequest(page, PAGE_SIZE, new Sort(Direction.DESC, "createdDate")));
final Page<MaterialSubRequest> requests = requestService.list(institute, null, new PageRequest(page, PAGE_SIZE, new Sort(Direction.DESC, "createdDate")));
return requests;
}
......
/**
* Copyright 2018 Global Crop Diversity Trust
*
* 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.genesys2.server.api.v1;
import java.io.IOException;
import org.genesys.blocks.model.JsonViews;
import org.genesys.catalog.api.FilteredPage;
import org.genesys.catalog.service.ShortFilterService;
import org.genesys2.server.api.ApiBaseController;
import org.genesys2.server.model.genesys.MaterialRequest;
import org.genesys2.server.model.genesys.MaterialSubRequest;
import org.genesys2.server.model.impl.FaoInstitute;
import org.genesys2.server.service.InstituteService;
import org.genesys2.server.service.RequestService;
import org.genesys2.server.service.RequestService.NoPidException;
import org.genesys2.server.service.filter.MaterialRequestFilter;
import org.genesys2.server.service.filter.MaterialSubRequestFilter;
import org.genesys2.server.service.impl.EasySMTAException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.annotation.JsonView;
import io.swagger.annotations.Api;
@RestController("requestsApi1")
@PreAuthorize("isAuthenticated()")
@RequestMapping(value = { RequestsController.CONTROLLER_URL })
@Api(tags = { "request" })
public class RequestsController extends ApiBaseController {
// Rest controller base URL
protected static final String CONTROLLER_URL = ApiBaseController.APIv1_BASE + "/requests";
@Autowired
private RequestService requestService;
@Autowired
private InstituteService instituteService;
/** The short filter service. */
@Autowired
protected ShortFilterService shortFilterService;
/**
* List requests by filterCode or filter
*
* @param page the page
* @param pageSize the page size
* @param direction the direction
* @param sort the sort
* @param filterCode short filter code
* @param filter the filter
* @return the page
* @throws IOException
*/
@PreAuthorize("hasRole('ADMINISTRATOR')")
@PostMapping(value = "/list", produces = { MediaType.APPLICATION_JSON_VALUE })
@JsonView({ JsonViews.Public.class })
public FilteredPage<MaterialRequest> list(@RequestParam(name = "p", required = false, defaultValue = "0") final int page,
@RequestParam(name = "l", required = false, defaultValue = "50") final int pageSize,
@RequestParam(name = "d", required = false, defaultValue = "ASC") final Sort.Direction direction,
@RequestParam(name = "s", required = false, defaultValue = "id") final String[] sort,
@RequestParam(name = "f", required = false) String filterCode,
@RequestBody(required = false) MaterialRequestFilter filter) throws IOException {
if (filterCode != null) {
filter = shortFilterService.filterByCode(filterCode, MaterialRequestFilter.class);
} else {
filterCode = shortFilterService.getCode(filter);
}
return new FilteredPage<>(filterCode, filter, requestService.list(filter, new PageRequest(page, Integer.min(pageSize, maxPageSize), direction, sort)));
}
/**
* Get request
*
* @return
*/
@PreAuthorize("hasRole('ADMINISTRATOR')")
@RequestMapping(value = "/r/{uuid:.{36}}", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
public MaterialRequest getRequest(@PathVariable("uuid") String uuid) {
LOG.info("Loading request uuid={}", uuid);
final MaterialRequest request = requestService.get(uuid);
return request;
}
/**
* Validate request
*
* @return
*/
@PreAuthorize("hasRole('ADMINISTRATOR')")
@PostMapping(value = "/r/{uuid:.{36}}/reconfirm", produces = { MediaType.APPLICATION_JSON_VALUE })
public MaterialRequest sendValidationEmail(@PathVariable("uuid") String uuid) {
LOG.info("Loading request uuid={}", uuid);
final MaterialRequest materialRequest = requestService.get(uuid);
return requestService.sendValidationEmail(materialRequest);
}
/**
* Validate request
*
* @return
* @throws EasySMTAException
* @throws NoPidException
*/
@PreAuthorize("hasRole('ADMINISTRATOR')")
@PostMapping(value = "/r/{uuid:.{36}}/validate", produces = { MediaType.APPLICATION_JSON_VALUE })
public MaterialRequest validateRequest(@PathVariable("uuid") String uuid) throws NoPidException, EasySMTAException {
LOG.info("Loading request uuid={}", uuid);
final MaterialRequest materialRequest = requestService.get(uuid);
return requestService.validateRequest(materialRequest);
}
/**
* Reload PID data
*
* @return
* @throws EasySMTAException
* @throws NoPidException
*/
@PreAuthorize("hasRole('ADMINISTRATOR')")
@PostMapping(value = "/r/{uuid:.{36}}/update-pid", produces = { MediaType.APPLICATION_JSON_VALUE })
public MaterialRequest recheckPid(@PathVariable("uuid") String uuid) throws NoPidException, EasySMTAException {
LOG.info("Loading request uuid={}", uuid);
final MaterialRequest materialRequest = requestService.get(uuid);
return requestService.recheckPid(materialRequest);
}
/**
* List institute requests
*
* @return
*/
@PostMapping(value = "/{instCode}", produces = { MediaType.APPLICATION_JSON_VALUE })
public FilteredPage<MaterialSubRequest> listInstituteRequests(@PathVariable("instCode") String instCode,
@RequestParam(name = "p", required = false, defaultValue = "0") final int page,
@RequestParam(name = "l", required = false, defaultValue = "50") final int pageSize,
@RequestParam(name = "d", required = false, defaultValue = "ASC") final Sort.Direction direction,
@RequestParam(name = "s", required = false, defaultValue = "id") final String[] sort,
@RequestParam(name = "f", required = false) String filterCode,
@RequestBody(required = false) MaterialSubRequestFilter filter) throws IOException {
LOG.info("Listing requests for {}", instCode);
final FaoInstitute institute = instituteService.getInstitute(instCode);
if (filterCode != null) {
filter = shortFilterService.filterByCode(filterCode, MaterialSubRequestFilter.class);
} else {
filterCode = shortFilterService.getCode(filter);
}
return new FilteredPage<>(filterCode, filter, requestService.list(institute, filter, new PageRequest(page, Integer.min(pageSize, maxPageSize), direction, sort)));
}
/**
* Get institute request
*
* @return
*/
@GetMapping(value = "/{instCode}/r/{uuid:.{36}}", produces = { MediaType.APPLICATION_JSON_VALUE })
public MaterialSubRequest getInstituteRequest(@PathVariable("instCode") String instCode, @PathVariable("uuid") String uuid) {
LOG.info("Loading request for {} uuid={}", instCode, uuid);
final FaoInstitute institute = instituteService.getInstitute(instCode);
final MaterialSubRequest request = requestService.get(institute, uuid);
return request;
}
}
......@@ -30,7 +30,6 @@ import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.apache.commons.lang.math.RandomUtils;
import org.genesys.blocks.model.AuditedVersionedModel;
import org.genesys2.server.api.serialization.MaterialRequestSerializer;
import org.hibernate.annotations.Type;
......@@ -73,8 +72,7 @@ public class MaterialRequest extends AuditedVersionedModel {
@PrePersist
void prepersist() {
if (this.uuid == null) {
this.uuid = UUID.nameUUIDFromBytes(("genesys:request:" + email + ":" + System.currentTimeMillis() + ":" + RandomUtils.nextInt(100)).getBytes())
.toString();
this.uuid = UUID.randomUUID().toString();
}
}
......
......@@ -29,7 +29,6 @@ import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.apache.commons.lang.math.RandomUtils;
import org.genesys.blocks.model.AuditedVersionedModel;
import org.genesys2.server.api.serialization.MaterialSubRequestSerializer;
import org.hibernate.annotations.Type;
......@@ -78,9 +77,7 @@ public class MaterialSubRequest extends AuditedVersionedModel {
@PrePersist
void prepersist() {
if (this.uuid == null) {
this.uuid = UUID.nameUUIDFromBytes(
("genesys:request:" + sourceRequest.getUuid() + ":" + instCode + ":" + System.currentTimeMillis() + ":" + RandomUtils.nextInt(100))
.getBytes()).toString();
this.uuid = UUID.randomUUID().toString();
}
}
......
......@@ -21,8 +21,9 @@ import java.util.List;
import org.genesys2.server.model.genesys.MaterialRequest;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
public interface MaterialRequestRepository extends JpaRepository<MaterialRequest, Long> {
public interface MaterialRequestRepository extends JpaRepository<MaterialRequest, Long>, QueryDslPredicateExecutor<MaterialRequest> {
List<MaterialRequest> findByEmail(String email);
......
......@@ -23,8 +23,9 @@ import org.genesys2.server.model.genesys.MaterialSubRequest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
public interface MaterialSubRequestRepository extends JpaRepository<MaterialSubRequest, Long> {
public interface MaterialSubRequestRepository extends JpaRepository<MaterialSubRequest, Long>, QueryDslPredicateExecutor<MaterialSubRequest> {
MaterialSubRequest findByUuid(String uuid);
......
......@@ -21,7 +21,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.genesys2.server.model.elastic.Institute;
import org.genesys2.server.model.impl.Country;
import org.genesys2.server.model.impl.FaoInstitute;
import org.genesys2.server.service.filter.InstituteFilter;
......
......@@ -22,6 +22,8 @@ import org.genesys2.server.model.genesys.MaterialRequest;
import org.genesys2.server.model.genesys.MaterialSubRequest;
import org.genesys2.server.model.impl.FaoInstitute;
import org.genesys2.server.service.TokenVerificationService.NoSuchVerificationTokenException;
import org.genesys2.server.service.filter.MaterialRequestFilter;
import org.genesys2.server.service.filter.MaterialSubRequestFilter;
import org.genesys2.server.service.impl.EasySMTAException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
......@@ -130,9 +132,9 @@ public interface RequestService {
}
}
Page<MaterialRequest> list(Pageable pageable);
Page<MaterialRequest> list(MaterialRequestFilter filter, Pageable pageable);
Page<MaterialSubRequest> list(FaoInstitute faoInstitute, Pageable pageable);
Page<MaterialSubRequest> list(FaoInstitute institute, MaterialSubRequestFilter filter, Pageable pageRequest);
MaterialRequest get(String uuid);
......
/*
* Copyright 2018 Global Crop Diversity Trust
*
* 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.genesys2.server.service.filter;
import static org.genesys2.server.model.genesys.QMaterialRequest.*;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import org.genesys.blocks.model.filters.AuditedVersionedModelFilter;
import org.genesys.blocks.model.filters.StringFilter;
import org.genesys2.server.model.genesys.MaterialRequest;
import org.genesys2.server.model.genesys.QMaterialRequest;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Predicate;
// TODO: Auto-generated Javadoc
/**
* Filter for {@link MaterialRequest}.
*/
public class MaterialRequestFilter extends AuditedVersionedModelFilter {
/** The identifiers. */
public Set<UUID> uuid;
/** The PID. */
public Set<String> pid;
/** The state. */
public Set<Integer> state;
/** The email. */
public StringFilter email;
/**
* Builds the query.
*
* @return the predicate
*/
public Predicate buildQuery() {
return buildQuery(materialRequest);
}
/**
* Builds the query.
*
* @param materialRequest the materialRequest
* @return the predicate
*/
public Predicate buildQuery(QMaterialRequest materialRequest) {
final BooleanBuilder and = new BooleanBuilder();
super.buildQuery(materialRequest._super, and);
if (uuid != null && !uuid.isEmpty()) {
and.and(materialRequest.uuid.in(uuid.stream().map(u -> u== null ? null : u.toString()).collect(Collectors.toSet())));
}
if (pid != null && !pid.isEmpty()) {
and.and(materialRequest.pid.in(pid));
}
if (state != null && !state.isEmpty()) {
and.and(materialRequest.state.in(state));
}
if (email != null) {
and.and(email.buildQuery(materialRequest.email));
}
return and;
}
}
/*
* Copyright 2018 Global Crop Diversity Trust
*
* 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.genesys2.server.service.filter;
import static org.genesys2.server.model.genesys.QMaterialSubRequest.*;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import org.genesys.blocks.model.filters.AuditedVersionedModelFilter;
import org.genesys.blocks.model.filters.StringFilter;
import org.genesys2.server.model.genesys.MaterialSubRequest;
import org.genesys2.server.model.genesys.QMaterialSubRequest;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Predicate;
// TODO: Auto-generated Javadoc
/**
* Filter for {@link MaterialSubRequest}.
*/
public class MaterialSubRequestFilter extends AuditedVersionedModelFilter {
/** The identifiers. */
public Set<UUID> uuid;
/** The PID. */
public Set<String> pid;
/** The state. */
public Set<Integer> state;
/** The email. */
public StringFilter email;
/**
* Builds the query.
*
* @return the predicate
*/
public Predicate buildQuery() {
return buildQuery(materialSubRequest);
}
/**
* Builds the query.
*
* @param materialSubRequest the materialSubRequest
* @return the predicate
*/
public Predicate buildQuery(QMaterialSubRequest materialSubRequest) {
final BooleanBuilder and = new BooleanBuilder();
super.buildQuery(materialSubRequest._super, and);
if (uuid != null && !uuid.isEmpty()) {
and.and(materialSubRequest.uuid.in(uuid.stream().map(u -> u== null ? null : u.toString()).collect(Collectors.toSet())));
}
if (pid != null && !pid.isEmpty()) {
and.and(materialSubRequest.sourceRequest.pid.in(pid));
}
if (state != null && !state.isEmpty()) {
and.and(materialSubRequest.state.in(state));
}
if (email != null) {
and.and(email.buildQuery(materialSubRequest.sourceRequest.email));
}
return and;
}
}
......@@ -26,13 +26,11 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.model.genesys.MaterialRequest;
import org.genesys2.server.model.genesys.MaterialSubRequest;
import org.genesys2.server.model.genesys.QMaterialSubRequest;
import org.genesys2.server.model.impl.Article;
import org.genesys2.server.model.impl.FaoInstitute;
import org.genesys2.server.model.impl.FaoInstituteSetting;
......@@ -48,6 +46,8 @@ import org.genesys2.server.service.RequestService;
import org.genesys2.server.service.TokenVerificationService;
import org.genesys2.server.service.TokenVerificationService.NoSuchVerificationTokenException;
import org.genesys2.server.service.TokenVerificationService.TokenExpiredException;
import org.genesys2.server.service.filter.MaterialRequestFilter;
import org.genesys2.server.service.filter.MaterialSubRequestFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -60,6 +60,10 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.querydsl.core.BooleanBuilder;
@Service
@Transactional(readOnly = true)
public class RequestServiceImpl implements RequestService {
......@@ -68,9 +72,8 @@ public class RequestServiceImpl implements RequestService {
private static final Logger LOG = LoggerFactory.getLogger(RequestServiceImpl.class);
// TODO FIX this!!!
// @Autowired
// private EasySMTA pidChecker;
@Autowired
private EasySMTA pidChecker;
@Autowired
private TokenVerificationService tokenVerificationService;
......@@ -111,19 +114,17 @@ public class RequestServiceImpl implements RequestService {
throw new RequestException("None of the selected accessions are available for distribution");
}
// TODO FIX this!!!
// Check Easy-SMTA for PID
EasySMTA.EasySMTAUserData pid;
// try {
// pid = pidChecker.getUserData(requestInfo.getEmail());
// } catch (EasySMTAException e) {
// throw new RequestException(e.getMessage(), e);
// }
try {
pid = pidChecker.getUserData(requestInfo.getEmail());
} catch (EasySMTAException e) {
throw new RequestException(e.getMessage(), e);
}
// final MaterialRequest request = createRequest(requestInfo, pid, availableAccessionIds);
final MaterialRequest request = createRequest(requestInfo, pid, availableAccessionIds);
// return sendValidationEmail(request);
return null;
return sendValidationEmail(request);
}
// Send email to the user with verification
......@@ -237,27 +238,26 @@ public class RequestServiceImpl implements RequestService {
@PreAuthorize("hasRole('ADMINISTRATOR')")
public MaterialRequest recheckPid(MaterialRequest materialRequest) throws NoPidException, EasySMTAException {
// re-test email for PID
// TODO FIX this!!!
// EasySMTA.EasySMTAUserData pid = pidChecker.getUserData(materialRequest.getEmail());
// if (pid == null) {
// throw new NoPidException("Email not registered with PID server");
// }
// materialRequest.setPid(pid.getPid());
// requestRepository.save(materialRequest);
EasySMTA.EasySMTAUserData pid = pidChecker.getUserData(materialRequest.getEmail());
if (pid == null) {
throw new NoPidException("Email not registered with PID server");
}
materialRequest.setPid(pid.getPid());
requestRepository.save(materialRequest);
try {
final RequestBody rb = mapper.readValue(materialRequest.getBody(), RequestBody.class);
// rb.pid = pid;
// materialRequest.setBody(serialize(rb));
rb.pid = pid;
materialRequest.setBody(serialize(rb));
// Need to update all subrequests
// for (final MaterialSubRequest subrequest : materialRequest.getSubRequests()) {
// final RequestBody rbs = mapper.readValue(subrequest.getBody(), RequestBody.class);
// rbs.pid = pid;