From ef40c5568fd2d42b558a395402238bf123f08639 Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Tue, 21 Apr 2020 17:54:00 +0300 Subject: [PATCH 01/18] Removed unnecessary condition when retrieving DMPs --- .../eu/eudat/logic/managers/DataManagementPlanManager.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java index 5473eb0e8..93dfc5691 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java @@ -161,8 +161,7 @@ public class DataManagementPlanManager { item.setDataset( item.getDataset().stream() .filter(dataset -> !dataset.getStatus().equals(Dataset.Status.DELETED.getValue()) && !dataset.getStatus().equals(Dataset.Status.CANCELED.getValue())).collect(Collectors.toList()).stream() - .filter(dataset -> dataset.getDmp().getUsers().stream().filter(userDMP -> userDMP.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())).findFirst().get().getUser().getId().equals(principalID) - || dataset.getDmp().getUsers().stream() + .filter(dataset -> dataset.getDmp().getUsers().stream() .filter(x -> x.getUser().getId().equals(principalID)) .collect(Collectors.toList()).size() > 0) .collect(Collectors.toSet())); From 4e686660894a5b5cd3dc9b2dea52d76ee384349f Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Wed, 22 Apr 2020 18:40:43 +0300 Subject: [PATCH 02/18] Re organize DMP controller and manager functions and added the ability to add custom organization (not configurable yet) (ref #255) --- .../main/java/eu/eudat/controllers/DMPs.java | 195 +-- .../security/ForbiddenException.java | 19 + .../managers/DataManagementPlanManager.java | 1311 +++++++++-------- .../eudat/models/data/dmp/Organisation.java | 16 +- dmp-frontend/src/app/ui/dmp/dmp.module.ts | 7 +- .../add-organization.component.html | 19 + .../add-organization.component.ts | 43 + .../add-organization.model.ts | 33 + .../general-tab/general-tab.component.html | 3 + .../general-tab/general-tab.component.ts | 32 + .../ui/dmp/overview/dmp-overview.component.ts | 4 +- dmp-frontend/src/assets/i18n/en.json | 8 + dmp-frontend/src/assets/i18n/es.json | 21 +- 13 files changed, 988 insertions(+), 723 deletions(-) create mode 100644 dmp-backend/web/src/main/java/eu/eudat/exceptions/security/ForbiddenException.java create mode 100644 dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.component.html create mode 100644 dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.component.ts create mode 100644 dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.model.ts diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java index 109ff34c2..62ff0fe59 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java @@ -82,13 +82,9 @@ public class DMPs extends BaseController { this.configLoader = configLoader; } - /*@Transactional - @RequestMapping(method = RequestMethod.GET, value = {"{id}/unlock"}, produces = "application/json") - public @ResponseBody - ResponseEntity> unlock(@PathVariable(value = "id") UUID id, Principal principal) throws Exception { - this.dataManagementPlanManager.unlock(id); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Unlocked")); - }*/ + /* + * Data Retrieval + * */ @RequestMapping(method = RequestMethod.POST, value = {"/paged"}, consumes = "application/json", produces = "application/json") public @ResponseBody @@ -102,11 +98,11 @@ public class DMPs extends BaseController { @RequestMapping(method = RequestMethod.GET, value = {"{id}"}) public @ResponseBody ResponseEntity getSingle(@PathVariable String id, @RequestHeader("Content-Type") String contentType, - @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws IllegalAccessException, InstantiationException, IOException { + @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws Exception { if (contentType.equals("application/xml") || contentType.equals("application/msword")) { return this.dataManagementPlanManager.getDocument(id, contentType, principal, this.configLoader); } else { - eu.eudat.models.data.dmp.DataManagementPlan dataManagementPlan = this.dataManagementPlanManager.getSingle(id, principal); + eu.eudat.models.data.dmp.DataManagementPlan dataManagementPlan = this.dataManagementPlanManager.getSingle(id, principal, false); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlan)); } } @@ -118,17 +114,11 @@ public class DMPs extends BaseController { return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(datasetProfileTableData)); } - @RequestMapping(method = RequestMethod.GET, value = {"rda/{id}"}) - public @ResponseBody - ResponseEntity getRDAJsonDocument(@PathVariable String id, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws IOException { - return this.dataManagementPlanManager.getRDAJsonDocument(id, datasetManager, principal); - } - @RequestMapping(method = RequestMethod.GET, value = {"/overview/{id}"}) public @ResponseBody ResponseEntity getOverviewSingle(@PathVariable String id,@ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) { try { - DataManagementPlanOverviewModel dataManagementPlan = this.dataManagementPlanManager.getOverviewSingle(id, principal); + DataManagementPlanOverviewModel dataManagementPlan = this.dataManagementPlanManager.getOverviewSingle(id, principal, false); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlan)); } catch (Exception e) { if (e instanceof UnauthorisedException) { @@ -141,26 +131,71 @@ public class DMPs extends BaseController { @RequestMapping(method = RequestMethod.GET, value = {"/public/{id}"}) public @ResponseBody - ResponseEntity getSinglePublic(@PathVariable String id) { - try { - eu.eudat.models.data.dmp.DataManagementPlan dataManagementPlan = this.dataManagementPlanManager.getSinglePublic(id, this.dynamicGrantConfiguration); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlan)); - } catch (Exception ex) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).message(ex.getMessage())); - } + ResponseEntity getSinglePublic(@PathVariable String id, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws Exception { +// try { + eu.eudat.models.data.dmp.DataManagementPlan dataManagementPlan = this.dataManagementPlanManager.getSingle(id, principal, true); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlan)); +// } catch (Exception ex) { +// return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).message(ex.getMessage())); +// } } @RequestMapping(method = RequestMethod.GET, value = {"/publicOverview/{id}"}) public @ResponseBody - ResponseEntity getOverviewSinglePublic(@PathVariable String id) { - try { - DataManagementPlanOverviewModel dataManagementPlan = this.dataManagementPlanManager.getOverviewSinglePublic(id); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlan)); - } catch (Exception ex) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).message(ex.getMessage())); - } + ResponseEntity getOverviewSinglePublic(@PathVariable String id, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws Exception { +// try { + DataManagementPlanOverviewModel dataManagementPlan = this.dataManagementPlanManager.getOverviewSingle(id, principal, true); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlan)); +// } catch (Exception ex) { +// return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).message(ex.getMessage())); +// } } + @RequestMapping(method = RequestMethod.POST, value = {"/dynamic"}, consumes = "application/json", produces = "application/json") + public @ResponseBody + ResponseEntity>>> getWithCriteria(@RequestBody RequestItem criteriaRequestItem, Principal principal) throws InstantiationException, IllegalAccessException { + List> dataTable = this.dataManagementPlanManager.getDynamicFields(criteriaRequestItem.getCriteria().getId(), this.dynamicGrantConfiguration, criteriaRequestItem.getCriteria()); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>>().status(ApiMessageCode.NO_MESSAGE).payload(dataTable)); + } + + /* + * Data Export + * */ + + @RequestMapping(method = RequestMethod.GET, value = {"rda/{id}"}) + public @ResponseBody + ResponseEntity getRDAJsonDocument(@PathVariable String id, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws IOException { + return this.dataManagementPlanManager.getRDAJsonDocument(id, datasetManager, principal); + } + + @RequestMapping(method = RequestMethod.GET, value = {"/getPDF/{id}"}) + public @ResponseBody + ResponseEntity getPDFDocument(@PathVariable String id, @RequestHeader("Content-Type") String contentType, + @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws IllegalAccessException, IOException, InstantiationException, InterruptedException { + FileEnvelope file = this.dataManagementPlanManager.getWordDocument(id, principal, configLoader); + String name = file.getFilename().substring(0, file.getFilename().length() - 5); + File pdffile = datasetManager.convertToPDF(file, environment); + InputStream resource = new FileInputStream(pdffile); + logger.info("Mime Type of " + name + " is " + + new MimetypesFileTypeMap().getContentType(file.getFile())); + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.setContentLength(pdffile.length()); + responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); + responseHeaders.set("Content-Disposition", "attachment;filename=" + name + ".pdf"); + responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition"); + responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type"); + + byte[] content = org.apache.poi.util.IOUtils.toByteArray(resource); + resource.close(); + Files.deleteIfExists(file.getFile().toPath()); + Files.deleteIfExists(pdffile.toPath()); + return new ResponseEntity<>(content, responseHeaders, HttpStatus.OK); + } + + /* + * Data Management + * */ + @Transactional @RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json") public @ResponseBody @@ -199,37 +234,6 @@ public class DMPs extends BaseController { } } - @RequestMapping(method = RequestMethod.POST, value = {"/dynamic"}, consumes = "application/json", produces = "application/json") - public @ResponseBody - ResponseEntity>>> getWithCriteria(@RequestBody RequestItem criteriaRequestItem, Principal principal) throws InstantiationException, IllegalAccessException { - List> dataTable = this.dataManagementPlanManager.getDynamicFields(criteriaRequestItem.getCriteria().getId(), this.dynamicGrantConfiguration, criteriaRequestItem.getCriteria()); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>>().status(ApiMessageCode.NO_MESSAGE).payload(dataTable)); - } - - @RequestMapping(method = RequestMethod.GET, value = {"/getPDF/{id}"}) - public @ResponseBody - ResponseEntity getPDFDocument(@PathVariable String id, @RequestHeader("Content-Type") String contentType, - @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws IllegalAccessException, IOException, InstantiationException, InterruptedException { - FileEnvelope file = this.dataManagementPlanManager.getWordDocument(id, principal, configLoader); - String name = file.getFilename().substring(0, file.getFilename().length() - 5); - File pdffile = datasetManager.convertToPDF(file, environment); - InputStream resource = new FileInputStream(pdffile); - logger.info("Mime Type of " + name + " is " + - new MimetypesFileTypeMap().getContentType(file.getFile())); - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.setContentLength(pdffile.length()); - responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); - responseHeaders.set("Content-Disposition", "attachment;filename=" + name + ".pdf"); - responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition"); - responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type"); - - byte[] content = org.apache.poi.util.IOUtils.toByteArray(resource); - resource.close(); - Files.deleteIfExists(file.getFile().toPath()); - Files.deleteIfExists(pdffile.toPath()); - return new ResponseEntity<>(content, responseHeaders, HttpStatus.OK); - } - @RequestMapping(method = RequestMethod.POST, value = {"/upload"}) public ResponseEntity dmpUpload(@RequestParam("file") MultipartFile[] files, Principal principal) throws Exception { if (files[0].getContentType().equals(APPLICATION_JSON.toString())) { @@ -241,29 +245,6 @@ public class DMPs extends BaseController { .status(ApiMessageCode.SUCCESS_MESSAGE)); } - @RequestMapping(method = RequestMethod.POST, value = {"/public/paged"}, consumes = "application/json", produces = "application/json") - public @ResponseBody - ResponseEntity>> getPublicPaged(@RequestBody DataManagmentPlanPublicTableRequest dmpTableRequest, - @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal, - @RequestParam String fieldsGroup) throws Exception { - DataTableData dmp = this.dataManagementPlanManager.getPublicPaged(dmpTableRequest, fieldsGroup, principal); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(dmp)); - } - - @RequestMapping(method = RequestMethod.POST, value = {"/test"}, consumes = "application/json", produces = "application/json") - public @ResponseBody - ResponseEntity>> test(@RequestBody DMPCriteria criteria, @ClaimedAuthorities(claims = {Authorities.ANONYMOUS}) Principal principal) throws Exception { - DatabaseRepository dbRepo = this.getApiContext().getOperationsContext().getDatabaseRepository(); - - DMPQuery query = criteria.buildQuery(dbRepo); - - List models = query.getQuery().toListWithFields(); - DataTableData dmp = new DataTableData<>(); - dmp.setData(models); - dmp.setTotalCount(query.getQuery().count()); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(dmp)); - } - @RequestMapping(method = RequestMethod.GET, value = {"/makepublic/{id}"}) public ResponseEntity> makePublic(@PathVariable String id, Principal principal) { try { @@ -285,6 +266,10 @@ public class DMPs extends BaseController { } } + /* + * DOI Generation + * */ + @Transactional @RequestMapping(method = RequestMethod.POST, value = {"/createZenodoDoi/{id}"}) public ResponseEntity> createZenodoDoi(@PathVariable String id, Principal principal) { @@ -297,7 +282,11 @@ public class DMPs extends BaseController { } } - @javax.transaction.Transactional + /* + * Data Index + * */ + + @Transactional @RequestMapping(method = RequestMethod.POST, value = {"/index"}) public @ResponseBody ResponseEntity> generateIndex(Principal principal) throws Exception { @@ -305,11 +294,45 @@ public class DMPs extends BaseController { return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Generated").payload(null)); } - @javax.transaction.Transactional + @Transactional @RequestMapping(method = RequestMethod.DELETE, value = {"/index"}) public @ResponseBody ResponseEntity> clearIndex(Principal principal) throws Exception { this.dataManagementPlanManager.clearIndex(principal); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Cleared").payload(null)); } + + /* + * Misc + * */ + + @RequestMapping(method = RequestMethod.POST, value = {"/test"}, consumes = "application/json", produces = "application/json") + public @ResponseBody + ResponseEntity>> test(@RequestBody DMPCriteria criteria, @ClaimedAuthorities(claims = {Authorities.ANONYMOUS}) Principal principal) throws Exception { + DatabaseRepository dbRepo = this.getApiContext().getOperationsContext().getDatabaseRepository(); + + DMPQuery query = criteria.buildQuery(dbRepo); + + List models = query.getQuery().toListWithFields(); + DataTableData dmp = new DataTableData<>(); + dmp.setData(models); + dmp.setTotalCount(query.getQuery().count()); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(dmp)); + } + + /*@RequestMapping(method = RequestMethod.POST, value = {"/public/paged"}, consumes = "application/json", produces = "application/json") + public @ResponseBody + ResponseEntity>> getPublicPaged(@RequestBody DataManagmentPlanPublicTableRequest dmpTableRequest, + @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal, + @RequestParam String fieldsGroup) throws Exception { + DataTableData dmp = this.dataManagementPlanManager.getPublicPaged(dmpTableRequest, fieldsGroup, principal); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(dmp)); + }*/ + /*@Transactional + @RequestMapping(method = RequestMethod.GET, value = {"{id}/unlock"}, produces = "application/json") + public @ResponseBody + ResponseEntity> unlock(@PathVariable(value = "id") UUID id, Principal principal) throws Exception { + this.dataManagementPlanManager.unlock(id); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Unlocked")); + }*/ } diff --git a/dmp-backend/web/src/main/java/eu/eudat/exceptions/security/ForbiddenException.java b/dmp-backend/web/src/main/java/eu/eudat/exceptions/security/ForbiddenException.java new file mode 100644 index 000000000..dfd623dae --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/exceptions/security/ForbiddenException.java @@ -0,0 +1,19 @@ +package eu.eudat.exceptions.security; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(value = HttpStatus.FORBIDDEN) +public class ForbiddenException extends RuntimeException { + public ForbiddenException() { + super(); + } + + public ForbiddenException(String message) { + super(message); + } + + public ForbiddenException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java index 93dfc5691..28f76210b 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java @@ -25,6 +25,7 @@ import eu.eudat.elastic.entities.Organization; import eu.eudat.elastic.entities.Tag; import eu.eudat.exceptions.datamanagementplan.DMPNewVersionException; import eu.eudat.exceptions.datamanagementplan.DMPWithDatasetsDeleteException; +import eu.eudat.exceptions.security.ForbiddenException; import eu.eudat.exceptions.security.NonValidTokenException; import eu.eudat.exceptions.security.UnauthorisedException; import eu.eudat.logic.builders.entity.UserInfoBuilder; @@ -125,6 +126,10 @@ public class DataManagementPlanManager { this.userManager = userManager; } + /* + * Data Retrieval + * */ + public DataTableData getPaged(DataManagementPlanTableRequest dataManagementPlanTableRequest, Principal principal, String fieldsGroup) throws Exception { UUID principalID = principal.getId(); List dmps = null; @@ -193,237 +198,22 @@ public class DataManagementPlanManager { return dataTable; } - public DataTableData getPublicPaged(DataManagmentPlanPublicTableRequest dataManagementPlanPublicTableRequest, String fieldsGroup, Principal principal) throws Exception { - dataManagementPlanPublicTableRequest.setQuery(databaseRepository.getDmpDao().asQueryable().withHint(HintedModelFactory.getHint(DataManagementPlanListingModel.class))); - QueryableList items = dataManagementPlanPublicTableRequest.applyCriteria(); - - if (principal.getId() != null && dataManagementPlanPublicTableRequest.getCriteria().getRole() != null) { - items.where((builder, root) -> { - Join userJoin = root.join("users", JoinType.LEFT); - return builder.and(builder.equal(userJoin.join("user", JoinType.LEFT).get("id"), principal.getId()), builder.equal(userJoin.get("role"), dataManagementPlanPublicTableRequest.getCriteria().getRole())); - }); - } - QueryableList pagedItems = PaginationManager.applyPaging(items, dataManagementPlanPublicTableRequest); - - DataTableData dataTable = new DataTableData<>(); - - CompletableFuture itemsFuture; - if (fieldsGroup.equals("listing")) { - itemsFuture = pagedItems.withHint(HintedModelFactory.getHint(DataManagementPlanListingModel.class)) - .selectAsync(item -> { - item.setDataset( - item.getDataset().stream() - .filter(dataset -> dataset.getStatus().equals(Dataset.Status.FINALISED.getValue())).collect(Collectors.toSet())); - return new DataManagementPlanListingModel().fromDataModelDatasets(item); - }) - .whenComplete((resultList, throwable) -> dataTable.setData(resultList)); - } else { - itemsFuture = pagedItems - .selectAsync(item -> new DataManagementPlanListingModel().fromDataModel(item)) - .whenComplete((resultList, throwable) -> dataTable.setData(resultList)); - } - - CompletableFuture countFuture = items.countAsync().whenComplete((count, throwable) -> { - dataTable.setTotalCount(count); - }); - CompletableFuture.allOf(itemsFuture, countFuture).join(); - return dataTable; - } - - public void unlock(UUID uuid) throws Exception { - apiContext.getOperationsContext().getDatabaseRepository().getDmpDao() - .asQueryable().where((builder, root) -> builder.equal(root.get("id"), uuid)) - .update(root -> root.get("status"), DMP.DMPStatus.ACTIVE.getValue()); - return; - } - - public FileEnvelope getWordDocument(String id, Principal principal, ConfigLoader configLoader) throws IOException { - return this.getWordDocument(id, principal, configLoader, false); - } - - public FileEnvelope getWordDocument(String id, Principal principal, ConfigLoader configLoader, Boolean versioned) throws IOException { - WordBuilder wordBuilder = new WordBuilder(); - VisibilityRuleService visibilityRuleService = this.utilitiesService.getVisibilityRuleService(); - DatasetWizardModel dataset = new DatasetWizardModel(); - XWPFDocument document = configLoader.getDocument(); - - eu.eudat.data.entities.DMP dmpEntity = databaseRepository.getDmpDao().find(UUID.fromString(id)); - if (!dmpEntity.isPublic() && dmpEntity.getUsers().stream().filter(userInfo -> userInfo.getUser().getId() == principal.getId()).collect(Collectors.toList()).size() == 0) - throw new UnauthorisedException(); - - // DMP info on top of the document. - wordBuilder.addParagraphContent("Data Management Plan Information", document, ParagraphStyle.HEADER1, BigInteger.ZERO); - // DMP title custom style. - wordBuilder.addParagraphContent(dmpEntity.getLabel(), document, ParagraphStyle.HEADER2, BigInteger.ZERO); - wordBuilder.addParagraphContent(dmpEntity.getDescription(), document, ParagraphStyle.TEXT, BigInteger.ZERO); - - wordBuilder.addParagraphContent("Funder", document, ParagraphStyle.HEADER3, BigInteger.ZERO); - if (dmpEntity.getGrant().getFunder() != null) - wordBuilder.addParagraphContent(dmpEntity.getGrant().getFunder().getLabel(), document, ParagraphStyle.TEXT, BigInteger.ZERO); - - wordBuilder.addParagraphContent("Grant", document, ParagraphStyle.HEADER3, BigInteger.ZERO); - wordBuilder.addParagraphContent(dmpEntity.getGrant().getLabel(), document, ParagraphStyle.TEXT, BigInteger.ZERO); - - wordBuilder.addParagraphContent("Organisations", document, ParagraphStyle.HEADER3, BigInteger.ZERO); - if (dmpEntity.getOrganisations().size() > 0) { - wordBuilder.addParagraphContent(dmpEntity.getOrganisations().stream().map(Organisation::getLabel).collect(Collectors.joining(", ")) - , document, ParagraphStyle.TEXT, BigInteger.ZERO); - } - - wordBuilder.addParagraphContent("Researchers", document, ParagraphStyle.HEADER3, BigInteger.ZERO); - if (dmpEntity.getResearchers().size() > 0) { - wordBuilder.addParagraphContent(dmpEntity.getResearchers().stream().map(Researcher::getLabel).collect(Collectors.joining(", ")) - , document, ParagraphStyle.TEXT, BigInteger.ZERO); - } - - /*wordBuilder.addParagraphContent("DMP Profile", document, ParagraphStyle.HEADER2, BigInteger.ZERO); - if (dmpEntity.getProfile() != null){ - wordBuilder.addParagraphContent(dmpEntity.getProfile().getLabel(), document, ParagraphStyle.TEXT, BigInteger.ZERO); - }*/ - - // Page break at the end of the DMP title. - XWPFParagraph parBreakDMP = document.createParagraph(); - parBreakDMP.setPageBreak(true); - - wordBuilder.addParagraphContent("Datasets", document, ParagraphStyle.HEADER1, BigInteger.ZERO); - // Space below Datasets. - XWPFParagraph parBreakDatasets = document.createParagraph(); - dmpEntity.getDataset().stream() - .filter(item -> item.getStatus() != Dataset.Status.CANCELED.getValue()) - .filter(item -> item.getStatus() != Dataset.Status.DELETED.getValue()) - .forEach(datasetEntity -> { - Map properties = new HashMap<>(); - if (datasetEntity.getProperties() != null) { - JSONObject jObject = new JSONObject(datasetEntity.getProperties()); - properties = jObject.toMap(); - } - - // Custom style for the Dataset title. - //wordBuilder.addParagraphContent("Title: " + datasetEntity.getLabel(), document, ParagraphStyle.HEADER1, BigInteger.ZERO); - XWPFParagraph datasetLabelParagraph = document.createParagraph(); - datasetLabelParagraph.setStyle("Heading2"); - XWPFRun runDatasetTitle1 = datasetLabelParagraph.createRun(); - runDatasetTitle1.setText("Title: "); - runDatasetTitle1.setBold(true); - runDatasetTitle1.setFontSize(12); - XWPFRun runDatasetTitle = datasetLabelParagraph.createRun(); - runDatasetTitle.setText(datasetEntity.getLabel()); - runDatasetTitle.setColor("2E75B6"); - runDatasetTitle.setBold(true); - runDatasetTitle.setFontSize(12); - - XWPFParagraph datasetTemplateParagraph = document.createParagraph(); - datasetTemplateParagraph.setStyle("Heading3"); - XWPFRun runDatasetTemplate1 = datasetTemplateParagraph.createRun(); - runDatasetTemplate1.setText("Template: "); - runDatasetTemplate1.setBold(true); - runDatasetTemplate1.setFontSize(12); - XWPFRun runDatasetTemplate = datasetTemplateParagraph.createRun(); - runDatasetTemplate.setText(datasetEntity.getProfile().getLabel()); - runDatasetTemplate.setColor("2E75B6"); - runDatasetTemplate.setBold(true); - runDatasetTemplate.setFontSize(12); - - XWPFParagraph externalReferencesParagraph = document.createParagraph(); - externalReferencesParagraph.setStyle("Heading3"); - XWPFRun externalReferencesRun = externalReferencesParagraph.createRun(); - externalReferencesRun.setText("External References"); - externalReferencesRun.setColor("2E75B6"); - externalReferencesRun.setBold(true); - externalReferencesRun.setFontSize(12); - - wordBuilder.addParagraphContent("Data Repositories", document, ParagraphStyle.HEADER4, BigInteger.ZERO); - if (datasetEntity.getDatasetDataRepositories().size() > 0) { - wordBuilder.addParagraphContent(datasetEntity.getDatasetDataRepositories().stream().map(DatasetDataRepository::getDataRepository).map(DataRepository::getLabel).collect(Collectors.joining(", ")) - , document, ParagraphStyle.TEXT, BigInteger.ZERO); - } - wordBuilder.addParagraphContent("External Datasets", document, ParagraphStyle.HEADER4, BigInteger.ZERO); - if (datasetEntity.getDatasetExternalDatasets().size() > 0) { - wordBuilder.addParagraphContent(datasetEntity.getDatasetExternalDatasets().stream().map(DatasetExternalDataset::getExternalDataset).map(ExternalDataset::getLabel).collect(Collectors.joining(", ")) - , document, ParagraphStyle.TEXT, BigInteger.ZERO); - } - wordBuilder.addParagraphContent("Registries", document, ParagraphStyle.HEADER4, BigInteger.ZERO); - if (datasetEntity.getRegistries().size() > 0) { - wordBuilder.addParagraphContent(datasetEntity.getRegistries().stream().map(Registry::getLabel).collect(Collectors.joining(", ")) - , document, ParagraphStyle.TEXT, BigInteger.ZERO); - } - wordBuilder.addParagraphContent("Services", document, ParagraphStyle.HEADER4, BigInteger.ZERO); - if (datasetEntity.getServices().size() > 0) { - wordBuilder.addParagraphContent(datasetEntity.getServices().stream().map(DatasetService::getService).map(Service::getLabel).collect(Collectors.joining(", ")) - , document, ParagraphStyle.TEXT, BigInteger.ZERO); - } - /*wordBuilder.addParagraphContent("Tags", document, ParagraphStyle.HEADER3, BigInteger.ZERO); - if (datasetEntity.().size() > 0) { - wordBuilder.addParagraphContent(datasetEntity.getServices().stream().map(DatasetService::getService).map(Service::getLabel).collect(Collectors.joining(", ")) - , document, ParagraphStyle.HEADER4, BigInteger.ZERO); - }*/ - - - wordBuilder.addParagraphContent(datasetEntity.getDescription(), document, ParagraphStyle.TEXT, BigInteger.ZERO); - - // Dataset Description custom style. - XWPFParagraph datasetDescriptionParagraph = document.createParagraph(); - datasetDescriptionParagraph.setStyle("Heading3"); - XWPFRun datasetDescriptionRun = datasetDescriptionParagraph.createRun(); - datasetDescriptionRun.setText("Dataset Description"); - datasetDescriptionRun.setColor("2E75B6"); - datasetDescriptionRun.setBold(true); - datasetDescriptionRun.setFontSize(12); - - PagedDatasetProfile pagedDatasetProfile = datasetManager.getPagedProfile(dataset, datasetEntity); - visibilityRuleService.setProperties(properties); - visibilityRuleService.buildVisibilityContext(pagedDatasetProfile.getRules()); - try { - wordBuilder.build(document, pagedDatasetProfile, visibilityRuleService); - } catch (IOException e) { - logger.error(e.getMessage(), e); - } - // Page break at the end of the Dataset. - XWPFParagraph parBreakDataset = document.createParagraph(); - }); - - // Removes the top empty headings. - for (int i = 0; i < 6; i++) { - document.removeBodyElement(0); - } - - String fileName = ""; - if (versioned) { - fileName = dmpEntity.getLabel() + " v" + dmpEntity.getVersion(); - } else { - fileName = dmpEntity.getLabel(); - } - fileName = fileName.replaceAll("[^a-zA-Z0-9+ ]", ""); - FileEnvelope exportEnvelope = new FileEnvelope(); - exportEnvelope.setFilename(fileName + ".docx"); - String uuid = UUID.randomUUID().toString(); - File exportFile = new File(this.environment.getProperty("temp.temp") + uuid + ".docx"); - FileOutputStream out = new FileOutputStream(exportFile); - document.write(out); - out.close(); - exportEnvelope.setFile(exportFile); - - return exportEnvelope; - } - - /*public File getPdfDocument(String id) throws InstantiationException, IllegalAccessException, InterruptedException, IOException { - File file = this.getWordDocument(id); - String fileName = file.getName(); - if (fileName.endsWith(".docx")){ - fileName = fileName.substring(0, fileName.length() - 5); - } - return this.datasetManager.convertToPDF(file, environment, fileName); - }*/ - - public eu.eudat.models.data.dmp.DataManagementPlan getSingle(String id, Principal principal) { + public eu.eudat.models.data.dmp.DataManagementPlan getSingle(String id, Principal principal, boolean isPublic) throws Exception { + eu.eudat.models.data.dmp.DataManagementPlan dataManagementPlan = new eu.eudat.models.data.dmp.DataManagementPlan(); DMP dataManagementPlanEntity = databaseRepository.getDmpDao().find(UUID.fromString(id)); - if (dataManagementPlanEntity.getUsers().stream().noneMatch(userInfo -> userInfo.getUser().getId() == principal.getId())) { + if (!isPublic && principal == null) { + throw new UnauthorisedException(); + } else if (!isPublic && (dataManagementPlanEntity.getUsers().stream().noneMatch(userInfo -> userInfo.getUser().getId() == principal.getId()))) { if (!dataManagementPlanEntity.isPublic()) { throw new UnauthorisedException(); } + } else if (isPublic && !dataManagementPlanEntity.isPublic()) { + throw new ForbiddenException("Selected DMP is not public"); } - eu.eudat.models.data.dmp.DataManagementPlan dataManagementPlan = new eu.eudat.models.data.dmp.DataManagementPlan(); dataManagementPlan.fromDataModel(dataManagementPlanEntity); + if (isPublic) { + dataManagementPlan.setDatasets(dataManagementPlan.getDatasets().stream().filter(dataset -> dataset.getStatus() == Dataset.Status.FINALISED.getValue()).collect(Collectors.toList())); + } Map dmpProperties = dataManagementPlanEntity.getDmpProperties() != null ? new org.json.JSONObject(dataManagementPlanEntity.getDmpProperties()).toMap() : null; if (dmpProperties != null && dataManagementPlan.getDynamicFields() != null) @@ -435,72 +225,29 @@ public class DataManagementPlanManager { return dataManagementPlan; } - public DataManagementPlanOverviewModel getOverviewSingle(String id, Principal principal) throws Exception { + public DataManagementPlanOverviewModel getOverviewSingle(String id, Principal principal, boolean isPublic) throws Exception { DMP dataManagementPlanEntity = databaseRepository.getDmpDao().find(UUID.fromString(id)); if (dataManagementPlanEntity.getStatus() == DMP.DMPStatus.DELETED.getValue()) { throw new Exception("DMP is deleted."); } - if (dataManagementPlanEntity.getUsers() - .stream().filter(userInfo -> userInfo.getUser().getId() == principal.getId()) - .collect(Collectors.toList()).size() == 0) + if (!isPublic && principal == null) { throw new UnauthorisedException(); + } else + if (!isPublic && dataManagementPlanEntity.getUsers() + .stream().noneMatch(userInfo -> userInfo.getUser().getId() == principal.getId())) { + throw new UnauthorisedException(); + } else if (isPublic && !dataManagementPlanEntity.isPublic()) { + throw new ForbiddenException("Selected DMP is not public"); + } DataManagementPlanOverviewModel datamanagementPlan = new DataManagementPlanOverviewModel(); datamanagementPlan.fromDataModelDatasets(dataManagementPlanEntity); + if (isPublic) { + datamanagementPlan.setDatasets(datamanagementPlan.getDatasets().stream().filter(dataset -> dataset.getStatus() == Dataset.Status.FINALISED.getValue()).collect(Collectors.toList())); + } return datamanagementPlan; } - public eu.eudat.models.data.dmp.DataManagementPlan getSinglePublic(String id, DynamicGrantConfiguration dynamicGrantConfiguration) throws Exception { - DMP dataManagementPlanEntity = databaseRepository.getDmpDao().find(UUID.fromString(id)); - - if (dataManagementPlanEntity != null && dataManagementPlanEntity.getStatus() == 1) { - eu.eudat.models.data.dmp.DataManagementPlan datamanagementPlan = new eu.eudat.models.data.dmp.DataManagementPlan(); - datamanagementPlan.fromDataModel(dataManagementPlanEntity); - datamanagementPlan.setDatasets(datamanagementPlan.getDatasets().stream().filter(dataset -> dataset.getStatus() == Dataset.Status.FINALISED.getValue()).collect(Collectors.toList())); - Map dmpProperties = dataManagementPlanEntity.getDmpProperties() != null ? new org.json.JSONObject(dataManagementPlanEntity.getDmpProperties()).toMap() : null; -// datamanagementPlan.setDynamicFields(dynamicGrantConfiguration.getFields().stream().map(item -> { -// DynamicFieldWithValue fieldWithValue = new DynamicFieldWithValue(); -// fieldWithValue.setId(item.getId()); -// fieldWithValue.setDependencies(item.getDependencies()); -// fieldWithValue.setName(item.getName()); -// fieldWithValue.setQueryProperty(item.getQueryProperty()); -// fieldWithValue.setRequired(item.getRequired()); -// return fieldWithValue; -// }).collect(Collectors.toList())); - - if (dmpProperties != null && datamanagementPlan.getDynamicFields() != null) - datamanagementPlan.getDynamicFields().forEach(item -> { - Map properties = (Map) dmpProperties.get(item.getId()); - if (properties != null) - item.setValue(new Tuple<>(properties.get("id"), properties.get("label"))); - }); - return datamanagementPlan; - } else { - throw new Exception("Selected DMP is not public"); - } - } - - public DataManagementPlanOverviewModel getOverviewSinglePublic(String id) throws Exception { - DMP dataManagementPlanEntity = databaseRepository.getDmpDao().find(UUID.fromString(id)); - if (dataManagementPlanEntity != null && dataManagementPlanEntity.getStatus() == 1) { - DataManagementPlanOverviewModel datamanagementPlan = new DataManagementPlanOverviewModel(); - datamanagementPlan.fromDataModelDatasets(dataManagementPlanEntity); - datamanagementPlan.setDatasets(datamanagementPlan.getDatasets().stream().filter(dataset -> dataset.getStatus() == Dataset.Status.FINALISED.getValue()).collect(Collectors.toList())); - return datamanagementPlan; - } else { - throw new Exception("Selected DMP is not public"); - } - } - - public List getWithCriteria(DMPDao dmpsRepository, DataManagementPlanCriteriaRequest dataManagementPlanCriteria, Principal principal) throws IllegalAccessException, InstantiationException { - UUID principalID = principal.getId(); - QueryableList items = dmpsRepository.getWithCriteria(dataManagementPlanCriteria.getCriteria()).withHint(HintedModelFactory.getHint(DataManagementPlan.class)); - List roles = new LinkedList<>(); - QueryableList authenticatedItems = dmpsRepository.getAuthenticated(items, principalID, roles); - List datamanagementPlans = authenticatedItems.select(item -> new DataManagementPlan().fromDataModel(item)); - return datamanagementPlans; - } - public List> getDynamicFields(String id, DynamicGrantConfiguration dynamicGrantConfiguration, DynamicFieldsCriteria criteria) throws IllegalAccessException, InstantiationException { List> result = new LinkedList<>(); RestTemplate restTemplate = new RestTemplate(); @@ -510,13 +257,13 @@ public class DataManagementPlanManager { HttpEntity entity = new HttpEntity<>("parameters", headers); Property property = dynamicGrantConfiguration.getConfiguration().getConfigurationProperties().stream() - .filter(item -> item.getId().equals(id)).findFirst().orElse(null); + .filter(item -> item.getId().equals(id)).findFirst().orElse(null); StringBuilder stringBuilder = new StringBuilder(); if (criteria.getLike() != null) stringBuilder.append("?search=" + criteria.getLike()); if (property.getDependencies() != null && !property.getDependencies().isEmpty() && criteria.getDynamicFields() != null && !criteria.getDynamicFields().isEmpty()) { property.getDependencies().stream().forEach(item -> { DynamicFieldsCriteria.DynamicFieldDependencyCriteria dependencyCriteria = criteria.getDynamicFields().stream().filter(dfield -> dfield.getProperty().equals(item.getId())) - .findFirst().orElse(null); + .findFirst().orElse(null); if (dependencyCriteria != null) { if (criteria.getLike() != null || property.getDependencies().indexOf(item) > 0) stringBuilder.append("&"); @@ -544,6 +291,24 @@ public class DataManagementPlanManager { return result; } + public DataTableData getDatasetProfilesUsedByDMP(DatasetProfileTableRequestItem datasetProfileTableRequestItem, Principal principal) { + datasetProfileTableRequestItem.getCriteria().setFilter(DatasetProfileCriteria.DatasetProfileFilter.DMPs.getValue()); + datasetProfileTableRequestItem.getCriteria().setUserId(principal.getId()); + + QueryableList items = apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().getWithCriteria(datasetProfileTableRequestItem.getCriteria()); + List listingModels = items.select(item -> new DatasetProfileListingModel().fromDataModel(item)); + + DataTableData data = new DataTableData<>(); + data.setData(listingModels); + data.setTotalCount((long) listingModels.size()); + + return data; + } + + /* + * Data Management + * */ + public DMP createOrUpdate(ApiContext apiContext, DataManagementPlanEditorModel dataManagementPlan, Principal principal) throws Exception { boolean setNotification = false; if (dataManagementPlan.getId() != null) { @@ -557,8 +322,8 @@ public class DataManagementPlanManager { } List datasetList = new ArrayList<>(dmp1.getDataset()); for (Dataset dataset : datasetList) { - if (dataManagementPlan.getProfiles().stream().filter(associatedProfile -> dataset.getProfile().getId().equals(associatedProfile.getId())).findAny().orElse(null) == null) - throw new Exception("Dataset Template for Dataset Description is missing from the DMP."); + if (dataManagementPlan.getProfiles().stream().filter(associatedProfile -> dataset.getProfile().getId().equals(associatedProfile.getId())).findAny().orElse(null) == null) + throw new Exception("Dataset Template for Dataset Description is missing from the DMP."); } if (dataManagementPlan.getStatus() == (int) DMP.DMPStatus.FINALISED.getValue() && dmp1.getStatus().equals(DMP.DMPStatus.FINALISED.getValue())) throw new Exception("DMP is finalized, therefore cannot be edited."); @@ -588,7 +353,7 @@ public class DataManagementPlanManager { newDmp.setCreated(dmp.getCreated() == null ? new Date() : dmp.getCreated()); if (newDmp.getUsers()!= null && newDmp.getUsers().stream().filter(userInfo -> userInfo.getUser().getId() == principal.getId()) - .collect(Collectors.toList()).size() == 0) { + .collect(Collectors.toList()).size() == 0) { List userDMPList = new ArrayList<>(newDmp.getUsers()); for (UserInfoListingModel userInfoListingModel : dataManagementPlan.getUsers()) { for (UserDMP userDMP : userDMPList) { @@ -611,8 +376,8 @@ public class DataManagementPlanManager { if (dataManagementPlan.getStatus() == DMP.DMPStatus.FINALISED.getValue()) { if (dataManagementPlan.getDatasetsToBeFinalized() != null && !dataManagementPlan.getDatasetsToBeFinalized().isEmpty()) { apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() - .asQueryable().where((builder, root) -> root.get("id").in(dataManagementPlan.getDatasetsToBeFinalized())) - .update(root -> root.get("status"), Dataset.Status.FINALISED.getValue()); + .asQueryable().where((builder, root) -> root.get("id").in(dataManagementPlan.getDatasetsToBeFinalized())) + .update(root -> root.get("status"), Dataset.Status.FINALISED.getValue()); List datasetsToBeCanceled = new LinkedList<>(); for (DatasetListingModel dataset : dataManagementPlan.getDatasets()) { @@ -622,8 +387,8 @@ public class DataManagementPlanManager { } if (!datasetsToBeCanceled.isEmpty()) apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() - .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeCanceled)) - .update(root -> root.get("status"), Dataset.Status.CANCELED.getValue()); + .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeCanceled)) + .update(root -> root.get("status"), Dataset.Status.CANCELED.getValue()); } else { List datasetsToBeCanceled = new LinkedList<>(); for (DatasetListingModel dataset : dataManagementPlan.getDatasets()) { @@ -633,8 +398,8 @@ public class DataManagementPlanManager { } if (!datasetsToBeCanceled.isEmpty()) apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() - .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeCanceled)) - .update(root -> root.get("status"), Dataset.Status.CANCELED.getValue()); + .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeCanceled)) + .update(root -> root.get("status"), Dataset.Status.CANCELED.getValue()); } } @@ -654,56 +419,6 @@ public class DataManagementPlanManager { return newDmp; } - private void sendNotification(DMP dmp, UserInfo user, NotificationType notificationType) { - List userDMPS = databaseRepository.getUserDmpDao().asQueryable().where(((builder, root) -> builder.equal(root.get("dmp").get("id"), dmp.getId()))).toList(); - for (UserDMP userDMP : userDMPS) { - if (!userDMP.getUser().getId().equals(user.getId())) { - Notification notification = new Notification(); - notification.setUserId(user); - notification.setType(notificationType); - notification.setNotifyState(NotifyState.PENDING); - notification.setIsActive(ActiveStatus.ACTIVE); - notification.setData("{" + - "\"userId\": \"" + userDMP.getUser().getId() + "\"" + - ", \"id\": \"" + userDMP.getDmp().getId() + "\"" + - ", \"name\": \"" + userDMP.getDmp().getLabel() + "\"" + - ", \"path\": \"" + notificationPaths.get(notificationType) +"\"" + - "}"); - notification.setCreatedAt(new Date()); - notification.setUpdatedAt(notification.getCreatedAt()); - notification.setContactTypeHint(ContactType.EMAIL); - notification.setContactHint(userDMP.getUser().getEmail()); - databaseRepository.getNotificationDao().createOrUpdate(notification); - } - } - - } - - private void assignUser(DMP dmp, UserInfo userInfo) { - UserDMP userDMP = new UserDMP(); - userDMP.setDmp(dmp); - userDMP.setUser(userInfo); - userDMP.setRole(UserDMP.UserDMPRoles.OWNER.getValue()); - databaseRepository.getUserDmpDao().createOrUpdate(userDMP); - } - - private void updateGroupIndex(UUID groupId) { - DataManagementPlanCriteria criteria = new DataManagementPlanCriteria(); - criteria.setGroupIds(Collections.singletonList(groupId)); - criteria.setAllVersions(true); - List dmps = databaseRepository.getDmpDao().getWithCriteria(criteria).toList(); - for (DMP dmp: dmps) { - try { - if (dmp.getUsers() != null) { - logger.info(dmp.getUsers().toString()); - } - this.updateIndex(dmp); - } catch (IOException e) { - logger.error(e.getMessage(), e); - } - } - } - public void newVersion(UUID uuid, DataManagementPlanNewVersionModel dataManagementPlan, Principal principal) throws Exception { DMP oldDmp = databaseRepository.getDmpDao().find(uuid); if (!isUserOwnerOfDmp(oldDmp, principal)) { @@ -850,11 +565,21 @@ public class DataManagementPlanManager { private void createOrganisationsIfTheyDontExist(DMP newDmp, OrganisationDao organisationRepository) { if (newDmp.getOrganisations() != null && !newDmp.getOrganisations().isEmpty()) { for (eu.eudat.data.entities.Organisation organisation : newDmp.getOrganisations()) { - OrganisationCriteria criteria = new OrganisationCriteria(); - criteria.setLike(organisation.getReference()); - List entries = organisationRepository.getWithCriteria(criteria).toList(); - if (entries != null && !entries.isEmpty()) organisation.setId(entries.get(0).getId()); - else organisationRepository.createOrUpdate(organisation); + boolean createNew = false; + if (organisation.getReference() != null) { + OrganisationCriteria criteria = new OrganisationCriteria(); + criteria.setLike(organisation.getReference()); + List entries = organisationRepository.getWithCriteria(criteria).toList(); + if (entries != null && !entries.isEmpty()) organisation.setId(entries.get(0).getId()); + else createNew = true; + } else { + createNew = true; + } + + if (createNew) { + organisation.setReference("Internal:" + UUID.randomUUID().toString()); + organisationRepository.createOrUpdate(organisation); + } } } } @@ -921,51 +646,6 @@ public class DataManagementPlanManager { } } - private void checkIfUserCanEditGrant(DMP dmp, UserInfo user) throws Exception{ - if (dmp.getGrant().getId() != null) { - Grant grant = apiContext.getOperationsContext().getDatabaseRepository().getGrantDao().find(dmp.getGrant().getId()); - if (grant.getFunder() != null && dmp.getGrant().getFunder() != null - && !grant.getFunder().getId().equals(dmp.getGrant().getFunder().getId())) { - if (grant.getCreationUser() == null) { - throw new Exception("Grant has no user, therefore, cannot be edited."); - } - if (!grant.getCreationUser().getId().equals(user.getId())) { - throw new Exception("User is not the owner of the Grant, therefore, cannot edit it."); - } - } - } - } - - private void checkDmpValidationRules(DMP dmp) throws Exception { - if (dmp.getLabel() == null || dmp.getLabel().trim().isEmpty()) { - throw new Exception("DMP has no label."); - } - if (dmp.getAssociatedDmps().size() == 0) { - throw new Exception("DMP does not contain Dataset Templates."); - } - if (dmp.getGrant() == null) { - throw new Exception("DMP has no Grant assigned."); - } - } - - private void assignGrandUserIfInternal(DMP dmp, UserInfo user) { - if (dmp.getGrant().getCreationUser() == null && (dmp.getGrant().getReference() != null && dmp.getGrant().getReference().startsWith("dmp:"))) { - dmp.getGrant().setCreationUser(user); - } - } - - private void assignFunderUserIfInternal(DMP dmp, UserInfo user) { - if (dmp.getGrant().getFunder().getCreationUser() == null && ( dmp.getGrant().getFunder().getReference() != null && dmp.getGrant().getFunder().getReference().startsWith("dmp:"))) { - dmp.getGrant().getFunder().setCreationUser(user); - } - } - - private void assignProjectUserIfInternal(DMP dmp, UserInfo user) { - if (dmp.getProject().getCreationUser() == null && (dmp.getProject().getReference() != null && dmp.getProject().getReference().startsWith("dmp:"))) { - dmp.getProject().setCreationUser(user); - } - } - private void copyDatasets(DMP newDmp, DatasetDao datasetDao) { List> futures = new LinkedList<>(); for (Dataset dataset : newDmp.getDataset()) { @@ -985,58 +665,58 @@ public class DataManagementPlanManager { logger.error(e.getMessage(), e); } datasetDao.asQueryable().withHint(HintedModelFactory.getHint(DatasetListingModel.class)).where((builder, root) -> builder.equal(root.get("id"), dataset.getId())).getSingleAsync() - .thenApplyAsync(entityDataset -> { - Dataset newDataset = new Dataset(); - newDataset.update(entityDataset); - newDataset.setDmp(newDmp); - newDataset.setStatus(Dataset.Status.SAVED.getValue()); - if (newDataset.getDatasetDataRepositories() != null) { - newDataset.setDatasetDataRepositories(newDataset.getDatasetDataRepositories().stream().map(item -> { - DataRepository dataRepository = new DataRepository(); - dataRepository.setId(item.getDataRepository().getId()); + .thenApplyAsync(entityDataset -> { + Dataset newDataset = new Dataset(); + newDataset.update(entityDataset); + newDataset.setDmp(newDmp); + newDataset.setStatus(Dataset.Status.SAVED.getValue()); + if (newDataset.getDatasetDataRepositories() != null) { + newDataset.setDatasetDataRepositories(newDataset.getDatasetDataRepositories().stream().map(item -> { + DataRepository dataRepository = new DataRepository(); + dataRepository.setId(item.getDataRepository().getId()); - DatasetDataRepository datasetDataRepository = new DatasetDataRepository(); - datasetDataRepository.setDataRepository(dataRepository); - datasetDataRepository.setDataset(newDataset); - datasetDataRepository.setData(item.getData()); - return datasetDataRepository; - }).collect(Collectors.toSet())); - } + DatasetDataRepository datasetDataRepository = new DatasetDataRepository(); + datasetDataRepository.setDataRepository(dataRepository); + datasetDataRepository.setDataset(newDataset); + datasetDataRepository.setData(item.getData()); + return datasetDataRepository; + }).collect(Collectors.toSet())); + } - if (newDataset.getDatasetExternalDatasets() != null) { - newDataset.setDatasetExternalDatasets(newDataset.getDatasetExternalDatasets().stream().map(item -> { - ExternalDataset externalDataset = new ExternalDataset(); - externalDataset.setId(item.getExternalDataset().getId()); - DatasetExternalDataset datasetExternalDataset = new DatasetExternalDataset(); - datasetExternalDataset.setExternalDataset(externalDataset); - datasetExternalDataset.setDataset(newDataset); - datasetExternalDataset.setData(item.getData()); - return datasetExternalDataset; - }).collect(Collectors.toSet())); - } + if (newDataset.getDatasetExternalDatasets() != null) { + newDataset.setDatasetExternalDatasets(newDataset.getDatasetExternalDatasets().stream().map(item -> { + ExternalDataset externalDataset = new ExternalDataset(); + externalDataset.setId(item.getExternalDataset().getId()); + DatasetExternalDataset datasetExternalDataset = new DatasetExternalDataset(); + datasetExternalDataset.setExternalDataset(externalDataset); + datasetExternalDataset.setDataset(newDataset); + datasetExternalDataset.setData(item.getData()); + return datasetExternalDataset; + }).collect(Collectors.toSet())); + } - if (newDataset.getRegistries() != null) { - newDataset.setRegistries(newDataset.getRegistries().stream().map(item -> { - Registry registry = new Registry(); - registry.setId(item.getId()); - return registry; - }).collect(Collectors.toSet())); - } + if (newDataset.getRegistries() != null) { + newDataset.setRegistries(newDataset.getRegistries().stream().map(item -> { + Registry registry = new Registry(); + registry.setId(item.getId()); + return registry; + }).collect(Collectors.toSet())); + } - if (newDataset.getServices() != null) { - newDataset.setServices(newDataset.getServices().stream().map(item -> { - Service service = new Service(); - service.setId(item.getId()); - DatasetService datasetService = new DatasetService(); - datasetService.setService(service); - datasetService.setDataset(newDataset); - datasetService.setData(item.getData()); - return datasetService; - }).collect(Collectors.toSet())); - } - newDataset.setCreated(new Date()); - return newDataset; - }).thenApplyAsync(item -> { + if (newDataset.getServices() != null) { + newDataset.setServices(newDataset.getServices().stream().map(item -> { + Service service = new Service(); + service.setId(item.getId()); + DatasetService datasetService = new DatasetService(); + datasetService.setService(service); + datasetService.setDataset(newDataset); + datasetService.setData(item.getData()); + return datasetService; + }).collect(Collectors.toSet())); + } + newDataset.setCreated(new Date()); + return newDataset; + }).thenApplyAsync(item -> { futures.add(datasetDao.createOrUpdateAsync(item).whenComplete(((dataset1, throwable) -> { eu.eudat.elastic.entities.Dataset datasetElastic = new eu.eudat.elastic.entities.Dataset(); datasetElastic.setId(dataset1.getId().toString()); @@ -1051,7 +731,7 @@ public class DataManagementPlanManager { datasetElastic.setCollaborators(dataset1.getDmp().getUsers().stream().map(user -> { Collaborator collaborator = new Collaborator(); collaborator.setId(user.getId().toString()); - // collaborator.setName(user.getUser().getName()); + // collaborator.setName(user.getUser().getName()); return collaborator; }).collect(Collectors.toList())); } @@ -1085,12 +765,269 @@ public class DataManagementPlanManager { } } + public void makePublic(UUID id, Principal principal) throws Exception { + DMP dmp = this.apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(id); + // Check if dmp is finalized and if user is owner. + if (!isUserOwnerOfDmp(dmp, principal)) + throw new Exception("User does not have the privilege to do this action."); + if (!dmp.getStatus().equals(DMP.DMPStatus.FINALISED.getValue())) + throw new Exception("DMP is not finalized"); + dmp.setPublic(true); + apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); + this.updateIndex(dmp); + DataManagementPlanCriteria criteria = new DataManagementPlanCriteria(); + criteria.setGroupIds(Collections.singletonList(dmp.getGroupId())); + criteria.setAllVersions(true); + apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().getWithCriteria(criteria).toList().stream().forEach(dmp1 -> { + dmp1.getDataset().forEach(dataset -> { + try { + List tags = new ArrayList<>(); + eu.eudat.elastic.entities.Dataset elastic = apiContext.getOperationsContext().getElasticRepository().getDatasetRepository().findDocument(dataset.getId().toString()); + if (elastic != null) { + tags = elastic.getTags(); + } + this.datasetManager.updateTags(dataset, tags); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + }); + }); + UserInfo user = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(principal.getId()); + sendNotification(dmp, user, NotificationType.DMP_PUBLISH); + } + + public void makeFinalize(UUID id, Principal principal, DatasetsToBeFinalized datasetsToBeFinalized) throws Exception { + DMP dmp = this.apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(id); + if (!isUserOwnerOfDmp(dmp, principal)) + throw new Exception("User does not have the privilege to do this action."); + if (dmp.getStatus().equals(DMP.DMPStatus.FINALISED.getValue())) + throw new Exception("DMP is already finalized"); + dmp.setStatus(DMP.DMPStatus.FINALISED.getValue()); + apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); + this.updateIndex(dmp); + List indexDatasets = new ArrayList<>(); + if (datasetsToBeFinalized != null && datasetsToBeFinalized.getUuids() != null && !datasetsToBeFinalized.getUuids().isEmpty()) { + apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() + .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeFinalized.getUuids())) + .update(root -> root.get("status"), Dataset.Status.FINALISED.getValue()); + List finalizedDatasets = dmp.getDataset().stream().filter(dataset -> datasetsToBeFinalized.getUuids().contains(dataset.getId())).collect(Collectors.toList()); + finalizedDatasets.forEach(dataset -> dataset.setStatus(Dataset.Status.FINALISED.getValue())); + indexDatasets.addAll(finalizedDatasets); + List datasetsToBeCanceled = new LinkedList<>(); + for (Dataset dataset : dmp.getDataset()) { + if (!dataset.getStatus().equals(Dataset.Status.FINALISED.getValue()) && !datasetsToBeFinalized.getUuids().contains(dataset.getId())) { + datasetsToBeCanceled.add(dataset.getId()); + } + } + if (!datasetsToBeCanceled.isEmpty()) { + apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() + .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeCanceled)) + .update(root -> root.get("status"), Dataset.Status.CANCELED.getValue()); + List cancelledDatasets = dmp.getDataset().stream().filter(dataset -> datasetsToBeCanceled.contains(dataset.getId())).collect(Collectors.toList()); + cancelledDatasets.forEach(dataset -> dataset.setStatus(Dataset.Status.CANCELED.getValue())); + indexDatasets.addAll(cancelledDatasets); + } + } else { + List datasetsToBeCanceled = new LinkedList<>(); + for (Dataset dataset : dmp.getDataset()) { + if (!dataset.getStatus().equals(Dataset.Status.FINALISED.getValue())) { + datasetsToBeCanceled.add(dataset.getId()); + } + } + if (!datasetsToBeCanceled.isEmpty()) { + apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() + .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeCanceled)) + .update(root -> root.get("status"), Dataset.Status.CANCELED.getValue()); + List cancelledDatasets = dmp.getDataset().stream().filter(dataset -> datasetsToBeCanceled.contains(dataset.getId())).collect(Collectors.toList()); + cancelledDatasets.forEach(dataset -> dataset.setStatus(Dataset.Status.CANCELED.getValue())); + indexDatasets.addAll(cancelledDatasets); + } + + UserInfo user = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(principal.getId()); + sendNotification(dmp, user, NotificationType.DMP_FINALISED); + } + this.updateDatasetsIndex(indexDatasets); + } + + /* + * Export Data + * */ + + public FileEnvelope getWordDocument(String id, Principal principal, ConfigLoader configLoader) throws IOException { + return this.getWordDocument(id, principal, configLoader, false); + } + + public FileEnvelope getWordDocument(String id, Principal principal, ConfigLoader configLoader, Boolean versioned) throws IOException { + WordBuilder wordBuilder = new WordBuilder(); + VisibilityRuleService visibilityRuleService = this.utilitiesService.getVisibilityRuleService(); + DatasetWizardModel dataset = new DatasetWizardModel(); + XWPFDocument document = configLoader.getDocument(); + + eu.eudat.data.entities.DMP dmpEntity = databaseRepository.getDmpDao().find(UUID.fromString(id)); + if (!dmpEntity.isPublic() && dmpEntity.getUsers().stream().filter(userInfo -> userInfo.getUser().getId() == principal.getId()).collect(Collectors.toList()).size() == 0) + throw new UnauthorisedException(); + + // DMP info on top of the document. + wordBuilder.addParagraphContent("Data Management Plan Information", document, ParagraphStyle.HEADER1, BigInteger.ZERO); + // DMP title custom style. + wordBuilder.addParagraphContent(dmpEntity.getLabel(), document, ParagraphStyle.HEADER2, BigInteger.ZERO); + wordBuilder.addParagraphContent(dmpEntity.getDescription(), document, ParagraphStyle.TEXT, BigInteger.ZERO); + + wordBuilder.addParagraphContent("Funder", document, ParagraphStyle.HEADER3, BigInteger.ZERO); + if (dmpEntity.getGrant().getFunder() != null) + wordBuilder.addParagraphContent(dmpEntity.getGrant().getFunder().getLabel(), document, ParagraphStyle.TEXT, BigInteger.ZERO); + + wordBuilder.addParagraphContent("Grant", document, ParagraphStyle.HEADER3, BigInteger.ZERO); + wordBuilder.addParagraphContent(dmpEntity.getGrant().getLabel(), document, ParagraphStyle.TEXT, BigInteger.ZERO); + + wordBuilder.addParagraphContent("Organisations", document, ParagraphStyle.HEADER3, BigInteger.ZERO); + if (dmpEntity.getOrganisations().size() > 0) { + wordBuilder.addParagraphContent(dmpEntity.getOrganisations().stream().map(Organisation::getLabel).collect(Collectors.joining(", ")) + , document, ParagraphStyle.TEXT, BigInteger.ZERO); + } + + wordBuilder.addParagraphContent("Researchers", document, ParagraphStyle.HEADER3, BigInteger.ZERO); + if (dmpEntity.getResearchers().size() > 0) { + wordBuilder.addParagraphContent(dmpEntity.getResearchers().stream().map(Researcher::getLabel).collect(Collectors.joining(", ")) + , document, ParagraphStyle.TEXT, BigInteger.ZERO); + } + + /*wordBuilder.addParagraphContent("DMP Profile", document, ParagraphStyle.HEADER2, BigInteger.ZERO); + if (dmpEntity.getProfile() != null){ + wordBuilder.addParagraphContent(dmpEntity.getProfile().getLabel(), document, ParagraphStyle.TEXT, BigInteger.ZERO); + }*/ + + // Page break at the end of the DMP title. + XWPFParagraph parBreakDMP = document.createParagraph(); + parBreakDMP.setPageBreak(true); + + wordBuilder.addParagraphContent("Datasets", document, ParagraphStyle.HEADER1, BigInteger.ZERO); + // Space below Datasets. + XWPFParagraph parBreakDatasets = document.createParagraph(); + dmpEntity.getDataset().stream() + .filter(item -> item.getStatus() != Dataset.Status.CANCELED.getValue()) + .filter(item -> item.getStatus() != Dataset.Status.DELETED.getValue()) + .forEach(datasetEntity -> { + Map properties = new HashMap<>(); + if (datasetEntity.getProperties() != null) { + JSONObject jObject = new JSONObject(datasetEntity.getProperties()); + properties = jObject.toMap(); + } + + // Custom style for the Dataset title. + //wordBuilder.addParagraphContent("Title: " + datasetEntity.getLabel(), document, ParagraphStyle.HEADER1, BigInteger.ZERO); + XWPFParagraph datasetLabelParagraph = document.createParagraph(); + datasetLabelParagraph.setStyle("Heading2"); + XWPFRun runDatasetTitle1 = datasetLabelParagraph.createRun(); + runDatasetTitle1.setText("Title: "); + runDatasetTitle1.setBold(true); + runDatasetTitle1.setFontSize(12); + XWPFRun runDatasetTitle = datasetLabelParagraph.createRun(); + runDatasetTitle.setText(datasetEntity.getLabel()); + runDatasetTitle.setColor("2E75B6"); + runDatasetTitle.setBold(true); + runDatasetTitle.setFontSize(12); + + XWPFParagraph datasetTemplateParagraph = document.createParagraph(); + datasetTemplateParagraph.setStyle("Heading3"); + XWPFRun runDatasetTemplate1 = datasetTemplateParagraph.createRun(); + runDatasetTemplate1.setText("Template: "); + runDatasetTemplate1.setBold(true); + runDatasetTemplate1.setFontSize(12); + XWPFRun runDatasetTemplate = datasetTemplateParagraph.createRun(); + runDatasetTemplate.setText(datasetEntity.getProfile().getLabel()); + runDatasetTemplate.setColor("2E75B6"); + runDatasetTemplate.setBold(true); + runDatasetTemplate.setFontSize(12); + + XWPFParagraph externalReferencesParagraph = document.createParagraph(); + externalReferencesParagraph.setStyle("Heading3"); + XWPFRun externalReferencesRun = externalReferencesParagraph.createRun(); + externalReferencesRun.setText("External References"); + externalReferencesRun.setColor("2E75B6"); + externalReferencesRun.setBold(true); + externalReferencesRun.setFontSize(12); + + wordBuilder.addParagraphContent("Data Repositories", document, ParagraphStyle.HEADER4, BigInteger.ZERO); + if (datasetEntity.getDatasetDataRepositories().size() > 0) { + wordBuilder.addParagraphContent(datasetEntity.getDatasetDataRepositories().stream().map(DatasetDataRepository::getDataRepository).map(DataRepository::getLabel).collect(Collectors.joining(", ")) + , document, ParagraphStyle.TEXT, BigInteger.ZERO); + } + wordBuilder.addParagraphContent("External Datasets", document, ParagraphStyle.HEADER4, BigInteger.ZERO); + if (datasetEntity.getDatasetExternalDatasets().size() > 0) { + wordBuilder.addParagraphContent(datasetEntity.getDatasetExternalDatasets().stream().map(DatasetExternalDataset::getExternalDataset).map(ExternalDataset::getLabel).collect(Collectors.joining(", ")) + , document, ParagraphStyle.TEXT, BigInteger.ZERO); + } + wordBuilder.addParagraphContent("Registries", document, ParagraphStyle.HEADER4, BigInteger.ZERO); + if (datasetEntity.getRegistries().size() > 0) { + wordBuilder.addParagraphContent(datasetEntity.getRegistries().stream().map(Registry::getLabel).collect(Collectors.joining(", ")) + , document, ParagraphStyle.TEXT, BigInteger.ZERO); + } + wordBuilder.addParagraphContent("Services", document, ParagraphStyle.HEADER4, BigInteger.ZERO); + if (datasetEntity.getServices().size() > 0) { + wordBuilder.addParagraphContent(datasetEntity.getServices().stream().map(DatasetService::getService).map(Service::getLabel).collect(Collectors.joining(", ")) + , document, ParagraphStyle.TEXT, BigInteger.ZERO); + } + /*wordBuilder.addParagraphContent("Tags", document, ParagraphStyle.HEADER3, BigInteger.ZERO); + if (datasetEntity.().size() > 0) { + wordBuilder.addParagraphContent(datasetEntity.getServices().stream().map(DatasetService::getService).map(Service::getLabel).collect(Collectors.joining(", ")) + , document, ParagraphStyle.HEADER4, BigInteger.ZERO); + }*/ + + + wordBuilder.addParagraphContent(datasetEntity.getDescription(), document, ParagraphStyle.TEXT, BigInteger.ZERO); + + // Dataset Description custom style. + XWPFParagraph datasetDescriptionParagraph = document.createParagraph(); + datasetDescriptionParagraph.setStyle("Heading3"); + XWPFRun datasetDescriptionRun = datasetDescriptionParagraph.createRun(); + datasetDescriptionRun.setText("Dataset Description"); + datasetDescriptionRun.setColor("2E75B6"); + datasetDescriptionRun.setBold(true); + datasetDescriptionRun.setFontSize(12); + + PagedDatasetProfile pagedDatasetProfile = datasetManager.getPagedProfile(dataset, datasetEntity); + visibilityRuleService.setProperties(properties); + visibilityRuleService.buildVisibilityContext(pagedDatasetProfile.getRules()); + try { + wordBuilder.build(document, pagedDatasetProfile, visibilityRuleService); + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + // Page break at the end of the Dataset. + XWPFParagraph parBreakDataset = document.createParagraph(); + }); + + // Removes the top empty headings. + for (int i = 0; i < 6; i++) { + document.removeBodyElement(0); + } + + String fileName = ""; + if (versioned) { + fileName = dmpEntity.getLabel() + " v" + dmpEntity.getVersion(); + } else { + fileName = dmpEntity.getLabel(); + } + fileName = fileName.replaceAll("[^a-zA-Z0-9+ ]", ""); + FileEnvelope exportEnvelope = new FileEnvelope(); + exportEnvelope.setFilename(fileName + ".docx"); + String uuid = UUID.randomUUID().toString(); + File exportFile = new File(this.environment.getProperty("temp.temp") + uuid + ".docx"); + FileOutputStream out = new FileOutputStream(exportFile); + document.write(out); + out.close(); + exportEnvelope.setFile(exportFile); + + return exportEnvelope; + } + private FileEnvelope getXmlDocument(String id, Principal principal) throws InstantiationException, IllegalAccessException, IOException { ExportXmlBuilder xmlBuilder = new ExportXmlBuilder(); VisibilityRuleService visibilityRuleService = utilitiesService.getVisibilityRuleService(); eu.eudat.data.entities.DMP dmp = databaseRepository.getDmpDao().find(UUID.fromString(id)); - if (!dmp.isPublic() && dmp.getUsers().stream().filter(userInfo -> userInfo.getUser().getId() == principal.getId()).collect(Collectors.toList()).size() == 0) - throw new UnauthorisedException(); + if (!dmp.isPublic() && dmp.getUsers().stream().filter(userInfo -> userInfo.getUser().getId() == principal.getId()).collect(Collectors.toList()).size() == 0) + throw new UnauthorisedException(); List datasets = dmp.getDataset().stream().collect(Collectors.toList()); /*String fileName = dmp.getLabel(); fileName = fileName.replaceAll("[^a-zA-Z0-9+ ]", "");*/ @@ -1223,13 +1160,13 @@ public class DataManagementPlanManager { public ResponseEntity getRDAJsonDocument(String id, DatasetManager datasetManager, Principal principal) throws IOException { eu.eudat.data.entities.DMP dmp = databaseRepository.getDmpDao().find(UUID.fromString(id)); - if (!dmp.isPublic() && dmp.getUsers().stream().noneMatch(userInfo -> userInfo.getUser().getId() == principal.getId())) - throw new UnauthorisedException(); + if (!dmp.isPublic() && dmp.getUsers().stream().noneMatch(userInfo -> userInfo.getUser().getId() == principal.getId())) + throw new UnauthorisedException(); // RDAExportModel rdaExportModel = new RDAExportModel().fromDataModel(dmp, datasetManager, principal); String result = rdaManager.convertToRDA(dmp); - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + /*ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);*/ String fileName = dmp.getLabel(); fileName = fileName.replaceAll("[^a-zA-Z0-9+ ]", ""); String uuid = UUID.randomUUID().toString(); @@ -1286,6 +1223,10 @@ public class DataManagementPlanManager { HttpStatus.OK); } + /* + * Data Import + * */ + public List createDmpFromXml(ApiContext apiContext, MultipartFile[] files, Principal principal) throws IOException, JAXBException, Exception { List dataManagementPlans = new ArrayList<>(); // Jaxb approach. @@ -1382,22 +1323,22 @@ public class DataManagementPlanManager { dm.setDefinition(dmpProfile); //createOrUpdate(apiContext, dm, principal); - DMP dmp = this.createOrUpdate(apiContext, dm, principal); - if (dmp.getOrganisations() == null) { - dmp.setOrganisations(new HashSet<>()); - } - if (dmp.getResearchers() == null) { - dmp.setResearchers(new HashSet<>()); - } - if (dmp.getDataset() == null) { - dmp.setDataset(new HashSet<>()); - } - if (dmp.getUsers() == null) { - dmp.setUsers(new HashSet<>()); - } - if (dmp.getAssociatedDmps() == null) { - dmp.setAssociatedDmps(new HashSet<>()); - } + DMP dmp = this.createOrUpdate(apiContext, dm, principal); + if (dmp.getOrganisations() == null) { + dmp.setOrganisations(new HashSet<>()); + } + if (dmp.getResearchers() == null) { + dmp.setResearchers(new HashSet<>()); + } + if (dmp.getDataset() == null) { + dmp.setDataset(new HashSet<>()); + } + if (dmp.getUsers() == null) { + dmp.setUsers(new HashSet<>()); + } + if (dmp.getAssociatedDmps() == null) { + dmp.setAssociatedDmps(new HashSet<>()); + } List datasets = new LinkedList<>(); for (DatasetImportModels das: dataManagementPlans.get(0).getDatasetImportModels()) { @@ -1415,7 +1356,7 @@ public class DataManagementPlanManager { datasetWizard.setDatasetProfileDefinition(this.datasetManager.getPagedProfile(datasetWizard, dataset)); datasetWizard.fromDataModel(dataset); this.datasetManager.createOrUpdate(datasetWizard, principal); - // datasets.add(new DatasetListingModel().fromDataModel(dataset)); + // datasets.add(new DatasetListingModel().fromDataModel(dataset)); } logger.info(dm.toString()); @@ -1484,49 +1425,55 @@ public class DataManagementPlanManager { return result; } - public DataTableData getDatasetProfilesUsedByDMP(DatasetProfileTableRequestItem datasetProfileTableRequestItem, Principal principal) { - datasetProfileTableRequestItem.getCriteria().setFilter(DatasetProfileCriteria.DatasetProfileFilter.DMPs.getValue()); - datasetProfileTableRequestItem.getCriteria().setUserId(principal.getId()); + /* + * Data assignments + * */ - QueryableList items = apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().getWithCriteria(datasetProfileTableRequestItem.getCriteria()); - List listingModels = items.select(item -> new DatasetProfileListingModel().fromDataModel(item)); - - DataTableData data = new DataTableData<>(); - data.setData(listingModels); - data.setTotalCount((long) listingModels.size()); - - return data; + private void assignUser(DMP dmp, UserInfo userInfo) { + UserDMP userDMP = new UserDMP(); + userDMP.setDmp(dmp); + userDMP.setUser(userInfo); + userDMP.setRole(UserDMP.UserDMPRoles.OWNER.getValue()); + databaseRepository.getUserDmpDao().createOrUpdate(userDMP); } - public void makePublic(UUID id, Principal principal) throws Exception { - DMP dmp = this.apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(id); - // Check if dmp is finalized and if user is owner. - if (!isUserOwnerOfDmp(dmp, principal)) - throw new Exception("User does not have the privilege to do this action."); - if (!dmp.getStatus().equals(DMP.DMPStatus.FINALISED.getValue())) - throw new Exception("DMP is not finalized"); - dmp.setPublic(true); - apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); - this.updateIndex(dmp); + private void assignGrandUserIfInternal(DMP dmp, UserInfo user) { + if (dmp.getGrant().getCreationUser() == null && (dmp.getGrant().getReference() != null && dmp.getGrant().getReference().startsWith("dmp:"))) { + dmp.getGrant().setCreationUser(user); + } + } + + private void assignFunderUserIfInternal(DMP dmp, UserInfo user) { + if (dmp.getGrant().getFunder().getCreationUser() == null && ( dmp.getGrant().getFunder().getReference() != null && dmp.getGrant().getFunder().getReference().startsWith("dmp:"))) { + dmp.getGrant().getFunder().setCreationUser(user); + } + } + + private void assignProjectUserIfInternal(DMP dmp, UserInfo user) { + if (dmp.getProject().getCreationUser() == null && (dmp.getProject().getReference() != null && dmp.getProject().getReference().startsWith("dmp:"))) { + dmp.getProject().setCreationUser(user); + } + } + + /* + * Data Index + * */ + + private void updateGroupIndex(UUID groupId) { DataManagementPlanCriteria criteria = new DataManagementPlanCriteria(); - criteria.setGroupIds(Collections.singletonList(dmp.getGroupId())); + criteria.setGroupIds(Collections.singletonList(groupId)); criteria.setAllVersions(true); - apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().getWithCriteria(criteria).toList().stream().forEach(dmp1 -> { - dmp1.getDataset().forEach(dataset -> { - try { - List tags = new ArrayList<>(); - eu.eudat.elastic.entities.Dataset elastic = apiContext.getOperationsContext().getElasticRepository().getDatasetRepository().findDocument(dataset.getId().toString()); - if (elastic != null) { - tags = elastic.getTags(); - } - this.datasetManager.updateTags(dataset, tags); - } catch (Exception e) { - logger.error(e.getMessage(), e); + List dmps = databaseRepository.getDmpDao().getWithCriteria(criteria).toList(); + for (DMP dmp: dmps) { + try { + if (dmp.getUsers() != null) { + logger.info(dmp.getUsers().toString()); } - }); - }); - UserInfo user = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(principal.getId()); - sendNotification(dmp, user, NotificationType.DMP_PUBLISH); + this.updateIndex(dmp); + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + } } private void updateDatasetsIndex(List datasets) { @@ -1546,63 +1493,72 @@ public class DataManagementPlanManager { }); } - public void makeFinalize(UUID id, Principal principal, DatasetsToBeFinalized datasetsToBeFinalized) throws Exception { - DMP dmp = this.apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(id); - if (!isUserOwnerOfDmp(dmp, principal)) - throw new Exception("User does not have the privilege to do this action."); - if (dmp.getStatus().equals(DMP.DMPStatus.FINALISED.getValue())) - throw new Exception("DMP is already finalized"); - dmp.setStatus(DMP.DMPStatus.FINALISED.getValue()); - apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); - this.updateIndex(dmp); - List indexDatasets = new ArrayList<>(); - if (datasetsToBeFinalized != null && datasetsToBeFinalized.getUuids() != null && !datasetsToBeFinalized.getUuids().isEmpty()) { - apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() - .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeFinalized.getUuids())) - .update(root -> root.get("status"), Dataset.Status.FINALISED.getValue()); - List finalizedDatasets = dmp.getDataset().stream().filter(dataset -> datasetsToBeFinalized.getUuids().contains(dataset.getId())).collect(Collectors.toList()); - finalizedDatasets.forEach(dataset -> dataset.setStatus(Dataset.Status.FINALISED.getValue())); - indexDatasets.addAll(finalizedDatasets); - List datasetsToBeCanceled = new LinkedList<>(); - for (Dataset dataset : dmp.getDataset()) { - if (!dataset.getStatus().equals(Dataset.Status.FINALISED.getValue()) && !datasetsToBeFinalized.getUuids().contains(dataset.getId())) { - datasetsToBeCanceled.add(dataset.getId()); - } - } - if (!datasetsToBeCanceled.isEmpty()) { - apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() - .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeCanceled)) - .update(root -> root.get("status"), Dataset.Status.CANCELED.getValue()); - List cancelledDatasets = dmp.getDataset().stream().filter(dataset -> datasetsToBeCanceled.contains(dataset.getId())).collect(Collectors.toList()); - cancelledDatasets.forEach(dataset -> dataset.setStatus(Dataset.Status.CANCELED.getValue())); - indexDatasets.addAll(cancelledDatasets); - } - } else { - List datasetsToBeCanceled = new LinkedList<>(); - for (Dataset dataset : dmp.getDataset()) { - if (!dataset.getStatus().equals(Dataset.Status.FINALISED.getValue())) { - datasetsToBeCanceled.add(dataset.getId()); - } - } - if (!datasetsToBeCanceled.isEmpty()) { - apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() - .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeCanceled)) - .update(root -> root.get("status"), Dataset.Status.CANCELED.getValue()); - List cancelledDatasets = dmp.getDataset().stream().filter(dataset -> datasetsToBeCanceled.contains(dataset.getId())).collect(Collectors.toList()); - cancelledDatasets.forEach(dataset -> dataset.setStatus(Dataset.Status.CANCELED.getValue())); - indexDatasets.addAll(cancelledDatasets); - } + private void updateIndex(DMP dmp) throws IOException { + DmpMapper mapper = new DmpMapper(apiContext, datasetManager); + Dmp elastic = mapper.toElastic(dmp); + apiContext.getOperationsContext().getElasticRepository().getDmpRepository().createOrUpdate(elastic); + } - UserInfo user = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(principal.getId()); - sendNotification(dmp, user, NotificationType.DMP_FINALISED); + public void generateIndex(Principal principal) { + if (principal.getAuthorities().contains(Authorities.ADMIN.getValue())) { + if (apiContext.getOperationsContext().getElasticRepository().getDmpRepository().createIndex()) { + List dmps = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().asQueryable().toList(); + dmps.forEach(dmp -> { + try { + this.updateIndex(dmp); + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + }); + } + } + } + + public void clearIndex(Principal principal) throws IOException { + if (principal.getAuthorities().contains(Authorities.ADMIN.getValue())) { + apiContext.getOperationsContext().getElasticRepository().getDmpRepository().clear(); + } + } + + /* + * Data Checkup + * */ + + private void checkIfUserCanEditGrant(DMP dmp, UserInfo user) throws Exception{ + if (dmp.getGrant().getId() != null) { + Grant grant = apiContext.getOperationsContext().getDatabaseRepository().getGrantDao().find(dmp.getGrant().getId()); + if (grant.getFunder() != null && dmp.getGrant().getFunder() != null + && !grant.getFunder().getId().equals(dmp.getGrant().getFunder().getId())) { + if (grant.getCreationUser() == null) { + throw new Exception("Grant has no user, therefore, cannot be edited."); + } + if (!grant.getCreationUser().getId().equals(user.getId())) { + throw new Exception("User is not the owner of the Grant, therefore, cannot edit it."); + } + } + } + } + + private void checkDmpValidationRules(DMP dmp) throws Exception { + if (dmp.getLabel() == null || dmp.getLabel().trim().isEmpty()) { + throw new Exception("DMP has no label."); + } + if (dmp.getAssociatedDmps().size() == 0) { + throw new Exception("DMP does not contain Dataset Templates."); + } + if (dmp.getGrant() == null) { + throw new Exception("DMP has no Grant assigned."); } - this.updateDatasetsIndex(indexDatasets); } private boolean isUserOwnerOfDmp(DMP dmp, Principal principal) { return (dmp.getUsers().stream().filter(userDMP -> userDMP.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())).findFirst().get().getUser().getId()).equals(principal.getId()); } + /* + * DOI Generation + * */ + private String getPreviousDOI(UUID groupId, UUID selfId) { DataManagementPlanCriteria criteria = new DataManagementPlanCriteria(); List groupIds = new ArrayList<>(); @@ -1691,74 +1647,74 @@ public class DataManagementPlanManager { String publishUrl = null; try { - if (previousDOI == null) { - String createUrl = this.environment.getProperty("zenodo.url") + "deposit/depositions" + "?access_token=" + zenodoToken; - createResponse = restTemplate.postForEntity(createUrl, request, Map.class).getBody(); - links = (LinkedHashMap) createResponse.get("links"); - } else { - unpublishedUrl = this.getUnpublishedDOI(previousDOI, zenodoToken, dmp.getVersion()); - if (unpublishedUrl == null) { - //It requires more than one step to create a new version - //First, get the deposit related to the concept DOI - String listUrl = this.environment.getProperty("zenodo.url") + "deposit/depositions" + "?q=conceptdoi:\"" + previousDOI + "\"&access_token=" + zenodoToken; - ResponseEntity listResponses = restTemplate.getForEntity(listUrl, Map[].class); - createResponse = listResponses.getBody()[0]; + if (previousDOI == null) { + String createUrl = this.environment.getProperty("zenodo.url") + "deposit/depositions" + "?access_token=" + zenodoToken; + createResponse = restTemplate.postForEntity(createUrl, request, Map.class).getBody(); links = (LinkedHashMap) createResponse.get("links"); - //Second, make the new version (not in the links?) - String newVersionUrl = links.get("self") + "/actions/newversion" + "?access_token=" + zenodoToken; - createResponse = restTemplate.postForObject(newVersionUrl, null, Map.class); - links = (LinkedHashMap) createResponse.get("links"); - //Third, get the new deposit - String latestDraftUrl = links.get("latest_draft") + "?access_token=" + zenodoToken; - createResponse = restTemplate.getForObject(latestDraftUrl, Map.class); - links = (LinkedHashMap) createResponse.get("links"); - //At this point it might fail to perform the next requests so enclose them with try catch - try { - //Forth, update the new deposit's metadata - String updateUrl = links.get("self") + "?access_token=" + zenodoToken; - restTemplate.put(updateUrl, request); - //And finally remove pre-existing files from it - String fileListUrl = links.get("self") + "/files" + "?access_token=" + zenodoToken; - ResponseEntity fileListResponse = restTemplate.getForEntity(fileListUrl, Map[].class); - for (Map file : fileListResponse.getBody()) { - String fileDeleteUrl = links.get("self") + "/files/" + file.get("id") + "?access_token=" + zenodoToken; - restTemplate.delete(fileDeleteUrl); + } else { + unpublishedUrl = this.getUnpublishedDOI(previousDOI, zenodoToken, dmp.getVersion()); + if (unpublishedUrl == null) { + //It requires more than one step to create a new version + //First, get the deposit related to the concept DOI + String listUrl = this.environment.getProperty("zenodo.url") + "deposit/depositions" + "?q=conceptdoi:\"" + previousDOI + "\"&access_token=" + zenodoToken; + ResponseEntity listResponses = restTemplate.getForEntity(listUrl, Map[].class); + createResponse = listResponses.getBody()[0]; + links = (LinkedHashMap) createResponse.get("links"); + //Second, make the new version (not in the links?) + String newVersionUrl = links.get("self") + "/actions/newversion" + "?access_token=" + zenodoToken; + createResponse = restTemplate.postForObject(newVersionUrl, null, Map.class); + links = (LinkedHashMap) createResponse.get("links"); + //Third, get the new deposit + String latestDraftUrl = links.get("latest_draft") + "?access_token=" + zenodoToken; + createResponse = restTemplate.getForObject(latestDraftUrl, Map.class); + links = (LinkedHashMap) createResponse.get("links"); + //At this point it might fail to perform the next requests so enclose them with try catch + try { + //Forth, update the new deposit's metadata + String updateUrl = links.get("self") + "?access_token=" + zenodoToken; + restTemplate.put(updateUrl, request); + //And finally remove pre-existing files from it + String fileListUrl = links.get("self") + "/files" + "?access_token=" + zenodoToken; + ResponseEntity fileListResponse = restTemplate.getForEntity(fileListUrl, Map[].class); + for (Map file : fileListResponse.getBody()) { + String fileDeleteUrl = links.get("self") + "/files/" + file.get("id") + "?access_token=" + zenodoToken; + restTemplate.delete(fileDeleteUrl); + } + } catch (Exception e) { + //In case the last two steps fail delete the latest Deposit it in order to create a new one (only one at a time is allowed) + restTemplate.delete(latestDraftUrl); + throw e; } - } catch (Exception e) { - //In case the last two steps fail delete the latest Deposit it in order to create a new one (only one at a time is allowed) - restTemplate.delete(latestDraftUrl); - throw e; } } - } - if (unpublishedUrl == null) { - // Second step, add the file to the entry. - HttpHeaders fileHeaders = new HttpHeaders(); - fileHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); - LinkedMultiValueMap addFileMap = new LinkedMultiValueMap<>(); + if (unpublishedUrl == null) { + // Second step, add the file to the entry. + HttpHeaders fileHeaders = new HttpHeaders(); + fileHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); + LinkedMultiValueMap addFileMap = new LinkedMultiValueMap<>(); - FileEnvelope file = getWordDocument(id.toString(), principal, configLoader); - addFileMap.add("filename", file.getFilename()); - FileSystemResource fileSystemResource = new FileSystemResource(file.getFile()); - addFileMap.add("file", fileSystemResource); - HttpEntity> addFileMapRequest = new HttpEntity<>(addFileMap, fileHeaders); + FileEnvelope file = getWordDocument(id.toString(), principal, configLoader); + addFileMap.add("filename", file.getFilename()); + FileSystemResource fileSystemResource = new FileSystemResource(file.getFile()); + addFileMap.add("file", fileSystemResource); + HttpEntity> addFileMapRequest = new HttpEntity<>(addFileMap, fileHeaders); - String addFileUrl = links.get("files") + "?access_token=" + zenodoToken; - ResponseEntity addFileResponse = restTemplate.postForEntity(addFileUrl, addFileMapRequest, String.class); - Files.deleteIfExists(file.getFile().toPath()); + String addFileUrl = links.get("files") + "?access_token=" + zenodoToken; + ResponseEntity addFileResponse = restTemplate.postForEntity(addFileUrl, addFileMapRequest, String.class); + Files.deleteIfExists(file.getFile().toPath()); - // Third post call to Zenodo to publish the entry and return the DOI. - publishUrl = links.get("publish") + "?access_token=" + zenodoToken; - } else { - publishUrl = unpublishedUrl + "?access_token=" + zenodoToken; - } - Map publishResponce = restTemplate.postForObject(publishUrl, "", Map.class); + // Third post call to Zenodo to publish the entry and return the DOI. + publishUrl = links.get("publish") + "?access_token=" + zenodoToken; + } else { + publishUrl = unpublishedUrl + "?access_token=" + zenodoToken; + } + Map publishResponce = restTemplate.postForObject(publishUrl, "", Map.class); - dmp.setDoi((String) publishResponce.get("conceptdoi")); - apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); - return (String) publishResponce.get("conceptdoi"); + dmp.setDoi((String) publishResponce.get("conceptdoi")); + apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); + return (String) publishResponce.get("conceptdoi"); } catch (HttpClientErrorException | HttpServerErrorException ex) { ObjectMapper ob = new ObjectMapper(); Map parsedException = ob.readValue(ex.getResponseBodyAsString(), HashMap.class); @@ -1766,30 +1722,133 @@ public class DataManagementPlanManager { } } - private void updateIndex(DMP dmp) throws IOException { - DmpMapper mapper = new DmpMapper(apiContext, datasetManager); - Dmp elastic = mapper.toElastic(dmp); - apiContext.getOperationsContext().getElasticRepository().getDmpRepository().createOrUpdate(elastic); - } + /* + * Misc + * */ - public void generateIndex(Principal principal) { - if (principal.getAuthorities().contains(Authorities.ADMIN.getValue())) { - if (apiContext.getOperationsContext().getElasticRepository().getDmpRepository().createIndex()) { - List dmps = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().asQueryable().toList(); - dmps.forEach(dmp -> { - try { - this.updateIndex(dmp); - } catch (IOException e) { - logger.error(e.getMessage(), e); - } - }); + private void sendNotification(DMP dmp, UserInfo user, NotificationType notificationType) { + List userDMPS = databaseRepository.getUserDmpDao().asQueryable().where(((builder, root) -> builder.equal(root.get("dmp").get("id"), dmp.getId()))).toList(); + for (UserDMP userDMP : userDMPS) { + if (!userDMP.getUser().getId().equals(user.getId())) { + Notification notification = new Notification(); + notification.setUserId(user); + notification.setType(notificationType); + notification.setNotifyState(NotifyState.PENDING); + notification.setIsActive(ActiveStatus.ACTIVE); + notification.setData("{" + + "\"userId\": \"" + userDMP.getUser().getId() + "\"" + + ", \"id\": \"" + userDMP.getDmp().getId() + "\"" + + ", \"name\": \"" + userDMP.getDmp().getLabel() + "\"" + + ", \"path\": \"" + notificationPaths.get(notificationType) +"\"" + + "}"); + notification.setCreatedAt(new Date()); + notification.setUpdatedAt(notification.getCreatedAt()); + notification.setContactTypeHint(ContactType.EMAIL); + notification.setContactHint(userDMP.getUser().getEmail()); + databaseRepository.getNotificationDao().createOrUpdate(notification); } } + } - public void clearIndex(Principal principal) throws IOException { - if (principal.getAuthorities().contains(Authorities.ADMIN.getValue())) { - apiContext.getOperationsContext().getElasticRepository().getDmpRepository().clear(); + /*public DataTableData getPublicPaged(DataManagmentPlanPublicTableRequest dataManagementPlanPublicTableRequest, String fieldsGroup, Principal principal) throws Exception { + dataManagementPlanPublicTableRequest.setQuery(databaseRepository.getDmpDao().asQueryable().withHint(HintedModelFactory.getHint(DataManagementPlanListingModel.class))); + QueryableList items = dataManagementPlanPublicTableRequest.applyCriteria(); + + if (principal.getId() != null && dataManagementPlanPublicTableRequest.getCriteria().getRole() != null) { + items.where((builder, root) -> { + Join userJoin = root.join("users", JoinType.LEFT); + return builder.and(builder.equal(userJoin.join("user", JoinType.LEFT).get("id"), principal.getId()), builder.equal(userJoin.get("role"), dataManagementPlanPublicTableRequest.getCriteria().getRole())); + }); + } + QueryableList pagedItems = PaginationManager.applyPaging(items, dataManagementPlanPublicTableRequest); + + DataTableData dataTable = new DataTableData<>(); + + CompletableFuture itemsFuture; + if (fieldsGroup.equals("listing")) { + itemsFuture = pagedItems.withHint(HintedModelFactory.getHint(DataManagementPlanListingModel.class)) + .selectAsync(item -> { + item.setDataset( + item.getDataset().stream() + .filter(dataset -> dataset.getStatus().equals(Dataset.Status.FINALISED.getValue())).collect(Collectors.toSet())); + return new DataManagementPlanListingModel().fromDataModelDatasets(item); + }) + .whenComplete((resultList, throwable) -> dataTable.setData(resultList)); + } else { + itemsFuture = pagedItems + .selectAsync(item -> new DataManagementPlanListingModel().fromDataModel(item)) + .whenComplete((resultList, throwable) -> dataTable.setData(resultList)); + } + + CompletableFuture countFuture = items.countAsync().whenComplete((count, throwable) -> { + dataTable.setTotalCount(count); + }); + CompletableFuture.allOf(itemsFuture, countFuture).join(); + return dataTable; + } +*/ + /*public void unlock(UUID uuid) throws Exception { + apiContext.getOperationsContext().getDatabaseRepository().getDmpDao() + .asQueryable().where((builder, root) -> builder.equal(root.get("id"), uuid)) + .update(root -> root.get("status"), DMP.DMPStatus.ACTIVE.getValue()); + return; + }*/ + /*public File getPdfDocument(String id) throws InstantiationException, IllegalAccessException, InterruptedException, IOException { + File file = this.getWordDocument(id); + String fileName = file.getName(); + if (fileName.endsWith(".docx")){ + fileName = fileName.substring(0, fileName.length() - 5); + } + return this.datasetManager.convertToPDF(file, environment, fileName); + }*/ + /*public eu.eudat.models.data.dmp.DataManagementPlan getSinglePublic(String id, DynamicGrantConfiguration dynamicGrantConfiguration) throws Exception { + DMP dataManagementPlanEntity = databaseRepository.getDmpDao().find(UUID.fromString(id)); + + if (dataManagementPlanEntity != null && dataManagementPlanEntity.getStatus() == 1) { + eu.eudat.models.data.dmp.DataManagementPlan datamanagementPlan = new eu.eudat.models.data.dmp.DataManagementPlan(); + datamanagementPlan.fromDataModel(dataManagementPlanEntity); + datamanagementPlan.setDatasets(datamanagementPlan.getDatasets().stream().filter(dataset -> dataset.getStatus() == Dataset.Status.FINALISED.getValue()).collect(Collectors.toList())); + Map dmpProperties = dataManagementPlanEntity.getDmpProperties() != null ? new org.json.JSONObject(dataManagementPlanEntity.getDmpProperties()).toMap() : null; +// datamanagementPlan.setDynamicFields(dynamicGrantConfiguration.getFields().stream().map(item -> { +// DynamicFieldWithValue fieldWithValue = new DynamicFieldWithValue(); +// fieldWithValue.setId(item.getId()); +// fieldWithValue.setDependencies(item.getDependencies()); +// fieldWithValue.setName(item.getName()); +// fieldWithValue.setQueryProperty(item.getQueryProperty()); +// fieldWithValue.setRequired(item.getRequired()); +// return fieldWithValue; +// }).collect(Collectors.toList())); + + if (dmpProperties != null && datamanagementPlan.getDynamicFields() != null) + datamanagementPlan.getDynamicFields().forEach(item -> { + Map properties = (Map) dmpProperties.get(item.getId()); + if (properties != null) + item.setValue(new Tuple<>(properties.get("id"), properties.get("label"))); + }); + return datamanagementPlan; + } else { + throw new Exception("Selected DMP is not public"); } } + + public DataManagementPlanOverviewModel getOverviewSinglePublic(String id) throws Exception { + DMP dataManagementPlanEntity = databaseRepository.getDmpDao().find(UUID.fromString(id)); + if (dataManagementPlanEntity != null && dataManagementPlanEntity.getStatus() == 1) { + DataManagementPlanOverviewModel datamanagementPlan = new DataManagementPlanOverviewModel(); + datamanagementPlan.fromDataModelDatasets(dataManagementPlanEntity); + datamanagementPlan.setDatasets(datamanagementPlan.getDatasets().stream().filter(dataset -> dataset.getStatus() == Dataset.Status.FINALISED.getValue()).collect(Collectors.toList())); + return datamanagementPlan; + } else { + throw new Exception("Selected DMP is not public"); + } + }*/ + /*public List getWithCriteria(DMPDao dmpsRepository, DataManagementPlanCriteriaRequest dataManagementPlanCriteria, Principal principal) throws IllegalAccessException, InstantiationException { + UUID principalID = principal.getId(); + QueryableList items = dmpsRepository.getWithCriteria(dataManagementPlanCriteria.getCriteria()).withHint(HintedModelFactory.getHint(DataManagementPlan.class)); + List roles = new LinkedList<>(); + QueryableList authenticatedItems = dmpsRepository.getAuthenticated(items, principalID, roles); + List datamanagementPlans = authenticatedItems.select(item -> new DataManagementPlan().fromDataModel(item)); + return datamanagementPlans; + }*/ } diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/Organisation.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/Organisation.java index 0cb2b1296..5c87d7ebd 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/Organisation.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/Organisation.java @@ -68,18 +68,22 @@ public class Organisation implements DataModel +

{{'ADDORGANIZATION-EDITOR.TITLE' | translate}}

+
+ + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + +
+
+
+
+
+
+
+ diff --git a/dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.component.ts b/dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.component.ts new file mode 100644 index 000000000..517cb2158 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.component.ts @@ -0,0 +1,43 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { ExternalResearcherService } from '@app/core/services/external-sources/researcher/external-researcher.service'; +import { BaseComponent } from '@common/base/base.component'; +import { takeUntil } from 'rxjs/operators'; +import { OrganizationEditorModel } from './add-organization.model'; + +@Component({ + selector: 'app-add-organization-component', + templateUrl: 'add-organization.component.html', +}) +export class AddOrganizationComponent extends BaseComponent implements OnInit { + + public formGroup: FormGroup; + + constructor( + private externalResearcherService: ExternalResearcherService, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any + ) { super(); } + + ngOnInit(): void { + const researcher = new OrganizationEditorModel(); + this.formGroup = researcher.buildForm(); + } + + send(value: any) { + this.externalResearcherService.createResearcher(this.formGroup.value) + .pipe(takeUntil(this._destroyed)) + .subscribe( + null, null, () => this.dialogRef.close() + ); + } + + addOrganization() { + this.dialogRef.close(this.formGroup.value); + } + + isFormValid() { + return this.formGroup.valid; + } +} diff --git a/dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.model.ts b/dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.model.ts new file mode 100644 index 000000000..444b3ae7c --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.model.ts @@ -0,0 +1,33 @@ +import { FormBuilder, FormGroup } from '@angular/forms'; +import { ResearcherModel } from '@app/core/model/researcher/researcher'; +import { BackendErrorValidator } from '@common/forms/validation/custom-validator'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; +import { ValidationContext } from '@common/forms/validation/validation-context'; +import { OrganizationModel } from '@app/core/model/organisation/organization'; + +export class OrganizationEditorModel { + public id: String; + public name: String; + public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); + + fromModel(item: OrganizationModel): OrganizationEditorModel { + this.id = item.id; + this.name = item.name; + return this; + } + + buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { + if (context == null) { context = this.createValidationContext(); } + const formGroup = new FormBuilder().group({ + name: [{ value: this.name, disabled: disabled }, context.getValidation('name').validators] + }); + + return formGroup; + } + + createValidationContext(): ValidationContext { + const baseContext: ValidationContext = new ValidationContext(); + baseContext.validation.push({ key: 'name', validators: [BackendErrorValidator(this.validationErrorModel, 'name')] }); + return baseContext; + } +} diff --git a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html index a1090650e..50d7d2fef 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html @@ -46,6 +46,9 @@ {{'GENERAL.VALIDATION.REQUIRED' | translate}} {{'DMP-EDITOR.FIELDS.ORGANISATIONS-HINT' | translate}} +
diff --git a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts index 4330d7332..f21ddfed9 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts @@ -20,6 +20,8 @@ import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from '@ngx-translate/core'; import { Observable } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; +import { AddOrganizationComponent } from '../add-organization/add-organization.component'; +import { isNullOrUndefined } from 'util'; @Component({ selector: 'app-general-tab', @@ -170,6 +172,36 @@ export class GeneralTabComponent extends BaseComponent implements OnInit { }); } + addOrganization(event: MouseEvent) { + event.stopPropagation(); + const dialogRef = this.dialog.open(AddOrganizationComponent, { + data: this.formGroup.get('organisations') + }); + dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { + if (result) { + const fullName = result.name; + const newItem = { + label: null, + name: fullName, + id: null, + status: 0, + key: "Internal", + }; + const organizationsArray = this.formGroup.get('organisations').value || []; + organizationsArray.push(newItem); + this.formGroup.get('organisations').setValue(organizationsArray); + } + }); + } + + canAddOrganizations(): boolean { + if (!isNullOrUndefined(this.formGroup.get('organizations'))) { + return this.formGroup.get('organiztions').disabled; + } else { + return false; + } + } + availableProfiles(event: MouseEvent) { event.stopPropagation(); const dialogRef = this.dialog.open(AvailableProfilesComponent, { diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts index 1bbe67bae..ca3ded5cc 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts @@ -106,10 +106,10 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { this.breadCrumbs = observableOf(breadCrumbs); }, (error: any) => { if (error.status === 404) { - return this.onFetchingDeletedCallbackError('/plans/'); + return this.onFetchingDeletedCallbackError('/explore-plans'); } if (error.status === 403) { - return this.onFetchingForbiddenCallbackError('/plans/'); + return this.onFetchingForbiddenCallbackError('/explore-plans'); } }); } diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index d357a19b0..3fb895575 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -953,6 +953,14 @@ "CANCEL": "Cancel" } }, + "ADDORGANIZATION-EDITOR": { + "TITLE": "Add an Organization", + "NAME": "Name", + "ACTIONS": { + "SAVE": "Save", + "CANCEL": "Cancel" + } + }, "DMP-WIZARD": { "FIRST-STEP": { "DMP": "DMP Editor", diff --git a/dmp-frontend/src/assets/i18n/es.json b/dmp-frontend/src/assets/i18n/es.json index 5716873cb..a9bef23eb 100644 --- a/dmp-frontend/src/assets/i18n/es.json +++ b/dmp-frontend/src/assets/i18n/es.json @@ -525,6 +525,10 @@ "ERROR": { "DELETED-DMP": "El PGD solicitado está borrado", "FORBIDEN-DMP": "You are not allowed to access this DMP" + }, + "MULTIPLE-DIALOG": { + "ZENODO-LOGIN": "Login with Zenodo", + "USE-DEFAULT": "Use Default Token" } }, "DATASET-LISTING": { @@ -825,7 +829,8 @@ "ACTIONS": { "SAVE": "Grabar", "CANCEL": "Cancelar", - "DELETE": "Borrar" + "DELETE": "Borrar", + "UPDATE": "Update" }, "VERSION-DIALOG": { "ABOUT": "Versionado es automático.", @@ -948,6 +953,14 @@ "CANCEL": "Cancelar" } }, + "ADDORGANIZATION-EDITOR": { + "TITLE": "Add an Organization", + "NAME": "Name", + "ACTIONS": { + "SAVE": "Save", + "CANCEL": "Cancel" + } + }, "DMP-WIZARD": { "FIRST-STEP": { "DMP": "Editor PGD", @@ -1086,6 +1099,12 @@ "SHOW-ALL": "Mostrar todo", "CREATOR": "Creador", "MEMBER": "Miembro" + }, + "ZENODO": { + "LOGIN": "Login to Zenodo", + "LOGOUT": "Remove Zenodo", + "TITLE": "Zenodo Account", + "DESCRIPTION": "Linked Zenodo Account:" } }, "DATASET-REFERENCED-MODELS": { From 0c443dfeba3b4b07db1e160371880a67137aa06c Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Wed, 22 Apr 2020 18:41:54 +0300 Subject: [PATCH 03/18] Renamed JSON Export to RDA JSON --- dmp-frontend/src/assets/i18n/en.json | 2 +- dmp-frontend/src/assets/i18n/es.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index 3fb895575..63fd0f3d6 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -128,7 +128,7 @@ "FILE-TYPES": { "PDF": "PDF", "XML": "XML", - "JSON": "JSON", + "JSON": "RDA JSON", "DOC": "Document" }, "LANGUAGES": { diff --git a/dmp-frontend/src/assets/i18n/es.json b/dmp-frontend/src/assets/i18n/es.json index a9bef23eb..7db704b15 100644 --- a/dmp-frontend/src/assets/i18n/es.json +++ b/dmp-frontend/src/assets/i18n/es.json @@ -128,7 +128,7 @@ "FILE-TYPES": { "PDF": "PDF", "XML": "XML", - "JSON": "JSON", + "JSON": "RDA JSON", "DOC": "Documento" }, "LANGUAGES": { From 05e2374f97e13cf98cc13b9b3068d7ba18d3f5e8 Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Wed, 22 Apr 2020 18:43:19 +0300 Subject: [PATCH 04/18] When exporting to JSON export it with pretty text --- .../web/src/main/java/eu/eudat/logic/managers/RDAManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/RDAManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/RDAManager.java index ff194455e..f7c9efde8 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/RDAManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/RDAManager.java @@ -32,7 +32,7 @@ public class RDAManager { ObjectMapper mapper = new ObjectMapper(); mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss Z")); - result = mapper.writeValueAsString(rdaDmp); + result = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rdaDmp); return result; } From 8ae58c9ef38de5776d5795dcde21ea1fc2cd7c5d Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Thu, 23 Apr 2020 10:48:14 +0300 Subject: [PATCH 05/18] Allow Organization Creator to be visible by configuration (ref #255) --- .../core/services/configuration/configuration.service.ts | 6 ++++++ .../ui/dmp/editor/general-tab/general-tab.component.html | 2 +- .../ui/dmp/editor/general-tab/general-tab.component.ts | 8 +++++++- dmp-frontend/src/assets/config/config.json | 3 ++- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/dmp-frontend/src/app/core/services/configuration/configuration.service.ts b/dmp-frontend/src/app/core/services/configuration/configuration.service.ts index e95d87773..e6d544816 100644 --- a/dmp-frontend/src/app/core/services/configuration/configuration.service.ts +++ b/dmp-frontend/src/app/core/services/configuration/configuration.service.ts @@ -57,6 +57,11 @@ export class ConfigurationService extends BaseComponent { return this._guideAssets; } + private _allowOrganizationCreator: boolean; + get allowOrganizationCreator():boolean { + return this._allowOrganizationCreator; + } + public loadConfiguration(): Promise { return new Promise((r, e) => { @@ -92,6 +97,7 @@ export class ConfigurationService extends BaseComponent { this._logging = Logging.parseValue(config.logging); this._lockInterval = config.lockInterval; this._guideAssets = config.guideAssets; + this._allowOrganizationCreator = config.allowOrganizationCreator; } } diff --git a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html index 50d7d2fef..620a27cb4 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html @@ -46,7 +46,7 @@ {{'GENERAL.VALIDATION.REQUIRED' | translate}} {{'DMP-EDITOR.FIELDS.ORGANISATIONS-HINT' | translate}} - diff --git a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts index f21ddfed9..1435dfaef 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts @@ -22,6 +22,7 @@ import { Observable } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; import { AddOrganizationComponent } from '../add-organization/add-organization.component'; import { isNullOrUndefined } from 'util'; +import { ConfigurationService } from '@app/core/services/configuration/configuration.service'; @Component({ selector: 'app-general-tab', @@ -71,7 +72,8 @@ export class GeneralTabComponent extends BaseComponent implements OnInit { private externalSourcesService: ExternalSourcesService, private _service: DmpService, private dialog: MatDialog, - private language: TranslateService + private language: TranslateService, + private configurationService: ConfigurationService ) { super(); } @@ -194,6 +196,10 @@ export class GeneralTabComponent extends BaseComponent implements OnInit { }); } + showOrganizationCreator(): boolean { + return this.configurationService.allowOrganizationCreator; + } + canAddOrganizations(): boolean { if (!isNullOrUndefined(this.formGroup.get('organizations'))) { return this.formGroup.get('organiztions').disabled; diff --git a/dmp-frontend/src/assets/config/config.json b/dmp-frontend/src/assets/config/config.json index 1c32e5676..7674363b7 100644 --- a/dmp-frontend/src/assets/config/config.json +++ b/dmp-frontend/src/assets/config/config.json @@ -49,5 +49,6 @@ "logLevels": ["debug", "info", "warning", "error"] }, "lockInterval": 60000, - "guideAssets": "assets/images/guide" + "guideAssets": "assets/images/guide", + "allowOrganizationCreator": true } From d67e68d0d95156d98949a850b2447b7376df2f88 Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Mon, 27 Apr 2020 16:21:03 +0300 Subject: [PATCH 06/18] Improve self deployment --- dmp-backend/Docker/dmp-backend.env | 1 + dmp-backend/Dockerfile | 34 ++- .../config/application-devel.properties | 5 +- .../resources/config/application.properties | 6 +- .../resources/logging/logback-production.xml | 4 +- .../resources/logging/logback-staging.xml | 4 +- dmp-frontend/Dockerfile | 45 ++-- dmp-frontend/mime.types | 48 ++++ dmp-frontend/nginx.conf | 35 +++ dmp-frontend/src/app/core/model/dmp/dmp.ts | 2 +- .../src/app/core/model/funder/funder.ts | 2 +- .../src/app/core/model/grant/grant-listing.ts | 2 +- .../core/model/organisation/organization.ts | 2 +- .../src/app/core/model/project/project.ts | 2 +- .../app/core/services/auth/auth.service.ts | 2 +- .../app/core/services/lock/lock.service.ts | 8 +- .../recent-edited-activity.component.ts | 4 +- .../app/ui/dmp/editor/dmp-editor.component.ts | 88 +++---- .../dmp/editor/grant-tab/funder-form-model.ts | 2 +- .../dmp/editor/grant-tab/grant-tab-model.ts | 2 +- .../editor/grant-tab/project-form-model.ts | 2 +- .../editor/people-tab/people-tab.component.ts | 2 +- .../dmp-listing-item.component.ts | 2 +- .../ui/dmp/overview/dmp-overview.component.ts | 4 +- .../ui/dmp/wizard/dmp-wizard-editor.model.ts | 2 +- .../explore-dmp-listing-item.component.ts | 4 +- .../app/ui/grant/editor/grant-editor.model.ts | 2 +- .../user-dialog/user-dialog.component.ts | 2 +- .../dmp-editor/dmp-editor-wizard-model.ts | 2 +- .../grant-editor/grant-editor-wizard-model.ts | 2 +- .../src/app/ui/sidebar/sidebar.component.ts | 6 +- dmp-frontend/src/assets/config/config.json | 2 +- docker-compose.yml | 239 +++--------------- openDMP/dmp-backend/opendmp-logs/.gitkeep | 0 openDMP/dmp-backend/tmp/.gitkeep | 0 openDMP/dmp-frontend/static-files/.gitkeep | 0 openDMP/dmp-frontend/webapp/.gitkeep | 0 {guide => user-guide}/UserGuideDRAFT.html | 0 38 files changed, 256 insertions(+), 313 deletions(-) create mode 100644 dmp-backend/Docker/dmp-backend.env create mode 100644 dmp-frontend/mime.types create mode 100644 dmp-frontend/nginx.conf create mode 100644 openDMP/dmp-backend/opendmp-logs/.gitkeep create mode 100644 openDMP/dmp-backend/tmp/.gitkeep create mode 100644 openDMP/dmp-frontend/static-files/.gitkeep create mode 100644 openDMP/dmp-frontend/webapp/.gitkeep rename {guide => user-guide}/UserGuideDRAFT.html (100%) diff --git a/dmp-backend/Docker/dmp-backend.env b/dmp-backend/Docker/dmp-backend.env new file mode 100644 index 000000000..eada87b0c --- /dev/null +++ b/dmp-backend/Docker/dmp-backend.env @@ -0,0 +1 @@ +PROFILE=staging \ No newline at end of file diff --git a/dmp-backend/Dockerfile b/dmp-backend/Dockerfile index 8701a23a0..4b9954a9e 100644 --- a/dmp-backend/Dockerfile +++ b/dmp-backend/Dockerfile @@ -1,11 +1,23 @@ -FROM openjdk:8-jdk-alpine -RUN apk add --update \ - curl \ - && rm -rf /var/cache/apk/* -VOLUME /tmp -ARG PROFILE=production -ENV PROF $PROFILE -ADD web/src/main/resources/ProjectConfiguration.xml /tmp/ProjectConfiguration.xml -ADD web/src/main/resources/ExternalUrls.xml /tmp/ExternalUrls.xml -ADD web/target/web-1.0-SNAPSHOT.jar app.jar -ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom" ,"-Dspring.profiles.active=${PROF}","-jar","/app.jar"] \ No newline at end of file +FROM maven:3-jdk-8-alpine AS MAVEN_BUILD + + + +COPY pom.xml /build/ +COPY data /build/data/ +COPY elastic /build/elastic/ +COPY logging /build/logging/ +COPY queryable /build/queryable/ +COPY web /build/web/ + + + +WORKDIR /build/ +RUN mvn package + + + +FROM openjdk:8-jre-alpine +WORKDIR /app + +COPY --from=MAVEN_BUILD /build/web/target/web-1.0-SNAPSHOT.jar /app/app.jar +ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom" ,"-Dspring.profiles.active=${PROFILE}","-jar","/app/app.jar"] \ No newline at end of file diff --git a/dmp-backend/web/src/main/resources/config/application-devel.properties b/dmp-backend/web/src/main/resources/config/application-devel.properties index 7051f6667..c7cb9d05e 100644 --- a/dmp-backend/web/src/main/resources/config/application-devel.properties +++ b/dmp-backend/web/src/main/resources/config/application-devel.properties @@ -77,4 +77,7 @@ zenodo.login.redirect_uri=http://localhost:4200/login/external/zenodo #############CONTACT EMAIL CONFIGURATIONS######### contact_email.mail= -language.path=tempLang/i18n/ \ No newline at end of file +language.path=i18n/ + +#############LOGGING######### +logging.config=classpath:logging/logback-${spring.profiles.active}.xml \ No newline at end of file diff --git a/dmp-backend/web/src/main/resources/config/application.properties b/dmp-backend/web/src/main/resources/config/application.properties index 610c84be8..229e7ed48 100644 --- a/dmp-backend/web/src/main/resources/config/application.properties +++ b/dmp-backend/web/src/main/resources/config/application.properties @@ -1,4 +1,4 @@ -server.port=8080 +server.port=8081 server.tomcat.max-threads = 20 server.tomcat.max-connections = 10000 logging.file=/logs/spring-boot-logging.log @@ -79,7 +79,7 @@ database.lock-fail-interval=120000 ##########################MISC########################################## #############USER GUIDE######### -userguide.path=guide/ +userguide.path=user-guide/ #############NOTIFICATION######### notification.rateInterval=30000 @@ -90,7 +90,7 @@ notification.finalised.subject=[OpenDMP] The {name} has been finalised notification.modifiedFinalised.subject=[OpenDMP] The {name} has been modified and finalised #############LOGGING######### -logging.config=classpath:logging/logback-${spring.profiles.active}.xml +logging.config=file:/app/logging/logback-${spring.profiles.active}.xml #############TEMP######### temp.temp=tmp/ \ No newline at end of file diff --git a/dmp-backend/web/src/main/resources/logging/logback-production.xml b/dmp-backend/web/src/main/resources/logging/logback-production.xml index 9b27c97dc..f62bc4664 100644 --- a/dmp-backend/web/src/main/resources/logging/logback-production.xml +++ b/dmp-backend/web/src/main/resources/logging/logback-production.xml @@ -7,9 +7,9 @@ - /files/logs/openDMP.log + /app/logs/openDMP.log - /files/logs/openDMP-%d{yyyy-MM-dd}.%i.log + /app/logs/openDMP-%d{yyyy-MM-dd}.%i.log 100MB diff --git a/dmp-backend/web/src/main/resources/logging/logback-staging.xml b/dmp-backend/web/src/main/resources/logging/logback-staging.xml index f1e40e210..143e8a18f 100644 --- a/dmp-backend/web/src/main/resources/logging/logback-staging.xml +++ b/dmp-backend/web/src/main/resources/logging/logback-staging.xml @@ -7,9 +7,9 @@ - /files/logs/openDMP.log + /app/logs/openDMP.log - /files/logs/openDMP-%d{yyyy-MM-dd}.%i.log + /app/logs/openDMP-%d{yyyy-MM-dd}.%i.log 100MB diff --git a/dmp-frontend/Dockerfile b/dmp-frontend/Dockerfile index a1aaa80d3..5e6fe52b2 100644 --- a/dmp-frontend/Dockerfile +++ b/dmp-frontend/Dockerfile @@ -1,17 +1,32 @@ -FROM johnpapa/angular-cli as angular -WORKDIR /app -COPY package.json /app/ -RUN npm cache clear --force && npm install +# stage1 as builder +FROM node:12-alpine as builder -COPY ./ /app/ -ARG env=dev -ARG aot=--no-aot -RUN echo $env -RUN echo $aot -RUN if [ "$env" = "prod" ]; then ng build --$env --$aot; else ng build --$aot; fi +WORKDIR /page -# Stage 1, based on Nginx, to have only the compiled app, ready for production with Nginx -FROM nginx:1.13 -COPY --from=angular /app/dist/ /usr/share/nginx/html -COPY --from=angular /app/static/ /usr/share/nginx/static -COPY ./nginx-custom.conf /etc/nginx/conf.d/default.conf +# copy the package.json to install dependencies +COPY package.json /page + +# Install the dependencies and make the folder +RUN npm install + +COPY . /page + +# Build the project and copy the files +RUN npm run ng build -- --deploy-url=/ --prod + +FROM nginx:alpine + +#!/bin/sh + +COPY nginx.conf /etc/nginx +COPY mime.types /etc/nginx + +## Remove default nginx index page +RUN rm -rf /usr/share/nginx/html/* + +# Copy from the stahg 1 +COPY --from=builder /page/dist /usr/share/nginx/html + +EXPOSE 4200 + +ENTRYPOINT ["nginx", "-g", "daemon off;", "-p", "/usr/share/nginx"] diff --git a/dmp-frontend/mime.types b/dmp-frontend/mime.types new file mode 100644 index 000000000..62bd4b668 --- /dev/null +++ b/dmp-frontend/mime.types @@ -0,0 +1,48 @@ +types { + text/html html htm shtml; + text/css css; + text/xml xml rss; + image/gif gif; + image/jpeg jpeg jpg; + application/x-javascript js; + text/plain txt; + text/x-component htc; + text/mathml mml; + image/png png; + image/x-icon ico; + image/x-jng jng; + image/vnd.wap.wbmp wbmp; + application/java-archive jar war ear; + application/mac-binhex40 hqx; + application/pdf pdf; + application/x-cocoa cco; + application/x-java-archive-diff jardiff; + application/x-java-jnlp-file jnlp; + application/x-makeself run; + application/x-perl pl pm; + application/x-pilot prc pdb; + application/x-rar-compressed rar; + application/x-redhat-package-manager rpm; + application/x-sea sea; + application/x-shockwave-flash swf; + application/x-stuffit sit; + application/x-tcl tcl tk; + application/x-x509-ca-cert der pem crt; + application/x-xpinstall xpi; + application/zip zip; + application/octet-stream deb; + application/octet-stream bin exe dll; + application/octet-stream dmg; + application/octet-stream eot; + application/octet-stream iso img; + application/octet-stream msi msp msm; + audio/mpeg mp3; + audio/x-realaudio ra; + video/mpeg mpeg mpg; + video/quicktime mov; + video/x-flv flv; + video/x-msvideo avi; + video/x-ms-wmv wmv; + video/x-ms-asf asx asf; + video/x-mng mng; +} \ No newline at end of file diff --git a/dmp-frontend/nginx.conf b/dmp-frontend/nginx.conf new file mode 100644 index 000000000..7b29b4cb8 --- /dev/null +++ b/dmp-frontend/nginx.conf @@ -0,0 +1,35 @@ + +events { + worker_connections 4096; ## Default: 1024 +} + +http { + include ./mime.types; + server { + + listen 4200; + + sendfile on; + + gzip on; + gzip_http_version 1.1; + gzip_disable "MSIE [1-6]\."; + gzip_min_length 1100; + gzip_vary on; + gzip_proxied expired no-cache no-store private auth; + gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; + gzip_comp_level 9; + + + + + + location / { + root /usr/share/nginx/html; + try_files $uri $uri/ /index.html =404; + add_header Cache-Control "no-store, no-cache, must-revalidate"; + } + + } + +} diff --git a/dmp-frontend/src/app/core/model/dmp/dmp.ts b/dmp-frontend/src/app/core/model/dmp/dmp.ts index 721c42608..15f226b0a 100644 --- a/dmp-frontend/src/app/core/model/dmp/dmp.ts +++ b/dmp-frontend/src/app/core/model/dmp/dmp.ts @@ -1,4 +1,4 @@ -import { Status } from "../../common/enum/Status"; +import { Status } from "../../common/enum/status"; import { DmpProfile, DmpProfileDefinition } from "../dmp-profile/dmp-profile"; import { OrganizationModel } from "../organisation/organization"; import { GrantListingModel } from "../grant/grant-listing"; diff --git a/dmp-frontend/src/app/core/model/funder/funder.ts b/dmp-frontend/src/app/core/model/funder/funder.ts index 8a0046dfb..a266d90ea 100644 --- a/dmp-frontend/src/app/core/model/funder/funder.ts +++ b/dmp-frontend/src/app/core/model/funder/funder.ts @@ -1,4 +1,4 @@ -import { Status } from "../../common/enum/Status"; +import { Status } from "../../common/enum/status"; export class FunderModel { id: string; diff --git a/dmp-frontend/src/app/core/model/grant/grant-listing.ts b/dmp-frontend/src/app/core/model/grant/grant-listing.ts index 9573ae4b6..d6d2fba85 100644 --- a/dmp-frontend/src/app/core/model/grant/grant-listing.ts +++ b/dmp-frontend/src/app/core/model/grant/grant-listing.ts @@ -1,6 +1,6 @@ import { UrlListingItem } from "../../../library/url-listing/url-listing-item"; import { GrantType } from '../../common/enum/grant-type'; -import { Status } from '../../common/enum/Status'; +import { Status } from '../../common/enum/status'; export interface GrantListingModel { id?: string; diff --git a/dmp-frontend/src/app/core/model/organisation/organization.ts b/dmp-frontend/src/app/core/model/organisation/organization.ts index 5fd54c7ab..9cdc13e05 100644 --- a/dmp-frontend/src/app/core/model/organisation/organization.ts +++ b/dmp-frontend/src/app/core/model/organisation/organization.ts @@ -1,4 +1,4 @@ -import { Status } from "../../common/enum/Status"; +import { Status } from "../../common/enum/status"; export interface OrganizationModel { id: string; diff --git a/dmp-frontend/src/app/core/model/project/project.ts b/dmp-frontend/src/app/core/model/project/project.ts index 6f401f312..bd467a575 100644 --- a/dmp-frontend/src/app/core/model/project/project.ts +++ b/dmp-frontend/src/app/core/model/project/project.ts @@ -1,4 +1,4 @@ -import { Status } from "../../common/enum/Status"; +import { Status } from "../../common/enum/status"; import { UrlListingItem } from "../../../library/url-listing/url-listing-item"; import { ProjectType } from "../../common/enum/project-type"; diff --git a/dmp-frontend/src/app/core/services/auth/auth.service.ts b/dmp-frontend/src/app/core/services/auth/auth.service.ts index a50261ba0..9b61514c4 100644 --- a/dmp-frontend/src/app/core/services/auth/auth.service.ts +++ b/dmp-frontend/src/app/core/services/auth/auth.service.ts @@ -5,7 +5,7 @@ import { MatSnackBar } from '@angular/material/snack-bar'; import { Router } from '@angular/router'; import { Credential } from '@app/core/model/auth/credential'; import { LoginInfo } from '@app/core/model/auth/login-info'; -import { Principal } from '@app/core/model/auth/Principal'; +import { Principal } from '@app/core/model/auth/principal'; import { ConfigurableProvider } from '@app/core/model/configurable-provider/configurableProvider'; import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; import { BaseService } from '@common/base/base.service'; diff --git a/dmp-frontend/src/app/core/services/lock/lock.service.ts b/dmp-frontend/src/app/core/services/lock/lock.service.ts index a816163e5..3404f1cc0 100644 --- a/dmp-frontend/src/app/core/services/lock/lock.service.ts +++ b/dmp-frontend/src/app/core/services/lock/lock.service.ts @@ -17,18 +17,18 @@ export class LockService { } checkLockStatus(id: string): Observable { - return this.http.get(`${this.actionUrl}target/status/${id}`, {headers: this.headers}); + return this.http.get(`${this.actionUrl}target/status/${id}`, { headers: this.headers }); } unlockTarget(id: string): Observable { - return this.http.delete(`${this.actionUrl}target/unlock/${id}`, {headers: this.headers}); + return this.http.delete(`${this.actionUrl}target/unlock/${id}`, { headers: this.headers }); } getSingle(id: string): Observable { - return this.http.get(`${this.actionUrl}target/${id}`, {headers: this.headers}); + return this.http.get(`${this.actionUrl}target/${id}`, { headers: this.headers }); } createOrUpdate(lock: LockModel): Observable { - return this.http.post(`${this.actionUrl}`, lock, {headers: this.headers}); + return this.http.post(`${this.actionUrl}`, lock, { headers: this.headers }); } } diff --git a/dmp-frontend/src/app/ui/dashboard/recent-edited-activity/recent-edited-activity.component.ts b/dmp-frontend/src/app/ui/dashboard/recent-edited-activity/recent-edited-activity.component.ts index 6e9b89b8b..bff497006 100644 --- a/dmp-frontend/src/app/ui/dashboard/recent-edited-activity/recent-edited-activity.component.ts +++ b/dmp-frontend/src/app/ui/dashboard/recent-edited-activity/recent-edited-activity.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { MatDialog } from '@angular/material'; import { Router } from '@angular/router'; import { RecentActivityType } from '@app/core/common/enum/recent-activity-type'; -import { Principal } from '@app/core/model/auth/Principal'; +import { Principal } from '@app/core/model/auth/principal'; import { DataTableRequest } from '@app/core/model/data-table/data-table-request'; import { DmpListingModel } from '@app/core/model/dmp/dmp-listing'; import { DmpCriteria } from '@app/core/query/dmp/dmp-criteria'; @@ -10,7 +10,7 @@ import { AuthService } from '@app/core/services/auth/auth.service'; import { DmpService } from '@app/core/services/dmp/dmp.service'; import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; -import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from '@ngx-translate/core'; import * as FileSaver from 'file-saver'; diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts index 889b303b5..1a03c4a27 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts @@ -34,7 +34,7 @@ import { TranslateService } from '@ngx-translate/core'; import * as FileSaver from 'file-saver'; import { Observable, of as observableOf, interval } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; -import { Principal } from "@app/core/model/auth/Principal"; +import { Principal } from "@app/core/model/auth/principal"; import { Role } from "@app/core/common/enum/role"; import { LockService } from '@app/core/services/lock/lock.service'; import { Location } from '@angular/common'; @@ -109,7 +109,7 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC // displayFn: (item) => item['label'], // titleFn: (item) => item['label'] // }; - switch(tabToNav) { + switch (tabToNav) { case 'general': this.selectedTab = 0; break; @@ -130,52 +130,52 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC .subscribe(async data => { this.lockService.checkLockStatus(data.id).pipe(takeUntil(this._destroyed)).subscribe(lockStatus => { this.lockStatus = lockStatus; - this.dmp = new DmpEditorModel(); - this.dmp.grant = new GrantTabModel(); - this.dmp.project = new ProjectFormModel(); - this.dmp.funder = new FunderFormModel(); - this.dmp.fromModel(data); - this.formGroup = this.dmp.buildForm(); - this.setIsUserOwner(); - if (!this.isUserOwner) { - this.isFinalized = true; - this.formGroup.disable(); - } + this.dmp = new DmpEditorModel(); + this.dmp.grant = new GrantTabModel(); + this.dmp.project = new ProjectFormModel(); + this.dmp.funder = new FunderFormModel(); + this.dmp.fromModel(data); + this.formGroup = this.dmp.buildForm(); + this.setIsUserOwner(); + if (!this.isUserOwner) { + this.isFinalized = true; + this.formGroup.disable(); + } - //this.registerFormEventsForDmpProfile(this.dmp.definition); - if (!this.editMode || this.dmp.status === DmpStatus.Finalized || lockStatus) { - this.isFinalized = true; - this.formGroup.disable(); - } + //this.registerFormEventsForDmpProfile(this.dmp.definition); + if (!this.editMode || this.dmp.status === DmpStatus.Finalized || lockStatus) { + this.isFinalized = true; + this.formGroup.disable(); + } - if (this.isAuthenticated) { - if (!lockStatus) { - this.lock = new LockModel(data.id, this.getUserFromDMP()); + if (this.isAuthenticated) { + if (!lockStatus) { + this.lock = new LockModel(data.id, this.getUserFromDMP()); - this.lockService.createOrUpdate(this.lock).pipe(takeUntil(this._destroyed)).subscribe(async result => { - this.lock.id = Guid.parse(result); - interval(this.configurationService.lockInterval).pipe(takeUntil(this._destroyed)).subscribe(() => this.pumpLock()); + this.lockService.createOrUpdate(this.lock).pipe(takeUntil(this._destroyed)).subscribe(async result => { + this.lock.id = Guid.parse(result); + interval(this.configurationService.lockInterval).pipe(takeUntil(this._destroyed)).subscribe(() => this.pumpLock()); + }); + } + // if (!this.isAuthenticated) { + const breadCrumbs = []; + breadCrumbs.push({ + parentComponentName: null, + label: this.language.instant('NAV-BAR.MY-DMPS'), + url: "/plans" }); + breadCrumbs.push({ + parentComponentName: 'DmpListingComponent', + label: this.dmp.label, + url: '/plans/edit/' + this.dmp.id, + // notFoundResolver: [await this.grantService.getSingle(this.dmp.grant.id).map(x => ({ label: x.label, url: '/grants/edit/' + x.id }) as BreadcrumbItem).toPromise()] + } + ); + this.breadCrumbs = observableOf(breadCrumbs); } - // if (!this.isAuthenticated) { - const breadCrumbs = []; - breadCrumbs.push({ - parentComponentName: null, - label: this.language.instant('NAV-BAR.MY-DMPS'), - url: "/plans" - }); - breadCrumbs.push({ - parentComponentName: 'DmpListingComponent', - label: this.dmp.label, - url: '/plans/edit/' + this.dmp.id, - // notFoundResolver: [await this.grantService.getSingle(this.dmp.grant.id).map(x => ({ label: x.label, url: '/grants/edit/' + x.id }) as BreadcrumbItem).toPromise()] - } - ); - this.breadCrumbs = observableOf(breadCrumbs); - } - this.associatedUsers = data.associatedUsers; - this.people = data.users; - }) + this.associatedUsers = data.associatedUsers; + this.people = data.users; + }) }); } else if (publicId != null) { this.isNew = false; @@ -567,7 +567,7 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC private pumpLock() { this.lock.touchedAt = new Date(); - this.lockService.createOrUpdate(this.lock).pipe(takeUntil(this._destroyed)).subscribe( async result => this.lock.id = Guid.parse(result)); + this.lockService.createOrUpdate(this.lock).pipe(takeUntil(this._destroyed)).subscribe(async result => this.lock.id = Guid.parse(result)); } // advancedClicked() { diff --git a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/funder-form-model.ts b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/funder-form-model.ts index 76adf4e24..4ad0c6e7d 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/funder-form-model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/funder-form-model.ts @@ -1,5 +1,5 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { Status } from '@app/core/common/enum/Status'; +import { Status } from '@app/core/common/enum/status'; import { FunderModel } from '@app/core/model/funder/funder'; import { BackendErrorValidator } from '@common/forms/validation/custom-validator'; import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; diff --git a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab-model.ts b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab-model.ts index afba9fce2..4c01cfbfc 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab-model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab-model.ts @@ -1,5 +1,5 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { Status } from '@app/core/common/enum/Status'; +import { Status } from '@app/core/common/enum/status'; import { GrantListingModel } from '@app/core/model/grant/grant-listing'; import { ValidJsonValidator } from '@app/library/auto-complete/auto-complete-custom-validator'; import { BackendErrorValidator } from '@common/forms/validation/custom-validator'; diff --git a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/project-form-model.ts b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/project-form-model.ts index 797dfee69..826221b30 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/project-form-model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/project-form-model.ts @@ -1,5 +1,5 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { Status } from '@app/core/common/enum/Status'; +import { Status } from '@app/core/common/enum/status'; import { ProjectModel } from '@app/core/model/project/project'; import { BackendErrorValidator } from '@common/forms/validation/custom-validator'; import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; diff --git a/dmp-frontend/src/app/ui/dmp/editor/people-tab/people-tab.component.ts b/dmp-frontend/src/app/ui/dmp/editor/people-tab/people-tab.component.ts index 1c303c446..e5f6b992c 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/people-tab/people-tab.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/people-tab/people-tab.component.ts @@ -3,7 +3,7 @@ import { FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; import { TranslateService } from '@ngx-translate/core'; -import { Principal } from '../../../../core/model/auth/Principal'; +import { Principal } from '../../../../core/model/auth/principal'; import { UserInfoListingModel } from '../../../../core/model/user/user-info-listing'; import { AuthService } from '../../../../core/services/auth/auth.service'; import { DmpService } from '../../../../core/services/dmp/dmp.service'; diff --git a/dmp-frontend/src/app/ui/dmp/listing/listing-item/dmp-listing-item.component.ts b/dmp-frontend/src/app/ui/dmp/listing/listing-item/dmp-listing-item.component.ts index 77f63bd4d..0f20ccc2d 100644 --- a/dmp-frontend/src/app/ui/dmp/listing/listing-item/dmp-listing-item.component.ts +++ b/dmp-frontend/src/app/ui/dmp/listing/listing-item/dmp-listing-item.component.ts @@ -5,7 +5,7 @@ import { DmpInvitationDialogComponent } from '../../invitation/dmp-invitation.co import { Router, ActivatedRoute } from '@angular/router'; import { DatasetService } from '../../../../core/services/dataset/dataset.service'; import { AuthService } from '../../../../core/services/auth/auth.service'; -import { Principal } from '../../../../core/model/auth/Principal'; +import { Principal } from '../../../../core/model/auth/principal'; import { TranslateService } from '@ngx-translate/core'; import { DmpStatus } from '../../../../core/common/enum/dmp-status'; diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts index ca3ded5cc..ea0064270 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts @@ -4,7 +4,7 @@ import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Params, Router } from '@angular/router'; import { DatasetStatus } from '@app/core/common/enum/dataset-status'; import { DmpStatus } from '@app/core/common/enum/dmp-status'; -import { Principal } from '@app/core/model/auth/Principal'; +import { Principal } from '@app/core/model/auth/principal'; import { DatasetOverviewModel } from '@app/core/model/dataset/dataset-overview'; import { DatasetsToBeFinalized } from '@app/core/model/dataset/datasets-toBeFinalized'; import { DmpOverviewModel } from '@app/core/model/dmp/dmp-overview'; @@ -357,7 +357,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { maxWidth: '600px', restoreFocus: false, data: { - message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ZENODO-DOI', { 'username': this.hasDOIToken ? this.authentication.current().zenodoEmail : 'default'}), + message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ZENODO-DOI', { 'username': this.hasDOIToken ? this.authentication.current().zenodoEmail : 'default' }), confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'), cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'), } diff --git a/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard-editor.model.ts b/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard-editor.model.ts index 4582e91e8..7edeacf8d 100644 --- a/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard-editor.model.ts +++ b/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard-editor.model.ts @@ -1,5 +1,5 @@ import { FormBuilder, FormGroup, Validators } from "@angular/forms"; -import { Status } from '@app/core/common/enum/Status'; +import { Status } from '@app/core/common/enum/status'; import { DmpProfile, DmpProfileDefinition } from '@app/core/model/dmp-profile/dmp-profile'; import { DmpModel } from '@app/core/model/dmp/dmp'; import { DmpDynamicField } from '@app/core/model/dmp/dmp-dynamic-field'; diff --git a/dmp-frontend/src/app/ui/explore-dmp/listing-item/explore-dmp-listing-item.component.ts b/dmp-frontend/src/app/ui/explore-dmp/listing-item/explore-dmp-listing-item.component.ts index 468b239d6..327bc33be 100644 --- a/dmp-frontend/src/app/ui/explore-dmp/listing-item/explore-dmp-listing-item.component.ts +++ b/dmp-frontend/src/app/ui/explore-dmp/listing-item/explore-dmp-listing-item.component.ts @@ -1,6 +1,6 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { DmpListingModel } from '../../../core/model/dmp/dmp-listing'; -import { Principal } from '../../../core/model/auth/Principal'; +import { Principal } from '../../../core/model/auth/principal'; import { AuthService } from '../../../core/services/auth/auth.service'; import { TranslateService } from '@ngx-translate/core'; import { Router, ActivatedRoute } from '@angular/router'; @@ -21,7 +21,7 @@ export class ExploreDmpListingItemComponent implements OnInit { private translate: TranslateService, private router: Router, private route: ActivatedRoute - ) { } + ) { } ngOnInit() { } diff --git a/dmp-frontend/src/app/ui/grant/editor/grant-editor.model.ts b/dmp-frontend/src/app/ui/grant/editor/grant-editor.model.ts index 8b783111c..28769e4a8 100644 --- a/dmp-frontend/src/app/ui/grant/editor/grant-editor.model.ts +++ b/dmp-frontend/src/app/ui/grant/editor/grant-editor.model.ts @@ -3,7 +3,7 @@ import { BackendErrorValidator } from '@common/forms/validation/custom-validator import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; import { ValidationContext } from '@common/forms/validation/validation-context'; import { GrantType } from '../../../core/common/enum/grant-type'; -import { Status } from '../../../core/common/enum/Status'; +import { Status } from '../../../core/common/enum/status'; import { ContentFile, GrantListingModel } from '../../../core/model/grant/grant-listing'; export class GrantEditorModel { diff --git a/dmp-frontend/src/app/ui/misc/navigation/user-dialog/user-dialog.component.ts b/dmp-frontend/src/app/ui/misc/navigation/user-dialog/user-dialog.component.ts index 326dd5280..21d7e79bc 100644 --- a/dmp-frontend/src/app/ui/misc/navigation/user-dialog/user-dialog.component.ts +++ b/dmp-frontend/src/app/ui/misc/navigation/user-dialog/user-dialog.component.ts @@ -2,7 +2,7 @@ import { Component, Inject, OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { Router } from '@angular/router'; -import { Principal } from '../../../../core/model/auth/Principal'; +import { Principal } from '../../../../core/model/auth/principal'; import { AuthService } from '../../../../core/services/auth/auth.service'; @Component({ diff --git a/dmp-frontend/src/app/ui/quick-wizard/dmp-editor/dmp-editor-wizard-model.ts b/dmp-frontend/src/app/ui/quick-wizard/dmp-editor/dmp-editor-wizard-model.ts index fa213f870..3ec776427 100644 --- a/dmp-frontend/src/app/ui/quick-wizard/dmp-editor/dmp-editor-wizard-model.ts +++ b/dmp-frontend/src/app/ui/quick-wizard/dmp-editor/dmp-editor-wizard-model.ts @@ -1,5 +1,5 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { Status } from '@app/core/common/enum/Status'; +import { Status } from '@app/core/common/enum/status'; import { DatasetProfileModel } from '@app/core/model/dataset/dataset-profile'; import { DmpProfileDefinition } from '@app/core/model/dmp-profile/dmp-profile'; import { DmpModel } from '@app/core/model/dmp/dmp'; diff --git a/dmp-frontend/src/app/ui/quick-wizard/grant-editor/grant-editor-wizard-model.ts b/dmp-frontend/src/app/ui/quick-wizard/grant-editor/grant-editor-wizard-model.ts index b8f30cc6e..90cbdd8ae 100644 --- a/dmp-frontend/src/app/ui/quick-wizard/grant-editor/grant-editor-wizard-model.ts +++ b/dmp-frontend/src/app/ui/quick-wizard/grant-editor/grant-editor-wizard-model.ts @@ -1,5 +1,5 @@ import { FormBuilder, FormGroup, Validators } from "@angular/forms"; -import { Status } from '@app/core/common/enum/Status'; +import { Status } from '@app/core/common/enum/status'; import { GrantListingModel } from '@app/core/model/grant/grant-listing'; import { ValidJsonValidator } from '@app/library/auto-complete/auto-complete-custom-validator'; import { BackendErrorValidator } from '@common/forms/validation/custom-validator'; diff --git a/dmp-frontend/src/app/ui/sidebar/sidebar.component.ts b/dmp-frontend/src/app/ui/sidebar/sidebar.component.ts index 9321cb07c..39335f81d 100644 --- a/dmp-frontend/src/app/ui/sidebar/sidebar.component.ts +++ b/dmp-frontend/src/app/ui/sidebar/sidebar.component.ts @@ -3,7 +3,7 @@ import { MatDialog } from '@angular/material/dialog'; import { TranslateService } from '@ngx-translate/core'; import { AuthService } from '../../core/services/auth/auth.service'; import { UserDialogComponent } from '../misc/navigation/user-dialog/user-dialog.component'; -import { Principal } from '../../core/model/auth/Principal'; +import { Principal } from '../../core/model/auth/principal'; import { AppRole } from '../../core/common/enum/app-role'; import { Router } from '@angular/router'; import { Location } from '@angular/common'; @@ -51,8 +51,8 @@ export const ADMIN_ROUTES: RouteInfo[] = [ { path: '/dmp-profiles', title: 'SIDE-BAR.DMP-TEMPLATES', icon: 'library_books' }, { path: '/dataset-profiles', title: 'SIDE-BAR.DATASET-TEMPLATES', icon: 'library_books' }, { path: '/users', title: 'SIDE-BAR.USERS', icon: 'people' }, - { path: '/language-editor', title: 'SIDE-BAR.LANGUAGE-EDITOR', icon: 'language'}, - { path: '/user-guide-editor', title: 'SIDE-BAR.GUIDE-EDITOR', icon: 'import_contacts'} + { path: '/language-editor', title: 'SIDE-BAR.LANGUAGE-EDITOR', icon: 'language' }, + { path: '/user-guide-editor', title: 'SIDE-BAR.GUIDE-EDITOR', icon: 'import_contacts' } ]; // export const HISTORY_ROUTES: RouteInfo[] = [ // { path: '/typography', title: 'SIDE-BAR.HISTORY-VISITED', icon: 'visibility'}, diff --git a/dmp-frontend/src/assets/config/config.json b/dmp-frontend/src/assets/config/config.json index 7674363b7..5f916f361 100644 --- a/dmp-frontend/src/assets/config/config.json +++ b/dmp-frontend/src/assets/config/config.json @@ -1,6 +1,6 @@ { "production": false, - "Server": "http://localhost:8080/api/", + "Server": "http://localhost:8081/api/", "App": "http://localhost:4200/", "HelpService": { "Enabled": false, diff --git a/docker-compose.yml b/docker-compose.yml index 1b94552b3..ac90b8444 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,212 +1,41 @@ ---- -version: '3' -services: - # The environment variable "TAG" is used throughout this file to - # specify the version of the images to run. The default is set in the - # '.env' file in this folder. It can be overridden with any normal - # technique for setting environment variables, for example: - # - # TAG=6.0.0-beta1 docker-compose up - # - # REF: https://docs.docker.com/compose/compose-file/#variable-substitution - # - # Also be sure to set the ELASTIC_VERSION variable. For released versions, - # ${TAG} and ${ELASTIC_VERSION} will be identical, but for pre-release - # versions, ${TAG} might contain an extra build identifier, like - # "6.0.0-beta1-3eab5b40", so a full invocation might look like: - # - # ELASTIC_VERSION=6.0.0-beta1 TAG=6.0.0-beta1-3eab5b40 docker-compose up - # - -##########################DMP###################################################################### +version: '2.2' +services: dmp-backend: - build: - context: ./dmp-backend - args: - PROFILE: ${PROFILE} - container_name: dmp-backend - ports: ['0.0.0.0:8080:8080'] - links: - # - logstash:logstash - - elasticsearch-dmp:elasticsearch-dmp - networks: ['stack','elasticsearch-dmp'] + build: + context: ./dmp-backend + container_name: opendmp-backend + env_file: ./dmp-backend/Docker/dmp-backend.env + restart: unless-stopped + mem_limit: 2048m + ports: + - "8081:8081" + networks: + - opendmp-backend-network + volumes: + - ./openDMP/dmp-backend/config:/app/config + - ./openDMP/dmp-backend/user-guide:/app/user-guide + - ./openDMP/dmp-backend/i18n:/app/i18n + - ./openDMP/dmp-backend/externalUrls:/app/externalUrls + - ./openDMP/dmp-backend/templates:/app/templates + - ./openDMP/dmp-backend/opendmp-logs:/app/logs + - ./openDMP/dmp-backend/tmp:/app/tmp + - ./openDMP/dmp-backend/logging:/app/logging dmp-frontend: build: - context: ./dmp-frontend - args: - env: ${ENV} - aot: ${AOT} - container_name: dmp-frontend + context: ./dmp-frontend + container_name: opendmp-frontend + mem_limit: 2048m + restart: unless-stopped + ports: + - "8080:4200" volumes: - - ./static:/usr/share/nginx/static - - /srv/docker/wwwcert:/usr/share/nginx/wwwcert - ports: ['0.0.0.0:80:80'] - networks: ['stack'] - -##########################ELASTIC###################################################################### - elasticsearch-dmp: - image: docker.elastic.co/elasticsearch/elasticsearch:${TAG} - container_name: elasticsearch-dmp - volumes: - - ./elastic-config/elasticsearch-custom.yml:/usr/share/elasticsearch/config/elasticsearch.yml - environment: ['http.host=0.0.0.0','transport.host=0.0.0.0','discovery.type=single-node'] - ports: ['0.0.0.0:9201:9200','0.0.0.0:9301:9300'] - networks: ['elasticsearch-dmp'] - volumes: - - esdata-dmp:/usr/share/elasticsearch/data - -##########################ELK-STACK###################################################################### - - elasticsearch: - image: docker.elastic.co/elasticsearch/elasticsearch:${TAG} - container_name: elasticsearch - environment: ['http.host=0.0.0.0', 'transport.host=127.0.0.1', 'ELASTIC_PASSWORD=${ELASTIC_PASSWORD}','discovery.type=single-node'] - ports: ['0.0.0.0:9200:9200'] - networks: ['stack'] - volumes: - - esdata:/usr/share/elasticsearch/data - - kibana: - image: docker.elastic.co/kibana/kibana:${TAG} - container_name: kibana - ports: ['0.0.0.0:5601:5601'] - networks: ['stack'] - depends_on: ['elasticsearch'] - - logstash: - image: docker.elastic.co/logstash/logstash:${TAG} - container_name: logstash - volumes: - - ./ELK.Docker/config/logstash.conf:/usr/share/logstash/pipeline/logstash.conf - ports: ['0.0.0.0:31311:31311'] - - networks: ['stack'] - depends_on: ['elasticsearch', 'setup_logstash'] - - #filebeat: - # image: docker.elastic.co/beats/filebeat:${TAG} - # container_name: filebeat - # command: -e -E 'output.elasticsearch.password=${ELASTIC_PASSWORD}' - # networks: ['stack'] - # depends_on: ['elasticsearch', 'setup_filebeat'] - - #heartbeat: - # image: docker.elastic.co/beats/heartbeat:${TAG} - # container_name: heartbeat - # command: -e -E 'output.elasticsearch.password=${ELASTIC_PASSWORD}' - # networks: ['stack'] - # depends_on: ['elasticsearch', 'setup_heartbeat'] - - # Run a short-lived container to set up Logstash. - setup_logstash: - image: centos:7 - container_name: setup_logstash - volumes: ['./ELK.Docker/scripts/setup-logstash.sh:/usr/local/bin/setup-logstash.sh:ro'] - command: ['/bin/bash', '-c', 'cat /usr/local/bin/setup-logstash.sh | tr -d "\r" | bash'] - environment: ['ELASTIC_PASSWORD=${ELASTIC_PASSWORD}'] - networks: ['stack'] - depends_on: ['elasticsearch'] - - setup_kibana: - image: centos:7 - container_name: setup_kibana - volumes: ['./ELK.Docker/scripts/setup-kibana.sh:/usr/local/bin/setup-kibana.sh:ro'] - command: ['/bin/bash', '-c', 'cat /usr/local/bin/setup-kibana.sh | tr -d "\r" | bash'] - environment: ['ELASTIC_PASSWORD=${ELASTIC_PASSWORD}'] - networks: ['stack'] - depends_on: ['elasticsearch'] - - #setup_filebeat: - # image: docker.elastic.co/beats/filebeat:${TAG} - # container_name: setup_filebeat - # volumes: ['./ELK.Docker/scripts/setup-beat.sh:/usr/local/bin/setup-beat.sh:ro'] - # command: ['/bin/bash', '-c', 'cat /usr/local/bin/setup-beat.sh | tr -d "\r" | bash -s filebeat'] - # environment: ['ELASTIC_PASSWORD=${ELASTIC_PASSWORD}'] - # networks: ['stack'] - # depends_on: ['kibana'] - - #setup_heartbeat: - # image: docker.elastic.co/beats/heartbeat:${TAG} - # container_name: setup_heartbeat - # volumes: ['./ELK.Docker/scripts/setup-beat.sh:/usr/local/bin/setup-beat.sh:ro'] - # command: ['/bin/bash', '-c', 'cat /usr/local/bin/setup-beat.sh | tr -d "\r" | bash -s heartbeat'] - # environment: ['ELASTIC_PASSWORD=${ELASTIC_PASSWORD}'] - # networks: ['stack'] - # depends_on: ['kibana'] - -##########################DOCSBOX###################################################################### - # web: - # restart: always - # build: ./docsbox-master/docsbox - # expose: - # - "8000" - # links: - # - redis:redis - # volumes: - # - docsbox:/home/docsbox - # - media:/home/docsbox/media - # command: gunicorn -b :8000 docsbox:app - # networks: ['stack'] - - # rqworker: - # restart: always - # build: ./docsbox-master/docsbox - # links: - # - redis:redis - # volumes: - # - web - # command: rq worker -c docsbox.settings - # networks: ['stack'] - - # rqscheduler: - # restart: always - # build: ./docsbox-master/docsbox - # links: - # - redis:redis - # volumes: - # - web - # command: rqscheduler -H redis -p 6379 -d 0 - # networks: ['stack'] - - # nginx: - # restart: always - # build: ./docsbox-master/nginx/ - # ports: - # - "81:80" - # volumes: - # - web - # links: - # - web:web - # networks: ['stack'] - - # redis: - # restart: always - # image: redis:latest - # expose: - # - "6379" - # volumes: - # - redisdata:/data - # networks: ['stack'] - - -##########################SETTINGS###################################################################### - -volumes: - esdata: - driver: local - esdata-dmp: - driver: local - #redisdata: - # driver: local - # docsbox: - # driver: local - # media: - # driver: local -networks: - stack: {} - elasticsearch-dmp: {} - - + - ./openDMP/dmp-frontend/static-files:/usr/share/nginx/static + - ./openDMP/dmp-frontend/webapp/config:/usr/share/nginx/html/assets/config + networks: + - opendmp-frontend-network +networks: + opendmp-frontend-network: + opendmp-backend-network: \ No newline at end of file diff --git a/openDMP/dmp-backend/opendmp-logs/.gitkeep b/openDMP/dmp-backend/opendmp-logs/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/openDMP/dmp-backend/tmp/.gitkeep b/openDMP/dmp-backend/tmp/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/openDMP/dmp-frontend/static-files/.gitkeep b/openDMP/dmp-frontend/static-files/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/openDMP/dmp-frontend/webapp/.gitkeep b/openDMP/dmp-frontend/webapp/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/guide/UserGuideDRAFT.html b/user-guide/UserGuideDRAFT.html similarity index 100% rename from guide/UserGuideDRAFT.html rename to user-guide/UserGuideDRAFT.html From 411de18e9f080de71819073a12859aeebcb00ac8 Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Tue, 28 Apr 2020 18:27:31 +0300 Subject: [PATCH 07/18] Fixed issue when creating DMP from the creation Wizard --- .../src/main/java/eu/eudat/models/data/project/Project.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/project/Project.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/project/Project.java index 430eb6017..c69e8617f 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/project/Project.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/project/Project.java @@ -164,7 +164,9 @@ public class Project implements DataModel Date: Wed, 29 Apr 2020 14:03:19 +0300 Subject: [PATCH 08/18] Added postgres on docker compose --- .../resources/config/application.properties | 2 +- dmp-db-scema/Docker/dmp-db.env | 5 +++ dmp-db-scema/initdb.sh | 7 ++++ .../{ => main}/DataManagementPlanDB.sql | 6 ++-- ...er_DMPDatasetprofile_DMPFinalizedDate.sql} | 35 ++++++++++--------- .../{DMPisPublic.sql => 03_DMPisPublic.sql} | 2 +- ...=> 04_RenameDatasetColumnFinalizedDat.sql} | 0 ...ublishedDat.sql => 05_DMPPublishedDat.sql} | 4 +-- ...ameDMPColumnsFinalizedDatPublishedDat.sql} | 0 .../{DMPCreateDOI.sql => 07_DMPCreateDOI.sql} | 2 +- dmp-db-scema/updates/01/08_Create_content.sql | 15 ++++++++ .../updates/01/Removes DatasetIsPublic.sql | 2 -- ...ql => 01_CreateLoginConfirmationEmail.sql} | 3 +- ...ll.sql => 02_UserInfo_email_drop_null.sql} | 0 ...file_Description_value_set_empty_text.sql} | 0 ...ile_adds_null_constraints_description.sql} | 0 ...nt.sql => 03_Renames-Project-to-Grant.sql} | 0 ...Funder-create.sql => 04_Funder-create.sql} | 0 ...der.sql => 05_Grant-add-column-Funder.sql} | 0 .../03/06_Renames-Grant-fk-Constraint.sql | 9 +++++ ...7_Renames-Grant-fk-creator-Constraint.sql} | 0 .../03/08. Renames-Grant-fk-Constraint.sql | 2 -- ...l => 08_Renames-Grant-pKey-Constraint.sql} | 0 ...ql => 09_Rename-Dmps-Project-to_Grant.sql} | 0 ...oject-create.sql => 10_Project-create.sql} | 0 ...ject.sql => 11_DMP-add-column-project.sql} | 0 .../updates/03/12_Remove_xml_types.sql | 18 ++++++++++ .../04/01_Funder_add_column_CreationUser.sql | 2 ++ ... 02_Funder_update_CreationUser_values.sql} | 2 +- .../04/03_Create_External_Datasets.sql | 15 ++++++++ ...itory_ExternalDataset_Registry_Service.sql | 11 ++++++ .../05_Researcher_add_column_CreationUser.sql | 2 ++ ...itory_ExternalDataset_Registry_Service.sql | 11 ------ .../04/Funder_add_column_CreationUser.sql | 2 -- .../04/Researcher_add_column_CreationUser.sql | 2 -- ...al_References_Reference_Prefix_Update.sql} | 0 ...under_Project_Reference_Prefix_Update.sql} | 0 ...First_Character_To_Lower_Where_Capital.sql | 6 ---- .../updates/08/02_Add_missing_columns.sql | 17 +++++++++ .../updates/08/03_Create_Credentials.sql | 25 +++++++++++++ .../updates/08/04_Create_UserToken.sql | 16 +++++++++ .../updates/08/05_Create_UserRole.sql | 18 ++++++++++ .../updates/08/06_Remove_UserAuth.sql | 1 + docker-compose.yml | 26 ++++++++++++-- 44 files changed, 213 insertions(+), 55 deletions(-) create mode 100644 dmp-db-scema/Docker/dmp-db.env create mode 100644 dmp-db-scema/initdb.sh rename dmp-db-scema/{ => main}/DataManagementPlanDB.sql (99%) rename dmp-db-scema/updates/01/{DMPUser DMPDatasetprofile DMPFinalizedDate .sql => 01_DMPUser_DMPDatasetprofile_DMPFinalizedDate.sql} (56%) rename dmp-db-scema/updates/01/{DMPisPublic.sql => 03_DMPisPublic.sql} (84%) rename dmp-db-scema/updates/01/{RenameDatasetColumnFinalizedDat.sql => 04_RenameDatasetColumnFinalizedDat.sql} (100%) rename dmp-db-scema/updates/01/{DMPPublishedDat.sql => 05_DMPPublishedDat.sql} (53%) rename dmp-db-scema/updates/01/{RenameDMPColumnsFinalizedDatPublishedDat.sql => 06_RenameDMPColumnsFinalizedDatPublishedDat.sql} (100%) rename dmp-db-scema/updates/01/{DMPCreateDOI.sql => 07_DMPCreateDOI.sql} (53%) create mode 100644 dmp-db-scema/updates/01/08_Create_content.sql delete mode 100644 dmp-db-scema/updates/01/Removes DatasetIsPublic.sql rename dmp-db-scema/updates/02/{CreateLoginConfirmationEmail.sql => 01_CreateLoginConfirmationEmail.sql} (90%) rename dmp-db-scema/updates/02/{UserInfo email drop null.sql => 02_UserInfo_email_drop_null.sql} (100%) rename dmp-db-scema/updates/03/{01. DatasetProfile_Description_value_set_empty_text.sql => 01_DatasetProfile_Description_value_set_empty_text.sql} (100%) rename dmp-db-scema/updates/03/{02. DatasetProfile_adds_null_constraints_description.sql => 02_DatasetProfile_adds_null_constraints_description.sql} (100%) rename dmp-db-scema/updates/03/{05. Renames-Project-to-Grant.sql => 03_Renames-Project-to-Grant.sql} (100%) rename dmp-db-scema/updates/03/{03. Funder-create.sql => 04_Funder-create.sql} (100%) rename dmp-db-scema/updates/03/{04. Grant-add-column-Funder.sql => 05_Grant-add-column-Funder.sql} (100%) create mode 100644 dmp-db-scema/updates/03/06_Renames-Grant-fk-Constraint.sql rename dmp-db-scema/updates/03/{07. Renames-Grant-fk-creator-Constraint.sql => 07_Renames-Grant-fk-creator-Constraint.sql} (100%) delete mode 100644 dmp-db-scema/updates/03/08. Renames-Grant-fk-Constraint.sql rename dmp-db-scema/updates/03/{06. Renames-Grant-pKey-Constraint.sql => 08_Renames-Grant-pKey-Constraint.sql} (100%) rename dmp-db-scema/updates/03/{09. Rename-Dmps-Project-to_Grant.sql => 09_Rename-Dmps-Project-to_Grant.sql} (100%) rename dmp-db-scema/updates/03/{10. Project-create.sql => 10_Project-create.sql} (100%) rename dmp-db-scema/updates/03/{11. DMP-add-column-project.sql => 11_DMP-add-column-project.sql} (100%) create mode 100644 dmp-db-scema/updates/03/12_Remove_xml_types.sql create mode 100644 dmp-db-scema/updates/04/01_Funder_add_column_CreationUser.sql rename dmp-db-scema/updates/04/{Funder_update_CreationUser_values.sql => 02_Funder_update_CreationUser_values.sql} (71%) create mode 100644 dmp-db-scema/updates/04/03_Create_External_Datasets.sql create mode 100644 dmp-db-scema/updates/04/04_Add_creationUser_on_DataRepository_ExternalDataset_Registry_Service.sql create mode 100644 dmp-db-scema/updates/04/05_Researcher_add_column_CreationUser.sql delete mode 100644 dmp-db-scema/updates/04/Add_creationUser_on_DataRepository_ExternalDataset_Registry_Service.sql delete mode 100644 dmp-db-scema/updates/04/Funder_add_column_CreationUser.sql delete mode 100644 dmp-db-scema/updates/04/Researcher_add_column_CreationUser.sql rename dmp-db-scema/updates/05/{External_References_Reference_Prefix_Update.sql => 01_External_References_Reference_Prefix_Update.sql} (100%) rename dmp-db-scema/updates/05/{Grant_Funder_Project_Reference_Prefix_Update.sql => 02_Grant_Funder_Project_Reference_Prefix_Update.sql} (100%) delete mode 100644 dmp-db-scema/updates/06/04_Update_Researcher_Reference_First_Character_To_Lower_Where_Capital.sql create mode 100644 dmp-db-scema/updates/08/02_Add_missing_columns.sql create mode 100644 dmp-db-scema/updates/08/03_Create_Credentials.sql create mode 100644 dmp-db-scema/updates/08/04_Create_UserToken.sql create mode 100644 dmp-db-scema/updates/08/05_Create_UserRole.sql create mode 100644 dmp-db-scema/updates/08/06_Remove_UserAuth.sql diff --git a/dmp-backend/web/src/main/resources/config/application.properties b/dmp-backend/web/src/main/resources/config/application.properties index 229e7ed48..84ae244b3 100644 --- a/dmp-backend/web/src/main/resources/config/application.properties +++ b/dmp-backend/web/src/main/resources/config/application.properties @@ -2,7 +2,7 @@ server.port=8081 server.tomcat.max-threads = 20 server.tomcat.max-connections = 10000 logging.file=/logs/spring-boot-logging.log -spring.profiles.active=devel +spring.profiles.active=staging eu.eudat.logic.proxy.allowed.host=https://eestore.paas2.uninett.no ####################INVITATION MAIL CONFIGURATIONS############## diff --git a/dmp-db-scema/Docker/dmp-db.env b/dmp-db-scema/Docker/dmp-db.env new file mode 100644 index 000000000..d79f408eb --- /dev/null +++ b/dmp-db-scema/Docker/dmp-db.env @@ -0,0 +1,5 @@ +ADMIN_USERNAME=admin +ADMIN_PASSWORD=CHANGEME +POSTGRES_DB=dmptool +POSTGRES_USER=dmptool +POSTGRES_PASSWORD=CHANGEME \ No newline at end of file diff --git a/dmp-db-scema/initdb.sh b/dmp-db-scema/initdb.sh new file mode 100644 index 000000000..5ea5aa8be --- /dev/null +++ b/dmp-db-scema/initdb.sh @@ -0,0 +1,7 @@ +psql -d dmptool -U dmptool -f main/DataManagementPlanDB.sql; +for j in $(ls updates); do + for i in $(ls updates/$j/*.sql); do + echo $i + psql --set=ADMIN_USERNAME="$ADMIN_USERNAME" --set=ADMIN_PASSWORD="$ADMIN_PASSWORD" -d dmptool -U dmptool -f $i; + done +done \ No newline at end of file diff --git a/dmp-db-scema/DataManagementPlanDB.sql b/dmp-db-scema/main/DataManagementPlanDB.sql similarity index 99% rename from dmp-db-scema/DataManagementPlanDB.sql rename to dmp-db-scema/main/DataManagementPlanDB.sql index 7c49dfbb8..9cad64fc8 100644 --- a/dmp-db-scema/DataManagementPlanDB.sql +++ b/dmp-db-scema/main/DataManagementPlanDB.sql @@ -34,7 +34,7 @@ DROP table if exists "UserAuth" cascade; -- CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog; --- CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; SET search_path = public, pg_catalog; @@ -550,8 +550,8 @@ ALTER TABLE "UserDMP" OWNER TO dmptool; REVOKE ALL ON SCHEMA public FROM PUBLIC; -REVOKE ALL ON SCHEMA public FROM postgres; -GRANT ALL ON SCHEMA public TO postgres; +-- REVOKE ALL ON SCHEMA public FROM postgres; +-- GRANT ALL ON SCHEMA public TO postgres; GRANT ALL ON SCHEMA public TO PUBLIC; diff --git a/dmp-db-scema/updates/01/DMPUser DMPDatasetprofile DMPFinalizedDate .sql b/dmp-db-scema/updates/01/01_DMPUser_DMPDatasetprofile_DMPFinalizedDate.sql similarity index 56% rename from dmp-db-scema/updates/01/DMPUser DMPDatasetprofile DMPFinalizedDate .sql rename to dmp-db-scema/updates/01/01_DMPUser_DMPDatasetprofile_DMPFinalizedDate.sql index 06d569813..8ed97954d 100644 --- a/dmp-db-scema/updates/01/DMPUser DMPDatasetprofile DMPFinalizedDate .sql +++ b/dmp-db-scema/updates/01/01_DMPUser_DMPDatasetprofile_DMPFinalizedDate.sql @@ -1,12 +1,12 @@ INSERT INTO public."UserDMP"( usr, dmp, role) SELECT "Creator", "ID", 0 - FROM public."DMP" + FROM public."DMP"; DELETE FROM public."UserDMP" as us1 using public."UserDMP" as us2 -where us1."id" < us2."id" AND us1."dmp" = us2."dmp" +where us1."id" < us2."id" AND us1."dmp" = us2."dmp"; @@ -31,30 +31,31 @@ WITH ( TABLESPACE pg_default; ALTER TABLE public."DMPDatasetProfile" - OWNER to dmtadm; - +-- OWNER to dmtadm; + OWNER to dmptool; ALTER TABLE public."UserDMP" - OWNER to dmtadm; +-- OWNER to dmtadm; + OWNER to dmptool; -INSERT INTO public."DMPDatasetProfile"( - dmp, datasetprofile) - SELECT "ID", unnest(xpath('/profiles/profile/@profileId', dmpp."AssociatedDmps"::xml)::text[]::UUID[]) - FROM public."DMP" as dmpp +--INSERT INTO public."DMPDatasetProfile"( +-- dmp, datasetprofile) +-- SELECT "ID", unnest(xpath('/profiles/profile/@profileId', dmpp."AssociatedDmps"::xml)::text[]::UUID[]) +-- FROM public."DMP" as dmpp; -Alter table public."DMP" -add "FinalizedDat" timestamp(6) with time zone +ALTER TABLE public."DMP" +ADD "FinalizedDat" timestamp(6) WITH time zone; -update public."DMP" SET "FinalizedDat" = "Modified" -where "Status" = 1 +UPDATE public."DMP" SET "FinalizedDat" = "Modified" +WHERE "Status" = 1; -Alter table public."Dataset" -add "FinalizedDat" timestamp(6) with time zone +ALTER TABLE public."Dataset" +ADD "FinalizedDat" timestamp(6) WITH time zone; -update public."Dataset" SET "FinalizedDat" = "Modified" -where "Status" = 1 +UPDATE public."Dataset" SET "FinalizedDat" = "Modified" +WHERE "Status" = 1; diff --git a/dmp-db-scema/updates/01/DMPisPublic.sql b/dmp-db-scema/updates/01/03_DMPisPublic.sql similarity index 84% rename from dmp-db-scema/updates/01/DMPisPublic.sql rename to dmp-db-scema/updates/01/03_DMPisPublic.sql index aef4dca4d..dab69e4d9 100644 --- a/dmp-db-scema/updates/01/DMPisPublic.sql +++ b/dmp-db-scema/updates/01/03_DMPisPublic.sql @@ -3,5 +3,5 @@ Add "isPublic" boolean NOT NULL Default False; UPDATE public."DMP" SET "isPublic" = True - WHERE "Status" = 1 + WHERE "Status" = 1; \ No newline at end of file diff --git a/dmp-db-scema/updates/01/RenameDatasetColumnFinalizedDat.sql b/dmp-db-scema/updates/01/04_RenameDatasetColumnFinalizedDat.sql similarity index 100% rename from dmp-db-scema/updates/01/RenameDatasetColumnFinalizedDat.sql rename to dmp-db-scema/updates/01/04_RenameDatasetColumnFinalizedDat.sql diff --git a/dmp-db-scema/updates/01/DMPPublishedDat.sql b/dmp-db-scema/updates/01/05_DMPPublishedDat.sql similarity index 53% rename from dmp-db-scema/updates/01/DMPPublishedDat.sql rename to dmp-db-scema/updates/01/05_DMPPublishedDat.sql index 541efc62f..d823b5134 100644 --- a/dmp-db-scema/updates/01/DMPPublishedDat.sql +++ b/dmp-db-scema/updates/01/05_DMPPublishedDat.sql @@ -1,6 +1,6 @@ ALTER TABLE public."DMP" -ADD "PublishedAt" timestamp(6) with time zone +ADD "PublishedAt" timestamp(6) WITH time zone; UPDATE public."DMP" SET "PublishedAt" = "FinalizedDat" -where "isPublic" = True \ No newline at end of file +where "isPublic" = True; \ No newline at end of file diff --git a/dmp-db-scema/updates/01/RenameDMPColumnsFinalizedDatPublishedDat.sql b/dmp-db-scema/updates/01/06_RenameDMPColumnsFinalizedDatPublishedDat.sql similarity index 100% rename from dmp-db-scema/updates/01/RenameDMPColumnsFinalizedDatPublishedDat.sql rename to dmp-db-scema/updates/01/06_RenameDMPColumnsFinalizedDatPublishedDat.sql diff --git a/dmp-db-scema/updates/01/DMPCreateDOI.sql b/dmp-db-scema/updates/01/07_DMPCreateDOI.sql similarity index 53% rename from dmp-db-scema/updates/01/DMPCreateDOI.sql rename to dmp-db-scema/updates/01/07_DMPCreateDOI.sql index 470304b4c..5e97960c0 100644 --- a/dmp-db-scema/updates/01/DMPCreateDOI.sql +++ b/dmp-db-scema/updates/01/07_DMPCreateDOI.sql @@ -1,2 +1,2 @@ ALTER TABLE public."DMP" -ADD COLUMN "DOI" text \ No newline at end of file +ADD COLUMN "DOI" text; \ No newline at end of file diff --git a/dmp-db-scema/updates/01/08_Create_content.sql b/dmp-db-scema/updates/01/08_Create_content.sql new file mode 100644 index 000000000..89c6190b9 --- /dev/null +++ b/dmp-db-scema/updates/01/08_Create_content.sql @@ -0,0 +1,15 @@ +CREATE TABLE public."Content" ( + "Id" uuid NOT NULL, + "Filename" character varying NOT NULL, + "Extension" character varying NOT NULL, + "ParentType" numeric NOT NULL, + "Uri" character varying NOT NULL, + "LocationType" numeric NOT NULL +); + + +ALTER TABLE public."Content" OWNER TO dmptool; + +ALTER TABLE ONLY public."Content" + ADD CONSTRAINT "Content_pkey" PRIMARY KEY ("Id"); + diff --git a/dmp-db-scema/updates/01/Removes DatasetIsPublic.sql b/dmp-db-scema/updates/01/Removes DatasetIsPublic.sql deleted file mode 100644 index 3734d4198..000000000 --- a/dmp-db-scema/updates/01/Removes DatasetIsPublic.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE public."Dataset" -DROP COLUMN "IsPublic" \ No newline at end of file diff --git a/dmp-db-scema/updates/02/CreateLoginConfirmationEmail.sql b/dmp-db-scema/updates/02/01_CreateLoginConfirmationEmail.sql similarity index 90% rename from dmp-db-scema/updates/02/CreateLoginConfirmationEmail.sql rename to dmp-db-scema/updates/02/01_CreateLoginConfirmationEmail.sql index 458b1b572..cf3807730 100644 --- a/dmp-db-scema/updates/02/CreateLoginConfirmationEmail.sql +++ b/dmp-db-scema/updates/02/01_CreateLoginConfirmationEmail.sql @@ -14,4 +14,5 @@ WITH ( TABLESPACE pg_default; ALTER TABLE public."LoginConfirmationEmail" - OWNER to dmtadm; \ No newline at end of file +-- OWNER to dmtadm; + OWNER to dmptool; \ No newline at end of file diff --git a/dmp-db-scema/updates/02/UserInfo email drop null.sql b/dmp-db-scema/updates/02/02_UserInfo_email_drop_null.sql similarity index 100% rename from dmp-db-scema/updates/02/UserInfo email drop null.sql rename to dmp-db-scema/updates/02/02_UserInfo_email_drop_null.sql diff --git a/dmp-db-scema/updates/03/01. DatasetProfile_Description_value_set_empty_text.sql b/dmp-db-scema/updates/03/01_DatasetProfile_Description_value_set_empty_text.sql similarity index 100% rename from dmp-db-scema/updates/03/01. DatasetProfile_Description_value_set_empty_text.sql rename to dmp-db-scema/updates/03/01_DatasetProfile_Description_value_set_empty_text.sql diff --git a/dmp-db-scema/updates/03/02. DatasetProfile_adds_null_constraints_description.sql b/dmp-db-scema/updates/03/02_DatasetProfile_adds_null_constraints_description.sql similarity index 100% rename from dmp-db-scema/updates/03/02. DatasetProfile_adds_null_constraints_description.sql rename to dmp-db-scema/updates/03/02_DatasetProfile_adds_null_constraints_description.sql diff --git a/dmp-db-scema/updates/03/05. Renames-Project-to-Grant.sql b/dmp-db-scema/updates/03/03_Renames-Project-to-Grant.sql similarity index 100% rename from dmp-db-scema/updates/03/05. Renames-Project-to-Grant.sql rename to dmp-db-scema/updates/03/03_Renames-Project-to-Grant.sql diff --git a/dmp-db-scema/updates/03/03. Funder-create.sql b/dmp-db-scema/updates/03/04_Funder-create.sql similarity index 100% rename from dmp-db-scema/updates/03/03. Funder-create.sql rename to dmp-db-scema/updates/03/04_Funder-create.sql diff --git a/dmp-db-scema/updates/03/04. Grant-add-column-Funder.sql b/dmp-db-scema/updates/03/05_Grant-add-column-Funder.sql similarity index 100% rename from dmp-db-scema/updates/03/04. Grant-add-column-Funder.sql rename to dmp-db-scema/updates/03/05_Grant-add-column-Funder.sql diff --git a/dmp-db-scema/updates/03/06_Renames-Grant-fk-Constraint.sql b/dmp-db-scema/updates/03/06_Renames-Grant-fk-Constraint.sql new file mode 100644 index 000000000..9c4dd0602 --- /dev/null +++ b/dmp-db-scema/updates/03/06_Renames-Grant-fk-Constraint.sql @@ -0,0 +1,9 @@ +ALTER TABLE public."Grant" +ADD COLUMN "Content" uuid; + + +ALTER TABLE public."Grant" +ADD CONSTRAINT fk_grant_content FOREIGN KEY ("Content") + REFERENCES public."Content" ("Id") MATCH SIMPLE + ON UPDATE NO ACTION + ON DELETE NO ACTION; \ No newline at end of file diff --git a/dmp-db-scema/updates/03/07. Renames-Grant-fk-creator-Constraint.sql b/dmp-db-scema/updates/03/07_Renames-Grant-fk-creator-Constraint.sql similarity index 100% rename from dmp-db-scema/updates/03/07. Renames-Grant-fk-creator-Constraint.sql rename to dmp-db-scema/updates/03/07_Renames-Grant-fk-creator-Constraint.sql diff --git a/dmp-db-scema/updates/03/08. Renames-Grant-fk-Constraint.sql b/dmp-db-scema/updates/03/08. Renames-Grant-fk-Constraint.sql deleted file mode 100644 index 493d9af69..000000000 --- a/dmp-db-scema/updates/03/08. Renames-Grant-fk-Constraint.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE public."Grant" -RENAME CONSTRAINT "fk_project_content" TO "fk_grant_content"; \ No newline at end of file diff --git a/dmp-db-scema/updates/03/06. Renames-Grant-pKey-Constraint.sql b/dmp-db-scema/updates/03/08_Renames-Grant-pKey-Constraint.sql similarity index 100% rename from dmp-db-scema/updates/03/06. Renames-Grant-pKey-Constraint.sql rename to dmp-db-scema/updates/03/08_Renames-Grant-pKey-Constraint.sql diff --git a/dmp-db-scema/updates/03/09. Rename-Dmps-Project-to_Grant.sql b/dmp-db-scema/updates/03/09_Rename-Dmps-Project-to_Grant.sql similarity index 100% rename from dmp-db-scema/updates/03/09. Rename-Dmps-Project-to_Grant.sql rename to dmp-db-scema/updates/03/09_Rename-Dmps-Project-to_Grant.sql diff --git a/dmp-db-scema/updates/03/10. Project-create.sql b/dmp-db-scema/updates/03/10_Project-create.sql similarity index 100% rename from dmp-db-scema/updates/03/10. Project-create.sql rename to dmp-db-scema/updates/03/10_Project-create.sql diff --git a/dmp-db-scema/updates/03/11. DMP-add-column-project.sql b/dmp-db-scema/updates/03/11_DMP-add-column-project.sql similarity index 100% rename from dmp-db-scema/updates/03/11. DMP-add-column-project.sql rename to dmp-db-scema/updates/03/11_DMP-add-column-project.sql diff --git a/dmp-db-scema/updates/03/12_Remove_xml_types.sql b/dmp-db-scema/updates/03/12_Remove_xml_types.sql new file mode 100644 index 000000000..5bfb2a5f8 --- /dev/null +++ b/dmp-db-scema/updates/03/12_Remove_xml_types.sql @@ -0,0 +1,18 @@ +ALTER TABLE public."Grant" +ALTER COLUMN "Reference" TYPE character varying(255); + +ALTER TABLE public."Grant" +ALTER COLUMN "Definition" TYPE character varying; + +ALTER TABLE public."Registry" +ALTER COLUMN "Reference" TYPE character varying; + +ALTER TABLE public."Service" +ALTER COLUMN "Reference" TYPE character varying; + +ALTER TABLE public."Researcher" +ALTER COLUMN "Reference" TYPE character varying; + +ALTER TABLE public."DataRepository" +ALTER COLUMN "Reference" TYPE character varying; + diff --git a/dmp-db-scema/updates/04/01_Funder_add_column_CreationUser.sql b/dmp-db-scema/updates/04/01_Funder_add_column_CreationUser.sql new file mode 100644 index 000000000..04aa6f4d3 --- /dev/null +++ b/dmp-db-scema/updates/04/01_Funder_add_column_CreationUser.sql @@ -0,0 +1,2 @@ +ALTER TABLE "Funder" +ADD COLUMN "CreationUser" uuid; \ No newline at end of file diff --git a/dmp-db-scema/updates/04/Funder_update_CreationUser_values.sql b/dmp-db-scema/updates/04/02_Funder_update_CreationUser_values.sql similarity index 71% rename from dmp-db-scema/updates/04/Funder_update_CreationUser_values.sql rename to dmp-db-scema/updates/04/02_Funder_update_CreationUser_values.sql index 130130ab9..2d7085f3e 100644 --- a/dmp-db-scema/updates/04/Funder_update_CreationUser_values.sql +++ b/dmp-db-scema/updates/04/02_Funder_update_CreationUser_values.sql @@ -1,4 +1,4 @@ Update "Funder" as funder set "CreationUser" = grant1."CreationUser" from "Grant" as grant1 - where funder."ID" = grant1."Funder" \ No newline at end of file + where funder."ID" = grant1."Funder" ; \ No newline at end of file diff --git a/dmp-db-scema/updates/04/03_Create_External_Datasets.sql b/dmp-db-scema/updates/04/03_Create_External_Datasets.sql new file mode 100644 index 000000000..5c55bcb70 --- /dev/null +++ b/dmp-db-scema/updates/04/03_Create_External_Datasets.sql @@ -0,0 +1,15 @@ +CREATE TABLE public."ExternalDataset" ( + "Id" uuid DEFAULT public.uuid_generate_v4() NOT NULL, + "Label" character varying NOT NULL, + "Abbreviation" character varying, + "Reference" character varying NOT NULL, + "Created" timestamp(4) with time zone NOT NULL, + "Modified" timestamp(4) with time zone NOT NULL +); + + +ALTER TABLE public."ExternalDataset" OWNER TO dmptool; + +ALTER TABLE ONLY public."ExternalDataset" + ADD CONSTRAINT "ExternalDataset_pkey" PRIMARY KEY ("Id"); + diff --git a/dmp-db-scema/updates/04/04_Add_creationUser_on_DataRepository_ExternalDataset_Registry_Service.sql b/dmp-db-scema/updates/04/04_Add_creationUser_on_DataRepository_ExternalDataset_Registry_Service.sql new file mode 100644 index 000000000..fd8dc380d --- /dev/null +++ b/dmp-db-scema/updates/04/04_Add_creationUser_on_DataRepository_ExternalDataset_Registry_Service.sql @@ -0,0 +1,11 @@ +ALTER TABLE "DataRepository" +ADD COLUMN "CreationUser" uuid; + +ALTER TABLE "ExternalDataset" +ADD COLUMN "CreationUser" uuid; + +ALTER TABLE "Registry" +ADD COLUMN "CreationUser" uuid; + +ALTER TABLE "Service" +ADD COLUMN "CreationUser" uuid; \ No newline at end of file diff --git a/dmp-db-scema/updates/04/05_Researcher_add_column_CreationUser.sql b/dmp-db-scema/updates/04/05_Researcher_add_column_CreationUser.sql new file mode 100644 index 000000000..d9627e5bf --- /dev/null +++ b/dmp-db-scema/updates/04/05_Researcher_add_column_CreationUser.sql @@ -0,0 +1,2 @@ +ALTER TABLE "Researcher" +ADD COLUMN "CreationUser" uuid; \ No newline at end of file diff --git a/dmp-db-scema/updates/04/Add_creationUser_on_DataRepository_ExternalDataset_Registry_Service.sql b/dmp-db-scema/updates/04/Add_creationUser_on_DataRepository_ExternalDataset_Registry_Service.sql deleted file mode 100644 index 4cc036bdb..000000000 --- a/dmp-db-scema/updates/04/Add_creationUser_on_DataRepository_ExternalDataset_Registry_Service.sql +++ /dev/null @@ -1,11 +0,0 @@ -ALTER TABLE "DataRepository" -ADD COLUMN "CreationUser" uuid - -ALTER TABLE "ExternalDataset" -ADD COLUMN "CreationUser" uuid - -ALTER TABLE "Registry" -ADD COLUMN "CreationUser" uuid - -ALTER TABLE "Service" -ADD COLUMN "CreationUser" uuid \ No newline at end of file diff --git a/dmp-db-scema/updates/04/Funder_add_column_CreationUser.sql b/dmp-db-scema/updates/04/Funder_add_column_CreationUser.sql deleted file mode 100644 index 7c84eb69f..000000000 --- a/dmp-db-scema/updates/04/Funder_add_column_CreationUser.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE "Funder" -ADD COLUMN "CreationUser" uuid \ No newline at end of file diff --git a/dmp-db-scema/updates/04/Researcher_add_column_CreationUser.sql b/dmp-db-scema/updates/04/Researcher_add_column_CreationUser.sql deleted file mode 100644 index 55b7a4542..000000000 --- a/dmp-db-scema/updates/04/Researcher_add_column_CreationUser.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE "Researcher" -ADD COLUMN "CreationUser" uuid \ No newline at end of file diff --git a/dmp-db-scema/updates/05/External_References_Reference_Prefix_Update.sql b/dmp-db-scema/updates/05/01_External_References_Reference_Prefix_Update.sql similarity index 100% rename from dmp-db-scema/updates/05/External_References_Reference_Prefix_Update.sql rename to dmp-db-scema/updates/05/01_External_References_Reference_Prefix_Update.sql diff --git a/dmp-db-scema/updates/05/Grant_Funder_Project_Reference_Prefix_Update.sql b/dmp-db-scema/updates/05/02_Grant_Funder_Project_Reference_Prefix_Update.sql similarity index 100% rename from dmp-db-scema/updates/05/Grant_Funder_Project_Reference_Prefix_Update.sql rename to dmp-db-scema/updates/05/02_Grant_Funder_Project_Reference_Prefix_Update.sql diff --git a/dmp-db-scema/updates/06/04_Update_Researcher_Reference_First_Character_To_Lower_Where_Capital.sql b/dmp-db-scema/updates/06/04_Update_Researcher_Reference_First_Character_To_Lower_Where_Capital.sql deleted file mode 100644 index 8c3bcc984..000000000 --- a/dmp-db-scema/updates/06/04_Update_Researcher_Reference_First_Character_To_Lower_Where_Capital.sql +++ /dev/null @@ -1,6 +0,0 @@ -UPDATE "Researcher" -SET "Reference" = CONCAT(LOWER(LEFT("Reference", 1)), SUBSTRING("Reference", 2)) -WHERE "ID" in ( - SELECT "ID" FROM "Researcher" - WHERE ASCII(LEFT("Reference", 1)) BETWEEN ASCII('A') AND ASCII('Z') -) \ No newline at end of file diff --git a/dmp-db-scema/updates/08/02_Add_missing_columns.sql b/dmp-db-scema/updates/08/02_Add_missing_columns.sql new file mode 100644 index 000000000..4036dcdc7 --- /dev/null +++ b/dmp-db-scema/updates/08/02_Add_missing_columns.sql @@ -0,0 +1,17 @@ +ALTER TABLE public."DMP" +ADD COLUMN "DmpProperties" text; + +ALTER TABLE public."DMP" +ADD COLUMN "GroupId" uuid; + +ALTER TABLE public."DMP" +ADD COLUMN "Properties" text; + +ALTER TABLE public."DatasetProfile" +ADD COLUMN "GroupId" uuid; + +ALTER TABLE public."DatasetProfile" +ADD COLUMN "Version" integer; + +ALTER TABLE public."Grant" +ADD COLUMN "Type" numeric NOT NULL; \ No newline at end of file diff --git a/dmp-db-scema/updates/08/03_Create_Credentials.sql b/dmp-db-scema/updates/08/03_Create_Credentials.sql new file mode 100644 index 000000000..0ffbf0f46 --- /dev/null +++ b/dmp-db-scema/updates/08/03_Create_Credentials.sql @@ -0,0 +1,25 @@ +CREATE TABLE public."Credential" ( + "Id" uuid NOT NULL, + "Status" numeric NOT NULL, + "Provider" numeric NOT NULL, + "Public" character varying NOT NULL, + "Secret" character varying NOT NULL, + "CreationTime" timestamp(4) with time zone NOT NULL, + "LastUpdateTime" timestamp(4) with time zone NOT NULL, + "UserId" uuid NOT NULL, + "ExternalId" character varying NOT NULL +); + + +ALTER TABLE public."Credential" OWNER TO dmptool; + +ALTER TABLE ONLY public."Credential" + ADD CONSTRAINT "Credential_pkey" PRIMARY KEY ("Id"); + +ALTER TABLE ONLY public."Credential" + ADD CONSTRAINT fkey_credential_user FOREIGN KEY ("UserId") REFERENCES public."UserInfo"(id); + +INSERT INTO public."UserInfo"(email, authorization_level, usertype, name, created, additionalinfo) VALUES ('fake@email.org', 1, 1, :'ADMIN_USERNAME', now(), '{}'); + +INSERT INTO public."Credential" VALUES (uuid_generate_v4(), 0, 5, :'ADMIN_USERNAME', :'ADMIN_PASSWORD', now(), now(), (SELECT public."UserInfo"."id" FROM public."UserInfo" WHERE name = 'admin'), 'dmp'); + diff --git a/dmp-db-scema/updates/08/04_Create_UserToken.sql b/dmp-db-scema/updates/08/04_Create_UserToken.sql new file mode 100644 index 000000000..85ff8103a --- /dev/null +++ b/dmp-db-scema/updates/08/04_Create_UserToken.sql @@ -0,0 +1,16 @@ +CREATE TABLE public."UserToken" ( + "Token" uuid NOT NULL, + "UserId" uuid NOT NULL, + "IssuedAt" timestamp(4) with time zone NOT NULL, + "ExpiresAt" timestamp(4) with time zone NOT NULL +); + + +ALTER TABLE public."UserToken" OWNER TO dmptool; + +ALTER TABLE ONLY public."UserToken" + ADD CONSTRAINT "UserToken_pkey" PRIMARY KEY ("Token"); + +ALTER TABLE ONLY public."UserToken" + ADD CONSTRAINT fkey_usetoken_user FOREIGN KEY ("UserId") REFERENCES public."UserInfo"(id); + diff --git a/dmp-db-scema/updates/08/05_Create_UserRole.sql b/dmp-db-scema/updates/08/05_Create_UserRole.sql new file mode 100644 index 000000000..0db9f39d0 --- /dev/null +++ b/dmp-db-scema/updates/08/05_Create_UserRole.sql @@ -0,0 +1,18 @@ +CREATE TABLE public."UserRole" ( + "Id" uuid DEFAULT public.uuid_generate_v4() NOT NULL, + "Role" numeric DEFAULT 0 NOT NULL, + "UserId" uuid NOT NULL +); + + +ALTER TABLE public."UserRole" OWNER TO dmptool; + +ALTER TABLE ONLY public."UserRole" + ADD CONSTRAINT "UserRole_pkey" PRIMARY KEY ("Id"); + +ALTER TABLE ONLY public."UserRole" + ADD CONSTRAINT "UserRole_userId_fkey" FOREIGN KEY ("UserId") REFERENCES public."UserInfo"(id); + + +INSERT INTO public."UserRole"("Role", "UserId") VALUES (2, (SELECT public."UserInfo"."id" FROM public."UserInfo" WHERE name = 'admin')); + diff --git a/dmp-db-scema/updates/08/06_Remove_UserAuth.sql b/dmp-db-scema/updates/08/06_Remove_UserAuth.sql new file mode 100644 index 000000000..5ed59655c --- /dev/null +++ b/dmp-db-scema/updates/08/06_Remove_UserAuth.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS "UserAuth" CASCADE; \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index ac90b8444..f5a46f45d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,8 +1,25 @@ -version: '2.2' +version: "2.4" services: + dmp-db: + image: postgres + container_name: opendmp-db + restart: unless-stopped + ports: + - "5001:5432" + expose: + - "5432" + volumes: + - dmpdata:/var/lib/postgresql/data + - ./dmp-db-scema:/docker-entrypoint-initdb.d/ + - ./dmp-db-scema/main:/main + - ./dmp-db-scema/updates:/updates + env_file: ./dmp-db-scema/Docker/dmp-db.env + networks: + - opendmp-backend-network + dmp-backend: - build: + build: context: ./dmp-backend container_name: opendmp-backend env_file: ./dmp-backend/Docker/dmp-backend.env @@ -38,4 +55,7 @@ services: networks: opendmp-frontend-network: - opendmp-backend-network: \ No newline at end of file + opendmp-backend-network: +volumes: + dmpdata: + external: true From 391a88a23640755553177f44aef32f34f25e413b Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Mon, 4 May 2020 15:47:30 +0300 Subject: [PATCH 09/18] The invite pop up will show only user collaborating with DMP that the current user also is collaborating (ref #258) --- .../data/dao/entities/UserAssociationDao.java | 15 ++++ .../dao/entities/UserAssociationDaoImpl.java | 73 +++++++++++++++++++ .../eudat/data/entities/UserAssociation.java | 66 +++++++++++++++++ .../controllers/UserInvitationController.java | 4 +- .../logic/managers/InvitationsManager.java | 25 ++++++- .../operations/DatabaseRepository.java | 2 + .../operations/DatabaseRepositoryImpl.java | 11 +++ .../updates/09/01_create_user_association.sql | 21 ++++++ 8 files changed, 212 insertions(+), 5 deletions(-) create mode 100644 dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/UserAssociationDao.java create mode 100644 dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/UserAssociationDaoImpl.java create mode 100644 dmp-backend/data/src/main/java/eu/eudat/data/entities/UserAssociation.java create mode 100644 dmp-db-scema/updates/09/01_create_user_association.sql diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/UserAssociationDao.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/UserAssociationDao.java new file mode 100644 index 000000000..bd80fa49b --- /dev/null +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/UserAssociationDao.java @@ -0,0 +1,15 @@ +package eu.eudat.data.dao.entities; + +import eu.eudat.data.dao.DatabaseAccessLayer; +import eu.eudat.data.entities.UserAssociation; +import eu.eudat.data.entities.UserInfo; + +import java.util.List; +import java.util.UUID; + +public interface UserAssociationDao extends DatabaseAccessLayer { + + public List getAssociated(UserInfo userId); + + public Boolean areAssociated(UserInfo firstUser, UserInfo secondUser); +} diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/UserAssociationDaoImpl.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/UserAssociationDaoImpl.java new file mode 100644 index 000000000..b8ecc0668 --- /dev/null +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/UserAssociationDaoImpl.java @@ -0,0 +1,73 @@ +package eu.eudat.data.dao.entities; + +import eu.eudat.data.dao.DatabaseAccess; +import eu.eudat.data.dao.databaselayer.service.DatabaseService; +import eu.eudat.data.entities.UserAssociation; +import eu.eudat.data.entities.UserInfo; +import eu.eudat.queryable.QueryableList; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +@Component("UserAssociationDao") +public class UserAssociationDaoImpl extends DatabaseAccess implements UserAssociationDao { + + @Autowired + public UserAssociationDaoImpl(DatabaseService databaseService) { + super(databaseService); + } + + @Override + public UserAssociation createOrUpdate(UserAssociation item) { + return this.getDatabaseService().createOrUpdate(item, UserAssociation.class); + } + + @Override + public CompletableFuture createOrUpdateAsync(UserAssociation item) { + return CompletableFuture.supplyAsync(() -> this.createOrUpdate(item)); + } + + @Override + public UserAssociation find(UUID id) { + return this.getDatabaseService().getQueryable(UserAssociation.class).where(((builder, root) -> builder.equal(root.get("id"), id))).getSingle(); + } + + @Override + public UserAssociation find(UUID id, String hint) { + throw new UnsupportedOperationException(); + } + + @Override + public void delete(UserAssociation item) { + this.getDatabaseService().delete(item); + } + + @Override + public QueryableList asQueryable() { + return this.getDatabaseService().getQueryable(UserAssociation.class); + } + + @Override + public List getAssociated(UserInfo userId) { + return this.getDatabaseService().getQueryable(UserAssociation.class).where(((builder, root) -> + builder.or(builder.equal(root.get("firstUser"), userId), builder.equal(root.get("secondUser"), userId)))).toList(); + } + + @Override + public Boolean areAssociated(UserInfo firstUser, UserInfo secondUser) { + return this.getDatabaseService().getQueryable(UserAssociation.class).where(((builder, root) -> + builder.or( + builder.and( + builder.equal(root.get("firstUser"), firstUser), + builder.equal(root.get("secondUser"), secondUser) + ), + builder.and( + builder.equal(root.get("secondUser"), firstUser), + builder.equal(root.get("firstUser"), secondUser) + ) + ))).count() > 0; + } +} diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/UserAssociation.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/UserAssociation.java new file mode 100644 index 000000000..898bbd8a6 --- /dev/null +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/UserAssociation.java @@ -0,0 +1,66 @@ +package eu.eudat.data.entities; + +import eu.eudat.queryable.queryableentity.DataEntity; +import org.hibernate.annotations.GenericGenerator; + +import javax.persistence.*; +import java.util.List; +import java.util.UUID; + +@Entity +@Table(name = "\"UserAssociation\"") +public class UserAssociation implements DataEntity { + + @Id + @GeneratedValue + @GenericGenerator(name = "uuid2", strategy = "uuid2") + @Column(name = "id", updatable = false, nullable = false, columnDefinition = "BINARY(16)") + private UUID id; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "\"firstUser\"") + private UserInfo firstUser; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "\"secondUser\"") + private UserInfo secondUser; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public UserInfo getFirstUser() { + return firstUser; + } + + public void setFirstUser(UserInfo firstUser) { + this.firstUser = firstUser; + } + + public UserInfo getSecondUser() { + return secondUser; + } + + public void setSecondUser(UserInfo secondUser) { + this.secondUser = secondUser; + } + + @Override + public void update(UserAssociation entity) { + + } + + @Override + public UUID getKeys() { + return null; + } + + @Override + public UserAssociation buildFromTuple(List tuple, List fields, String base) { + return null; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/UserInvitationController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/UserInvitationController.java index 3e09dd43b..b6d045a67 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/UserInvitationController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/UserInvitationController.java @@ -48,8 +48,8 @@ public class UserInvitationController extends BaseController { @RequestMapping(method = RequestMethod.POST, value = {"/getUsers"}, consumes = "application/json", produces = "application/json") public @ResponseBody - ResponseEntity>> getUsers(@RequestBody UserInfoRequestItem userInfoRequestItem) throws IllegalAccessException, InstantiationException { - List users = invitationsManager.getUsers(userInfoRequestItem); + ResponseEntity>> getUsers(Principal principal) throws IllegalAccessException, InstantiationException { + List users = invitationsManager.getUsers(principal); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.SUCCESS_MESSAGE).payload(users)); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/InvitationsManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/InvitationsManager.java index eea0d1c41..2625fdfd3 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/InvitationsManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/InvitationsManager.java @@ -1,6 +1,7 @@ package eu.eudat.logic.managers; import eu.eudat.data.entities.DMP; +import eu.eudat.data.entities.UserAssociation; import eu.eudat.data.entities.UserDMP; import eu.eudat.data.entities.UserInfo; import eu.eudat.exceptions.security.UnauthorisedException; @@ -38,15 +39,27 @@ public class InvitationsManager { UserDMP userDMP = new UserDMP(); userDMP.setUser(userInfo); userInfoToUserDmp.add(userDMP); + if (!apiContext.getOperationsContext().getDatabaseRepository().getUserAssociationDao().areAssociated(principalUser, userInfo)) { + UserAssociation userAssociation = new UserAssociation(); + userAssociation.setFirstUser(principalUser); + userAssociation.setSecondUser(userInfo); + } } DMP dataManagementPlan = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(invitation.getDataManagementPlan()); apiContext.getUtilitiesService().getInvitationService().createInvitations(apiContext.getOperationsContext().getDatabaseRepository().getInvitationDao(), apiContext.getUtilitiesService().getMailService(), invitation.getUsers().stream().map(item -> item.toDataModel()).collect(Collectors.toList()), dataManagementPlan, principalUser); apiContext.getUtilitiesService().getInvitationService().assignToDmp(apiContext.getOperationsContext().getDatabaseRepository().getDmpDao(), userInfoToUserDmp, dataManagementPlan); } - public List getUsers(UserInfoRequestItem userInfoRequestItem) throws InstantiationException, IllegalAccessException { - QueryableList users = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().getWithCriteria(userInfoRequestItem.getCriteria()); - List userModels = users.select(item -> new UserInfoInvitationModel().fromDataModel(item)); + public List getUsers(Principal principal) throws InstantiationException, IllegalAccessException { + UserInfo principalUser = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(principal.getId()); + List users = apiContext.getOperationsContext().getDatabaseRepository().getUserAssociationDao().getAssociated(principalUser).stream().map(userAssociation -> { + if (userAssociation.getFirstUser().getId().equals(principal.getId())) { + return userAssociation.getSecondUser(); + } else { + return userAssociation.getFirstUser(); + } + }).collect(Collectors.toList()); + List userModels = users.stream().map(userInfo -> new UserInfoInvitationModel().fromDataModel(userInfo)).collect(Collectors.toList()); return userModels; } @@ -60,6 +73,12 @@ public class InvitationsManager { userDMP.setUser(invitedUser); userDMP.setDmp(invitation.getDmp()); userDMP.setRole(UserDMP.UserDMPRoles.USER.getValue()); + if (!apiContext.getOperationsContext().getDatabaseRepository().getUserAssociationDao().areAssociated(invitedUser, invitation.getUser())) { + UserAssociation userAssociation = new UserAssociation(); + userAssociation.setFirstUser(invitedUser); + userAssociation.setSecondUser(invitation.getUser()); + apiContext.getOperationsContext().getDatabaseRepository().getUserAssociationDao().createOrUpdate(userAssociation); + } DMP datamanagementPlan = invitation.getDmp(); apiContext.getOperationsContext().getDatabaseRepository().getUserDmpDao().createOrUpdate(userDMP); apiContext.getUtilitiesService().getInvitationService().assignToDmp(apiContext.getOperationsContext().getDatabaseRepository().getDmpDao(), userDMP, datamanagementPlan); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java index 539e417a6..516f7e949 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java @@ -56,5 +56,7 @@ public interface DatabaseRepository { NotificationDao getNotificationDao(); + UserAssociationDao getUserAssociationDao(); + void detachEntity(T entity); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java index a87ba7734..ff5f6506e 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java @@ -37,6 +37,7 @@ public class DatabaseRepositoryImpl implements DatabaseRepository { private FunderDao funderDao; private LockDao lockDao; private NotificationDao notificationDao; + private UserAssociationDao userAssociationDao; private EntityManager entityManager; @@ -290,6 +291,16 @@ public class DatabaseRepositoryImpl implements DatabaseRepository { return notificationDao; } + @Override + public UserAssociationDao getUserAssociationDao() { + return userAssociationDao; + } + + @Autowired + public void setUserAssociationDao(UserAssociationDao userAssociationDao) { + this.userAssociationDao = userAssociationDao; + } + @Autowired public void setNotificationDao(NotificationDao notificationDao) { this.notificationDao = notificationDao; diff --git a/dmp-db-scema/updates/09/01_create_user_association.sql b/dmp-db-scema/updates/09/01_create_user_association.sql new file mode 100644 index 000000000..c569ca2fe --- /dev/null +++ b/dmp-db-scema/updates/09/01_create_user_association.sql @@ -0,0 +1,21 @@ +CREATE TABLE public."UserAssociation" ( + id uuid NOT NULL, + "firstUser" uuid NOT NULL, + "secondUser" uuid NOT NULL +); + + +ALTER TABLE public."UserAssociation" OWNER TO dmptool; + +ALTER TABLE ONLY public."UserAssociation" + ADD CONSTRAINT pk_user_association PRIMARY KEY (id); + +ALTER TABLE ONLY public."UserAssociation" + ADD CONSTRAINT fk_userinfo_user_association_1 FOREIGN KEY ("firstUser") REFERENCES public."UserInfo"(id); + +ALTER TABLE ONLY public."UserAssociation" + ADD CONSTRAINT fk_userinfo_user_association_2 FOREIGN KEY ("secondUser") REFERENCES public."UserInfo"(id); + +INSERT INTO public."DBVersion" VALUES ('DMPDB', '00.00.002', '2020-05-04 13:42:00.000000+03', now(), 'Add User Association'); + + From 08737cbbf01034eea56cd1958304187ef954910c Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Mon, 4 May 2020 16:00:23 +0300 Subject: [PATCH 10/18] Minor bugfix --- .../main/java/eu/eudat/logic/managers/InvitationsManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/InvitationsManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/InvitationsManager.java index 2625fdfd3..2191298a2 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/InvitationsManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/InvitationsManager.java @@ -43,6 +43,7 @@ public class InvitationsManager { UserAssociation userAssociation = new UserAssociation(); userAssociation.setFirstUser(principalUser); userAssociation.setSecondUser(userInfo); + apiContext.getOperationsContext().getDatabaseRepository().getUserAssociationDao().createOrUpdate(userAssociation); } } DMP dataManagementPlan = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(invitation.getDataManagementPlan()); From 5d6fbd3e3713836b669df8521e1a39561930541a Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Mon, 4 May 2020 17:15:52 +0300 Subject: [PATCH 11/18] Improve self deployment --- .../config/application-staging.properties | 16 +++++++------ .../08/07_Remove_no_null_requirement.sql | 2 ++ .../08/08_create_datasetexternaldataset.sql | 19 +++++++++++++++ .../updates/08/09_Create_Invitation.sql | 23 +++++++++++++++++++ .../updates/08/10_Create_User_preference.sql | 16 +++++++++++++ docker-compose.yml | 1 + 6 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 dmp-db-scema/updates/08/07_Remove_no_null_requirement.sql create mode 100644 dmp-db-scema/updates/08/08_create_datasetexternaldataset.sql create mode 100644 dmp-db-scema/updates/08/09_Create_Invitation.sql create mode 100644 dmp-db-scema/updates/08/10_Create_User_preference.sql diff --git a/dmp-backend/web/src/main/resources/config/application-staging.properties b/dmp-backend/web/src/main/resources/config/application-staging.properties index 93e304d2f..4b92d0245 100644 --- a/dmp-backend/web/src/main/resources/config/application-staging.properties +++ b/dmp-backend/web/src/main/resources/config/application-staging.properties @@ -1,9 +1,9 @@ dmp.domain = https://devel.opendmp.eu ####################PERSISTENCE OVERRIDES CONFIGURATIONS########## -database.url= -database.username= -database.password= +database.url=jdbc:postgresql://dmp-db:5432/dmptool +database.username=dmptool +database.password=CHANGEME ####################ELASTIIC SEARCH TAGS OVERRIDES CONFIGURATIONS########## elasticsearch.host = tags-elastic-search @@ -18,10 +18,10 @@ http-logger.server-address = http://logstash:31311 pdf.converter.url=http://docsbox-web/ ####################CONFIGURATION FILES OVERRIDES CONFIGURATIONS########## -configuration.externalUrls=/tmp/ExternalUrls.xml +configuration.externalUrls=externalUrls/ExternalUrls.xml configuration.rda=/tmp/RDACommonStandards.txt -configuration.h2020template=tmp/h2020.docx -configuration.configurable_login_providers= +configuration.h2020template=documents/h2020.docx +configuration.configurable_login_providers=/tmp/ConfigurableLoginProviders.json ####################INVITATION MAIL CONFIGURATIONS############## ####################GENERIC MAIL CONFIGURATIONS################# @@ -86,4 +86,6 @@ zenodo.url=https://sandbox.zenodo.org/api/ zenodo.access_token= #############CONTACT EMAIL CONFIGURATIONS######### -contact_email.mail= \ No newline at end of file +contact_email.mail= + +language.path=i18n/ \ No newline at end of file diff --git a/dmp-db-scema/updates/08/07_Remove_no_null_requirement.sql b/dmp-db-scema/updates/08/07_Remove_no_null_requirement.sql new file mode 100644 index 000000000..8cda5cf9c --- /dev/null +++ b/dmp-db-scema/updates/08/07_Remove_no_null_requirement.sql @@ -0,0 +1,2 @@ +AlTER TABLE "DMP" +ALTER COLUMN "Creator" DROP NOT NULL; \ No newline at end of file diff --git a/dmp-db-scema/updates/08/08_create_datasetexternaldataset.sql b/dmp-db-scema/updates/08/08_create_datasetexternaldataset.sql new file mode 100644 index 000000000..76e84fe22 --- /dev/null +++ b/dmp-db-scema/updates/08/08_create_datasetexternaldataset.sql @@ -0,0 +1,19 @@ +CREATE TABLE public."DatasetExternalDataset" ( + "Id" uuid DEFAULT public.uuid_generate_v4() NOT NULL, + "Dataset" uuid NOT NULL, + "ExternalDataset" uuid NOT NULL, + "Role" numeric, + "Data" character varying +); + +ALTER TABLE public."DatasetExternalDataset" OWNER TO dmptool; + +ALTER TABLE ONLY public."DatasetExternalDataset" + ADD CONSTRAINT "DatasetExternalDataset_pkey" PRIMARY KEY ("Id"); + +ALTER TABLE ONLY public."DatasetExternalDataset" + ADD CONSTRAINT fkey_datasetexternaldataset_dataset FOREIGN KEY ("Dataset") REFERENCES public."Dataset"("ID"); + +ALTER TABLE ONLY public."DatasetExternalDataset" + ADD CONSTRAINT fkey_datasetexternaldataset_externaldataset FOREIGN KEY ("ExternalDataset") REFERENCES public."ExternalDataset"("Id"); + diff --git a/dmp-db-scema/updates/08/09_Create_Invitation.sql b/dmp-db-scema/updates/08/09_Create_Invitation.sql new file mode 100644 index 000000000..c820248b1 --- /dev/null +++ b/dmp-db-scema/updates/08/09_Create_Invitation.sql @@ -0,0 +1,23 @@ +CREATE TABLE public."Invitation" ( + "Id" uuid NOT NULL, + "InvitationEmail" character varying NOT NULL, + "Token" uuid NOT NULL, + "CreationUser" uuid NOT NULL, + "Dmp" uuid NOT NULL, + "Properties" xml, + "AcceptedInvitation" boolean +); + + +ALTER TABLE public."Invitation" OWNER TO dmptool; + +ALTER TABLE ONLY public."Invitation" + ADD CONSTRAINT "Invitation_pkey" PRIMARY KEY ("Id"); + + +ALTER TABLE ONLY public."Invitation" + ADD CONSTRAINT fk_invitation_creator FOREIGN KEY ("CreationUser") REFERENCES public."UserInfo"(id); + + +ALTER TABLE ONLY public."Invitation" + ADD CONSTRAINT fk_invitation_dmp FOREIGN KEY ("Dmp") REFERENCES public."DMP"("ID"); \ No newline at end of file diff --git a/dmp-db-scema/updates/08/10_Create_User_preference.sql b/dmp-db-scema/updates/08/10_Create_User_preference.sql new file mode 100644 index 000000000..edae5bb93 --- /dev/null +++ b/dmp-db-scema/updates/08/10_Create_User_preference.sql @@ -0,0 +1,16 @@ +CREATE TABLE public."UserPreference" ( + "Id" uuid NOT NULL, + "UserId" uuid NOT NULL, + "Data" json NOT NULL, + "PreferenceType" smallint NOT NULL +); + + +ALTER TABLE public."UserPreference" OWNER TO dmptool; + +ALTER TABLE ONLY public."UserPreference" + ADD CONSTRAINT "UserPreference_pkey" PRIMARY KEY ("Id"); + + +ALTER TABLE ONLY public."UserPreference" + ADD CONSTRAINT userpreference_user_fk FOREIGN KEY ("UserId") REFERENCES public."UserInfo"(id); diff --git a/docker-compose.yml b/docker-compose.yml index f5a46f45d..18412a920 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -38,6 +38,7 @@ services: - ./openDMP/dmp-backend/opendmp-logs:/app/logs - ./openDMP/dmp-backend/tmp:/app/tmp - ./openDMP/dmp-backend/logging:/app/logging + - ./openDMP/dmp-backend/documents:/app/documents dmp-frontend: build: From f397ce6c7202571acc278aab02b296a49de358c1 Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Mon, 4 May 2020 17:19:23 +0300 Subject: [PATCH 12/18] Fixed issue when creating new users --- .../authentication/AbstractAuthenticationService.java | 6 +++--- dmp-db-scema/updates/08/02_Add_missing_columns.sql | 8 +++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/AbstractAuthenticationService.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/AbstractAuthenticationService.java index 78c6a9830..6d08acb0c 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/AbstractAuthenticationService.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/AbstractAuthenticationService.java @@ -134,10 +134,10 @@ public abstract class AbstractAuthenticationService implements AuthenticationSer .name(profile.getName()).verified_email(profile.getIsVerified()) .email(profile.getEmail()).created(new Date()).lastloggedin(new Date()) .additionalinfo("{\"data\":{\"avatar\":{\"url\":\"" + profile.getAvatarUrl() - + "\"}},{\"zenodoToken\":\"" + profile.getZenodoId() - + "\", \"expirationDate\": \"" + Instant.now().plusSeconds(profile.getZenodoExpire()).toEpochMilli() + + "\"},\"zenodoToken\":\"" + profile.getZenodoId() + + "\", \"expirationDate\": \"" + Instant.now().plusSeconds((profile.getZenodoExpire() != null ? profile.getZenodoExpire(): 0)).toEpochMilli() + "\", \"zenodoRefresh\": \"" + profile.getZenodoRefresh() - + (profile.getProvider() == TokenValidatorFactoryImpl.LoginProvider.ZENODO ? "\", \"zenodoEmail\": \"" + profile.getEmail() : "") +"\"}") + + (profile.getProvider() == TokenValidatorFactoryImpl.LoginProvider.ZENODO ? "\", \"zenodoEmail\": \"" + profile.getEmail() : "") +"\"}}") .authorization_level((short) 1).usertype((short) 1) .build(); diff --git a/dmp-db-scema/updates/08/02_Add_missing_columns.sql b/dmp-db-scema/updates/08/02_Add_missing_columns.sql index 4036dcdc7..2cecd31cb 100644 --- a/dmp-db-scema/updates/08/02_Add_missing_columns.sql +++ b/dmp-db-scema/updates/08/02_Add_missing_columns.sql @@ -14,4 +14,10 @@ ALTER TABLE public."DatasetProfile" ADD COLUMN "Version" integer; ALTER TABLE public."Grant" -ADD COLUMN "Type" numeric NOT NULL; \ No newline at end of file +ADD COLUMN "Type" numeric NOT NULL; + +ALTER TABLE public."DatasetDataRepository" +ADD COLUMN "Data" character varying; + +ALTER TABLE public."DatasetService" +ADD COLUMN "Data" character varying; \ No newline at end of file From 7784547bea54b31ceedeab57a9566a3c8dbdce78 Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Tue, 5 May 2020 18:31:32 +0300 Subject: [PATCH 13/18] When generating DOI it will remain unpublished until the DMP got published, add reference identifier to the DMP (public overview) and add collaborators (associated users and researchers) to DOI generation (ref #257) --- .../managers/DataManagementPlanManager.java | 78 ++++++++++++++----- 1 file changed, 60 insertions(+), 18 deletions(-) diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java index 28f76210b..1d1c9bec8 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java @@ -794,6 +794,7 @@ public class DataManagementPlanManager { }); UserInfo user = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(principal.getId()); sendNotification(dmp, user, NotificationType.DMP_PUBLISH); + this.createZenodoDoi(dmp.getId(), principal, null); } public void makeFinalize(UUID id, Principal principal, DatasetsToBeFinalized datasetsToBeFinalized) throws Exception { @@ -1610,8 +1611,8 @@ public class DataManagementPlanManager { throw new Exception("User is not authorized to invoke this action"); if (!dmp.getStatus().equals(DMP.DMPStatus.FINALISED.getValue())) throw new Exception("DMP is not finalized"); - if (dmp.getDoi() != null) - throw new Exception("DMP already has a DOI"); + /*if (dmp.getDoi() != null) + throw new Exception("DMP already has a DOI");*/ String zenodoToken = ""; try { @@ -1626,18 +1627,51 @@ public class DataManagementPlanManager { HttpHeaders headers = new HttpHeaders(); headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); headers.setContentType(MediaType.APPLICATION_JSON); - String createData = "{\n" + - " \"metadata\": {\n" + - " \"title\": \"" + dmp.getLabel() + "\",\n" + - " \"upload_type\": \"publication\",\n" + - " \"publication_type\": \"datamanagementplan\",\n" + - " \"description\": \"" + (dmp.getDescription() != null && !dmp.getDescription().isEmpty() ? dmp.getDescription() : "

") + "\",\n" + - " \"version\": \"" + dmp.getVersion() + "\",\n" + - " \"creators\": [{\n" + - " \t\t\"name\": \"" + dmp.getUsers().stream().filter(userDMP -> userDMP.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())).findFirst().get().getUser().getName() + "\",\n" + - " \t\t\"affiliation\": \"OpenDMP\"}]\n" + - " }\n" + - "}"; + String createData = null; + StringBuilder dataBuilder = new StringBuilder(); + dataBuilder.append("{\n \"metadata\": {\n"); + dataBuilder.append( " \"title\": \"").append(dmp.getLabel()).append("\",\n"); + dataBuilder.append(" \"upload_type\": \"publication\",\n"); + dataBuilder.append(" \"publication_type\": \"datamanagementplan\",\n"); + dataBuilder.append(" \"description\": \"").append((dmp.getDescription() != null && !dmp.getDescription().isEmpty() ? dmp.getDescription() : "

")).append("\",\n"); + dataBuilder.append(" \"version\": \"").append(dmp.getVersion()).append("\",\n"); + dataBuilder.append(" \"related_identifiers\": [{\n"); + dataBuilder.append(" \t\t\"identifier\": \"").append((this.environment.getProperty("dmp.domain") + "/explore-plans/publicOverview/" + id.toString())).append("\",\n"); + dataBuilder.append(" \t\t\"relation\": \"isIdenticalTo\"}],\n"); + dataBuilder.append(" \"contributors\": ["); + int i = 0; + for(UserDMP userDMP: dmp.getUsers()) { + if (i > 0) { + dataBuilder.append(",\n"); + } + dataBuilder.append("{\n"); + dataBuilder.append(" \t\t\"name\": \"").append(userDMP.getUser().getName()).append("\",\n"); + dataBuilder.append(" \t\t\"type\": \"").append("ProjectMember").append("\",\n"); + dataBuilder.append(" \t\t\"affiliation\": \"OpenDMP\"\n}"); + i++; + } + for(Researcher researcher: dmp.getResearchers()) { + if (i > 0) { + dataBuilder.append(",\n"); + } + dataBuilder.append("{\n"); + dataBuilder.append(" \t\t\"name\": \"").append(researcher.getLabel()).append("\",\n"); + dataBuilder.append(" \t\t\"type\": \"").append("Researcher").append("\",\n"); + String referenceHead = researcher.getReference().split(":")[0]; + String referenceTail = researcher.getReference().replace(referenceHead + ":", ""); + dataBuilder.append(" \t\t\"affiliation\": \"" + referenceHead + "\""); + if (referenceHead.toUpperCase().equals("ORCID")) { + dataBuilder.append(",\n \t\t\"orcid\": \"" + referenceTail + "\""); + } + dataBuilder.append("\n}"); + i++; + } + dataBuilder.append("],\n"); + dataBuilder.append(" \"creators\": [{\n"); + dataBuilder.append(" \t\t\"name\": \"").append(dmp.getUsers().stream().filter(userDMP -> userDMP.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())).findFirst().get().getUser().getName()).append("\",\n"); + dataBuilder.append(" \t\t\"affiliation\": \"OpenDMP\"}]\n"); + dataBuilder.append(" }\n").append("}"); + createData = dataBuilder.toString(); JsonNode createDataJSON = new ObjectMapper().readTree(createData); HttpEntity request = new HttpEntity<>(createDataJSON, headers); Map createResponse = null; @@ -1645,12 +1679,14 @@ public class DataManagementPlanManager { String previousDOI = this.getPreviousDOI(dmp.getGroupId(), dmp.getId()); String unpublishedUrl = null; String publishUrl = null; + String finalDoi = null; try { if (previousDOI == null) { String createUrl = this.environment.getProperty("zenodo.url") + "deposit/depositions" + "?access_token=" + zenodoToken; createResponse = restTemplate.postForEntity(createUrl, request, Map.class).getBody(); links = (LinkedHashMap) createResponse.get("links"); + finalDoi = (String) createResponse.get("conceptdoi"); } else { unpublishedUrl = this.getUnpublishedDOI(previousDOI, zenodoToken, dmp.getVersion()); if (unpublishedUrl == null) { @@ -1668,6 +1704,7 @@ public class DataManagementPlanManager { String latestDraftUrl = links.get("latest_draft") + "?access_token=" + zenodoToken; createResponse = restTemplate.getForObject(latestDraftUrl, Map.class); links = (LinkedHashMap) createResponse.get("links"); + finalDoi = (String) createResponse.get("conceptdoi"); //At this point it might fail to perform the next requests so enclose them with try catch try { //Forth, update the new deposit's metadata @@ -1710,11 +1747,16 @@ public class DataManagementPlanManager { } else { publishUrl = unpublishedUrl + "?access_token=" + zenodoToken; } - Map publishResponce = restTemplate.postForObject(publishUrl, "", Map.class); + if (dmp.isPublic()) { + Map publishResponce = restTemplate.postForObject(publishUrl, "", Map.class); + finalDoi = (String) publishResponce.get("conceptdoi"); + } - dmp.setDoi((String) publishResponce.get("conceptdoi")); - apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); - return (String) publishResponce.get("conceptdoi"); + if (finalDoi != null) { + dmp.setDoi(finalDoi); + apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); + } + return finalDoi; } catch (HttpClientErrorException | HttpServerErrorException ex) { ObjectMapper ob = new ObjectMapper(); Map parsedException = ob.readValue(ex.getResponseBodyAsString(), HashMap.class); From 42b2ff67f6f5b95fffa82bd0da99b544e80a7cd6 Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Wed, 6 May 2020 18:02:19 +0300 Subject: [PATCH 14/18] Fixed issue when retrieving grants using funderId --- .../java/eu/eudat/logic/proxy/fetching/RemoteFetcher.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/fetching/RemoteFetcher.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/fetching/RemoteFetcher.java index cd29be9e8..05f966bac 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/fetching/RemoteFetcher.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/fetching/RemoteFetcher.java @@ -169,9 +169,13 @@ public class RemoteFetcher { completedPath = completedPath.replace("{like}", ""); } if (externalUrlCriteria.getFunderId() != null) { - String funderId = externalUrlCriteria.getFunderId(); + String funderPrefix = externalUrlCriteria.getFunderId().split(":")[0]; + String funderId = externalUrlCriteria.getFunderId().replace(funderPrefix + ":", ""); + if (funderId.toCharArray()[0] == ':') { + funderId = externalUrlCriteria.getFunderId(); + } try { - funderId = URLEncoder.encode(externalUrlCriteria.getFunderId(), "UTF-8"); + funderId = URLEncoder.encode(funderId, "UTF-8"); } catch (UnsupportedEncodingException e) { logger.error(e.getMessage(), e); } From 0eb0707fd5ccfb852c4c56d74f542b6a2de3955b Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Wed, 6 May 2020 18:11:33 +0300 Subject: [PATCH 15/18] Add openaire grant on DOI creation (ref #257) --- .../eudat/data/dao/entities/DoiFunderDao.java | 11 ++++ .../data/dao/entities/DoiFunderDaoImpl.java | 55 +++++++++++++++++ .../eu/eudat/data/entities/DoiFunder.java | 61 +++++++++++++++++++ .../managers/DataManagementPlanManager.java | 8 +++ .../operations/DatabaseRepository.java | 2 + .../operations/DatabaseRepositoryImpl.java | 11 ++++ dmp-db-scema/updates/09/02_doifunder.sql | 24 ++++++++ 7 files changed, 172 insertions(+) create mode 100644 dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DoiFunderDao.java create mode 100644 dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DoiFunderDaoImpl.java create mode 100644 dmp-backend/data/src/main/java/eu/eudat/data/entities/DoiFunder.java create mode 100644 dmp-db-scema/updates/09/02_doifunder.sql diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DoiFunderDao.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DoiFunderDao.java new file mode 100644 index 000000000..038b4b4b2 --- /dev/null +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DoiFunderDao.java @@ -0,0 +1,11 @@ +package eu.eudat.data.dao.entities; + +import eu.eudat.data.dao.DatabaseAccessLayer; +import eu.eudat.data.entities.DoiFunder; + +import java.util.UUID; + +public interface DoiFunderDao extends DatabaseAccessLayer { + + DoiFunder findFunderByName(String name); +} diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DoiFunderDaoImpl.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DoiFunderDaoImpl.java new file mode 100644 index 000000000..3e775b952 --- /dev/null +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DoiFunderDaoImpl.java @@ -0,0 +1,55 @@ +package eu.eudat.data.dao.entities; + +import eu.eudat.data.dao.DatabaseAccess; +import eu.eudat.data.dao.databaselayer.service.DatabaseService; +import eu.eudat.data.entities.DoiFunder; +import eu.eudat.queryable.QueryableList; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +@Component("DoiFunderDao") +public class DoiFunderDaoImpl extends DatabaseAccess implements DoiFunderDao { + + @Autowired + public DoiFunderDaoImpl(DatabaseService databaseService) { + super(databaseService); + } + + @Override + public DoiFunder findFunderByName(String name) { + return this.asQueryable().toList().stream().filter(doiFunder -> name.contains(doiFunder.getName()) || doiFunder.getName().contains(name)).findFirst().orElse(null); + } + + @Override + public DoiFunder createOrUpdate(DoiFunder item) { + return this.getDatabaseService().createOrUpdate(item, DoiFunder.class); + } + + @Override + public CompletableFuture createOrUpdateAsync(DoiFunder item) { + return CompletableFuture.supplyAsync(() -> this.createOrUpdate(item)); + } + + @Override + public DoiFunder find(UUID id) { + return this.getDatabaseService().getQueryable(DoiFunder.class).where(((builder, root) -> builder.equal(root.get("id"), id))).getSingle(); + } + + @Override + public DoiFunder find(UUID id, String hint) { + throw new UnsupportedOperationException(); + } + + @Override + public void delete(DoiFunder item) { + this.getDatabaseService().delete(item); + } + + @Override + public QueryableList asQueryable() { + return this.getDatabaseService().getQueryable(DoiFunder.class); + } +} diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/DoiFunder.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/DoiFunder.java new file mode 100644 index 000000000..6ee816210 --- /dev/null +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/DoiFunder.java @@ -0,0 +1,61 @@ +package eu.eudat.data.entities; + +import eu.eudat.queryable.queryableentity.DataEntity; + +import javax.persistence.*; +import java.util.List; +import java.util.UUID; + +@Entity +@Table(name = "\"DoiFunder\"") +public class DoiFunder implements DataEntity { + + @Id + private UUID id; + + @Column(name = "name") + private String name; + + @Column(name = "doi") + private String doi; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDoi() { + return doi; + } + + public void setDoi(String doi) { + this.doi = doi; + } + + @Override + public void update(DoiFunder entity) { + this.name = entity.name; + this.doi = entity.doi; + } + + @Override + public UUID getKeys() { + return id; + } + + @Override + public DoiFunder buildFromTuple(List tuple, List fields, String base) { + return null; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java index 1d1c9bec8..a2815c328 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java @@ -1667,6 +1667,14 @@ public class DataManagementPlanManager { i++; } dataBuilder.append("],\n"); + String grantReferenceHead = dmp.getGrant().getReference().split(":")[0]; + if (grantReferenceHead.equals("openaire")) { + String grantReferenceTail = dmp.getGrant().getReference().split(":")[3]; + DoiFunder doiFunder = this.apiContext.getOperationsContext().getDatabaseRepository().getDoiFunderDao().findFunderByName(dmp.getGrant().getFunder().getLabel()); + String finalId = doiFunder.getDoi() + "::" + grantReferenceTail; + dataBuilder.append(" \"grants\": [{\n"); + dataBuilder.append(" \t\t\"id\": \"").append(finalId).append("\"\n}],\n"); + } dataBuilder.append(" \"creators\": [{\n"); dataBuilder.append(" \t\t\"name\": \"").append(dmp.getUsers().stream().filter(userDMP -> userDMP.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())).findFirst().get().getUser().getName()).append("\",\n"); dataBuilder.append(" \t\t\"affiliation\": \"OpenDMP\"}]\n"); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java index 516f7e949..ff6518354 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java @@ -58,5 +58,7 @@ public interface DatabaseRepository { UserAssociationDao getUserAssociationDao(); + DoiFunderDao getDoiFunderDao(); + void detachEntity(T entity); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java index ff5f6506e..01aa5093a 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java @@ -38,6 +38,7 @@ public class DatabaseRepositoryImpl implements DatabaseRepository { private LockDao lockDao; private NotificationDao notificationDao; private UserAssociationDao userAssociationDao; + private DoiFunderDao doiFunderDao; private EntityManager entityManager; @@ -296,6 +297,16 @@ public class DatabaseRepositoryImpl implements DatabaseRepository { return userAssociationDao; } + @Override + public DoiFunderDao getDoiFunderDao() { + return doiFunderDao; + } + + @Autowired + public void setDoiFunderDao(DoiFunderDao doiFunderDao) { + this.doiFunderDao = doiFunderDao; + } + @Autowired public void setUserAssociationDao(UserAssociationDao userAssociationDao) { this.userAssociationDao = userAssociationDao; diff --git a/dmp-db-scema/updates/09/02_doifunder.sql b/dmp-db-scema/updates/09/02_doifunder.sql new file mode 100644 index 000000000..228c6b4a5 --- /dev/null +++ b/dmp-db-scema/updates/09/02_doifunder.sql @@ -0,0 +1,24 @@ +CREATE TABLE public."DoiFunder" ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, + name character varying, + doi character varying +); + + +ALTER TABLE public."DoiFunder" OWNER TO dmptool; + +COPY public."DoiFunder" (id, name, doi) FROM stdin; +ad9bad58-52a9-4c0c-85e1-ca8d0bf72c5f Australian Research Council 10.13039/501100000923 +a778e6fe-17d1-4e5b-978f-2a290f096530 European Commission 10.13039/501100000780 +ef314bc9-b72c-4c88-9ca8-e23d4f564136 Fundação para a Ciência e a Tecnologia 10.13039/501100001871 +19a21b03-9313-4497-b69c-91c8396aeda8 Ministarstvo Prosvete, Nauke i Tehnološkog Razvoja 10.13039/501100004564 +d6430393-daac-403a-bb76-36100662b4d6 Ministarstvo Znanosti, Obrazovanja i Sporta 10.13039/501100006588 +4b06a13f-8392-4aa4-ae28-6b6ab68fc266 National Health and Medical Research Council 10.13039/501100000925 +cbcac800-69cb-42fe-95af-5de1594987e2 National Science Foundation 10.13039/100000001 +3c8b88c6-710c-4a9c-bf39-bc35259cc7bf Nederlandse Organisatie voor Wetenschappelijk Onderzoek 10.13039/501100003246 +1816a401-cf74-4ff9-939d-faf1aad21b60 Wellcome Trust 10.13039/100004440 +\. + +ALTER TABLE ONLY public."DoiFunder" + ADD CONSTRAINT "DoiFunder_pkey" PRIMARY KEY (id); + From b539544075039d3f02a95482de911537f84a3d8c Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Thu, 7 May 2020 10:57:20 +0300 Subject: [PATCH 16/18] Add link to relevant zenodo entity on DOI overview with root link configurable (ref #264) --- .../core/services/configuration/configuration.service.ts | 6 ++++++ .../src/app/ui/dmp/overview/dmp-overview.component.html | 2 +- .../src/app/ui/dmp/overview/dmp-overview.component.ts | 6 ++++++ dmp-frontend/src/assets/config/config.json | 3 ++- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/dmp-frontend/src/app/core/services/configuration/configuration.service.ts b/dmp-frontend/src/app/core/services/configuration/configuration.service.ts index e6d544816..8ede16604 100644 --- a/dmp-frontend/src/app/core/services/configuration/configuration.service.ts +++ b/dmp-frontend/src/app/core/services/configuration/configuration.service.ts @@ -62,6 +62,11 @@ export class ConfigurationService extends BaseComponent { return this._allowOrganizationCreator; } + private _doiLink: string; + get doiLink(): string { + return this._doiLink; + } + public loadConfiguration(): Promise { return new Promise((r, e) => { @@ -98,6 +103,7 @@ export class ConfigurationService extends BaseComponent { this._lockInterval = config.lockInterval; this._guideAssets = config.guideAssets; this._allowOrganizationCreator = config.allowOrganizationCreator; + this._doiLink = config.doiLink; } } diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html index cb45ad27f..5151ecd9b 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html @@ -71,7 +71,7 @@
- {{ 'DMP-EDITOR.TITLE.SUBTITLE' | translate }}: {{ dmp.doi }} + {{ 'DMP-EDITOR.TITLE.SUBTITLE' | translate }}: {{ dmp.doi }}
diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts index ea0064270..c363c8595 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts @@ -522,6 +522,12 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { this.router.navigate(['/datasets/new/' + rowId]); } + createDoiLink(doi: string): string { + const doiarr = doi.split('.'); + const id = doiarr[doiarr.length - 1]; + return this.configurationService.doiLink + id; + } + // advancedClicked() { // const dialogRef = this.dialog.open(ExportMethodDialogComponent, { // maxWidth: '500px', diff --git a/dmp-frontend/src/assets/config/config.json b/dmp-frontend/src/assets/config/config.json index 5f916f361..09730c8b9 100644 --- a/dmp-frontend/src/assets/config/config.json +++ b/dmp-frontend/src/assets/config/config.json @@ -50,5 +50,6 @@ }, "lockInterval": 60000, "guideAssets": "assets/images/guide", - "allowOrganizationCreator": true + "allowOrganizationCreator": true, + "doiLink": "https://sandbox.zenodo.org/record/" } From 50c45b72713255c1c1b26f0b422e6d7e4e718d3c Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Fri, 8 May 2020 18:27:16 +0300 Subject: [PATCH 17/18] Show status on dataset profile listing and filter them based on status (ref #265) --- .../dao/criteria/DatasetProfileCriteria.java | 9 +++++++++ .../data/dao/entities/DatasetProfileDaoImpl.java | 3 +++ .../dataset-profile/dataset-profile.module.ts | 4 +++- .../criteria/dataset-profile.component.html | 7 +++++++ .../dataset-profile-listing.component.html | 7 +++++++ .../listing/dataset-profile-listing.component.ts | 2 +- .../listing/pipe/parse-status.pipe.ts | 16 ++++++++++++++++ dmp-frontend/src/assets/i18n/en.json | 8 +++++++- 8 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/listing/pipe/parse-status.pipe.ts diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DatasetProfileCriteria.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DatasetProfileCriteria.java index b8e2c35c4..cc556701d 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DatasetProfileCriteria.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DatasetProfileCriteria.java @@ -33,6 +33,7 @@ public class DatasetProfileCriteria extends Criteria { private Short filter; private UUID userId; private boolean finalized; + private Integer status; public boolean getAllVersions() { return allVersions; } public void setAllVersions(boolean allVersions) { this.allVersions = allVersions; } @@ -60,4 +61,12 @@ public class DatasetProfileCriteria extends Criteria { public void setFinalized(boolean finalized) { this.finalized = finalized; } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } } diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetProfileDaoImpl.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetProfileDaoImpl.java index b06d5d8fd..36fcc5433 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetProfileDaoImpl.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetProfileDaoImpl.java @@ -52,6 +52,9 @@ public class DatasetProfileDaoImpl extends DatabaseAccess implem builder.notEqual(root.get("id"), criteria.getUserId()))); } } + if (criteria.getStatus() != null) { + query.where(((builder, root) -> builder.equal(root.get("status"), criteria.getStatus()))); + } if (criteria.getFinalized()) { query.where(((builder, root) -> builder.equal(root.get("status"), DatasetProfile.Status.FINALIZED.getValue()))); } else { diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts index 1e7c9eb19..af103eebc 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts @@ -27,6 +27,7 @@ import { DialodConfirmationUploadDatasetProfiles } from '@app/ui/admin/dataset-p import { DatasetProfileListingComponent } from '@app/ui/admin/dataset-profile/listing/dataset-profile-listing.component'; import { CommonFormsModule } from '@common/forms/common-forms.module'; import { CommonUiModule } from '@common/ui/common-ui.module'; +import { ParseStatus } from './listing/pipe/parse-status.pipe'; @NgModule({ imports: [ @@ -59,7 +60,8 @@ import { CommonUiModule } from '@common/ui/common-ui.module'; DatasetProfileEditorInternalDmpEntitiesFieldComponent, DatasetProfileEditorResearchersAutoCompleteFieldComponent, DatasetProfileEditorDatasetsAutoCompleteFieldComponent, - DatasetProfileEditorDmpsAutoCompleteFieldComponent + DatasetProfileEditorDmpsAutoCompleteFieldComponent, + ParseStatus ], entryComponents: [ DialodConfirmationUploadDatasetProfiles diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component.html index 8026e4251..c303267ef 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component.html +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component.html @@ -5,6 +5,13 @@ + + + {{'DATASET-PROFILE-STATUS.NONE' | translate}} + {{'DATASET-PROFILE-STATUS.DRAFT' | translate}} + {{'DATASET-PROFILE-STATUS.FINALIZED' | translate}} + +
diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.html index 44a5c5adf..b0e01d2c1 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.html +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.html @@ -27,6 +27,13 @@ {{row.created | date:'shortDate'}} + + + {{'DATASET-PROFILE-LISTING.COLUMNS.STATUS' | + translate}} + {{ (row.status | parseStatus) | translate}} + + {{'DATASET-PROFILE-LISTING.COLUMNS.ACTIONS' | translate}} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.ts index 8f903dedd..230ebf16f 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.ts @@ -30,7 +30,7 @@ export class DatasetProfileListingComponent extends BaseComponent implements OnI breadCrumbs: Observable; dataSource: DatasetDataSource | null; - displayedColumns: String[] = ['label', 'description', 'created', 'actions']; + displayedColumns: String[] = ['label', 'description', 'created', 'status', 'actions']; pageEvent: PageEvent; titlePrefix: String; dmpId: String; diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/listing/pipe/parse-status.pipe.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/pipe/parse-status.pipe.ts new file mode 100644 index 000000000..33cbd4b8c --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/pipe/parse-status.pipe.ts @@ -0,0 +1,16 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'parseStatus', + pure: true +}) +export class ParseStatus implements PipeTransform { + transform(value: any, ...args: any[]) { + return this.parseStatus(value); + } + + + parseStatus(status: number): string { + return status != 0 ? 'DATASET-PROFILE-STATUS.FINALIZED' : 'DATASET-PROFILE-STATUS.DRAFT'; + } +} diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index 63fd0f3d6..64210103d 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -765,7 +765,8 @@ } }, "DATASET-PROFILE": { - "LIKE": "Search" + "LIKE": "Search", + "STATUS": "Status" }, "DATA-SETS": { "PERIOD-FROM": "Start", @@ -1261,5 +1262,10 @@ } }, "HINT": "(Suggested Default Name)" + }, + "DATASET-PROFILE-STATUS": { + "NONE": "None", + "DRAFT": "Draft", + "FINALIZED": "Finalized" } } From 19b8a493700b6293ff0bbee73915ada95a2e0db9 Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Mon, 11 May 2020 11:46:16 +0300 Subject: [PATCH 18/18] Fixed issue with doiFunder sql --- dmp-db-scema/updates/09/02_doifunder.sql | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/dmp-db-scema/updates/09/02_doifunder.sql b/dmp-db-scema/updates/09/02_doifunder.sql index 228c6b4a5..cb6742516 100644 --- a/dmp-db-scema/updates/09/02_doifunder.sql +++ b/dmp-db-scema/updates/09/02_doifunder.sql @@ -5,20 +5,20 @@ CREATE TABLE public."DoiFunder" ( ); -ALTER TABLE public."DoiFunder" OWNER TO dmptool; - -COPY public."DoiFunder" (id, name, doi) FROM stdin; -ad9bad58-52a9-4c0c-85e1-ca8d0bf72c5f Australian Research Council 10.13039/501100000923 -a778e6fe-17d1-4e5b-978f-2a290f096530 European Commission 10.13039/501100000780 -ef314bc9-b72c-4c88-9ca8-e23d4f564136 Fundação para a Ciência e a Tecnologia 10.13039/501100001871 -19a21b03-9313-4497-b69c-91c8396aeda8 Ministarstvo Prosvete, Nauke i Tehnološkog Razvoja 10.13039/501100004564 -d6430393-daac-403a-bb76-36100662b4d6 Ministarstvo Znanosti, Obrazovanja i Sporta 10.13039/501100006588 -4b06a13f-8392-4aa4-ae28-6b6ab68fc266 National Health and Medical Research Council 10.13039/501100000925 -cbcac800-69cb-42fe-95af-5de1594987e2 National Science Foundation 10.13039/100000001 -3c8b88c6-710c-4a9c-bf39-bc35259cc7bf Nederlandse Organisatie voor Wetenschappelijk Onderzoek 10.13039/501100003246 -1816a401-cf74-4ff9-939d-faf1aad21b60 Wellcome Trust 10.13039/100004440 -\. - ALTER TABLE ONLY public."DoiFunder" ADD CONSTRAINT "DoiFunder_pkey" PRIMARY KEY (id); +ALTER TABLE public."DoiFunder" OWNER TO dmptool; + +INSERT INTO public."DoiFunder"(name, doi) VALUES ('Australian Research Council', '10.13039/501100000923'); +INSERT INTO public."DoiFunder"(name, doi) VALUES ('European Commission', '10.13039/501100000780'); +INSERT INTO public."DoiFunder"(name, doi) VALUES ('Fundação para a Ciência e a Tecnologia', '10.13039/501100001871'); +INSERT INTO public."DoiFunder"(name, doi) VALUES ('Ministarstvo Prosvete, Nauke i Tehnološkog Razvoja', '10.13039/501100004564'); +INSERT INTO public."DoiFunder"(name, doi) VALUES ('Ministarstvo Znanosti, Obrazovanja i Sporta', '10.13039/501100006588'); +INSERT INTO public."DoiFunder"(name, doi) VALUES ('National Health and Medical Research Council', '10.13039/501100000925'); +INSERT INTO public."DoiFunder"(name, doi) VALUES ('National Science Foundation','10.13039/100000001'); +INSERT INTO public."DoiFunder"(name, doi) VALUES ('Nederlandse Organisatie voor Wetenschappelijk Onderzoek', '10.13039/501100003246'); +INSERT INTO public."DoiFunder"(name, doi) VALUES ('Wellcome Trust', '10.13039/100004440'); + + +