ContractController.java
package access.api;
import access.config.Config;
import access.exception.NotFoundException;
import access.exception.UserRestrictionException;
import access.jira.JiraClient;
import access.jira.JiraIssue;
import access.model.Application;
import access.model.Contract;
import access.model.EntityType;
import access.model.User;
import access.repository.ApplicationRepository;
import access.repository.ContractRepository;
import access.repository.UserRepository;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static access.SwaggerOpenIdConfig.API_TOKENS_SCHEME_NAME;
import static access.SwaggerOpenIdConfig.OPEN_ID_SCHEME_NAME;
@RestController
@RequestMapping(value = {"/api/v1/contracts"}, produces = MediaType.APPLICATION_JSON_VALUE)
@Transactional
@EnableConfigurationProperties(Config.class)
@SecurityRequirement(name = OPEN_ID_SCHEME_NAME, scopes = {"openid"})
@SecurityRequirement(name = API_TOKENS_SCHEME_NAME)
public class ContractController implements UserAccessRights {
private static final Log LOG = LogFactory.getLog(ContractController.class);
private final ContractRepository contractRepository;
private final ApplicationRepository applicationRepository;
private final UserRepository userRepository;
private final Config config;
private final JiraClient jiraClient;
public ContractController(ContractRepository contractRepository,
ApplicationRepository applicationRepository,
UserRepository userRepository,
Config config,
JiraClient jiraClient) {
this.contractRepository = contractRepository;
this.applicationRepository = applicationRepository;
this.userRepository = userRepository;
this.config = config;
this.jiraClient = jiraClient;
}
@GetMapping("/unsigned")
public ResponseEntity<List<Contract>> unsigned(User user) {
LOG.debug("/unsigned contracts");
confirmSuperUser(user);
return ResponseEntity.ok(contractRepository.findBySignedContractFalse());
}
@GetMapping("/{applicationId}")
public ResponseEntity<Contract> get(User user, @PathVariable("applicationId") Long applicationId) {
LOG.debug("/get contract for applicationId " + applicationId);
Application application = applicationRepository.findById(applicationId)
.orElseThrow(() -> new NotFoundException("Application not found"));
user = reinitializeUser(user, userRepository);
confirmInstitutionAdmin(user, application.getOrganization());
Contract contract = contractRepository.findByApplicationId(applicationId)
.orElseThrow(() -> new NotFoundException("Contract not found"));
return ResponseEntity.ok(contract);
}
@PostMapping("/{applicationId}")
public ResponseEntity<Contract> create(User user,
@PathVariable("applicationId") Long applicationId,
@Validated @RequestBody Contract contract) {
LOG.debug("/create contract for applicationId " + applicationId + " by " + user.getEmail());
Application application = applicationRepository.findById(applicationId)
.orElseThrow(() -> new NotFoundException("Application not found"));
user = reinitializeUser(user, userRepository);
confirmInstitutionAdmin(user, application.getOrganization());
contract.setApplication(application);
Contract saved = contractRepository.save(contract);
String summary = String.format("User %s submitted a contract for application %s.",
user.getName(), application.getName());
String jiraKey = jiraClient.create(new JiraIssue(
application.getName(),
null,
String.format("%s%nVisit: %s/system/contracts",
summary, config.getClientUrl()),
summary,
EntityType.oidc10_rp,
user.getEmail()
));
LOG.info("Created Jira issue for new Contract: " + jiraKey);
saved.setTicketKey(jiraKey);
saved = contractRepository.save(saved);
return ResponseEntity.status(HttpStatus.CREATED).body(saved);
}
@PutMapping("/{applicationId}")
public ResponseEntity<Contract> update(User user,
@PathVariable("applicationId") Long applicationId,
@Validated @RequestBody Contract contract) {
LOG.debug("/update contract for applicationId " + applicationId + " by " + user.getEmail());
Application application = applicationRepository.findById(applicationId)
.orElseThrow(() -> new NotFoundException("Application not found"));
user = reinitializeUser(user, userRepository);
confirmInstitutionAdmin(user, application.getOrganization());
if (contract.isSignedContract() && !user.isSuperUser()) {
throw new UserRestrictionException("Only super users can sign a contract");
}
contractRepository.findById(contract.getId())
.orElseThrow(() -> new NotFoundException("Contract not found"));
contract.setApplication(application);
Contract saved = contractRepository.save(contract);
if (contract.isSignedContract() && !application.isSignedContract()) {
application.setSignedContract(true);
applicationRepository.save(application);
}
return ResponseEntity.status(HttpStatus.CREATED).body(saved);
}
}