fix:sample/plate 之前的开发
This commit is contained in:
@@ -5,12 +5,16 @@
|
||||
*/
|
||||
package io.swagger.api.core;
|
||||
|
||||
import io.swagger.model.core.CommonCropListResponse;
|
||||
import io.swagger.model.core.CommonCropNamesResponse;
|
||||
import io.swagger.model.core.CommonCropNewRequest;
|
||||
import jakarta.validation.Valid;
|
||||
import io.swagger.annotations.*;
|
||||
|
||||
import org.brapi.test.BrAPITestServer.exceptions.BrAPIServerException;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
@@ -33,4 +37,44 @@ public interface CommonCropNamesApi {
|
||||
@ApiParam(value = "The size of the pages to be returned. Default is `1000`.") @Valid @RequestParam(value = "pageSize", required = false) Integer pageSize,
|
||||
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization) throws BrAPIServerException;
|
||||
|
||||
@ApiOperation(value = "Create a Common Crop", nickname = "commoncropnamesCropsPost", notes = "Add a new common crop name to the database", response = CommonCropListResponse.class, authorizations = {
|
||||
@Authorization(value = "AuthorizationToken") }, tags = { "Common Crop Names", })
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = CommonCropListResponse.class),
|
||||
@ApiResponse(code = 400, message = "Bad Request", response = String.class),
|
||||
@ApiResponse(code = 401, message = "Unauthorized", response = String.class),
|
||||
@ApiResponse(code = 403, message = "Forbidden", response = String.class),
|
||||
@ApiResponse(code = 409, message = "Conflict", response = String.class) })
|
||||
@RequestMapping(value = "/commoncropnames/crops", produces = { "application/json" }, consumes = {
|
||||
"application/json" }, method = RequestMethod.POST)
|
||||
ResponseEntity<CommonCropListResponse> commoncropnamesCropsPost(
|
||||
@ApiParam(value = "Common crop to create", required = true) @Valid @RequestBody CommonCropNewRequest body,
|
||||
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization) throws BrAPIServerException;
|
||||
|
||||
@ApiOperation(value = "Update a Common Crop", nickname = "commoncropnamesCropsCropDbIdPut", notes = "Update an existing common crop name", response = CommonCropListResponse.class, authorizations = {
|
||||
@Authorization(value = "AuthorizationToken") }, tags = { "Common Crop Names", })
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = CommonCropListResponse.class),
|
||||
@ApiResponse(code = 400, message = "Bad Request", response = String.class),
|
||||
@ApiResponse(code = 401, message = "Unauthorized", response = String.class),
|
||||
@ApiResponse(code = 403, message = "Forbidden", response = String.class),
|
||||
@ApiResponse(code = 404, message = "Not Found", response = String.class),
|
||||
@ApiResponse(code = 409, message = "Conflict", response = String.class) })
|
||||
@RequestMapping(value = "/commoncropnames/crops/{cropDbId}", produces = { "application/json" }, consumes = {
|
||||
"application/json" }, method = RequestMethod.PUT)
|
||||
ResponseEntity<CommonCropListResponse> commoncropnamesCropsCropDbIdPut(
|
||||
@ApiParam(value = "Crop identifier (common crop name or database id)", required = true) @PathVariable("cropDbId") String cropDbId,
|
||||
@ApiParam(value = "Updated common crop name", required = true) @Valid @RequestBody CommonCropNewRequest body,
|
||||
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization) throws BrAPIServerException;
|
||||
|
||||
@ApiOperation(value = "Delete a Common Crop", nickname = "commoncropnamesCropsCropDbIdDelete", notes = "Delete a common crop name from the database", response = CommonCropListResponse.class, authorizations = {
|
||||
@Authorization(value = "AuthorizationToken") }, tags = { "Common Crop Names", })
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = CommonCropListResponse.class),
|
||||
@ApiResponse(code = 401, message = "Unauthorized", response = String.class),
|
||||
@ApiResponse(code = 403, message = "Forbidden", response = String.class),
|
||||
@ApiResponse(code = 404, message = "Not Found", response = String.class),
|
||||
@ApiResponse(code = 409, message = "Conflict", response = String.class) })
|
||||
@RequestMapping(value = "/commoncropnames/crops/{cropDbId}", produces = { "application/json" }, method = RequestMethod.DELETE)
|
||||
ResponseEntity<CommonCropListResponse> commoncropnamesCropsCropDbIdDelete(
|
||||
@ApiParam(value = "Crop identifier (common crop name or database id)", required = true) @PathVariable("cropDbId") String cropDbId,
|
||||
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization) throws BrAPIServerException;
|
||||
|
||||
}
|
||||
|
||||
@@ -80,6 +80,19 @@ public interface LocationsApi {
|
||||
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException;
|
||||
|
||||
@ApiOperation(value = "Delete an existing Location", nickname = "locationsLocationDbIdDelete", notes = "Delete an existing location", response = LocationSingleResponse.class, authorizations = {
|
||||
@Authorization(value = "AuthorizationToken") }, tags = { "Locations", })
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = LocationSingleResponse.class),
|
||||
@ApiResponse(code = 401, message = "Unauthorized", response = String.class),
|
||||
@ApiResponse(code = 403, message = "Forbidden", response = String.class),
|
||||
@ApiResponse(code = 404, message = "Not Found", response = String.class),
|
||||
@ApiResponse(code = 409, message = "Conflict", response = String.class) })
|
||||
@RequestMapping(value = "/locations/{locationDbId}", produces = { "application/json" }, method = RequestMethod.DELETE)
|
||||
ResponseEntity<LocationSingleResponse> locationsLocationDbIdDelete(
|
||||
@ApiParam(value = "The internal DB id for a location", required = true) @PathVariable("locationDbId") String locationDbId,
|
||||
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException;
|
||||
|
||||
@ApiOperation(value = "Create new Locations", nickname = "locationsPost", notes = "Add new locations to database * The `countryCode` is as per [ISO_3166-1_alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) spec. * `altitude` is in meters.", response = LocationListResponse.class, authorizations = {
|
||||
@Authorization(value = "AuthorizationToken") }, tags = { "Locations", })
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = LocationListResponse.class),
|
||||
|
||||
@@ -79,6 +79,19 @@ public interface PeopleApi {
|
||||
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException;
|
||||
|
||||
@ApiOperation(value = "Delete an existing Person", nickname = "peoplePersonDbIdDelete", notes = "Delete an existing Person", response = PersonSingleResponse.class, authorizations = {
|
||||
@Authorization(value = "AuthorizationToken") }, tags = { "People", })
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = PersonSingleResponse.class),
|
||||
@ApiResponse(code = 401, message = "Unauthorized", response = String.class),
|
||||
@ApiResponse(code = 403, message = "Forbidden", response = String.class),
|
||||
@ApiResponse(code = 404, message = "Not Found", response = String.class),
|
||||
@ApiResponse(code = 409, message = "Conflict", response = String.class) })
|
||||
@RequestMapping(value = "/people/{personDbId}", produces = { "application/json" }, method = RequestMethod.DELETE)
|
||||
ResponseEntity<PersonSingleResponse> peoplePersonDbIdDelete(
|
||||
@ApiParam(value = "The unique ID of a person", required = true) @PathVariable("personDbId") String personDbId,
|
||||
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException;
|
||||
|
||||
@ApiOperation(value = "Create new People", nickname = "peoplePost", notes = "Create new People entities. `personDbId` is generated and managed by the server.", response = PersonListResponse.class, authorizations = {
|
||||
@Authorization(value = "AuthorizationToken") }, tags = { "People", })
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = PersonListResponse.class),
|
||||
|
||||
@@ -77,4 +77,16 @@ public interface SeasonsApi {
|
||||
@ApiParam(value = "") @Valid @RequestBody Season body,
|
||||
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization) throws BrAPIServerException;
|
||||
|
||||
@ApiOperation(value = "Delete an existing Season", nickname = "seasonsSeasonDbIdDelete", notes = "Delete an existing Season", response = SeasonSingleResponse.class, authorizations = {
|
||||
@Authorization(value = "AuthorizationToken") }, tags = { "Seasons", })
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = SeasonSingleResponse.class),
|
||||
@ApiResponse(code = 401, message = "Unauthorized", response = String.class),
|
||||
@ApiResponse(code = 403, message = "Forbidden", response = String.class),
|
||||
@ApiResponse(code = 404, message = "Not Found", response = String.class),
|
||||
@ApiResponse(code = 409, message = "Conflict", response = String.class) })
|
||||
@RequestMapping(value = "/seasons/{seasonDbId}", produces = { "application/json" }, method = RequestMethod.DELETE)
|
||||
ResponseEntity<SeasonSingleResponse> seasonsSeasonDbIdDelete(
|
||||
@ApiParam(value = "The unique identifier for a season. For backward compatibility it can be a string like '2012', '1957-2004'", required = true) @PathVariable("seasonDbId") String seasonDbId,
|
||||
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization) throws BrAPIServerException;
|
||||
|
||||
}
|
||||
|
||||
@@ -12,12 +12,15 @@ import io.swagger.annotations.*;
|
||||
import org.brapi.test.BrAPITestServer.exceptions.BrAPIServerException;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import io.swagger.model.germ.BreedingMethod;
|
||||
import jakarta.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
@javax.annotation.processing.Generated(value = "io.swagger.codegen.v3.generators.java.SpringCodegen", date = "2020-03-20T16:33:36.513Z[GMT]")
|
||||
@Api(value = "breedingmethods", description = "the breedingmethods API")
|
||||
@@ -50,4 +53,43 @@ public interface BreedingMethodsApi {
|
||||
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException;
|
||||
|
||||
@ApiOperation(value = "POST new Breeding Methods", nickname = "breedingmethodsPost", notes = "Add new breeding method entries to the database", response = BreedingMethodListResponse.class, authorizations = {
|
||||
@Authorization(value = "AuthorizationToken") }, tags = { "Germplasm", })
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = BreedingMethodListResponse.class),
|
||||
@ApiResponse(code = 400, message = "Bad Request", response = String.class),
|
||||
@ApiResponse(code = 401, message = "Unauthorized", response = String.class),
|
||||
@ApiResponse(code = 403, message = "Forbidden", response = String.class) })
|
||||
@RequestMapping(value = "/breedingmethods", produces = { "application/json" }, consumes = {
|
||||
"application/json" }, method = RequestMethod.POST)
|
||||
ResponseEntity<BreedingMethodListResponse> breedingmethodsPost(@ApiParam(value = "") @Valid @RequestBody List<BreedingMethod> body,
|
||||
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException;
|
||||
|
||||
@ApiOperation(value = "Update existing Breeding Method", nickname = "breedingmethodsBreedingMethodDbIdPut", notes = "Update existing Breeding Method", response = BreedingMethodSingleResponse.class, authorizations = {
|
||||
@Authorization(value = "AuthorizationToken") }, tags = { "Germplasm", })
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = BreedingMethodSingleResponse.class),
|
||||
@ApiResponse(code = 400, message = "Bad Request", response = String.class),
|
||||
@ApiResponse(code = 401, message = "Unauthorized", response = String.class),
|
||||
@ApiResponse(code = 403, message = "Forbidden", response = String.class) })
|
||||
@RequestMapping(value = "/breedingmethods/{breedingMethodDbId}", produces = { "application/json" }, consumes = {
|
||||
"application/json" }, method = RequestMethod.PUT)
|
||||
ResponseEntity<BreedingMethodSingleResponse> breedingmethodsBreedingMethodDbIdPut(
|
||||
@ApiParam(value = "Internal database identifier for a breeding method", required = true) @PathVariable("breedingMethodDbId") String breedingMethodDbId,
|
||||
@ApiParam(value = "") @Valid @RequestBody BreedingMethod body,
|
||||
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException;
|
||||
|
||||
@ApiOperation(value = "Delete an existing Breeding Method", nickname = "breedingmethodsBreedingMethodDbIdDelete", notes = "Delete an existing Breeding Method", response = BreedingMethodSingleResponse.class, authorizations = {
|
||||
@Authorization(value = "AuthorizationToken") }, tags = { "Germplasm", })
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = BreedingMethodSingleResponse.class),
|
||||
@ApiResponse(code = 401, message = "Unauthorized", response = String.class),
|
||||
@ApiResponse(code = 403, message = "Forbidden", response = String.class),
|
||||
@ApiResponse(code = 404, message = "Not Found", response = String.class),
|
||||
@ApiResponse(code = 409, message = "Conflict", response = String.class) })
|
||||
@RequestMapping(value = "/breedingmethods/{breedingMethodDbId}", produces = { "application/json" }, method = RequestMethod.DELETE)
|
||||
ResponseEntity<BreedingMethodSingleResponse> breedingmethodsBreedingMethodDbIdDelete(
|
||||
@ApiParam(value = "Internal database identifier for a breeding method", required = true) @PathVariable("breedingMethodDbId") String breedingMethodDbId,
|
||||
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException;
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.springframework.web.bind.annotation.RequestHeader;
|
||||
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.PathVariable;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
@@ -80,4 +81,16 @@ public interface OntologiesApi {
|
||||
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization,
|
||||
@ApiParam(value = "") @Valid @RequestBody List<OntologyNewRequest> body) throws BrAPIServerException;
|
||||
|
||||
@ApiOperation(value = "Delete an existing Ontology record", nickname = "ontologiesOntologyDbIdDelete", notes = "Delete an existing Ontology record", response = OntologySingleResponse.class, authorizations = {
|
||||
@Authorization(value = "AuthorizationToken") }, tags = { "Ontologies", })
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = OntologySingleResponse.class),
|
||||
@ApiResponse(code = 401, message = "Unauthorized", response = String.class),
|
||||
@ApiResponse(code = 403, message = "Forbidden", response = String.class),
|
||||
@ApiResponse(code = 404, message = "Not Found", response = String.class),
|
||||
@ApiResponse(code = 409, message = "Conflict", response = String.class) })
|
||||
@RequestMapping(value = "/ontologies/{ontologyDbId}", produces = { "application/json" }, method = RequestMethod.DELETE)
|
||||
ResponseEntity<OntologySingleResponse> ontologiesOntologyDbIdDelete(
|
||||
@ApiParam(value = "The unique identifier for an ontology definition. Use this parameter to filter results based on a specific ontology Use `GET /ontologies` to find the list of available ontologies on a server.", required = true) @PathVariable("ontologyDbId") String ontologyDbId,
|
||||
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization) throws BrAPIServerException;
|
||||
|
||||
}
|
||||
|
||||
@@ -87,4 +87,17 @@ public interface TraitsApi {
|
||||
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException;
|
||||
|
||||
@ApiOperation(value = "Delete an existing Trait", nickname = "traitsTraitDbIdDelete", notes = "Delete an existing trait", response = TraitSingleResponse.class, authorizations = {
|
||||
@Authorization(value = "AuthorizationToken") }, tags = { "Traits", })
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = TraitSingleResponse.class),
|
||||
@ApiResponse(code = 401, message = "Unauthorized", response = String.class),
|
||||
@ApiResponse(code = 403, message = "Forbidden", response = String.class),
|
||||
@ApiResponse(code = 404, message = "Not Found", response = String.class),
|
||||
@ApiResponse(code = 409, message = "Conflict", response = String.class) })
|
||||
@RequestMapping(value = "/traits/{traitDbId}", produces = { "application/json" }, method = RequestMethod.DELETE)
|
||||
ResponseEntity<TraitSingleResponse> traitsTraitDbIdDelete(
|
||||
@ApiParam(value = "Id of the trait to delete.", required = true) @PathVariable("traitDbId") String traitDbId,
|
||||
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException;
|
||||
|
||||
}
|
||||
|
||||
63
src/main/java/io/swagger/model/core/CommonCrop.java
Normal file
63
src/main/java/io/swagger/model/core/CommonCrop.java
Normal file
@@ -0,0 +1,63 @@
|
||||
package io.swagger.model.core;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Validated
|
||||
public class CommonCrop {
|
||||
|
||||
@JsonProperty("cropDbId")
|
||||
private String cropDbId = null;
|
||||
|
||||
@JsonProperty("commonCropName")
|
||||
private String commonCropName = null;
|
||||
|
||||
public CommonCrop cropDbId(String cropDbId) {
|
||||
this.cropDbId = cropDbId;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ApiModelProperty(example = "Tomatillo", value = "Crop identifier; uses common crop name for compatibility with GET /commoncropnames")
|
||||
public String getCropDbId() {
|
||||
return cropDbId;
|
||||
}
|
||||
|
||||
public void setCropDbId(String cropDbId) {
|
||||
this.cropDbId = cropDbId;
|
||||
}
|
||||
|
||||
public CommonCrop commonCropName(String commonCropName) {
|
||||
this.commonCropName = commonCropName;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ApiModelProperty(example = "Tomatillo", required = true, value = "Common crop name")
|
||||
public String getCommonCropName() {
|
||||
return commonCropName;
|
||||
}
|
||||
|
||||
public void setCommonCropName(String commonCropName) {
|
||||
this.commonCropName = commonCropName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
CommonCrop commonCrop = (CommonCrop) o;
|
||||
return Objects.equals(cropDbId, commonCrop.cropDbId)
|
||||
&& Objects.equals(commonCropName, commonCrop.commonCropName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(cropDbId, commonCropName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package io.swagger.model.core;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.model.BrAPIResponse;
|
||||
import io.swagger.model.Context;
|
||||
import io.swagger.model.Metadata;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Validated
|
||||
public class CommonCropListResponse implements BrAPIResponse<CommonCropListResponseResult> {
|
||||
|
||||
@JsonProperty("@context")
|
||||
private Context _atContext = null;
|
||||
|
||||
@JsonProperty("metadata")
|
||||
private Metadata metadata = null;
|
||||
|
||||
@JsonProperty("result")
|
||||
private CommonCropListResponseResult result = null;
|
||||
|
||||
public CommonCropListResponse _atContext(Context _atContext) {
|
||||
this._atContext = _atContext;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void set_atContext(Context _atContext) {
|
||||
this._atContext = _atContext;
|
||||
}
|
||||
|
||||
public CommonCropListResponse metadata(Metadata metadata) {
|
||||
this.metadata = metadata;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ApiModelProperty(required = true, value = "")
|
||||
@Valid
|
||||
public Metadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public void setMetadata(Metadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public CommonCropListResponse result(CommonCropListResponseResult result) {
|
||||
this.result = result;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ApiModelProperty(required = true, value = "")
|
||||
@Valid
|
||||
public CommonCropListResponseResult getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setResult(CommonCropListResponseResult result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
CommonCropListResponse that = (CommonCropListResponse) o;
|
||||
return Objects.equals(_atContext, that._atContext)
|
||||
&& Objects.equals(metadata, that.metadata)
|
||||
&& Objects.equals(result, that.result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(_atContext, metadata, result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package io.swagger.model.core;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.model.BrAPIResponseResult;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Validated
|
||||
public class CommonCropListResponseResult implements BrAPIResponseResult<CommonCrop> {
|
||||
|
||||
@JsonProperty("data")
|
||||
@Valid
|
||||
private List<CommonCrop> data = new ArrayList<>();
|
||||
|
||||
public CommonCropListResponseResult data(List<CommonCrop> data) {
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommonCropListResponseResult addDataItem(CommonCrop dataItem) {
|
||||
this.data.add(dataItem);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ApiModelProperty(required = true, value = "Crop mutation results")
|
||||
@Valid
|
||||
public List<CommonCrop> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(List<CommonCrop> data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
CommonCropListResponseResult that = (CommonCropListResponseResult) o;
|
||||
return Objects.equals(data, that.data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package io.swagger.model.core;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Validated
|
||||
public class CommonCropNewRequest {
|
||||
|
||||
@JsonProperty("commonCropName")
|
||||
private String commonCropName = null;
|
||||
|
||||
public CommonCropNewRequest commonCropName(String commonCropName) {
|
||||
this.commonCropName = commonCropName;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ApiModelProperty(example = "Maize", required = true, value = "Common crop name")
|
||||
public String getCommonCropName() {
|
||||
return commonCropName;
|
||||
}
|
||||
|
||||
public void setCommonCropName(String commonCropName) {
|
||||
this.commonCropName = commonCropName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
CommonCropNewRequest that = (CommonCropNewRequest) o;
|
||||
return Objects.equals(commonCropName, that.commonCropName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(commonCropName);
|
||||
}
|
||||
}
|
||||
49
src/main/java/io/swagger/model/geno/ReferenceBasesPage.java
Normal file
49
src/main/java/io/swagger/model/geno/ReferenceBasesPage.java
Normal file
@@ -0,0 +1,49 @@
|
||||
package io.swagger.model.geno;
|
||||
|
||||
public class ReferenceBasesPage {
|
||||
private String referenceBasesDbId;
|
||||
private String referenceDbId;
|
||||
private String referenceName;
|
||||
private Integer pageNumber;
|
||||
private String bases;
|
||||
|
||||
public String getReferenceBasesDbId() {
|
||||
return referenceBasesDbId;
|
||||
}
|
||||
|
||||
public void setReferenceBasesDbId(String referenceBasesDbId) {
|
||||
this.referenceBasesDbId = referenceBasesDbId;
|
||||
}
|
||||
|
||||
public String getReferenceDbId() {
|
||||
return referenceDbId;
|
||||
}
|
||||
|
||||
public void setReferenceDbId(String referenceDbId) {
|
||||
this.referenceDbId = referenceDbId;
|
||||
}
|
||||
|
||||
public String getReferenceName() {
|
||||
return referenceName;
|
||||
}
|
||||
|
||||
public void setReferenceName(String referenceName) {
|
||||
this.referenceName = referenceName;
|
||||
}
|
||||
|
||||
public Integer getPageNumber() {
|
||||
return pageNumber;
|
||||
}
|
||||
|
||||
public void setPageNumber(Integer pageNumber) {
|
||||
this.pageNumber = pageNumber;
|
||||
}
|
||||
|
||||
public String getBases() {
|
||||
return bases;
|
||||
}
|
||||
|
||||
public void setBases(String bases) {
|
||||
this.bases = bases;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package io.swagger.model.geno;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import io.swagger.model.BrAPIResponse;
|
||||
import io.swagger.model.Context;
|
||||
import io.swagger.model.Metadata;
|
||||
|
||||
public class ReferenceBasesPageListResponse implements BrAPIResponse<ReferenceBasesPageListResponseResult> {
|
||||
@JsonProperty("@context")
|
||||
private Context _atContext;
|
||||
|
||||
private Metadata metadata;
|
||||
private ReferenceBasesPageListResponseResult result;
|
||||
|
||||
public void set_atContext(Context _atContext) {
|
||||
this._atContext = _atContext;
|
||||
}
|
||||
|
||||
public Metadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public void setMetadata(Metadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public ReferenceBasesPageListResponseResult getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setResult(ReferenceBasesPageListResponseResult result) {
|
||||
this.result = result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package io.swagger.model.geno;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.swagger.model.BrAPIResponseResult;
|
||||
|
||||
public class ReferenceBasesPageListResponseResult implements BrAPIResponseResult<ReferenceBasesPage> {
|
||||
private List<ReferenceBasesPage> data;
|
||||
|
||||
public List<ReferenceBasesPage> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(List<ReferenceBasesPage> data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package io.swagger.model.geno;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import io.swagger.model.BrAPIResponse;
|
||||
import io.swagger.model.Context;
|
||||
import io.swagger.model.Metadata;
|
||||
|
||||
public class ReferenceBasesPageSingleResponse implements BrAPIResponse<ReferenceBasesPage> {
|
||||
@JsonProperty("@context")
|
||||
private Context _atContext;
|
||||
|
||||
private Metadata metadata;
|
||||
private ReferenceBasesPage result;
|
||||
|
||||
public void set_atContext(Context _atContext) {
|
||||
this._atContext = _atContext;
|
||||
}
|
||||
|
||||
public Metadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public void setMetadata(Metadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public ReferenceBasesPage getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setResult(ReferenceBasesPage result) {
|
||||
this.result = result;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package org.brapi.test.BrAPITestServer.auth;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.brapi.test.BrAPITestServer.system.security.SystemJwtAuthFilter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
@@ -11,40 +11,26 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
||||
import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableWebSecurity
|
||||
@EnableMethodSecurity
|
||||
public class BrapiTestServerAuthConfig {
|
||||
|
||||
@Value( "${security.oidc_discovery_url}" )
|
||||
private String oidcDiscoveryUrl;
|
||||
|
||||
@Value("${security.issuer_url}")private String issuerUrl;
|
||||
|
||||
@Value( "${security.enabled:true}" )
|
||||
private boolean authEnabled;
|
||||
|
||||
@Bean
|
||||
AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
|
||||
return authenticationConfiguration.getAuthenticationManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
|
||||
public SecurityFilterChain filterChain(HttpSecurity http, SystemJwtAuthFilter systemJwtAuthFilter) throws Exception {
|
||||
http.csrf(CsrfConfigurer::disable)
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.anyRequest()
|
||||
.permitAll() //TODO: secure this
|
||||
) //.authenticated().and()
|
||||
.addFilter(new BrapiTestServerJWTAuthFilter(
|
||||
authenticationManager,
|
||||
oidcDiscoveryUrl,
|
||||
issuerUrl,
|
||||
authEnabled))
|
||||
// this disables session creation on Spring Security
|
||||
.sessionManagement(sm -> sm
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
|
||||
.requestMatchers("/auth/**").permitAll()
|
||||
.anyRequest().permitAll())
|
||||
.addFilterBefore(systemJwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
.sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
|
||||
return http.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,225 +0,0 @@
|
||||
package org.brapi.test.BrAPITestServer.auth;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||
import com.auth0.jwt.interfaces.JWTVerifier;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
public class BrapiTestServerJWTAuthFilter extends BasicAuthenticationFilter {
|
||||
private static final Logger log = LoggerFactory.getLogger(BrapiTestServerJWTAuthFilter.class);
|
||||
private static final List<String> ADMIN_IDS = Arrays.asList("dummyAdmin", "ps664@cornell.edu");
|
||||
|
||||
private final String oidcDiscoveryUrl;
|
||||
private final String issuerUrl;
|
||||
private final boolean authEnabled;
|
||||
|
||||
public BrapiTestServerJWTAuthFilter(AuthenticationManager authManager,
|
||||
String oidcDiscoveryUrl,
|
||||
String issuerUrl,
|
||||
boolean authEnabled) {
|
||||
super(authManager);
|
||||
this.oidcDiscoveryUrl = oidcDiscoveryUrl;
|
||||
this.issuerUrl = issuerUrl;
|
||||
this.authEnabled = authEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
String header = req.getHeader("Authorization");
|
||||
|
||||
//Auth disabled by config property
|
||||
if (!authEnabled) {
|
||||
List<GrantedAuthority> authorities = new ArrayList<>();
|
||||
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
|
||||
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
|
||||
AuthDetails bypassDetails = new AuthDetails();
|
||||
bypassDetails.setUserId("anonymousUser");
|
||||
bypassDetails.setExpirationTimestamp(Long.MAX_VALUE);
|
||||
bypassDetails.setRoles(new ArrayList<>());
|
||||
bypassDetails.getRoles().add("ROLE_USER");
|
||||
bypassDetails.getRoles().add("ROLE_ADMIN");
|
||||
UsernamePasswordAuthenticationToken authentication =
|
||||
new UsernamePasswordAuthenticationToken(bypassDetails.getUserId(), null, authorities);
|
||||
authentication.setDetails(bypassDetails);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
chain.doFilter(req, res);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Anonymous User
|
||||
if (header == null || !header.startsWith("Bearer ")) {
|
||||
chain.doFilter(req, res);
|
||||
return;
|
||||
}
|
||||
|
||||
// Token Available
|
||||
try {
|
||||
String token = header.replaceFirst("Bearer ", "");
|
||||
AuthDetails userDetails = validateToken(token);
|
||||
|
||||
if (userDetails != null) {
|
||||
List<GrantedAuthority> authorities = getAuthorities(userDetails);
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||
userDetails.getUserId(), null, authorities);
|
||||
authentication.setDetails(userDetails);
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
} else {
|
||||
throw new GeneralSecurityException("Auth Error");
|
||||
}
|
||||
|
||||
chain.doFilter(req, res);
|
||||
|
||||
} catch (GeneralSecurityException e) {
|
||||
String msg = determineExceptionCause(e);
|
||||
log.error(msg);
|
||||
res.addHeader("WWW-Authenticate", "Basic realm=\"\"");
|
||||
res.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
res.setContentType("text/plain;charset=UTF-8");
|
||||
res.getWriter().print(msg);
|
||||
res.getWriter().flush();
|
||||
// res.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase() + " - " + msg);
|
||||
}
|
||||
}
|
||||
|
||||
private String determineExceptionCause(GeneralSecurityException e) {
|
||||
String msg = HttpStatus.UNAUTHORIZED.toString() + " - ";
|
||||
Throwable exception = e;
|
||||
msg += exception.getMessage();
|
||||
while (exception.getCause() != null){
|
||||
exception = exception.getCause();
|
||||
msg += " - " + exception.getMessage();
|
||||
}
|
||||
msg += "\nPlease go to https://brapi.org/oauth and login to generate a fresh token, or use the dummy token 'XXXX'";
|
||||
return "\"" + msg + "\"";
|
||||
}
|
||||
|
||||
private AuthDetails validateToken(String token)
|
||||
throws FileNotFoundException, IOException, GeneralSecurityException {
|
||||
|
||||
AuthDetails userDetails = null;
|
||||
if (token.equals("XXXX") || token.equals("YYYY") || token.equals("ZZZZ")) {
|
||||
userDetails = validateDummyToken(token);
|
||||
} else {
|
||||
userDetails = validateOAuthToken(token);
|
||||
}
|
||||
return userDetails;
|
||||
}
|
||||
|
||||
private AuthDetails validateDummyToken(String token) {
|
||||
AuthDetails details = null;
|
||||
if (token.equals("XXXX")) {
|
||||
details = new AuthDetails();
|
||||
details.setUserId("dummy");
|
||||
details.setExpirationTimestamp(Long.MAX_VALUE);
|
||||
} else if (token.equals("YYYY")) {
|
||||
details = new AuthDetails();
|
||||
details.setUserId("dummyAdmin");
|
||||
details.setExpirationTimestamp(Long.MAX_VALUE);
|
||||
} else if (token.equals("ZZZZ")) {
|
||||
details = new AuthDetails();
|
||||
details.setUserId("anonymousUser");
|
||||
details.setExpirationTimestamp(Long.MAX_VALUE);
|
||||
}
|
||||
return details;
|
||||
}
|
||||
|
||||
private AuthDetails validateOAuthToken(String token) throws GeneralSecurityException {
|
||||
try {
|
||||
token = token.replaceFirst("Bearer ", "");
|
||||
RSAPublicKey pubKey = getPublicKey(oidcDiscoveryUrl);
|
||||
|
||||
Algorithm algorithm = Algorithm.RSA256(pubKey, null);
|
||||
JWTVerifier verifier = JWT.require(algorithm).withIssuer(issuerUrl)
|
||||
.build();
|
||||
DecodedJWT jwt = verifier.verify(token);
|
||||
|
||||
AuthDetails details = new AuthDetails();
|
||||
details.setUserId(jwt.getClaim("email").asString());
|
||||
details.setExpirationTimestamp(jwt.getExpiresAt());
|
||||
return details;
|
||||
} catch (JWTVerificationException e) {
|
||||
throw new GeneralSecurityException("Invalid JWT", e);
|
||||
} catch (Exception e) {
|
||||
throw new GeneralSecurityException("JWT Verification Process Failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
private RSAPublicKey getPublicKey(String discoveryURL) {
|
||||
try {
|
||||
JsonNode discovery = (new ObjectMapper()).readTree(new URL(discoveryURL));
|
||||
String jwksURL = discovery.findValue("jwks_uri").asText();
|
||||
ArrayNode jwks = (new ObjectMapper()).readTree(new URL(jwksURL)).withArray("keys");
|
||||
String keyVal = null;
|
||||
for(JsonNode jwk: jwks){
|
||||
String algo = jwk.findValue("alg").asText();
|
||||
if(algo.equals("RS256")){
|
||||
keyVal = jwk.findValue("x5c").get(0).asText();
|
||||
}
|
||||
}
|
||||
|
||||
String certb64 = keyVal;
|
||||
byte[] certder = Base64.decodeBase64(certb64);
|
||||
InputStream certstream = new ByteArrayInputStream(certder);
|
||||
Certificate cert = CertificateFactory.getInstance("X.509").generateCertificate(certstream);
|
||||
RSAPublicKey pubKey = (RSAPublicKey) cert.getPublicKey();
|
||||
return pubKey;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} catch (CertificateException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private List<GrantedAuthority> getAuthorities(AuthDetails userDetails) {
|
||||
List<GrantedAuthority> auth = new ArrayList<>();
|
||||
if (userDetails != null) {
|
||||
GrantedAuthority user = new SimpleGrantedAuthority("ROLE_USER");
|
||||
auth.add(user);
|
||||
userDetails.addRole("ROLE_USER");
|
||||
if (ADMIN_IDS.contains(userDetails.getUserId())) {
|
||||
GrantedAuthority admin = new SimpleGrantedAuthority("ROLE_ADMIN");
|
||||
auth.add(admin);
|
||||
userDetails.addRole("ROLE_ADMIN");
|
||||
}
|
||||
}
|
||||
return auth;
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package org.brapi.test.BrAPITestServer.auth.oldTokens;
|
||||
|
||||
import io.swagger.model.core.ServerInfoResponse;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiResponse;
|
||||
import io.swagger.annotations.ApiResponses;
|
||||
import io.swagger.annotations.Authorization;
|
||||
import org.brapi.test.BrAPITestServer.controller.core.BrAPIController;
|
||||
import org.brapi.test.BrAPITestServer.exceptions.BrAPIServerException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
@javax.annotation.processing.Generated(value = "io.swagger.codegen.v3.generators.java.SpringCodegen", date = "2020-03-20T16:31:52.030Z[GMT]")
|
||||
@Controller
|
||||
public class TokenController extends BrAPIController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(TokenController.class);
|
||||
|
||||
private final HttpServletRequest request;
|
||||
|
||||
@org.springframework.beans.factory.annotation.Autowired
|
||||
public TokenController(HttpServletRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@ApiOperation(value = "Get the list of implemented Calls", nickname = "tokenPost", response = ServerInfoResponse.class, authorizations = {
|
||||
@Authorization(value = "AuthorizationToken") }, tags = { "Server Info", })
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = ServerInfoResponse.class),
|
||||
@ApiResponse(code = 400, message = "Bad Request", response = String.class),
|
||||
@ApiResponse(code = 401, message = "Unauthorized", response = String.class),
|
||||
@ApiResponse(code = 403, message = "Forbidden", response = String.class) })
|
||||
@RequestMapping(value = "/token", produces = { "application/json" }, method = RequestMethod.POST)
|
||||
@CrossOrigin
|
||||
public ResponseEntity<TokenResponse> tokenPost(@RequestBody TokenRequest body)
|
||||
throws BrAPIServerException {
|
||||
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_ANONYMOUS", "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
|
||||
return new ResponseEntity<TokenResponse>(new TokenResponse(), HttpStatus.OK);
|
||||
}
|
||||
|
||||
private class TokenResponse{
|
||||
@JsonProperty("access_token")
|
||||
private final String accessToken = "YYYY";
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package org.brapi.test.BrAPITestServer.auth.oldTokens;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class TokenRequest {
|
||||
@JsonProperty("username")
|
||||
private Optional<String> username = null;
|
||||
|
||||
@JsonProperty("password")
|
||||
private Optional<String> password = null;
|
||||
|
||||
public TokenRequest() {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public Optional<String> getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(Optional<String> username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public Optional<String> getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(Optional<String> password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.brapi.test.BrAPITestServer.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class BrApiWebConfig implements WebMvcConfigurer {
|
||||
|
||||
private static final String BRAPI_PREFIX = "/brapi/v2";
|
||||
private static final String BRAPI_CONTROLLER_PACKAGE = "org.brapi.test.BrAPITestServer.controller";
|
||||
|
||||
@Override
|
||||
public void configurePathMatch(PathMatchConfigurer configurer) {
|
||||
configurer.addPathPrefix(BRAPI_PREFIX, BrApiWebConfig::isBrApiController);
|
||||
}
|
||||
|
||||
static boolean isBrApiController(Class<?> controllerClass) {
|
||||
return controllerClass.isAnnotationPresent(RestController.class)
|
||||
&& controllerClass.getPackageName().startsWith(BRAPI_CONTROLLER_PACKAGE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.brapi.test.BrAPITestServer.config;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class OpenApiResourceController {
|
||||
|
||||
@GetMapping(value = "/brapi/v2/openapi.json", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ResponseEntity<Resource> openApiDocument() {
|
||||
return ResponseEntity.ok(new ClassPathResource("static/openapi.json"));
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
package org.brapi.test.BrAPITestServer.controller.core;
|
||||
|
||||
import io.swagger.model.Metadata;
|
||||
import io.swagger.model.core.CommonCrop;
|
||||
import io.swagger.model.core.CommonCropListResponse;
|
||||
import io.swagger.model.core.CommonCropListResponseResult;
|
||||
import io.swagger.model.core.CommonCropNamesResponse;
|
||||
import io.swagger.model.core.CommonCropNamesResponseResult;
|
||||
import io.swagger.model.core.CommonCropNewRequest;
|
||||
import io.swagger.api.core.CommonCropNamesApi;
|
||||
|
||||
import org.brapi.test.BrAPITestServer.exceptions.BrAPIServerException;
|
||||
@@ -13,6 +17,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
@@ -50,5 +56,48 @@ public class CommonCropNamesApiController extends BrAPIController implements Com
|
||||
return responseOK(new CommonCropNamesResponse(), new CommonCropNamesResponseResult(), crops, metadata);
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@Override
|
||||
public ResponseEntity<CommonCropListResponse> commoncropnamesCropsPost(
|
||||
@Valid @RequestBody CommonCropNewRequest body,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization) throws BrAPIServerException {
|
||||
|
||||
validateAcceptHeader(request);
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
|
||||
CommonCrop crop = cropService.createCrop(body.getCommonCropName());
|
||||
return responseOK(new CommonCropListResponse(), new CommonCropListResponseResult(), List.of(crop));
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@Override
|
||||
public ResponseEntity<CommonCropListResponse> commoncropnamesCropsCropDbIdPut(
|
||||
@PathVariable("cropDbId") String cropDbId,
|
||||
@Valid @RequestBody CommonCropNewRequest body,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization) throws BrAPIServerException {
|
||||
|
||||
validateAcceptHeader(request);
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
|
||||
CommonCrop crop = cropService.updateCrop(cropDbId, body.getCommonCropName());
|
||||
return responseOK(new CommonCropListResponse(), new CommonCropListResponseResult(), List.of(crop));
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@Override
|
||||
public ResponseEntity<CommonCropListResponse> commoncropnamesCropsCropDbIdDelete(
|
||||
@PathVariable("cropDbId") String cropDbId,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization) throws BrAPIServerException {
|
||||
|
||||
validateAcceptHeader(request);
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
|
||||
CommonCrop crop = cropService.deleteCrop(cropDbId);
|
||||
return responseOK(new CommonCropListResponse(), new CommonCropListResponseResult(), List.of(crop));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -98,6 +98,19 @@ public class LocationsApiController extends BrAPIController implements Locations
|
||||
return responseOK(new LocationSingleResponse(), data);
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@Override
|
||||
public ResponseEntity<LocationSingleResponse> locationsLocationDbIdDelete(
|
||||
@PathVariable("locationDbId") String locationDbId,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization) throws BrAPIServerException {
|
||||
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
Location data = locationService.deleteLocation(locationDbId);
|
||||
return responseOK(new LocationSingleResponse(), data);
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@Override
|
||||
public ResponseEntity<LocationListResponse> locationsPost(@Valid @RequestBody List<LocationNewRequest> body,
|
||||
|
||||
@@ -96,6 +96,19 @@ public class PeopleApiController extends BrAPIController implements PeopleApi {
|
||||
return responseOK(new PersonSingleResponse(), data);
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@Override
|
||||
public ResponseEntity<PersonSingleResponse> peoplePersonDbIdDelete(
|
||||
@PathVariable("personDbId") String personDbId,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization) throws BrAPIServerException {
|
||||
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
Person data = peopleService.deletePerson(personDbId);
|
||||
return responseOK(new PersonSingleResponse(), data);
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@Override
|
||||
public ResponseEntity<PersonListResponse> peoplePost(@Valid @RequestBody List<PersonNewRequest> body,
|
||||
|
||||
@@ -95,5 +95,18 @@ public class SeasonsApiController extends BrAPIController implements SeasonsApi
|
||||
return responseOK(new SeasonSingleResponse(), data);
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@Override
|
||||
public ResponseEntity<SeasonSingleResponse> seasonsSeasonDbIdDelete(
|
||||
@PathVariable("seasonDbId") String seasonDbId,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization) throws BrAPIServerException {
|
||||
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
Season data = seasonService.deleteSeason(seasonDbId);
|
||||
return responseOK(new SeasonSingleResponse(), data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
package org.brapi.test.BrAPITestServer.controller.geno;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.brapi.test.BrAPITestServer.controller.core.BrAPIController;
|
||||
import org.brapi.test.BrAPITestServer.exceptions.BrAPIServerException;
|
||||
import org.brapi.test.BrAPITestServer.model.dto.geno.ReferenceBasesWriteRequest;
|
||||
import org.brapi.test.BrAPITestServer.model.dto.geno.ReferenceSetWriteRequest;
|
||||
import org.brapi.test.BrAPITestServer.model.dto.geno.ReferenceWriteRequest;
|
||||
import org.brapi.test.BrAPITestServer.service.geno.ReferenceBasesService;
|
||||
import org.brapi.test.BrAPITestServer.service.geno.ReferenceService;
|
||||
import org.brapi.test.BrAPITestServer.service.geno.ReferenceSetService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
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 io.swagger.model.Metadata;
|
||||
import io.swagger.model.geno.Reference;
|
||||
import io.swagger.model.geno.ReferenceBasesPage;
|
||||
import io.swagger.model.geno.ReferenceBasesPageListResponse;
|
||||
import io.swagger.model.geno.ReferenceBasesPageListResponseResult;
|
||||
import io.swagger.model.geno.ReferenceBasesPageSingleResponse;
|
||||
import io.swagger.model.geno.ReferenceSet;
|
||||
import io.swagger.model.geno.ReferenceSetsListResponse;
|
||||
import io.swagger.model.geno.ReferenceSetsListResponseResult;
|
||||
import io.swagger.model.geno.ReferenceSetsSingleResponse;
|
||||
import io.swagger.model.geno.ReferenceSingleResponse;
|
||||
import io.swagger.model.geno.ReferencesListResponse;
|
||||
import io.swagger.model.geno.ReferencesListResponseResult;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
@RestController
|
||||
public class GenotypingReferenceWriteController extends BrAPIController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(GenotypingReferenceWriteController.class);
|
||||
|
||||
private final ReferenceSetService referenceSetService;
|
||||
private final ReferenceService referenceService;
|
||||
private final ReferenceBasesService referenceBasesService;
|
||||
private final HttpServletRequest request;
|
||||
|
||||
@Autowired
|
||||
public GenotypingReferenceWriteController(ReferenceSetService referenceSetService, ReferenceService referenceService,
|
||||
ReferenceBasesService referenceBasesService, HttpServletRequest request) {
|
||||
this.referenceSetService = referenceSetService;
|
||||
this.referenceService = referenceService;
|
||||
this.referenceBasesService = referenceBasesService;
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@RequestMapping(value = "/referencesets", produces = { "application/json" }, consumes = {
|
||||
"application/json" }, method = RequestMethod.POST)
|
||||
public ResponseEntity<ReferenceSetsListResponse> referenceSetsPost(@RequestBody ReferenceSetWriteRequest body,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException {
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
ReferenceSet data = referenceSetService.saveReferenceSet(body);
|
||||
return responseOK(new ReferenceSetsListResponse(), new ReferenceSetsListResponseResult(), List.of(data));
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@RequestMapping(value = "/referencesets/{referenceSetDbId}", produces = { "application/json" }, consumes = {
|
||||
"application/json" }, method = RequestMethod.PUT)
|
||||
public ResponseEntity<ReferenceSetsSingleResponse> referenceSetsReferenceSetDbIdPut(
|
||||
@PathVariable("referenceSetDbId") String referenceSetDbId, @RequestBody ReferenceSetWriteRequest body,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException {
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
ReferenceSet data = referenceSetService.updateReferenceSet(referenceSetDbId, body);
|
||||
return responseOK(new ReferenceSetsSingleResponse(), data);
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@RequestMapping(value = "/referencesets/{referenceSetDbId}", produces = {
|
||||
"application/json" }, method = RequestMethod.DELETE)
|
||||
public ResponseEntity<ReferenceSetsSingleResponse> referenceSetsReferenceSetDbIdDelete(
|
||||
@PathVariable("referenceSetDbId") String referenceSetDbId,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException {
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
ReferenceSet data = referenceSetService.deleteReferenceSet(referenceSetDbId);
|
||||
return responseOK(new ReferenceSetsSingleResponse(), data);
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@RequestMapping(value = "/references", produces = { "application/json" }, consumes = {
|
||||
"application/json" }, method = RequestMethod.POST)
|
||||
public ResponseEntity<ReferencesListResponse> referencesPost(@RequestBody ReferenceWriteRequest body,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException {
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
Reference data = referenceService.saveReference(body);
|
||||
return responseOK(new ReferencesListResponse(), new ReferencesListResponseResult(), List.of(data));
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@RequestMapping(value = "/references/{referenceDbId}", produces = { "application/json" }, consumes = {
|
||||
"application/json" }, method = RequestMethod.PUT)
|
||||
public ResponseEntity<ReferenceSingleResponse> referencesReferenceDbIdPut(
|
||||
@PathVariable("referenceDbId") String referenceDbId, @RequestBody ReferenceWriteRequest body,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException {
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
Reference data = referenceService.updateReference(referenceDbId, body);
|
||||
return responseOK(new ReferenceSingleResponse(), data);
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@RequestMapping(value = "/references/{referenceDbId}", produces = {
|
||||
"application/json" }, method = RequestMethod.DELETE)
|
||||
public ResponseEntity<ReferenceSingleResponse> referencesReferenceDbIdDelete(
|
||||
@PathVariable("referenceDbId") String referenceDbId,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException {
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
Reference data = referenceService.deleteReference(referenceDbId);
|
||||
return responseOK(new ReferenceSingleResponse(), data);
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@RequestMapping(value = "/referencebases", produces = { "application/json" }, method = RequestMethod.GET)
|
||||
public ResponseEntity<ReferenceBasesPageListResponse> referenceBasesGet(
|
||||
@RequestParam(value = "page", required = false) Integer page,
|
||||
@RequestParam(value = "pageSize", required = false) Integer pageSize,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException {
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_ANONYMOUS", "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
Metadata metadata = generateMetaDataTemplate(page, pageSize);
|
||||
List<ReferenceBasesPage> data = referenceBasesService.findReferenceBasesPages(metadata);
|
||||
return responseOK(new ReferenceBasesPageListResponse(), new ReferenceBasesPageListResponseResult(), data,
|
||||
metadata);
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@RequestMapping(value = "/referencebases", produces = { "application/json" }, consumes = {
|
||||
"application/json" }, method = RequestMethod.POST)
|
||||
public ResponseEntity<ReferenceBasesPageListResponse> referenceBasesPost(@RequestBody ReferenceBasesWriteRequest body,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException {
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
ReferenceBasesPage data = referenceBasesService.saveReferenceBasesPage(body);
|
||||
return responseOK(new ReferenceBasesPageListResponse(), new ReferenceBasesPageListResponseResult(), List.of(data));
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@RequestMapping(value = "/referencebases/{referenceBasesDbId}", produces = { "application/json" }, consumes = {
|
||||
"application/json" }, method = RequestMethod.PUT)
|
||||
public ResponseEntity<ReferenceBasesPageSingleResponse> referenceBasesReferenceBasesDbIdPut(
|
||||
@PathVariable("referenceBasesDbId") String referenceBasesDbId, @RequestBody ReferenceBasesWriteRequest body,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException {
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
ReferenceBasesPage data = referenceBasesService.updateReferenceBasesPage(referenceBasesDbId, body);
|
||||
return responseOK(new ReferenceBasesPageSingleResponse(), data);
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@RequestMapping(value = "/referencebases/{referenceBasesDbId}", produces = {
|
||||
"application/json" }, method = RequestMethod.DELETE)
|
||||
public ResponseEntity<ReferenceBasesPageSingleResponse> referenceBasesReferenceBasesDbIdDelete(
|
||||
@PathVariable("referenceBasesDbId") String referenceBasesDbId,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException {
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
ReferenceBasesPage data = referenceBasesService.deleteReferenceBasesPage(referenceBasesDbId);
|
||||
return responseOK(new ReferenceBasesPageSingleResponse(), data);
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,10 @@ import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
|
||||
@@ -66,5 +68,43 @@ public class BreedingMethodsApiController extends BrAPIController implements Bre
|
||||
return responseOK(new BreedingMethodSingleResponse(), data);
|
||||
}
|
||||
|
||||
}
|
||||
@CrossOrigin
|
||||
@Override
|
||||
public ResponseEntity<BreedingMethodListResponse> breedingmethodsPost(@Valid @RequestBody List<BreedingMethod> body,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization) throws BrAPIServerException {
|
||||
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
List<BreedingMethod> data = breedingMethodService.saveBreedingMethods(body);
|
||||
return responseOK(new BreedingMethodListResponse(), new BreedingMethodListResponseResult(), data);
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@Override
|
||||
public ResponseEntity<BreedingMethodSingleResponse> breedingmethodsBreedingMethodDbIdPut(
|
||||
@PathVariable("breedingMethodDbId") String breedingMethodDbId,
|
||||
@Valid @RequestBody BreedingMethod body,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization) throws BrAPIServerException {
|
||||
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
BreedingMethod data = breedingMethodService.updateBreedingMethod(breedingMethodDbId, body);
|
||||
return responseOK(new BreedingMethodSingleResponse(), data);
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@Override
|
||||
public ResponseEntity<BreedingMethodSingleResponse> breedingmethodsBreedingMethodDbIdDelete(
|
||||
@PathVariable("breedingMethodDbId") String breedingMethodDbId,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization) throws BrAPIServerException {
|
||||
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
BreedingMethod data = breedingMethodService.deleteBreedingMethod(breedingMethodDbId);
|
||||
return responseOK(new BreedingMethodSingleResponse(), data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -99,5 +99,18 @@ public class OntologiesApiController extends BrAPIController implements Ontologi
|
||||
return responseOK(new OntologySingleResponse(), data);
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@Override
|
||||
public ResponseEntity<OntologySingleResponse> ontologiesOntologyDbIdDelete(
|
||||
@PathVariable("ontologyDbId") String ontologyDbId,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization) throws BrAPIServerException {
|
||||
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
Ontology data = ontologyService.deleteOntology(ontologyDbId);
|
||||
return responseOK(new OntologySingleResponse(), data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -105,5 +105,18 @@ public class TraitsApiController extends BrAPIController implements TraitsApi {
|
||||
return responseOK(new TraitSingleResponse(), data);
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@Override
|
||||
public ResponseEntity<TraitSingleResponse> traitsTraitDbIdDelete(@PathVariable("traitDbId") String traitDbId,
|
||||
@RequestHeader(value = "Authorization", required = false) String authorization)
|
||||
throws BrAPIServerException {
|
||||
|
||||
log.debug("Request: " + request.getRequestURI());
|
||||
validateSecurityContext(request, "ROLE_USER");
|
||||
validateAcceptHeader(request);
|
||||
Trait data = traitService.deleteTrait(traitDbId);
|
||||
return responseOK(new TraitSingleResponse(), data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.brapi.test.BrAPITestServer.model.dto.geno;
|
||||
|
||||
public class ReferenceBasesWriteRequest {
|
||||
private String referenceBasesDbId;
|
||||
private String referenceDbId;
|
||||
private Integer pageNumber;
|
||||
private String bases;
|
||||
|
||||
public String getReferenceBasesDbId() {
|
||||
return referenceBasesDbId;
|
||||
}
|
||||
|
||||
public void setReferenceBasesDbId(String referenceBasesDbId) {
|
||||
this.referenceBasesDbId = referenceBasesDbId;
|
||||
}
|
||||
|
||||
public String getReferenceDbId() {
|
||||
return referenceDbId;
|
||||
}
|
||||
|
||||
public void setReferenceDbId(String referenceDbId) {
|
||||
this.referenceDbId = referenceDbId;
|
||||
}
|
||||
|
||||
public Integer getPageNumber() {
|
||||
return pageNumber;
|
||||
}
|
||||
|
||||
public void setPageNumber(Integer pageNumber) {
|
||||
this.pageNumber = pageNumber;
|
||||
}
|
||||
|
||||
public String getBases() {
|
||||
return bases;
|
||||
}
|
||||
|
||||
public void setBases(String bases) {
|
||||
this.bases = bases;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package org.brapi.test.BrAPITestServer.model.dto.geno;
|
||||
|
||||
import io.swagger.model.geno.OntologyTerm;
|
||||
|
||||
public class ReferenceSetWriteRequest {
|
||||
private String referenceSetDbId;
|
||||
private String referenceSetName;
|
||||
private String assemblyPUI;
|
||||
private String description;
|
||||
private Boolean isDerived;
|
||||
private String md5checksum;
|
||||
private String sourceURI;
|
||||
private OntologyTerm species;
|
||||
private String sourceGermplasmDbId;
|
||||
|
||||
public String getReferenceSetDbId() {
|
||||
return referenceSetDbId;
|
||||
}
|
||||
|
||||
public void setReferenceSetDbId(String referenceSetDbId) {
|
||||
this.referenceSetDbId = referenceSetDbId;
|
||||
}
|
||||
|
||||
public String getReferenceSetName() {
|
||||
return referenceSetName;
|
||||
}
|
||||
|
||||
public void setReferenceSetName(String referenceSetName) {
|
||||
this.referenceSetName = referenceSetName;
|
||||
}
|
||||
|
||||
public String getAssemblyPUI() {
|
||||
return assemblyPUI;
|
||||
}
|
||||
|
||||
public void setAssemblyPUI(String assemblyPUI) {
|
||||
this.assemblyPUI = assemblyPUI;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Boolean getIsDerived() {
|
||||
return isDerived;
|
||||
}
|
||||
|
||||
public void setIsDerived(Boolean isDerived) {
|
||||
this.isDerived = isDerived;
|
||||
}
|
||||
|
||||
public String getMd5checksum() {
|
||||
return md5checksum;
|
||||
}
|
||||
|
||||
public void setMd5checksum(String md5checksum) {
|
||||
this.md5checksum = md5checksum;
|
||||
}
|
||||
|
||||
public String getSourceURI() {
|
||||
return sourceURI;
|
||||
}
|
||||
|
||||
public void setSourceURI(String sourceURI) {
|
||||
this.sourceURI = sourceURI;
|
||||
}
|
||||
|
||||
public OntologyTerm getSpecies() {
|
||||
return species;
|
||||
}
|
||||
|
||||
public void setSpecies(OntologyTerm species) {
|
||||
this.species = species;
|
||||
}
|
||||
|
||||
public String getSourceGermplasmDbId() {
|
||||
return sourceGermplasmDbId;
|
||||
}
|
||||
|
||||
public void setSourceGermplasmDbId(String sourceGermplasmDbId) {
|
||||
this.sourceGermplasmDbId = sourceGermplasmDbId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.brapi.test.BrAPITestServer.model.dto.geno;
|
||||
|
||||
public class ReferenceWriteRequest {
|
||||
private String referenceDbId;
|
||||
private String referenceName;
|
||||
private String referenceSetDbId;
|
||||
private Integer length;
|
||||
private String md5checksum;
|
||||
private Float sourceDivergence;
|
||||
|
||||
public String getReferenceDbId() {
|
||||
return referenceDbId;
|
||||
}
|
||||
|
||||
public void setReferenceDbId(String referenceDbId) {
|
||||
this.referenceDbId = referenceDbId;
|
||||
}
|
||||
|
||||
public String getReferenceName() {
|
||||
return referenceName;
|
||||
}
|
||||
|
||||
public void setReferenceName(String referenceName) {
|
||||
this.referenceName = referenceName;
|
||||
}
|
||||
|
||||
public String getReferenceSetDbId() {
|
||||
return referenceSetDbId;
|
||||
}
|
||||
|
||||
public void setReferenceSetDbId(String referenceSetDbId) {
|
||||
this.referenceSetDbId = referenceSetDbId;
|
||||
}
|
||||
|
||||
public Integer getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public void setLength(Integer length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public String getMd5checksum() {
|
||||
return md5checksum;
|
||||
}
|
||||
|
||||
public void setMd5checksum(String md5checksum) {
|
||||
this.md5checksum = md5checksum;
|
||||
}
|
||||
|
||||
public Float getSourceDivergence() {
|
||||
return sourceDivergence;
|
||||
}
|
||||
|
||||
public void setSourceDivergence(Float sourceDivergence) {
|
||||
this.sourceDivergence = sourceDivergence;
|
||||
}
|
||||
}
|
||||
@@ -27,21 +27,29 @@ public class PersonEntity extends BrAPIPrimaryEntity {
|
||||
@Column
|
||||
private String instituteName;
|
||||
|
||||
public String getName() {
|
||||
String name = getFirstName();
|
||||
if (!getLastName().isEmpty())
|
||||
name = (name + " " + getLastName()).trim();
|
||||
private static String safeText(String value) {
|
||||
return value == null ? "" : value;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
String name = safeText(getFirstName());
|
||||
String lastName = safeText(getLastName());
|
||||
if (!lastName.isEmpty()) {
|
||||
name = (name + " " + lastName).trim();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getFullName() {
|
||||
String name = getFirstName();
|
||||
if (!getMiddleName().isEmpty())
|
||||
name = (name + " " + getMiddleName()).trim();
|
||||
if (!getLastName().isEmpty())
|
||||
name = (name + " " + getLastName()).trim();
|
||||
|
||||
String name = safeText(getFirstName());
|
||||
String middleName = safeText(getMiddleName());
|
||||
String lastName = safeText(getLastName());
|
||||
if (!middleName.isEmpty()) {
|
||||
name = (name + " " + middleName).trim();
|
||||
}
|
||||
if (!lastName.isEmpty()) {
|
||||
name = (name + " " + lastName).trim();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ public class TrialEntity extends BrAPIPrimaryEntity {
|
||||
private String documentationURL;
|
||||
@Column
|
||||
private Date endDate;
|
||||
@OneToMany(mappedBy = "trial")
|
||||
@OneToMany(mappedBy = "trial", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||
private List<PublicationEntity> publications;
|
||||
@Column
|
||||
private Date startDate;
|
||||
|
||||
@@ -32,4 +32,12 @@ public class ReferenceBasesPageEntity extends BrAPIPrimaryEntity {
|
||||
this.bases = bases;
|
||||
}
|
||||
|
||||
public Integer getPageNumber() {
|
||||
return pageNumber;
|
||||
}
|
||||
|
||||
public void setPageNumber(Integer pageNumber) {
|
||||
this.pageNumber = pageNumber;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -42,11 +42,13 @@ public class BrAPIRepositoryImpl<T extends BrAPIPrimaryEntity, ID extends Serial
|
||||
|
||||
public Optional<T> findById(ID id) {
|
||||
Optional<T> response = super.findById(id);
|
||||
if (response.isPresent()) {
|
||||
if (response.isPresent() && !hasAdminRole()) {
|
||||
String userId = getCurrentUserId();
|
||||
if (!(null == response.get().getAuthUserId()
|
||||
|| userId.equals(response.get().getAuthUserId())
|
||||
|| "anonymousUser".equals(response.get().getAuthUserId()))) {
|
||||
String authUserId = response.get().getAuthUserId();
|
||||
if (!(authUserId == null
|
||||
|| authUserId.isBlank()
|
||||
|| userId.equals(authUserId)
|
||||
|| "anonymousUser".equals(authUserId))) {
|
||||
response = Optional.empty();
|
||||
}
|
||||
}
|
||||
@@ -72,12 +74,22 @@ public class BrAPIRepositoryImpl<T extends BrAPIPrimaryEntity, ID extends Serial
|
||||
private String getCurrentUserId() {
|
||||
SecurityContext context = SecurityContextHolder.getContext();
|
||||
String userId = "";
|
||||
if (context.getAuthentication().getPrincipal() != null) {
|
||||
if (context.getAuthentication() != null && context.getAuthentication().getPrincipal() != null) {
|
||||
userId = context.getAuthentication().getPrincipal().toString();
|
||||
}
|
||||
return userId;
|
||||
}
|
||||
|
||||
private boolean hasAdminRole() {
|
||||
SecurityContext context = SecurityContextHolder.getContext();
|
||||
if (context.getAuthentication() == null) {
|
||||
return false;
|
||||
}
|
||||
return context.getAuthentication().getAuthorities().stream()
|
||||
.map(auth -> auth.getAuthority())
|
||||
.anyMatch("ROLE_ADMIN"::equals);
|
||||
}
|
||||
|
||||
private SearchQueryBuilder<T> applyUserId(SearchQueryBuilder<T> searchQuery) {
|
||||
|
||||
SecurityContext context = SecurityContextHolder.getContext();
|
||||
|
||||
@@ -7,4 +7,5 @@ import org.springframework.data.domain.Pageable;
|
||||
|
||||
public interface ReferenceBaseRepository extends BrAPIRepository<ReferenceBasesPageEntity, String> {
|
||||
public Page<ReferenceBasesPageEntity> findByReferenceIdAndPageNumber(String referenceId, int pageNumber, Pageable pageReq);
|
||||
public Page<ReferenceBasesPageEntity> findByReferenceId(String referenceId, Pageable pageReq);
|
||||
}
|
||||
|
||||
@@ -5,4 +5,6 @@ import org.brapi.test.BrAPITestServer.repository.BrAPIRepository;
|
||||
|
||||
public interface GermplasmRepository extends BrAPIRepository<GermplasmEntity, String> {
|
||||
|
||||
long countByBreedingMethod_Id(String breedingMethodId);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.brapi.test.BrAPITestServer.service.core;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.brapi.test.BrAPITestServer.exceptions.BrAPIServerDbIdNotFoundException;
|
||||
@@ -8,12 +9,14 @@ import org.brapi.test.BrAPITestServer.exceptions.BrAPIServerException;
|
||||
import org.brapi.test.BrAPITestServer.model.entity.core.CropEntity;
|
||||
import org.brapi.test.BrAPITestServer.repository.core.CropRepository;
|
||||
import org.brapi.test.BrAPITestServer.service.PagingUtility;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import io.swagger.model.Metadata;
|
||||
import io.swagger.model.core.CommonCrop;
|
||||
|
||||
@Service
|
||||
public class CropService {
|
||||
@@ -73,4 +76,58 @@ public class CropService {
|
||||
return entity;
|
||||
}
|
||||
|
||||
public CommonCrop createCrop(String commonCropName) throws BrAPIServerException {
|
||||
String name = validateCropName(commonCropName);
|
||||
if (findCropEntity(name) != null) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT, "Crop already exists: " + name);
|
||||
}
|
||||
return convertToCommonCrop(saveCropEntity(name));
|
||||
}
|
||||
|
||||
public CommonCrop updateCrop(String cropDbId, String commonCropName) throws BrAPIServerException {
|
||||
String name = validateCropName(commonCropName);
|
||||
CropEntity entity = resolveCropEntity(cropDbId);
|
||||
if (!name.equals(entity.getCropName()) && findCropEntity(name) != null) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT, "Crop already exists: " + name);
|
||||
}
|
||||
entity.setCropName(name);
|
||||
return convertToCommonCrop(cropRepository.saveAndFlush(entity));
|
||||
}
|
||||
|
||||
public CommonCrop deleteCrop(String cropDbId) throws BrAPIServerException {
|
||||
CropEntity entity = resolveCropEntity(cropDbId);
|
||||
CommonCrop deleted = convertToCommonCrop(entity);
|
||||
try {
|
||||
cropRepository.delete(entity);
|
||||
cropRepository.flush();
|
||||
} catch (DataIntegrityViolationException e) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT, "Crop is in use and cannot be deleted");
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
private CropEntity resolveCropEntity(String cropDbId) throws BrAPIServerException {
|
||||
Optional<CropEntity> byId = cropRepository.findById(cropDbId);
|
||||
if (byId.isPresent()) {
|
||||
return byId.get();
|
||||
}
|
||||
return getCropEntity(cropDbId);
|
||||
}
|
||||
|
||||
private String validateCropName(String commonCropName) throws BrAPIServerException {
|
||||
if (commonCropName == null || commonCropName.isBlank()) {
|
||||
throw new BrAPIServerException(HttpStatus.BAD_REQUEST, "commonCropName is required");
|
||||
}
|
||||
return commonCropName.trim();
|
||||
}
|
||||
|
||||
public CommonCrop convertToCommonCrop(CropEntity entity) {
|
||||
CommonCrop crop = new CommonCrop();
|
||||
if (entity != null) {
|
||||
crop.setCropDbId(entity.getCropName());
|
||||
crop.setCommonCropName(entity.getCropName());
|
||||
}
|
||||
return crop;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.brapi.test.BrAPITestServer.service.PagingUtility;
|
||||
import org.brapi.test.BrAPITestServer.service.SearchQueryBuilder;
|
||||
import org.brapi.test.BrAPITestServer.service.UpdateUtility;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -118,6 +119,18 @@ public class LocationService {
|
||||
return convertFromEntity(savedEntity);
|
||||
}
|
||||
|
||||
public Location deleteLocation(String locationDbId) throws BrAPIServerException {
|
||||
LocationEntity entity = getLocationEntity(locationDbId, HttpStatus.NOT_FOUND);
|
||||
Location deleted = convertFromEntity(entity);
|
||||
try {
|
||||
locationRepository.delete(entity);
|
||||
locationRepository.flush();
|
||||
} catch (DataIntegrityViolationException e) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT, "Location is in use and cannot be deleted");
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public List<Location> saveLocations(@Valid List<LocationNewRequest> body) throws BrAPIServerException {
|
||||
List<Location> savedLocations = new ArrayList<>();
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.brapi.test.BrAPITestServer.model.entity.core.PersonEntity;
|
||||
import org.brapi.test.BrAPITestServer.repository.core.PeopleRepository;
|
||||
import org.brapi.test.BrAPITestServer.service.PagingUtility;
|
||||
import org.brapi.test.BrAPITestServer.service.SearchQueryBuilder;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -101,6 +102,18 @@ public class PeopleService {
|
||||
return convertToPerson(savedEntity);
|
||||
}
|
||||
|
||||
public Person deletePerson(String personDbId) throws BrAPIServerException {
|
||||
PersonEntity entity = getPersonEntity(personDbId, HttpStatus.NOT_FOUND);
|
||||
Person deleted = convertToPerson(entity);
|
||||
try {
|
||||
peopleRepository.delete(entity);
|
||||
peopleRepository.flush();
|
||||
} catch (DataIntegrityViolationException e) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT, "Person is in use and cannot be deleted");
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public List<Person> savePeople(List<PersonNewRequest> body) {
|
||||
List<Person> savedPeople = new ArrayList<>();
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.brapi.test.BrAPITestServer.repository.core.SeasonRepository;
|
||||
import org.brapi.test.BrAPITestServer.service.PagingUtility;
|
||||
import org.brapi.test.BrAPITestServer.service.SearchQueryBuilder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -79,6 +80,18 @@ public class SeasonService {
|
||||
return convertFromEntity(savedEntity);
|
||||
}
|
||||
|
||||
public Season deleteSeason(String seasonDbId) throws BrAPIServerException {
|
||||
SeasonEntity entity = getSeasonEntity(seasonDbId, HttpStatus.NOT_FOUND);
|
||||
Season deleted = convertFromEntity(entity);
|
||||
try {
|
||||
seasonRepository.delete(entity);
|
||||
seasonRepository.flush();
|
||||
} catch (DataIntegrityViolationException e) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT, "Season is in use and cannot be deleted");
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public List<Season> saveSeasons(@Valid List<Season> body) {
|
||||
List<Season> savedSeasons = new ArrayList<>();
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ public class StudyService {
|
||||
Page<StudyEntity> studiesPage = studyRepository.findAllBySearch(searchQuery, pageReq);
|
||||
PagingUtility.calculateMetaData(metaData, studiesPage);
|
||||
|
||||
List<Study> studies = studiesPage.map(this::convertFromEntity).getContent();
|
||||
List<Study> studies = studiesPage.map(this::convertFromEntityForList).getContent();
|
||||
return studies;
|
||||
}
|
||||
|
||||
@@ -301,61 +301,18 @@ public class StudyService {
|
||||
}
|
||||
}
|
||||
|
||||
private Study convertFromEntity(StudyEntity entity) {
|
||||
/** List/search responses: avoid lazy-loading heavy child collections (dataLinks, variables, etc.). */
|
||||
private Study convertFromEntityForList(StudyEntity entity) {
|
||||
Study study = new Study();
|
||||
|
||||
study.setActive(entity.isActive());
|
||||
study.setAdditionalInfo(entity.getAdditionalInfoMap());
|
||||
|
||||
if (entity.getContacts() != null) {
|
||||
study.setContacts(entity.getContacts().stream().map(this.peopleService::convertToContact)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
study.setExternalReferences(entity.getExternalReferencesMap());
|
||||
study.setCulturalPractices(entity.getCulturalPractices());
|
||||
|
||||
if (entity.getDataLinks() != null) {
|
||||
study.setDataLinks(
|
||||
entity.getDataLinks().stream().map(this::convertFromEntity).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
study.setDocumentationURL(entity.getDocumentationURL());
|
||||
study.setEndDate(DateUtility.toOffsetDateTime(entity.getEndDate()));
|
||||
|
||||
if (entity.getEnvironmentParameters() != null) {
|
||||
study.setEnvironmentParameters(entity.getEnvironmentParameters().stream().map(this::convertFromEntity)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
study.setExperimentalDesign(convertFromEntity(entity.getExperimentalDesign()));
|
||||
study.setExternalReferences(entity.getExternalReferencesMap());
|
||||
study.setGrowthFacility(convertFromEntity(entity.getGrowthFacility()));
|
||||
study.setLastUpdate(convertFromEntity(entity.getLastUpdate()));
|
||||
study.setLicense(entity.getLicense());
|
||||
|
||||
if (entity.getLocation() != null) {
|
||||
study.setLocationDbId(entity.getLocation().getId());
|
||||
study.setLocationName(entity.getLocation().getLocationName());
|
||||
}
|
||||
|
||||
if (entity.getObservationLevels() != null) {
|
||||
study.setObservationLevels(
|
||||
entity.getObservationLevels().stream().map(this::convertFromEntity).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
study.setObservationUnitsDescription(entity.getObservationUnitsDescription());
|
||||
|
||||
if (entity.getObservationVariables() != null) {
|
||||
study.setObservationVariableDbIds(entity.getObservationVariables().stream().map(e -> {
|
||||
return e.getId();
|
||||
}).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
if (entity.getSeasons() != null) {
|
||||
study.setSeasons(entity.getSeasons().stream().map(e -> {
|
||||
return e.getId();
|
||||
}).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
study.setStartDate(DateUtility.toOffsetDateTime(entity.getStartDate()));
|
||||
study.setStudyCode(entity.getStudyCode());
|
||||
study.setStudyDbId(entity.getId());
|
||||
@@ -364,20 +321,27 @@ public class StudyService {
|
||||
study.setStudyPUI(entity.getStudyPUI());
|
||||
study.setStudyType(entity.getStudyType());
|
||||
|
||||
if (entity.getContacts() != null) {
|
||||
study.setContacts(entity.getContacts().stream().map(this.peopleService::convertToContact)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
if (entity.getSeasons() != null) {
|
||||
study.setSeasons(entity.getSeasons().stream().map(SeasonEntity::getId).collect(Collectors.toList()));
|
||||
}
|
||||
if (entity.getLocation() != null) {
|
||||
study.setLocationDbId(entity.getLocation().getId());
|
||||
study.setLocationName(entity.getLocation().getLocationName());
|
||||
}
|
||||
if (entity.getTrial() != null) {
|
||||
study.setTrialDbId(entity.getTrial().getId());
|
||||
study.setTrialName(entity.getTrial().getTrialName());
|
||||
if (entity.getTrial().getProgram() != null) {
|
||||
if (entity.getTrial().getProgram().getCrop() != null) {
|
||||
study.setCommonCropName(entity.getTrial().getProgram().getCrop().getCropName());
|
||||
}
|
||||
if (entity.getTrial().getProgram() != null && entity.getTrial().getProgram().getCrop() != null) {
|
||||
study.setCommonCropName(entity.getTrial().getProgram().getCrop().getCropName());
|
||||
}
|
||||
}
|
||||
if (entity.getProgram() != null) {
|
||||
if (entity.getProgram().getCrop() != null) {
|
||||
study.setCommonCropName(entity.getProgram().getCrop().getCropName());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (entity.getProgram() != null && entity.getProgram().getCrop() != null) {
|
||||
study.setCommonCropName(entity.getProgram().getCrop().getCropName());
|
||||
}
|
||||
if (entity.getCrop() != null) {
|
||||
study.setCommonCropName(entity.getCrop().getCropName());
|
||||
}
|
||||
@@ -385,6 +349,37 @@ public class StudyService {
|
||||
return study;
|
||||
}
|
||||
|
||||
private Study convertFromEntity(StudyEntity entity) {
|
||||
Study study = convertFromEntityForList(entity);
|
||||
|
||||
if (entity.getDataLinks() != null) {
|
||||
study.setDataLinks(
|
||||
entity.getDataLinks().stream().map(this::convertFromEntity).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
if (entity.getEnvironmentParameters() != null) {
|
||||
study.setEnvironmentParameters(entity.getEnvironmentParameters().stream().map(this::convertFromEntity)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
study.setExperimentalDesign(convertFromEntity(entity.getExperimentalDesign()));
|
||||
study.setGrowthFacility(convertFromEntity(entity.getGrowthFacility()));
|
||||
study.setLastUpdate(convertFromEntity(entity.getLastUpdate()));
|
||||
|
||||
if (entity.getObservationLevels() != null) {
|
||||
study.setObservationLevels(
|
||||
entity.getObservationLevels().stream().map(this::convertFromEntity).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
if (entity.getObservationVariables() != null) {
|
||||
study.setObservationVariableDbIds(entity.getObservationVariables().stream().map(e -> {
|
||||
return e.getId();
|
||||
}).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
return study;
|
||||
}
|
||||
|
||||
private ObservationUnitHierarchyLevel convertFromEntity(ObservationLevelEntity entity) {
|
||||
ObservationUnitHierarchyLevel level = null;
|
||||
if (entity != null) {
|
||||
|
||||
@@ -240,13 +240,17 @@ public class TrialService {
|
||||
if (body.getExternalReferences() != null)
|
||||
entity.setExternalReferences(body.getExternalReferences());
|
||||
if (body.getPublications() != null) {
|
||||
if (entity.getPublications() != null) {
|
||||
for (PublicationEntity pub : entity.getPublications()) {
|
||||
pub.setTrial(null);
|
||||
if (entity.getPublications() == null) {
|
||||
entity.setPublications(new ArrayList<>());
|
||||
}
|
||||
entity.getPublications().clear();
|
||||
for (TrialNewRequestPublications pub : body.getPublications()) {
|
||||
PublicationEntity publicationEntity = convertToEntity(pub);
|
||||
if (publicationEntity != null) {
|
||||
publicationEntity.setTrial(entity);
|
||||
entity.getPublications().add(publicationEntity);
|
||||
}
|
||||
}
|
||||
entity.setPublications(
|
||||
body.getPublications().stream().map(this::convertToEntity).collect(Collectors.toList()));
|
||||
}
|
||||
if (body.getStartDate() != null)
|
||||
entity.setStartDate(DateUtility.toDate(body.getStartDate()));
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
package org.brapi.test.BrAPITestServer.service.geno;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.brapi.test.BrAPITestServer.exceptions.BrAPIServerDbIdNotFoundException;
|
||||
import org.brapi.test.BrAPITestServer.exceptions.BrAPIServerException;
|
||||
import org.brapi.test.BrAPITestServer.model.dto.geno.ReferenceBasesWriteRequest;
|
||||
import org.brapi.test.BrAPITestServer.model.entity.geno.ReferenceBasesPageEntity;
|
||||
import org.brapi.test.BrAPITestServer.model.entity.geno.ReferenceEntity;
|
||||
import org.brapi.test.BrAPITestServer.repository.geno.ReferenceBaseRepository;
|
||||
import org.brapi.test.BrAPITestServer.service.PagingUtility;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import io.swagger.model.Metadata;
|
||||
import io.swagger.model.geno.ReferenceBasesPage;
|
||||
|
||||
@Service
|
||||
public class ReferenceBasesService {
|
||||
private static final Pattern BASES_PATTERN = Pattern.compile("^[ACGTNacgtn*.-]*$");
|
||||
|
||||
private final ReferenceBaseRepository referenceBaseRepository;
|
||||
private final ReferenceService referenceService;
|
||||
|
||||
public ReferenceBasesService(ReferenceBaseRepository referenceBaseRepository, ReferenceService referenceService) {
|
||||
this.referenceBaseRepository = referenceBaseRepository;
|
||||
this.referenceService = referenceService;
|
||||
}
|
||||
|
||||
public List<ReferenceBasesPage> findReferenceBasesPages(Metadata metadata) {
|
||||
Pageable pageReq = PagingUtility.getPageRequest(metadata);
|
||||
Page<ReferenceBasesPageEntity> page = referenceBaseRepository.findAll(pageReq);
|
||||
List<ReferenceBasesPage> data = page.getContent().stream().map(this::convertFromEntity).collect(Collectors.toList());
|
||||
PagingUtility.calculateMetaData(metadata, page);
|
||||
return data;
|
||||
}
|
||||
|
||||
public ReferenceBasesPage getReferenceBasesPage(String referenceBasesDbId) throws BrAPIServerException {
|
||||
return convertFromEntity(getReferenceBasesPageEntity(referenceBasesDbId, HttpStatus.NOT_FOUND));
|
||||
}
|
||||
|
||||
public ReferenceBasesPage saveReferenceBasesPage(ReferenceBasesWriteRequest request) throws BrAPIServerException {
|
||||
validateRequest(request, true);
|
||||
if (request.getReferenceBasesDbId() != null
|
||||
&& referenceBaseRepository.findById(request.getReferenceBasesDbId()).isPresent()) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT,
|
||||
"ReferenceBases already exists: " + request.getReferenceBasesDbId());
|
||||
}
|
||||
assertUniquePageNumber(null, request.getReferenceDbId(), request.getPageNumber());
|
||||
ReferenceBasesPageEntity entity = new ReferenceBasesPageEntity();
|
||||
if (request.getReferenceBasesDbId() != null && !request.getReferenceBasesDbId().isBlank()) {
|
||||
entity.setId(request.getReferenceBasesDbId().trim());
|
||||
}
|
||||
updateEntity(entity, request);
|
||||
return convertFromEntity(referenceBaseRepository.save(entity));
|
||||
}
|
||||
|
||||
public ReferenceBasesPage updateReferenceBasesPage(String referenceBasesDbId, ReferenceBasesWriteRequest request)
|
||||
throws BrAPIServerException {
|
||||
validateRequest(request, false);
|
||||
ReferenceBasesPageEntity entity = getReferenceBasesPageEntity(referenceBasesDbId, HttpStatus.NOT_FOUND);
|
||||
assertUniquePageNumber(referenceBasesDbId, request.getReferenceDbId(), request.getPageNumber());
|
||||
updateEntity(entity, request);
|
||||
return convertFromEntity(referenceBaseRepository.save(entity));
|
||||
}
|
||||
|
||||
public ReferenceBasesPage deleteReferenceBasesPage(String referenceBasesDbId) throws BrAPIServerException {
|
||||
ReferenceBasesPageEntity entity = getReferenceBasesPageEntity(referenceBasesDbId, HttpStatus.NOT_FOUND);
|
||||
ReferenceBasesPage deleted = convertFromEntity(entity);
|
||||
try {
|
||||
referenceBaseRepository.delete(entity);
|
||||
referenceBaseRepository.flush();
|
||||
} catch (DataIntegrityViolationException e) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT, "ReferenceBases cannot be deleted");
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
private ReferenceBasesPageEntity getReferenceBasesPageEntity(String referenceBasesDbId, HttpStatus errorStatus)
|
||||
throws BrAPIServerException {
|
||||
Optional<ReferenceBasesPageEntity> entityOpt = referenceBaseRepository.findById(referenceBasesDbId);
|
||||
if (entityOpt.isPresent()) {
|
||||
return entityOpt.get();
|
||||
}
|
||||
throw new BrAPIServerDbIdNotFoundException("referenceBases", referenceBasesDbId, errorStatus);
|
||||
}
|
||||
|
||||
private void validateRequest(ReferenceBasesWriteRequest request, boolean creating) throws BrAPIServerException {
|
||||
if (request.getReferenceDbId() == null || request.getReferenceDbId().isBlank()) {
|
||||
throw new BrAPIServerException(HttpStatus.BAD_REQUEST, "referenceDbId is required");
|
||||
}
|
||||
if (request.getPageNumber() == null) {
|
||||
throw new BrAPIServerException(HttpStatus.BAD_REQUEST, "pageNumber is required");
|
||||
}
|
||||
if (request.getPageNumber() < 0) {
|
||||
throw new BrAPIServerException(HttpStatus.BAD_REQUEST, "pageNumber must be non-negative");
|
||||
}
|
||||
if (creating && (request.getBases() == null || request.getBases().isBlank())) {
|
||||
throw new BrAPIServerException(HttpStatus.BAD_REQUEST, "bases is required");
|
||||
}
|
||||
if (request.getBases() != null) {
|
||||
if (request.getBases().length() > 2048) {
|
||||
throw new BrAPIServerException(HttpStatus.BAD_REQUEST, "bases cannot exceed 2048 characters");
|
||||
}
|
||||
if (!BASES_PATTERN.matcher(request.getBases()).matches()) {
|
||||
throw new BrAPIServerException(HttpStatus.BAD_REQUEST, "bases contains invalid characters");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void assertUniquePageNumber(String currentId, String referenceDbId, Integer pageNumber)
|
||||
throws BrAPIServerException {
|
||||
Pageable pageReq = PageRequest.of(0, 1000, Sort.by("pageNumber"));
|
||||
Page<ReferenceBasesPageEntity> page = referenceBaseRepository.findByReferenceId(referenceDbId, pageReq);
|
||||
for (ReferenceBasesPageEntity existing : page.getContent()) {
|
||||
if (pageNumber != null && pageNumber.equals(existing.getPageNumber())
|
||||
&& (currentId == null || !currentId.equals(existing.getId()))) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT,
|
||||
"pageNumber already exists for this reference: " + pageNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateEntity(ReferenceBasesPageEntity entity, ReferenceBasesWriteRequest request)
|
||||
throws BrAPIServerException {
|
||||
ReferenceEntity reference = referenceService.getReferenceEntity(request.getReferenceDbId());
|
||||
entity.setReference(reference);
|
||||
entity.setPageNumber(request.getPageNumber());
|
||||
if (request.getBases() != null) {
|
||||
entity.setBases(request.getBases().trim().toUpperCase());
|
||||
}
|
||||
}
|
||||
|
||||
private ReferenceBasesPage convertFromEntity(ReferenceBasesPageEntity entity) {
|
||||
ReferenceBasesPage page = new ReferenceBasesPage();
|
||||
page.setReferenceBasesDbId(entity.getId());
|
||||
page.setPageNumber(entity.getPageNumber());
|
||||
page.setBases(entity.getBases());
|
||||
if (entity.getReference() != null) {
|
||||
page.setReferenceDbId(entity.getReference().getId());
|
||||
page.setReferenceName(entity.getReference().getReferenceName());
|
||||
}
|
||||
return page;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.brapi.test.BrAPITestServer.service.geno;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -9,6 +10,7 @@ import jakarta.validation.Valid;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.brapi.test.BrAPITestServer.exceptions.BrAPIServerDbIdNotFoundException;
|
||||
import org.brapi.test.BrAPITestServer.exceptions.BrAPIServerException;
|
||||
import org.brapi.test.BrAPITestServer.model.dto.geno.ReferenceWriteRequest;
|
||||
import org.brapi.test.BrAPITestServer.model.entity.geno.ReferenceBasesPageEntity;
|
||||
import org.brapi.test.BrAPITestServer.model.entity.geno.ReferenceEntity;
|
||||
import org.brapi.test.BrAPITestServer.model.entity.geno.ReferenceSetEntity;
|
||||
@@ -17,6 +19,7 @@ import org.brapi.test.BrAPITestServer.repository.geno.ReferenceRepository;
|
||||
import org.brapi.test.BrAPITestServer.service.PagingUtility;
|
||||
import org.brapi.test.BrAPITestServer.service.SearchQueryBuilder;
|
||||
import org.brapi.test.BrAPITestServer.service.UpdateUtility;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -38,10 +41,13 @@ public class ReferenceService {
|
||||
|
||||
private final ReferenceRepository referenceRepository;
|
||||
private final ReferenceBaseRepository referenceBaseRepository;
|
||||
private final ReferenceSetService referenceSetService;
|
||||
|
||||
public ReferenceService(ReferenceRepository referenceRepository, ReferenceBaseRepository referenceBaseRepository) {
|
||||
public ReferenceService(ReferenceRepository referenceRepository, ReferenceBaseRepository referenceBaseRepository,
|
||||
ReferenceSetService referenceSetService) {
|
||||
this.referenceRepository = referenceRepository;
|
||||
this.referenceBaseRepository = referenceBaseRepository;
|
||||
this.referenceSetService = referenceSetService;
|
||||
}
|
||||
|
||||
public List<Reference> findReferences(String referenceDbId, String referenceSetDbId, String accession,
|
||||
@@ -121,7 +127,7 @@ public class ReferenceService {
|
||||
if (entity.getReferenceSet() != null) {
|
||||
ReferenceSetEntity refSetEntity = entity.getReferenceSet();
|
||||
ref.setReferenceSetDbId(refSetEntity.getId());
|
||||
ref.setReferenceName(refSetEntity.getReferenceSetName());
|
||||
ref.setReferenceSetName(refSetEntity.getReferenceSetName());
|
||||
ref.setIsDerived(refSetEntity.getIsDerived());
|
||||
ref.setSourceURI(entity.getReferenceSet().getSourceURI());
|
||||
OntologyTerm term = new OntologyTerm().term(entity.getReferenceSet().getSpeciesOntologyTerm())
|
||||
@@ -226,4 +232,56 @@ public class ReferenceService {
|
||||
return bases;
|
||||
}
|
||||
|
||||
public Reference saveReference(ReferenceWriteRequest request) throws BrAPIServerException {
|
||||
if (request.getReferenceName() == null || request.getReferenceName().isBlank()) {
|
||||
throw new BrAPIServerException(HttpStatus.BAD_REQUEST, "referenceName is required");
|
||||
}
|
||||
if (request.getReferenceSetDbId() == null || request.getReferenceSetDbId().isBlank()) {
|
||||
throw new BrAPIServerException(HttpStatus.BAD_REQUEST, "referenceSetDbId is required");
|
||||
}
|
||||
if (request.getReferenceDbId() != null && referenceRepository.findById(request.getReferenceDbId()).isPresent()) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT, "Reference already exists: " + request.getReferenceDbId());
|
||||
}
|
||||
ReferenceEntity entity = new ReferenceEntity();
|
||||
if (request.getReferenceDbId() != null && !request.getReferenceDbId().isBlank()) {
|
||||
entity.setId(request.getReferenceDbId().trim());
|
||||
}
|
||||
updateEntity(entity, request);
|
||||
return convertFromEntity(referenceRepository.save(entity));
|
||||
}
|
||||
|
||||
public Reference updateReference(String referenceDbId, ReferenceWriteRequest request) throws BrAPIServerException {
|
||||
ReferenceEntity entity = getReferenceEntity(referenceDbId, HttpStatus.NOT_FOUND);
|
||||
updateEntity(entity, request);
|
||||
return convertFromEntity(referenceRepository.save(entity));
|
||||
}
|
||||
|
||||
public Reference deleteReference(String referenceDbId) throws BrAPIServerException {
|
||||
ReferenceEntity entity = getReferenceEntity(referenceDbId, HttpStatus.NOT_FOUND);
|
||||
Pageable pageReq = PageRequest.of(0, 1);
|
||||
Page<ReferenceBasesPageEntity> basesPage = referenceBaseRepository.findByReferenceId(referenceDbId, pageReq);
|
||||
if (basesPage.getTotalElements() > 0) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT, "Reference is referenced by ReferenceBases records");
|
||||
}
|
||||
Reference deleted = convertFromEntity(entity);
|
||||
try {
|
||||
referenceRepository.delete(entity);
|
||||
referenceRepository.flush();
|
||||
} catch (DataIntegrityViolationException e) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT, "Reference is in use and cannot be deleted");
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
private void updateEntity(ReferenceEntity entity, ReferenceWriteRequest request) throws BrAPIServerException {
|
||||
entity.setReferenceName(request.getReferenceName().trim());
|
||||
ReferenceSetEntity referenceSet = referenceSetService.getReferenceSetEntity(request.getReferenceSetDbId());
|
||||
entity.setReferenceSet(referenceSet);
|
||||
entity.setLength(request.getLength());
|
||||
entity.setMd5checksum(request.getMd5checksum());
|
||||
if (request.getSourceDivergence() != null) {
|
||||
entity.setSourceDivergence(BigDecimal.valueOf(request.getSourceDivergence()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,12 +6,23 @@ import java.util.Optional;
|
||||
|
||||
import org.brapi.test.BrAPITestServer.exceptions.BrAPIServerDbIdNotFoundException;
|
||||
import org.brapi.test.BrAPITestServer.exceptions.BrAPIServerException;
|
||||
import org.brapi.test.BrAPITestServer.model.dto.geno.ReferenceSetWriteRequest;
|
||||
import org.brapi.test.BrAPITestServer.model.entity.germ.GermplasmEntity;
|
||||
import org.brapi.test.BrAPITestServer.model.entity.geno.ReferenceEntity;
|
||||
import org.brapi.test.BrAPITestServer.model.entity.geno.ReferenceSetEntity;
|
||||
import org.brapi.test.BrAPITestServer.model.entity.geno.VariantEntity;
|
||||
import org.brapi.test.BrAPITestServer.model.entity.geno.VariantSetEntity;
|
||||
import org.brapi.test.BrAPITestServer.repository.geno.ReferenceRepository;
|
||||
import org.brapi.test.BrAPITestServer.repository.geno.ReferenceSetRepository;
|
||||
import org.brapi.test.BrAPITestServer.repository.geno.VariantRepository;
|
||||
import org.brapi.test.BrAPITestServer.repository.geno.VariantSetRepository;
|
||||
import org.brapi.test.BrAPITestServer.service.germ.GermplasmService;
|
||||
import org.brapi.test.BrAPITestServer.service.PagingUtility;
|
||||
import org.brapi.test.BrAPITestServer.service.SearchQueryBuilder;
|
||||
import org.brapi.test.BrAPITestServer.service.UpdateUtility;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -26,9 +37,19 @@ import io.swagger.model.geno.ReferenceSourceGermplasm;
|
||||
public class ReferenceSetService {
|
||||
|
||||
private final ReferenceSetRepository referenceSetRepository;
|
||||
private final ReferenceRepository referenceRepository;
|
||||
private final VariantSetRepository variantSetRepository;
|
||||
private final VariantRepository variantRepository;
|
||||
private final GermplasmService germplasmService;
|
||||
|
||||
public ReferenceSetService(ReferenceSetRepository referenceSetRepository) {
|
||||
public ReferenceSetService(ReferenceSetRepository referenceSetRepository, ReferenceRepository referenceRepository,
|
||||
VariantSetRepository variantSetRepository, VariantRepository variantRepository,
|
||||
GermplasmService germplasmService) {
|
||||
this.referenceSetRepository = referenceSetRepository;
|
||||
this.referenceRepository = referenceRepository;
|
||||
this.variantSetRepository = variantSetRepository;
|
||||
this.variantRepository = variantRepository;
|
||||
this.germplasmService = germplasmService;
|
||||
}
|
||||
|
||||
public List<ReferenceSet> findReferenceSets(String referenceSetDbId, String accession, String assemblyPUI,
|
||||
@@ -124,4 +145,77 @@ public class ReferenceSetService {
|
||||
return refSet;
|
||||
}
|
||||
|
||||
public ReferenceSet saveReferenceSet(ReferenceSetWriteRequest request) throws BrAPIServerException {
|
||||
if (request.getReferenceSetName() == null || request.getReferenceSetName().isBlank()) {
|
||||
throw new BrAPIServerException(HttpStatus.BAD_REQUEST, "referenceSetName is required");
|
||||
}
|
||||
if (request.getReferenceSetDbId() != null && referenceSetRepository.findById(request.getReferenceSetDbId()).isPresent()) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT, "ReferenceSet already exists: " + request.getReferenceSetDbId());
|
||||
}
|
||||
ReferenceSetEntity entity = new ReferenceSetEntity();
|
||||
if (request.getReferenceSetDbId() != null && !request.getReferenceSetDbId().isBlank()) {
|
||||
entity.setId(request.getReferenceSetDbId().trim());
|
||||
}
|
||||
updateEntity(entity, request);
|
||||
return convertFromEntity(referenceSetRepository.save(entity));
|
||||
}
|
||||
|
||||
public ReferenceSet updateReferenceSet(String referenceSetDbId, ReferenceSetWriteRequest request)
|
||||
throws BrAPIServerException {
|
||||
ReferenceSetEntity entity = getReferenceSetEntity(referenceSetDbId, HttpStatus.NOT_FOUND);
|
||||
updateEntity(entity, request);
|
||||
return convertFromEntity(referenceSetRepository.save(entity));
|
||||
}
|
||||
|
||||
public ReferenceSet deleteReferenceSet(String referenceSetDbId) throws BrAPIServerException {
|
||||
ReferenceSetEntity entity = getReferenceSetEntity(referenceSetDbId, HttpStatus.NOT_FOUND);
|
||||
assertNoReferenceSetDependencies(referenceSetDbId);
|
||||
ReferenceSet deleted = convertFromEntity(entity);
|
||||
try {
|
||||
referenceSetRepository.delete(entity);
|
||||
referenceSetRepository.flush();
|
||||
} catch (DataIntegrityViolationException e) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT, "ReferenceSet is in use and cannot be deleted");
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
private void assertNoReferenceSetDependencies(String referenceSetDbId) throws BrAPIServerException {
|
||||
Pageable pageReq = PageRequest.of(0, 1);
|
||||
SearchQueryBuilder<ReferenceEntity> referenceQuery = new SearchQueryBuilder<ReferenceEntity>(ReferenceEntity.class)
|
||||
.appendSingle(referenceSetDbId, "referenceSet.id");
|
||||
if (referenceRepository.findAllBySearch(referenceQuery, pageReq).getTotalElements() > 0) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT, "ReferenceSet is referenced by Reference records");
|
||||
}
|
||||
SearchQueryBuilder<VariantSetEntity> variantSetQuery = new SearchQueryBuilder<VariantSetEntity>(VariantSetEntity.class)
|
||||
.appendSingle(referenceSetDbId, "referenceSet.id");
|
||||
if (variantSetRepository.findAllBySearch(variantSetQuery, pageReq).getTotalElements() > 0) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT, "ReferenceSet is referenced by VariantSet records");
|
||||
}
|
||||
SearchQueryBuilder<VariantEntity> variantQuery = new SearchQueryBuilder<VariantEntity>(VariantEntity.class)
|
||||
.appendSingle(referenceSetDbId, "referenceSet.id");
|
||||
if (variantRepository.findAllBySearch(variantQuery, pageReq).getTotalElements() > 0) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT, "ReferenceSet is referenced by Variant records");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateEntity(ReferenceSetEntity entity, ReferenceSetWriteRequest request) throws BrAPIServerException {
|
||||
entity.setReferenceSetName(request.getReferenceSetName().trim());
|
||||
entity.setAssemblyPUI(request.getAssemblyPUI());
|
||||
entity.setDescription(request.getDescription());
|
||||
entity.setIsDerived(request.getIsDerived());
|
||||
entity.setMd5checksum(request.getMd5checksum());
|
||||
entity.setSourceURI(request.getSourceURI());
|
||||
if (request.getSpecies() != null) {
|
||||
entity.setSpeciesOntologyTerm(request.getSpecies().getTerm());
|
||||
entity.setSpeciesOntologyTermURI(request.getSpecies().getTermURI());
|
||||
}
|
||||
if (request.getSourceGermplasmDbId() != null && !request.getSourceGermplasmDbId().isBlank()) {
|
||||
GermplasmEntity germplasm = germplasmService.getGermplasmEntity(request.getSourceGermplasmDbId());
|
||||
entity.setSourceGermplasm(germplasm);
|
||||
} else if (request.getSourceGermplasmDbId() != null) {
|
||||
entity.setSourceGermplasm(null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
package org.brapi.test.BrAPITestServer.service.germ;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import org.brapi.test.BrAPITestServer.exceptions.BrAPIServerDbIdNotFoundException;
|
||||
import org.brapi.test.BrAPITestServer.exceptions.BrAPIServerException;
|
||||
import org.brapi.test.BrAPITestServer.model.entity.germ.BreedingMethodEntity;
|
||||
import org.brapi.test.BrAPITestServer.repository.germ.BreedingMethodRepository;
|
||||
import org.brapi.test.BrAPITestServer.repository.germ.GermplasmRepository;
|
||||
import org.brapi.test.BrAPITestServer.service.PagingUtility;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -20,9 +24,12 @@ import io.swagger.model.germ.BreedingMethod;
|
||||
public class BreedingMethodService {
|
||||
|
||||
private final BreedingMethodRepository breedingMethodRepository;
|
||||
private final GermplasmRepository germplasmRepository;
|
||||
|
||||
public BreedingMethodService(BreedingMethodRepository breedingMethodRepository) {
|
||||
public BreedingMethodService(BreedingMethodRepository breedingMethodRepository,
|
||||
GermplasmRepository germplasmRepository) {
|
||||
this.breedingMethodRepository = breedingMethodRepository;
|
||||
this.germplasmRepository = germplasmRepository;
|
||||
}
|
||||
|
||||
public List<BreedingMethod> findBreedingMethods(Metadata metadata) {
|
||||
@@ -52,6 +59,50 @@ public class BreedingMethodService {
|
||||
return breedingMethodEntity;
|
||||
}
|
||||
|
||||
public List<BreedingMethod> saveBreedingMethods(@Valid List<BreedingMethod> body) throws BrAPIServerException {
|
||||
List<BreedingMethod> savedMethods = new ArrayList<>();
|
||||
|
||||
for (BreedingMethod method : body) {
|
||||
validateBreedingMethodName(method.getBreedingMethodName());
|
||||
BreedingMethodEntity entity = new BreedingMethodEntity();
|
||||
updateEntity(entity, method);
|
||||
BreedingMethodEntity savedEntity = breedingMethodRepository.save(entity);
|
||||
savedMethods.add(convertFromEntity(savedEntity));
|
||||
}
|
||||
|
||||
return savedMethods;
|
||||
}
|
||||
|
||||
public BreedingMethod updateBreedingMethod(String breedingMethodDbId, BreedingMethod body) throws BrAPIServerException {
|
||||
BreedingMethodEntity entity = getBreedingMethodEntity(breedingMethodDbId, HttpStatus.NOT_FOUND);
|
||||
updateEntity(entity, body);
|
||||
BreedingMethodEntity savedEntity = breedingMethodRepository.save(entity);
|
||||
return convertFromEntity(savedEntity);
|
||||
}
|
||||
|
||||
public BreedingMethod deleteBreedingMethod(String breedingMethodDbId) throws BrAPIServerException {
|
||||
BreedingMethodEntity entity = getBreedingMethodEntity(breedingMethodDbId, HttpStatus.NOT_FOUND);
|
||||
long usageCount = germplasmRepository.countByBreedingMethod_Id(breedingMethodDbId);
|
||||
if (usageCount > 0) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT,
|
||||
"Breeding method is in use by germplasm and cannot be deleted");
|
||||
}
|
||||
BreedingMethod deleted = convertFromEntity(entity);
|
||||
breedingMethodRepository.delete(entity);
|
||||
breedingMethodRepository.flush();
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public long countGermplasmUsage(String breedingMethodDbId) {
|
||||
return germplasmRepository.countByBreedingMethod_Id(breedingMethodDbId);
|
||||
}
|
||||
|
||||
private void validateBreedingMethodName(String breedingMethodName) throws BrAPIServerException {
|
||||
if (breedingMethodName == null || breedingMethodName.trim().isEmpty()) {
|
||||
throw new BrAPIServerException(HttpStatus.BAD_REQUEST, "breedingMethodName is required");
|
||||
}
|
||||
}
|
||||
|
||||
private BreedingMethod convertFromEntity(BreedingMethodEntity entity) {
|
||||
BreedingMethod method = new BreedingMethod();
|
||||
method.setAbbreviation(entity.getAbbreviation());
|
||||
@@ -61,4 +112,17 @@ public class BreedingMethodService {
|
||||
return method;
|
||||
}
|
||||
|
||||
private void updateEntity(BreedingMethodEntity entity, BreedingMethod request) throws BrAPIServerException {
|
||||
if (request.getBreedingMethodName() != null) {
|
||||
validateBreedingMethodName(request.getBreedingMethodName());
|
||||
entity.setName(request.getBreedingMethodName().trim());
|
||||
}
|
||||
if (request.getAbbreviation() != null) {
|
||||
entity.setAbbreviation(request.getAbbreviation().trim().isEmpty() ? null : request.getAbbreviation().trim());
|
||||
}
|
||||
if (request.getDescription() != null) {
|
||||
entity.setDescription(request.getDescription().trim().isEmpty() ? null : request.getDescription().trim());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.brapi.test.BrAPITestServer.repository.pheno.OntologyRepository;
|
||||
import org.brapi.test.BrAPITestServer.service.PagingUtility;
|
||||
import org.brapi.test.BrAPITestServer.service.UpdateUtility;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -76,6 +77,18 @@ public class OntologyService {
|
||||
return convertFromEntity(savedEntity);
|
||||
}
|
||||
|
||||
public Ontology deleteOntology(String ontologyDbId) throws BrAPIServerException {
|
||||
OntologyEntity entity = getOntologyEntity(ontologyDbId, HttpStatus.NOT_FOUND);
|
||||
Ontology deleted = convertFromEntity(entity);
|
||||
try {
|
||||
ontologyRepository.delete(entity);
|
||||
ontologyRepository.flush();
|
||||
} catch (DataIntegrityViolationException e) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT, "Ontology is in use and cannot be deleted");
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public Ontology convertFromEntity(OntologyEntity entity) {
|
||||
Ontology ontology = new Ontology();
|
||||
UpdateUtility.convertFromEntity(entity, ontology);
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.brapi.test.BrAPITestServer.service.PagingUtility;
|
||||
import org.brapi.test.BrAPITestServer.service.SearchQueryBuilder;
|
||||
import org.brapi.test.BrAPITestServer.service.UpdateUtility;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -59,6 +60,18 @@ public class TraitService {
|
||||
return convertFromEntity(savedEntity);
|
||||
}
|
||||
|
||||
public Trait deleteTrait(String traitDbId) throws BrAPIServerException {
|
||||
TraitEntity entity = getTraitEntity(traitDbId, HttpStatus.NOT_FOUND);
|
||||
Trait deleted = convertFromEntity(entity);
|
||||
try {
|
||||
traitRepository.delete(entity);
|
||||
traitRepository.flush();
|
||||
} catch (DataIntegrityViolationException e) {
|
||||
throw new BrAPIServerException(HttpStatus.CONFLICT, "Trait is in use and cannot be deleted");
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public List<Trait> saveTraits(@Valid List<TraitBaseClass> body) throws BrAPIServerException {
|
||||
List<Trait> savedTraits = new ArrayList<>();
|
||||
for (TraitBaseClass request : body) {
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.brapi.test.BrAPITestServer.system.config;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "jwt")
|
||||
public class JwtProperties {
|
||||
|
||||
private String secretKey = "change-me-in-production";
|
||||
private int accessTokenExpireMinutes = 1440;
|
||||
|
||||
public String getSecretKey() {
|
||||
return secretKey;
|
||||
}
|
||||
|
||||
public void setSecretKey(String secretKey) {
|
||||
this.secretKey = secretKey;
|
||||
}
|
||||
|
||||
public int getAccessTokenExpireMinutes() {
|
||||
return accessTokenExpireMinutes;
|
||||
}
|
||||
|
||||
public void setAccessTokenExpireMinutes(int accessTokenExpireMinutes) {
|
||||
this.accessTokenExpireMinutes = accessTokenExpireMinutes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.brapi.test.BrAPITestServer.system.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
|
||||
@Configuration
|
||||
@EnableJpaRepositories(basePackages = "org.brapi.test.BrAPITestServer.system.repository")
|
||||
public class SystemJpaConfig {
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.brapi.test.BrAPITestServer.system.controller;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import org.brapi.test.BrAPITestServer.system.dto.LoginRequest;
|
||||
import org.brapi.test.BrAPITestServer.system.dto.RegisterRequest;
|
||||
import org.brapi.test.BrAPITestServer.system.dto.TokenResponse;
|
||||
import org.brapi.test.BrAPITestServer.system.service.AuthService;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
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.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/auth")
|
||||
@CrossOrigin
|
||||
public class AuthController {
|
||||
|
||||
private final AuthService authService;
|
||||
|
||||
public AuthController(AuthService authService) {
|
||||
this.authService = authService;
|
||||
}
|
||||
|
||||
@PostMapping("/register")
|
||||
public ResponseEntity<TokenResponse> register(@Valid @RequestBody RegisterRequest request) {
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(authService.register(request));
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
public ResponseEntity<TokenResponse> login(@Valid @RequestBody LoginRequest request) {
|
||||
return ResponseEntity.ok(authService.login(request));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.brapi.test.BrAPITestServer.system.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class AuthErrorResponse {
|
||||
|
||||
private String message;
|
||||
private Object detail;
|
||||
|
||||
public AuthErrorResponse() {
|
||||
}
|
||||
|
||||
public AuthErrorResponse(String message) {
|
||||
this.message = message;
|
||||
this.detail = message;
|
||||
}
|
||||
|
||||
public AuthErrorResponse(String message, Object detail) {
|
||||
this.message = message;
|
||||
this.detail = detail;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public Object getDetail() {
|
||||
return detail;
|
||||
}
|
||||
|
||||
public void setDetail(Object detail) {
|
||||
this.detail = detail;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.brapi.test.BrAPITestServer.system.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public class LoginRequest {
|
||||
|
||||
@NotBlank
|
||||
@Size(min = 1, max = 100)
|
||||
private String account;
|
||||
|
||||
@NotBlank
|
||||
@Size(min = 1, max = 128)
|
||||
private String password;
|
||||
|
||||
public String getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public void setAccount(String account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package org.brapi.test.BrAPITestServer.system.dto;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public class RegisterRequest {
|
||||
|
||||
@NotBlank
|
||||
@Size(min = 3, max = 100)
|
||||
private String account;
|
||||
|
||||
@NotBlank
|
||||
@Size(min = 6, max = 128)
|
||||
private String password;
|
||||
|
||||
@NotBlank
|
||||
@Size(min = 1, max = 100)
|
||||
private String name;
|
||||
|
||||
@NotBlank
|
||||
@Email
|
||||
@Size(min = 3, max = 255)
|
||||
private String email;
|
||||
|
||||
@Size(max = 50)
|
||||
private String phone;
|
||||
|
||||
public String getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public void setAccount(String account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.brapi.test.BrAPITestServer.system.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class TokenResponse {
|
||||
|
||||
@JsonProperty("access_token")
|
||||
private String accessToken;
|
||||
|
||||
@JsonProperty("token_type")
|
||||
private String tokenType = "bearer";
|
||||
|
||||
@JsonProperty("expires_at")
|
||||
private String expiresAt;
|
||||
|
||||
private UserResponse user;
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void setAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public String getTokenType() {
|
||||
return tokenType;
|
||||
}
|
||||
|
||||
public void setTokenType(String tokenType) {
|
||||
this.tokenType = tokenType;
|
||||
}
|
||||
|
||||
public String getExpiresAt() {
|
||||
return expiresAt;
|
||||
}
|
||||
|
||||
public void setExpiresAt(String expiresAt) {
|
||||
this.expiresAt = expiresAt;
|
||||
}
|
||||
|
||||
public UserResponse getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(UserResponse user) {
|
||||
this.user = user;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package org.brapi.test.BrAPITestServer.system.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class UserResponse {
|
||||
|
||||
private UUID id;
|
||||
private String account;
|
||||
private String name;
|
||||
private String email;
|
||||
private String phone;
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public void setAccount(String account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package org.brapi.test.BrAPITestServer.system.entity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.PrePersist;
|
||||
import jakarta.persistence.PreUpdate;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
@Table(name = "sys_users")
|
||||
public class SysUserEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.UUID)
|
||||
private UUID id;
|
||||
|
||||
@Column(nullable = false, length = 100, unique = true)
|
||||
private String account;
|
||||
|
||||
@Column(name = "password_hash", nullable = false)
|
||||
private String passwordHash;
|
||||
|
||||
@Column(nullable = false, length = 100)
|
||||
private String name;
|
||||
|
||||
@Column(nullable = false, length = 255, unique = true)
|
||||
private String email;
|
||||
|
||||
@Column(length = 50)
|
||||
private String phone;
|
||||
|
||||
@Column(name = "created_at", nullable = false)
|
||||
private Instant createdAt;
|
||||
|
||||
@Column(name = "updated_at", nullable = false)
|
||||
private Instant updatedAt;
|
||||
|
||||
@PrePersist
|
||||
void onCreate() {
|
||||
Instant now = Instant.now();
|
||||
createdAt = now;
|
||||
updatedAt = now;
|
||||
}
|
||||
|
||||
@PreUpdate
|
||||
void onUpdate() {
|
||||
updatedAt = Instant.now();
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public void setAccount(String account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public String getPasswordHash() {
|
||||
return passwordHash;
|
||||
}
|
||||
|
||||
public void setPasswordHash(String passwordHash) {
|
||||
this.passwordHash = passwordHash;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
public Instant getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(Instant createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public Instant getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public void setUpdatedAt(Instant updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package org.brapi.test.BrAPITestServer.system.entity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.PrePersist;
|
||||
import jakarta.persistence.PreUpdate;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
@Table(name = "user_sessions")
|
||||
public class UserSessionEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.UUID)
|
||||
private UUID id;
|
||||
|
||||
@Column(name = "user_id", nullable = false)
|
||||
private UUID userId;
|
||||
|
||||
@Column(nullable = false, length = 64, unique = true)
|
||||
private String jti;
|
||||
|
||||
@Column(name = "token_hash", nullable = false)
|
||||
private String tokenHash;
|
||||
|
||||
@Column(name = "expires_at", nullable = false)
|
||||
private Instant expiresAt;
|
||||
|
||||
@Column(name = "revoked_at")
|
||||
private Instant revokedAt;
|
||||
|
||||
@Column(name = "created_at", nullable = false)
|
||||
private Instant createdAt;
|
||||
|
||||
@Column(name = "updated_at", nullable = false)
|
||||
private Instant updatedAt;
|
||||
|
||||
@PrePersist
|
||||
void onCreate() {
|
||||
Instant now = Instant.now();
|
||||
createdAt = now;
|
||||
updatedAt = now;
|
||||
}
|
||||
|
||||
@PreUpdate
|
||||
void onUpdate() {
|
||||
updatedAt = Instant.now();
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public UUID getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(UUID userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getJti() {
|
||||
return jti;
|
||||
}
|
||||
|
||||
public void setJti(String jti) {
|
||||
this.jti = jti;
|
||||
}
|
||||
|
||||
public String getTokenHash() {
|
||||
return tokenHash;
|
||||
}
|
||||
|
||||
public void setTokenHash(String tokenHash) {
|
||||
this.tokenHash = tokenHash;
|
||||
}
|
||||
|
||||
public Instant getExpiresAt() {
|
||||
return expiresAt;
|
||||
}
|
||||
|
||||
public void setExpiresAt(Instant expiresAt) {
|
||||
this.expiresAt = expiresAt;
|
||||
}
|
||||
|
||||
public Instant getRevokedAt() {
|
||||
return revokedAt;
|
||||
}
|
||||
|
||||
public void setRevokedAt(Instant revokedAt) {
|
||||
this.revokedAt = revokedAt;
|
||||
}
|
||||
|
||||
public Instant getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(Instant createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public Instant getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public void setUpdatedAt(Instant updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.brapi.test.BrAPITestServer.system.exception;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
public class AuthApiException extends RuntimeException {
|
||||
|
||||
private final HttpStatus status;
|
||||
|
||||
public AuthApiException(HttpStatus status, String message) {
|
||||
super(message);
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public HttpStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.brapi.test.BrAPITestServer.system.exception;
|
||||
|
||||
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||
import com.auth0.jwt.exceptions.TokenExpiredException;
|
||||
import org.brapi.test.BrAPITestServer.system.dto.AuthErrorResponse;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RestControllerAdvice(basePackages = "org.brapi.test.BrAPITestServer.system")
|
||||
public class AuthExceptionHandler {
|
||||
|
||||
@ExceptionHandler(AuthApiException.class)
|
||||
public ResponseEntity<AuthErrorResponse> handleAuthApiException(AuthApiException ex) {
|
||||
String message = ex.getMessage();
|
||||
return ResponseEntity.status(ex.getStatus()).body(new AuthErrorResponse(message, message));
|
||||
}
|
||||
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public ResponseEntity<AuthErrorResponse> handleValidationException(MethodArgumentNotValidException ex) {
|
||||
Map<String, String> fieldErrors = new LinkedHashMap<>();
|
||||
for (FieldError error : ex.getBindingResult().getFieldErrors()) {
|
||||
fieldErrors.put(error.getField(), error.getDefaultMessage());
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY)
|
||||
.body(new AuthErrorResponse("Validation failed", fieldErrors));
|
||||
}
|
||||
|
||||
@ExceptionHandler(TokenExpiredException.class)
|
||||
public ResponseEntity<AuthErrorResponse> handleTokenExpired(TokenExpiredException ex) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN)
|
||||
.body(new AuthErrorResponse("Token expired", "Token expired"));
|
||||
}
|
||||
|
||||
@ExceptionHandler(JWTVerificationException.class)
|
||||
public ResponseEntity<AuthErrorResponse> handleJwtVerification(JWTVerificationException ex) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
|
||||
.body(new AuthErrorResponse("Invalid token signature", "Invalid token signature"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.brapi.test.BrAPITestServer.system.repository;
|
||||
|
||||
import org.brapi.test.BrAPITestServer.system.entity.SysUserEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface SysUserRepository extends JpaRepository<SysUserEntity, UUID> {
|
||||
|
||||
Optional<SysUserEntity> findByAccount(String account);
|
||||
|
||||
boolean existsByAccount(String account);
|
||||
|
||||
boolean existsByEmail(String email);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.brapi.test.BrAPITestServer.system.repository;
|
||||
|
||||
import org.brapi.test.BrAPITestServer.system.entity.SysUserEntity;
|
||||
import org.brapi.test.BrAPITestServer.system.entity.UserSessionEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface UserSessionRepository extends JpaRepository<UserSessionEntity, UUID> {
|
||||
|
||||
@Query("""
|
||||
SELECT u FROM SysUserEntity u
|
||||
JOIN UserSessionEntity s ON s.userId = u.id
|
||||
WHERE u.id = :userId
|
||||
AND s.jti = :jti
|
||||
AND s.tokenHash = :tokenHash
|
||||
AND s.revokedAt IS NULL
|
||||
AND s.expiresAt > :now
|
||||
""")
|
||||
Optional<SysUserEntity> findActiveUserBySession(
|
||||
@Param("userId") UUID userId,
|
||||
@Param("jti") String jti,
|
||||
@Param("tokenHash") String tokenHash,
|
||||
@Param("now") Instant now);
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package org.brapi.test.BrAPITestServer.system.security;
|
||||
|
||||
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||
import com.auth0.jwt.exceptions.TokenExpiredException;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.brapi.test.BrAPITestServer.auth.AuthDetails;
|
||||
import org.brapi.test.BrAPITestServer.system.entity.SysUserEntity;
|
||||
import org.brapi.test.BrAPITestServer.system.service.TokenService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class SystemJwtAuthFilter extends OncePerRequestFilter {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SystemJwtAuthFilter.class);
|
||||
private static final String ANONYMOUS_KEY = "anonymousKey";
|
||||
|
||||
private final TokenService tokenService;
|
||||
private final boolean authEnabled;
|
||||
|
||||
public SystemJwtAuthFilter(
|
||||
TokenService tokenService,
|
||||
@Value("${security.enabled:true}") boolean authEnabled) {
|
||||
this.tokenService = tokenService;
|
||||
this.authEnabled = authEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldNotFilter(HttpServletRequest request) {
|
||||
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
|
||||
return true;
|
||||
}
|
||||
String path = request.getRequestURI();
|
||||
return path.startsWith("/auth/");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
if (!authEnabled) {
|
||||
setAuthenticatedUser("anonymousUser", Long.MAX_VALUE, true);
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
String header = request.getHeader("Authorization");
|
||||
if (header == null || !header.startsWith("Bearer ")) {
|
||||
setAnonymousUser();
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
String token = header.substring("Bearer ".length()).trim();
|
||||
try {
|
||||
SysUserEntity user = tokenService.resolveActiveUser(token)
|
||||
.orElseThrow(() -> new JWTVerificationException("Session invalid or expired"));
|
||||
var decoded = tokenService.verifyToken(token);
|
||||
Date expiresAt = decoded.getExpiresAt();
|
||||
long expirationMillis = expiresAt != null ? expiresAt.getTime() : Long.MAX_VALUE;
|
||||
setAuthenticatedUser(user.getId().toString(), expirationMillis, false);
|
||||
filterChain.doFilter(request, response);
|
||||
} catch (TokenExpiredException ex) {
|
||||
writeAuthError(response, HttpStatus.FORBIDDEN, "Token expired");
|
||||
} catch (JWTVerificationException ex) {
|
||||
writeAuthError(response, HttpStatus.UNAUTHORIZED,
|
||||
ex.getMessage() != null ? ex.getMessage() : "Invalid token signature");
|
||||
} catch (Exception ex) {
|
||||
log.error("Authentication failed", ex);
|
||||
writeAuthError(response, HttpStatus.UNAUTHORIZED, "Session invalid or expired");
|
||||
}
|
||||
}
|
||||
|
||||
private void setAnonymousUser() {
|
||||
AnonymousAuthenticationToken authentication = new AnonymousAuthenticationToken(
|
||||
ANONYMOUS_KEY,
|
||||
"anonymousUser",
|
||||
List.of(new SimpleGrantedAuthority("ROLE_ANONYMOUS")));
|
||||
AuthDetails details = new AuthDetails();
|
||||
details.setUserId("anonymousUser");
|
||||
details.setExpirationTimestamp(Long.MAX_VALUE);
|
||||
details.addRole("ROLE_ANONYMOUS");
|
||||
authentication.setDetails(details);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
}
|
||||
|
||||
private void setAuthenticatedUser(String userId, long expirationMillis, boolean grantAdmin) {
|
||||
List<SimpleGrantedAuthority> authorities = grantAdmin
|
||||
? List.of(
|
||||
new SimpleGrantedAuthority("ROLE_USER"),
|
||||
new SimpleGrantedAuthority("ROLE_ADMIN"),
|
||||
new SimpleGrantedAuthority("ROLE_ANONYMOUS"))
|
||||
: List.of(new SimpleGrantedAuthority("ROLE_USER"));
|
||||
|
||||
UsernamePasswordAuthenticationToken authentication =
|
||||
new UsernamePasswordAuthenticationToken(userId, null, authorities);
|
||||
AuthDetails details = new AuthDetails();
|
||||
details.setUserId(userId);
|
||||
details.setExpirationTimestamp(expirationMillis);
|
||||
details.addRole("ROLE_USER");
|
||||
if (grantAdmin) {
|
||||
details.addRole("ROLE_ADMIN");
|
||||
details.addRole("ROLE_ANONYMOUS");
|
||||
}
|
||||
authentication.setDetails(details);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
}
|
||||
|
||||
private void writeAuthError(HttpServletResponse response, HttpStatus status, String message) throws IOException {
|
||||
response.setStatus(status.value());
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
||||
String body = "{\"message\":\"" + escapeJson(message) + "\",\"detail\":\"" + escapeJson(message) + "\"}";
|
||||
response.getWriter().write(body);
|
||||
}
|
||||
|
||||
private String escapeJson(String value) {
|
||||
return value.replace("\\", "\\\\").replace("\"", "\\\"");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package org.brapi.test.BrAPITestServer.system.service;
|
||||
|
||||
import org.brapi.test.BrAPITestServer.system.dto.LoginRequest;
|
||||
import org.brapi.test.BrAPITestServer.system.dto.RegisterRequest;
|
||||
import org.brapi.test.BrAPITestServer.system.dto.TokenResponse;
|
||||
import org.brapi.test.BrAPITestServer.system.entity.SysUserEntity;
|
||||
import org.brapi.test.BrAPITestServer.system.exception.AuthApiException;
|
||||
import org.brapi.test.BrAPITestServer.system.repository.SysUserRepository;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class AuthService {
|
||||
|
||||
private final SysUserRepository sysUserRepository;
|
||||
private final PasswordService passwordService;
|
||||
private final TokenService tokenService;
|
||||
|
||||
public AuthService(
|
||||
SysUserRepository sysUserRepository,
|
||||
PasswordService passwordService,
|
||||
TokenService tokenService) {
|
||||
this.sysUserRepository = sysUserRepository;
|
||||
this.passwordService = passwordService;
|
||||
this.tokenService = tokenService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public TokenResponse register(RegisterRequest request) {
|
||||
String account = normalizeAccount(request.getAccount());
|
||||
String email = normalizeEmail(request.getEmail());
|
||||
String phone = normalizeOptional(request.getPhone());
|
||||
|
||||
if (sysUserRepository.existsByAccount(account) || sysUserRepository.existsByEmail(email)) {
|
||||
throw new AuthApiException(HttpStatus.CONFLICT, "Account or email already exists");
|
||||
}
|
||||
|
||||
SysUserEntity user = new SysUserEntity();
|
||||
user.setAccount(account);
|
||||
user.setPasswordHash(passwordService.hashPassword(request.getPassword()));
|
||||
user.setName(request.getName().trim());
|
||||
user.setEmail(email);
|
||||
user.setPhone(phone);
|
||||
sysUserRepository.save(user);
|
||||
|
||||
return tokenService.issueToken(user);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public TokenResponse login(LoginRequest request) {
|
||||
String account = normalizeAccount(request.getAccount());
|
||||
SysUserEntity user = sysUserRepository.findByAccount(account)
|
||||
.orElseThrow(() -> new AuthApiException(HttpStatus.UNAUTHORIZED, "Invalid account or password"));
|
||||
|
||||
if (!passwordService.verifyPassword(request.getPassword(), user.getPasswordHash())) {
|
||||
throw new AuthApiException(HttpStatus.UNAUTHORIZED, "Invalid account or password");
|
||||
}
|
||||
|
||||
return tokenService.issueToken(user);
|
||||
}
|
||||
|
||||
private String normalizeAccount(String account) {
|
||||
return account == null ? "" : account.trim();
|
||||
}
|
||||
|
||||
private String normalizeEmail(String email) {
|
||||
return email == null ? "" : email.trim().toLowerCase();
|
||||
}
|
||||
|
||||
private String normalizeOptional(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package org.brapi.test.BrAPITestServer.system.service;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.HexFormat;
|
||||
|
||||
@Service
|
||||
public class PasswordService {
|
||||
|
||||
private static final String ALGORITHM = "PBKDF2WithHmacSHA256";
|
||||
private static final int ITERATIONS = 210_000;
|
||||
private static final int KEY_LENGTH = 256;
|
||||
private static final int SALT_BYTES = 16;
|
||||
|
||||
public String hashPassword(String password) {
|
||||
byte[] salt = new byte[SALT_BYTES];
|
||||
new SecureRandom().nextBytes(salt);
|
||||
String digest = pbkdf2(password, salt);
|
||||
return "pbkdf2_sha256$" + ITERATIONS + "$" + HexFormat.of().formatHex(salt) + "$" + digest;
|
||||
}
|
||||
|
||||
public boolean verifyPassword(String password, String passwordHash) {
|
||||
if (passwordHash == null || passwordHash.isBlank()) {
|
||||
return false;
|
||||
}
|
||||
String[] parts = passwordHash.split("\\$");
|
||||
if (parts.length != 4 || !"pbkdf2_sha256".equals(parts[0])) {
|
||||
return false;
|
||||
}
|
||||
int iterations;
|
||||
try {
|
||||
iterations = Integer.parseInt(parts[1]);
|
||||
} catch (NumberFormatException ex) {
|
||||
return false;
|
||||
}
|
||||
byte[] salt = HexFormat.of().parseHex(parts[2]);
|
||||
String expected = parts[3];
|
||||
String actual = pbkdf2(password, salt, iterations);
|
||||
return constantTimeEquals(expected, actual);
|
||||
}
|
||||
|
||||
private String pbkdf2(String password, byte[] salt) {
|
||||
return pbkdf2(password, salt, ITERATIONS);
|
||||
}
|
||||
|
||||
private String pbkdf2(String password, byte[] salt, int iterations) {
|
||||
try {
|
||||
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations, KEY_LENGTH);
|
||||
SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
|
||||
return HexFormat.of().formatHex(factory.generateSecret(spec).getEncoded());
|
||||
} catch (NoSuchAlgorithmException | InvalidKeySpecException ex) {
|
||||
throw new IllegalStateException("Failed to hash password", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean constantTimeEquals(String left, String right) {
|
||||
if (left == null || right == null || left.length() != right.length()) {
|
||||
return false;
|
||||
}
|
||||
int result = 0;
|
||||
for (int i = 0; i < left.length(); i++) {
|
||||
result |= left.charAt(i) ^ right.charAt(i);
|
||||
}
|
||||
return result == 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package org.brapi.test.BrAPITestServer.system.service;
|
||||
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||
import org.brapi.test.BrAPITestServer.system.config.JwtProperties;
|
||||
import org.brapi.test.BrAPITestServer.system.dto.TokenResponse;
|
||||
import org.brapi.test.BrAPITestServer.system.dto.UserResponse;
|
||||
import org.brapi.test.BrAPITestServer.system.entity.SysUserEntity;
|
||||
import org.brapi.test.BrAPITestServer.system.entity.UserSessionEntity;
|
||||
import org.brapi.test.BrAPITestServer.system.repository.UserSessionRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Date;
|
||||
import java.util.HexFormat;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class TokenService {
|
||||
|
||||
private static final DateTimeFormatter ISO_FORMATTER =
|
||||
DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(ZoneOffset.UTC);
|
||||
|
||||
private final JwtProperties jwtProperties;
|
||||
private final UserSessionRepository userSessionRepository;
|
||||
|
||||
public TokenService(JwtProperties jwtProperties, UserSessionRepository userSessionRepository) {
|
||||
this.jwtProperties = jwtProperties;
|
||||
this.userSessionRepository = userSessionRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public TokenResponse issueToken(SysUserEntity user) {
|
||||
Instant issuedAt = Instant.now();
|
||||
Instant expiresAt = issuedAt.plus(jwtProperties.getAccessTokenExpireMinutes(), ChronoUnit.MINUTES);
|
||||
String jti = generateJti();
|
||||
String accessToken = createAccessToken(user, jti, issuedAt, expiresAt);
|
||||
|
||||
UserSessionEntity session = new UserSessionEntity();
|
||||
session.setUserId(user.getId());
|
||||
session.setJti(jti);
|
||||
session.setTokenHash(hashToken(accessToken));
|
||||
session.setExpiresAt(expiresAt);
|
||||
userSessionRepository.save(session);
|
||||
|
||||
TokenResponse response = new TokenResponse();
|
||||
response.setAccessToken(accessToken);
|
||||
response.setExpiresAt(ISO_FORMATTER.format(expiresAt));
|
||||
response.setUser(toUserResponse(user));
|
||||
return response;
|
||||
}
|
||||
|
||||
public Optional<SysUserEntity> resolveActiveUser(String accessToken) {
|
||||
DecodedJWT jwt = verifyToken(accessToken);
|
||||
UUID userId = UUID.fromString(jwt.getSubject());
|
||||
String jti = jwt.getId();
|
||||
return userSessionRepository.findActiveUserBySession(
|
||||
userId, jti, hashToken(accessToken), Instant.now());
|
||||
}
|
||||
|
||||
public DecodedJWT verifyToken(String accessToken) {
|
||||
try {
|
||||
Algorithm algorithm = Algorithm.HMAC256(jwtProperties.getSecretKey());
|
||||
return JWT.require(algorithm).build().verify(accessToken);
|
||||
} catch (JWTVerificationException | IllegalArgumentException ex) {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
private String createAccessToken(SysUserEntity user, String jti, Instant issuedAt, Instant expiresAt) {
|
||||
Algorithm algorithm = Algorithm.HMAC256(jwtProperties.getSecretKey());
|
||||
return JWT.create()
|
||||
.withSubject(user.getId().toString())
|
||||
.withClaim("account", user.getAccount())
|
||||
.withJWTId(jti)
|
||||
.withIssuedAt(Date.from(issuedAt))
|
||||
.withExpiresAt(Date.from(expiresAt))
|
||||
.sign(algorithm);
|
||||
}
|
||||
|
||||
private String generateJti() {
|
||||
byte[] bytes = new byte[16];
|
||||
new SecureRandom().nextBytes(bytes);
|
||||
return HexFormat.of().formatHex(bytes);
|
||||
}
|
||||
|
||||
public String hashToken(String accessToken) {
|
||||
try {
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
byte[] hashed = digest.digest(accessToken.getBytes(StandardCharsets.UTF_8));
|
||||
return HexFormat.of().formatHex(hashed);
|
||||
} catch (NoSuchAlgorithmException ex) {
|
||||
throw new IllegalStateException("SHA-256 not available", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public UserResponse toUserResponse(SysUserEntity user) {
|
||||
UserResponse response = new UserResponse();
|
||||
response.setId(user.getId());
|
||||
response.setAccount(user.getAccount());
|
||||
response.setName(user.getName());
|
||||
response.setEmail(user.getEmail());
|
||||
response.setPhone(user.getPhone());
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
server.port = 8080
|
||||
server.servlet.context-path=/brapi/v2
|
||||
|
||||
|
||||
spring.datasource.url=jdbc:postgresql://localhost:5432/brapi-java
|
||||
spring.datasource.username=postgres
|
||||
@@ -18,5 +16,7 @@ spring.flyway.baselineOnMigrate=true
|
||||
|
||||
spring.mvc.dispatch-options-request=true
|
||||
|
||||
security.oidc_discovery_url=https://example.com/auth/.well-known/openid-configuration
|
||||
security.issuer_url=http://example.com/issuerurl
|
||||
security.enabled=true
|
||||
|
||||
jwt.secret-key=change-me-in-production
|
||||
jwt.access-token-expire-minutes=1440
|
||||
|
||||
30
src/main/resources/db/migration/V002__create_auth_tables.sql
Normal file
30
src/main/resources/db/migration/V002__create_auth_tables.sql
Normal file
@@ -0,0 +1,30 @@
|
||||
-- Auth tables for login/register (sys_users + user_sessions)
|
||||
|
||||
-- See docs/dev/backend/auth.md
|
||||
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sys_users (
|
||||
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
account VARCHAR(100) NOT NULL,
|
||||
|
||||
password_hash TEXT NOT NULL,
|
||||
|
||||
name VARCHAR(100) NOT NULL,
|
||||
|
||||
email VARCHAR(255) NOT NULL,
|
||||
|
||||
phone VARCHAR(50),
|
||||
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
|
||||
);
|
||||
|
||||
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS ux_users_account ON sys_users (account);
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user