Fixed security issues with Dataset Description access
This commit is contained in:
parent
03619a65fc
commit
2b30d4e2d2
|
@ -11,6 +11,7 @@ import eu.eudat.data.query.items.table.dmp.DataManagementPlanTableRequest;
|
|||
import eu.eudat.data.query.items.table.dmp.DataManagmentPlanPublicTableRequest;
|
||||
import eu.eudat.exceptions.datamanagementplan.DMPNewVersionException;
|
||||
import eu.eudat.exceptions.datamanagementplan.DMPWithDatasetsDeleteException;
|
||||
import eu.eudat.exceptions.security.UnauthorisedException;
|
||||
import eu.eudat.logic.managers.DataManagementPlanManager;
|
||||
import eu.eudat.logic.managers.DatasetManager;
|
||||
import eu.eudat.logic.proxy.config.configloaders.ConfigLoader;
|
||||
|
@ -123,7 +124,11 @@ public class DMPs extends BaseController {
|
|||
DataManagementPlanOverviewModel dataManagementPlan = this.dataManagementPlanManager.getOverviewSingle(id, principal);
|
||||
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<DataManagementPlanOverviewModel>().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlan));
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ResponseItem<DataManagementPlanOverviewModel>().status(ApiMessageCode.ERROR_MESSAGE));
|
||||
if (e instanceof UnauthorisedException) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new ResponseItem<DataManagementPlanOverviewModel>().status(ApiMessageCode.ERROR_MESSAGE));
|
||||
} else {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ResponseItem<DataManagementPlanOverviewModel>().status(ApiMessageCode.ERROR_MESSAGE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import eu.eudat.data.entities.Dataset;
|
|||
import eu.eudat.data.query.items.item.dataset.DatasetWizardAutocompleteRequest;
|
||||
import eu.eudat.data.query.items.item.datasetprofile.DatasetProfileWizardAutocompleteRequest;
|
||||
import eu.eudat.exceptions.datasetwizard.DatasetWizardCannotUnlockException;
|
||||
import eu.eudat.exceptions.security.UnauthorisedException;
|
||||
import eu.eudat.logic.managers.DatasetManager;
|
||||
import eu.eudat.logic.managers.DatasetWizardManager;
|
||||
import eu.eudat.logic.managers.UserManager;
|
||||
|
@ -15,6 +16,7 @@ import eu.eudat.models.data.datasetwizard.DataManagentPlanListingModel;
|
|||
import eu.eudat.models.data.datasetwizard.DatasetWizardModel;
|
||||
import eu.eudat.models.data.dmp.AssociatedProfile;
|
||||
import eu.eudat.models.data.helpers.responses.ResponseItem;
|
||||
import eu.eudat.models.data.listingmodels.DataManagementPlanOverviewModel;
|
||||
import eu.eudat.models.data.security.Principal;
|
||||
import eu.eudat.models.data.user.composite.PagedDatasetProfile;
|
||||
import eu.eudat.types.ApiMessageCode;
|
||||
|
@ -30,6 +32,7 @@ import org.springframework.http.ResponseEntity;
|
|||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.transaction.Transactional;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
@ -79,32 +82,43 @@ public class DatasetWizardController extends BaseController {
|
|||
@Transactional
|
||||
@RequestMapping(method = RequestMethod.GET, value = {"{id}"}, produces = "application/json")
|
||||
public @ResponseBody
|
||||
ResponseEntity getSingle(@PathVariable String id, @RequestHeader("Content-Type") String contentType, @ClaimedAuthorities(claims = {ANONYMOUS}) Principal principal) throws IllegalAccessException, IOException, InstantiationException {
|
||||
if(contentType.equals("application/xml")) {
|
||||
VisibilityRuleService visibilityRuleService = this.getApiContext().getUtilitiesService().getVisibilityRuleService();
|
||||
return this.datasetManager.getDocument(id, visibilityRuleService, contentType);
|
||||
}
|
||||
else if (contentType.equals("application/msword")) {
|
||||
File file = datasetManager.getWordDocument(this.configLoader, id, this.getApiContext().getUtilitiesService().getVisibilityRuleService());
|
||||
InputStream resource = new FileInputStream(file);
|
||||
HttpHeaders responseHeaders = new HttpHeaders();
|
||||
responseHeaders.setContentLength(file.length());
|
||||
responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
|
||||
responseHeaders.set("Content-Disposition", "attachment;filename=" + file.getName());
|
||||
responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition");
|
||||
responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type");
|
||||
ResponseEntity getSingle(@PathVariable String id, @RequestHeader("Content-Type") String contentType, Principal principal) throws IllegalAccessException, IOException, InstantiationException {
|
||||
try {
|
||||
if (contentType.equals("application/xml")) {
|
||||
VisibilityRuleService visibilityRuleService = this.getApiContext().getUtilitiesService().getVisibilityRuleService();
|
||||
return this.datasetManager.getDocument(id, visibilityRuleService, contentType, principal);
|
||||
} else if (contentType.equals("application/msword")) {
|
||||
File file = datasetManager.getWordDocument(this.configLoader, id, this.getApiContext().getUtilitiesService().getVisibilityRuleService(), principal);
|
||||
InputStream resource = new FileInputStream(file);
|
||||
HttpHeaders responseHeaders = new HttpHeaders();
|
||||
responseHeaders.setContentLength(file.length());
|
||||
responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
|
||||
responseHeaders.set("Content-Disposition", "attachment;filename=" + file.getName());
|
||||
responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition");
|
||||
responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type");
|
||||
|
||||
byte[] content = IOUtils.toByteArray(resource);
|
||||
resource.close();
|
||||
Files.deleteIfExists(file.toPath());
|
||||
return new ResponseEntity<>(content,
|
||||
responseHeaders,
|
||||
HttpStatus.OK);
|
||||
}
|
||||
else {
|
||||
DatasetWizardModel dataset = this.datasetManager.getSingle(id);
|
||||
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<DatasetWizardModel>().status(ApiMessageCode.NO_MESSAGE).payload(dataset));
|
||||
byte[] content = IOUtils.toByteArray(resource);
|
||||
resource.close();
|
||||
Files.deleteIfExists(file.toPath());
|
||||
return new ResponseEntity<>(content,
|
||||
responseHeaders,
|
||||
HttpStatus.OK);
|
||||
} else {
|
||||
DatasetWizardModel dataset = this.datasetManager.getSingle(id, principal);
|
||||
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<DatasetWizardModel>().status(ApiMessageCode.NO_MESSAGE).payload(dataset));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (e instanceof UnauthorisedException) {
|
||||
if (e instanceof UnauthorisedException) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new ResponseItem<DataManagementPlanOverviewModel>().status(ApiMessageCode.ERROR_MESSAGE));
|
||||
} else if (e instanceof NoResultException) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ResponseItem<DataManagementPlanOverviewModel>().status(ApiMessageCode.ERROR_MESSAGE));
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null; // ????
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = {"/public/{id}"}, produces = "application/json")
|
||||
|
@ -137,8 +151,8 @@ public class DatasetWizardController extends BaseController {
|
|||
|
||||
@RequestMapping(method = RequestMethod.GET, value = {"/getPDF/{id}"})
|
||||
public @ResponseBody
|
||||
ResponseEntity<byte[]> getPDFDocument(@PathVariable String id) throws IllegalAccessException, IOException, InstantiationException, InterruptedException {
|
||||
File file = datasetManager.getWordDocument(this.configLoader, id, this.getApiContext().getUtilitiesService().getVisibilityRuleService());
|
||||
ResponseEntity<byte[]> getPDFDocument(@PathVariable String id, Principal principal) throws IllegalAccessException, IOException, InstantiationException, InterruptedException {
|
||||
File file = datasetManager.getWordDocument(this.configLoader, id, this.getApiContext().getUtilitiesService().getVisibilityRuleService(), principal);
|
||||
String fileName = file.getName();
|
||||
if (fileName.endsWith(".docx")){
|
||||
fileName = fileName.substring(0, fileName.length() - 5);
|
||||
|
|
|
@ -1035,7 +1035,7 @@ public class DataManagementPlanManager {
|
|||
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();
|
||||
RDAExportModel rdaExportModel = new RDAExportModel().fromDataModel(dmp, datasetManager);
|
||||
RDAExportModel rdaExportModel = new RDAExportModel().fromDataModel(dmp, datasetManager, principal);
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
||||
|
|
|
@ -14,6 +14,7 @@ import eu.eudat.data.query.items.table.dataset.DatasetTableRequest;
|
|||
import eu.eudat.data.query.items.table.datasetprofile.DatasetProfileTableRequestItem;
|
||||
import eu.eudat.elastic.criteria.DatasetCriteria;
|
||||
import eu.eudat.elastic.repository.DatasetRepository;
|
||||
import eu.eudat.exceptions.security.UnauthorisedException;
|
||||
import eu.eudat.logic.builders.BuilderFactory;
|
||||
import eu.eudat.logic.builders.entity.UserInfoBuilder;
|
||||
import eu.eudat.logic.proxy.config.configloaders.ConfigLoader;
|
||||
|
@ -186,9 +187,13 @@ public class DatasetManager {
|
|||
return dataTable;
|
||||
}
|
||||
|
||||
public DatasetWizardModel getSingle(String id) {
|
||||
public DatasetWizardModel getSingle(String id, Principal principal) {
|
||||
DatasetWizardModel dataset = new DatasetWizardModel();
|
||||
eu.eudat.data.entities.Dataset datasetEntity = databaseRepository.getDatasetDao().find(UUID.fromString(id), HintedModelFactory.getHint(DatasetWizardModel.class));
|
||||
if (datasetEntity.getDmp().getUsers()
|
||||
.stream().filter(userInfo -> userInfo.getUser().getId() == principal.getId())
|
||||
.collect(Collectors.toList()).size() == 0)
|
||||
throw new UnauthorisedException();
|
||||
eu.eudat.elastic.entities.Dataset datasetElastic;
|
||||
try {
|
||||
datasetElastic = datasetRepository.exists() ?
|
||||
|
@ -261,11 +266,15 @@ public class DatasetManager {
|
|||
return pagedDatasetProfile;
|
||||
}
|
||||
|
||||
public File getWordDocument(ConfigLoader configLoader, String id, VisibilityRuleService visibilityRuleService) throws IOException {
|
||||
public File getWordDocument(ConfigLoader configLoader, String id, VisibilityRuleService visibilityRuleService, Principal principal) throws IOException {
|
||||
WordBuilder wordBuilder = new WordBuilder();
|
||||
DatasetWizardModel dataset = new DatasetWizardModel();
|
||||
XWPFDocument document = configLoader.getDocument();
|
||||
eu.eudat.data.entities.Dataset datasetEntity = databaseRepository.getDatasetDao().find(UUID.fromString(id), HintedModelFactory.getHint(DatasetWizardModel.class));
|
||||
if (!datasetEntity.getDmp().isPublic() && datasetEntity.getDmp().getUsers()
|
||||
.stream().filter(userInfo -> userInfo.getUser().getId() == principal.getId())
|
||||
.collect(Collectors.toList()).size() == 0)
|
||||
throw new UnauthorisedException();
|
||||
wordBuilder.addParagraphContent(datasetEntity.getLabel(), document, ParagraphStyle.HEADER1, BigInteger.ZERO);
|
||||
|
||||
// Space below Dataset title.
|
||||
|
@ -342,10 +351,14 @@ public class DatasetManager {
|
|||
return exportFile;
|
||||
}
|
||||
|
||||
public FileEnvelope getXmlDocument(String id, VisibilityRuleService visibilityRuleService) throws InstantiationException, IllegalAccessException, IOException {
|
||||
public FileEnvelope getXmlDocument(String id, VisibilityRuleService visibilityRuleService, Principal principal) throws InstantiationException, IllegalAccessException, IOException {
|
||||
ExportXmlBuilder xmlBuilder = new ExportXmlBuilder();
|
||||
DatasetWizardModel dataset = new DatasetWizardModel();
|
||||
eu.eudat.data.entities.Dataset datasetEntity = databaseRepository.getDatasetDao().find(UUID.fromString(id), HintedModelFactory.getHint(DatasetWizardModel.class));
|
||||
if (!datasetEntity.getDmp().isPublic() && datasetEntity.getDmp().getUsers()
|
||||
.stream().filter(userInfo -> userInfo.getUser().getId() == principal.getId())
|
||||
.collect(Collectors.toList()).size() == 0)
|
||||
throw new UnauthorisedException();
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
if (datasetEntity.getProperties() != null) {
|
||||
JSONObject jobject = new JSONObject(datasetEntity.getProperties());
|
||||
|
@ -595,8 +608,8 @@ public class DatasetManager {
|
|||
datasetDao.createOrUpdate(dataset);
|
||||
}
|
||||
|
||||
public ResponseEntity<byte[]> getDocument(String id, VisibilityRuleService visibilityRuleService, String contentType) throws IllegalAccessException, IOException, InstantiationException {
|
||||
FileEnvelope envelope = getXmlDocument(id, visibilityRuleService);
|
||||
public ResponseEntity<byte[]> getDocument(String id, VisibilityRuleService visibilityRuleService, String contentType, Principal principal) throws IllegalAccessException, IOException, InstantiationException {
|
||||
FileEnvelope envelope = getXmlDocument(id, visibilityRuleService, principal);
|
||||
InputStream resource = new FileInputStream(envelope.getFile());
|
||||
logger.info("Mime Type of " + envelope.getFilename() + " is " +
|
||||
new MimetypesFileTypeMap().getContentType(envelope.getFile()));
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.jayway.jsonpath.JsonPath;
|
|||
import eu.eudat.data.entities.Dataset;
|
||||
import eu.eudat.logic.managers.DatasetManager;
|
||||
import eu.eudat.logic.utilities.builders.XmlBuilder;
|
||||
import eu.eudat.models.data.security.Principal;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -149,7 +150,7 @@ public class DatasetRDAExportModel {
|
|||
}
|
||||
|
||||
|
||||
public DatasetRDAExportModel fromDataModel(Dataset dataset, DatasetManager datasetManager) {
|
||||
public DatasetRDAExportModel fromDataModel(Dataset dataset, DatasetManager datasetManager, Principal principal) {
|
||||
// Map of template Ids to rda values.
|
||||
JSONObject jObject = new JSONObject(dataset.getProperties());
|
||||
Map<String, Object> templateIdsToValues = jObject.toMap();
|
||||
|
@ -165,7 +166,7 @@ public class DatasetRDAExportModel {
|
|||
// Transform the answered dataset description to json so we can parse it and fill the rda model.
|
||||
JSONObject datasetDescriptionJson = null;
|
||||
try {
|
||||
String jsonResult = mapper.writeValueAsString(datasetManager.getSingle(dataset.getId().toString()).getDatasetProfileDefinition());
|
||||
String jsonResult = mapper.writeValueAsString(datasetManager.getSingle(dataset.getId().toString(), principal).getDatasetProfileDefinition());
|
||||
datasetDescriptionJson = new JSONObject(jsonResult);
|
||||
} catch (JsonProcessingException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
|
|
|
@ -5,6 +5,7 @@ import eu.eudat.data.entities.Dataset;
|
|||
import eu.eudat.data.entities.UserDMP;
|
||||
import eu.eudat.data.entities.UserInfo;
|
||||
import eu.eudat.logic.managers.DatasetManager;
|
||||
import eu.eudat.models.data.security.Principal;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
@ -127,7 +128,7 @@ public class DmpRDAExportModel {
|
|||
this.title = title;
|
||||
}
|
||||
|
||||
public DmpRDAExportModel fromDataModel(DMP entity, DatasetManager datasetManager) {
|
||||
public DmpRDAExportModel fromDataModel(DMP entity, DatasetManager datasetManager, Principal principal) {
|
||||
DmpRDAExportModel dmpRda = new DmpRDAExportModel();
|
||||
dmpRda.contact = new ContactRDAExportModel().fromDataModel(entity.getUsers().stream().filter(x -> x.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())).findFirst().get().getUser());
|
||||
if (entity.getUsers().stream().anyMatch(x -> x.getRole().equals(UserDMP.UserDMPRoles.USER.getValue()))) {
|
||||
|
@ -142,7 +143,7 @@ public class DmpRDAExportModel {
|
|||
dmpRda.dataset = new LinkedList<>();
|
||||
for (Dataset dataset : entity.getDataset()) {
|
||||
if (dataset.getStatus() != Dataset.Status.DELETED.getValue() && dataset.getStatus() != Dataset.Status.CANCELED.getValue())
|
||||
dmpRda.dataset.add(new DatasetRDAExportModel().fromDataModel(dataset, datasetManager));
|
||||
dmpRda.dataset.add(new DatasetRDAExportModel().fromDataModel(dataset, datasetManager, principal));
|
||||
}
|
||||
dmpRda.description = entity.getDescription().replace("\n", " ");
|
||||
if (entity.getDoi() != null) {
|
||||
|
|
|
@ -3,6 +3,7 @@ package eu.eudat.models.data.rda;
|
|||
import eu.eudat.data.entities.DMP;
|
||||
import eu.eudat.data.entities.Dataset;
|
||||
import eu.eudat.logic.managers.DatasetManager;
|
||||
import eu.eudat.models.data.security.Principal;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
@ -17,8 +18,8 @@ public class RDAExportModel {
|
|||
this.dmp = dmp;
|
||||
}
|
||||
|
||||
public RDAExportModel fromDataModel(DMP dmp, DatasetManager datasetManager) {
|
||||
this.dmp = new DmpRDAExportModel().fromDataModel(dmp, datasetManager);
|
||||
public RDAExportModel fromDataModel(DMP dmp, DatasetManager datasetManager, Principal principal) {
|
||||
this.dmp = new DmpRDAExportModel().fromDataModel(dmp, datasetManager, principal);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,8 +162,17 @@ export class DatasetWizardComponent extends BaseComponent implements OnInit, IBr
|
|||
})
|
||||
},
|
||||
error => {
|
||||
this.uiNotificationService.snackBarNotification(this.language.instant('DATASET-WIZARD.MESSAGES.DATASET-NOT-FOUND'), SnackBarNotificationLevel.Error);
|
||||
this.router.navigate(['/datasets/edit/' + this.itemId]);
|
||||
switch (error.status) {
|
||||
case 403:
|
||||
this.uiNotificationService.snackBarNotification(this.language.instant('DATASET-WIZARD.MESSAGES.DATASET-NOT-ALLOWED'), SnackBarNotificationLevel.Error);
|
||||
break;
|
||||
case 404:
|
||||
this.uiNotificationService.snackBarNotification(this.language.instant('DATASET-WIZARD.MESSAGES.DATASET-NOT-FOUND'), SnackBarNotificationLevel.Error);
|
||||
break;
|
||||
default:
|
||||
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.ERRORS.HTTP-REQUEST-ERROR'), SnackBarNotificationLevel.Error);
|
||||
}
|
||||
this.router.navigate(['/datasets/']);
|
||||
return observableOf(null);
|
||||
});
|
||||
} else if (dmpId != null) {
|
||||
|
|
|
@ -74,6 +74,9 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
|
|||
if (error.status === 404) {
|
||||
return this.onFetchingDeletedCallbackError('/plans/');
|
||||
}
|
||||
if (error.status === 403) {
|
||||
return this.onFetchingForbiddenCallbackError('/plans/');
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (publicId != null) {
|
||||
|
@ -93,6 +96,9 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
|
|||
if (error.status === 404) {
|
||||
return this.onFetchingDeletedCallbackError('/plans/');
|
||||
}
|
||||
if (error.status === 403) {
|
||||
return this.onFetchingForbiddenCallbackError('/plans/');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -103,6 +109,11 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
|
|||
this.router.navigate([redirectRoot]);
|
||||
}
|
||||
|
||||
onFetchingForbiddenCallbackError(redirectRoot: string) {
|
||||
this.uiNotificationService.snackBarNotification(this.language.instant('DMP-OVERVIEW.ERROR.FORBIDEN-DMP'), SnackBarNotificationLevel.Error);
|
||||
this.router.navigate([redirectRoot]);
|
||||
}
|
||||
|
||||
setIsUserOwner() {
|
||||
if (this.dmp) {
|
||||
const principal: Principal = this.authentication.current();
|
||||
|
|
|
@ -491,6 +491,7 @@
|
|||
},
|
||||
"MESSAGES": {
|
||||
"DATASET-NOT-FOUND": "Dataset Description does not exist",
|
||||
"DATASET-NOT-ALLOWED": "You have no access to this Dataset Description",
|
||||
"SUCCESS-UPDATE-DATASET-PROFILE": "Dataset Description Template updated successfully"
|
||||
},
|
||||
"UPLOAD": {
|
||||
|
@ -519,7 +520,8 @@
|
|||
"TEMPLATES-INVOLVED": "Dataset Description Templates Involved"
|
||||
},
|
||||
"ERROR": {
|
||||
"DELETED-DMP": "The requested DMP is deleted"
|
||||
"DELETED-DMP": "The requested DMP is deleted",
|
||||
"FORBIDEN-DMP": "You are not allowed to access this DMP"
|
||||
}
|
||||
},
|
||||
"DATASET-LISTING": {
|
||||
|
|
|
@ -489,6 +489,7 @@
|
|||
},
|
||||
"MESSAGES": {
|
||||
"DATASET-NOT-FOUND": "No existe la descripción del Dataset",
|
||||
"DATASET-NOT-ALLOWED": "You have no access to this Dataset Description",
|
||||
"SUCCESS-UPDATE-DATASET-PROFILE": "Plantilla de descripción del Dataset actualizada correctamente"
|
||||
},
|
||||
"UPLOAD": {
|
||||
|
@ -517,7 +518,8 @@
|
|||
"TEMPLATES-INVOLVED": "Plantillas de descripción del Dataset implicadas"
|
||||
},
|
||||
"ERROR": {
|
||||
"DELETED-DMP": "El PGD solicitado está borrado"
|
||||
"DELETED-DMP": "El PGD solicitado está borrado",
|
||||
"FORBIDEN-DMP": "You are not allowed to access this DMP"
|
||||
}
|
||||
},
|
||||
"DATASET-LISTING": {
|
||||
|
|
Loading…
Reference in New Issue