Skip to content
Snippets Groups Projects
Commit a8294209 authored by Martin Weise's avatar Martin Weise
Browse files

Merge branch '401-getting-a-pid-fails-with-invalid-publication-date' into 'dev'

Added date validation for identifier publication date

See merge request !234
parents 25410932 c0b61ebd
Branches
Tags
5 merge requests!250Master,!246Dev,!244Dev,!243Dev,!234Added date validation for identifier publication date
......@@ -63,7 +63,8 @@
<mapstruct.version>1.5.5.Final</mapstruct.version>
<rabbitmq.version>5.20.0</rabbitmq.version>
<jackson-datatype.version>2.15.0</jackson-datatype.version>
<commons.version>2.11.0</commons.version>
<commons-io.version>2.15.0</commons-io.version>
<commons-validator.version>1.8.0</commons-validator.version>
<guava.version>33.0.0-jre</guava.version>
<jacoco.version>0.8.11</jacoco.version>
<jwt.version>4.3.0</jwt.version>
......@@ -238,7 +239,12 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.version}</version>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>${commons-validator.version}</version>
</dependency>
<!-- AMPQ -->
<dependency>
......
......@@ -37,6 +37,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.security.Principal;
import java.time.Instant;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
......@@ -163,6 +164,12 @@ public class IdentifierEndpoint {
QueryStoreException, QueryNotFoundException, ImageNotSupportedException, UserNotFoundException,
DatabaseConnectionException, RemoteUnavailableException {
log.debug("endpoint create identifier, data={}, {}", data, PrincipalUtil.formatForDebug(principal));
/* check data */
if (!endpointValidator.validatePublicationDate(data)) {
log.error("Failed to create identifier: publication date is invalid");
throw new IdentifierRequestException("Failed to create identifier: publication date is invalid");
}
/* check access */
DatabaseAccess access = null;
try {
access = accessService.find(data.getDatabaseId(), UserUtil.getId(principal));
......@@ -172,6 +179,7 @@ public class IdentifierEndpoint {
throw new NotAllowedException("Failed to create identifier: insufficient role");
}
}
/* create identifier */
final Database database = databaseService.find(data.getDatabaseId());
switch (data.getType()) {
case VIEW -> {
......
......@@ -5,19 +5,19 @@ import at.tuwien.api.database.query.ExecuteStatementDto;
import at.tuwien.api.database.table.TableCreateDto;
import at.tuwien.api.database.table.columns.ColumnCreateDto;
import at.tuwien.api.database.table.columns.ColumnTypeDto;
import at.tuwien.api.identifier.IdentifierSaveDto;
import at.tuwien.config.QueryConfig;
import at.tuwien.entities.database.AccessType;
import at.tuwien.entities.database.Database;
import at.tuwien.entities.database.DatabaseAccess;
import at.tuwien.entities.database.table.Table;
import at.tuwien.entities.user.User;
import at.tuwien.exception.*;
import at.tuwien.repository.mdb.IdentifierRepository;
import at.tuwien.service.AccessService;
import at.tuwien.service.DatabaseService;
import at.tuwien.service.TableService;
import at.tuwien.utils.UserUtil;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.validator.GenericValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
......@@ -321,4 +321,34 @@ public class EndpointValidator {
throw new NotAllowedException("Access not allowed: no write access for table with id " + tableId);
}
/**
* Precondition: identifier.getPublicationYear() is not null
*
* @param identifier The identifier that will be created.
* @return True if the publication date is valid, false otherwise.
*/
public boolean validatePublicationDate(IdentifierSaveDto identifier) {
if (identifier.getPublicationMonth() != null && (identifier.getPublicationMonth() < 1 || identifier.getPublicationMonth() > 12)) {
log.trace("publication month {} needs to fulfill: 1 >= publicationMonth <= 12", identifier.getPublicationMonth());
return false;
}
if (identifier.getPublicationDay() != null && (identifier.getPublicationDay() < 1 || identifier.getPublicationDay() > 31)) {
log.trace("publication day {} needs to fulfill: 1 >= publicationDay <= 31", identifier.getPublicationDay());
return false;
}
if (identifier.getPublicationMonth() != null && identifier.getPublicationDay() != null) {
final String paddedMonth = identifier.getPublicationMonth() < 9 ? "0" + identifier.getPublicationMonth() : "" + identifier.getPublicationMonth();
final boolean result = GenericValidator.isDate(identifier.getPublicationYear() + "-" + paddedMonth + "-"
+ identifier.getPublicationDay(), "yyyy-MM-dd", true);
if (!result) {
log.trace("publication date {}-{}-{} needs to be valid", identifier.getPublicationYear(), paddedMonth,
identifier.getPublicationDay());
return false;
}
return true;
}
log.trace("publication date is valid");
return true;
}
}
......@@ -7,6 +7,7 @@ import at.tuwien.annotations.MockOpensearch;
import at.tuwien.api.database.table.TableCreateDto;
import at.tuwien.api.database.table.columns.ColumnCreateDto;
import at.tuwien.api.database.table.columns.ColumnTypeDto;
import at.tuwien.api.identifier.IdentifierSaveDto;
import at.tuwien.entities.database.table.Table;
import at.tuwien.exception.*;
import at.tuwien.repository.mdb.IdentifierRepository;
......@@ -29,7 +30,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.util.List;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.when;
......@@ -46,9 +47,6 @@ public class EndpointValidatorUnitTest extends BaseUnitTest {
@MockBean
private AccessService accessService;
@MockBean
private IdentifierRepository identifierRepository;
@MockBean
private TableService tableService;
......@@ -463,4 +461,136 @@ public class EndpointValidatorUnitTest extends BaseUnitTest {
});
}
@Test
public void validatePublicationDate_succeeds() {
final IdentifierSaveDto request = IdentifierSaveDto.builder()
.publicationYear(2024)
.publicationMonth(1)
.publicationDay(25)
.build();
/* test */
assertTrue(endpointValidator.validatePublicationDate(request));
}
@Test
public void validatePublicationDate_missingDay_succeeds() {
final IdentifierSaveDto request = IdentifierSaveDto.builder()
.publicationYear(2024)
.publicationMonth(1)
.build();
/* test */
assertTrue(endpointValidator.validatePublicationDate(request));
}
@Test
public void validatePublicationDate_missingMonth_succeeds() {
final IdentifierSaveDto request = IdentifierSaveDto.builder()
.publicationYear(2024)
.publicationDay(1)
.build();
/* test */
assertTrue(endpointValidator.validatePublicationDate(request));
}
@Test
public void validatePublicationDate_missingDayMonth_succeeds() {
final IdentifierSaveDto request = IdentifierSaveDto.builder()
.publicationYear(2024)
.build();
/* test */
assertTrue(endpointValidator.validatePublicationDate(request));
}
@Test
public void validatePublicationDate_yearEarly_succeeds() {
final IdentifierSaveDto request = IdentifierSaveDto.builder()
.publicationYear(1300)
.build();
/* test */
assertTrue(endpointValidator.validatePublicationDate(request));
}
@Test
public void validatePublicationDate_yearLate_succeeds() {
final IdentifierSaveDto request = IdentifierSaveDto.builder()
.publicationYear(12345)
.build();
/* test */
assertTrue(endpointValidator.validatePublicationDate(request));
}
@Test
public void validatePublicationDate_monthInvalid1_fails() {
final IdentifierSaveDto request = IdentifierSaveDto.builder()
.publicationYear(2024)
.publicationMonth(0)
.build();
/* test */
assertFalse(endpointValidator.validatePublicationDate(request));
}
@Test
public void validatePublicationDate_monthInvalid2_fails() {
final IdentifierSaveDto request = IdentifierSaveDto.builder()
.publicationYear(2024)
.publicationMonth(13)
.build();
/* test */
assertFalse(endpointValidator.validatePublicationDate(request));
}
@Test
public void validatePublicationDate_dayInvalid1_fails() {
final IdentifierSaveDto request = IdentifierSaveDto.builder()
.publicationYear(2024)
.publicationDay(0)
.build();
/* test */
assertFalse(endpointValidator.validatePublicationDate(request));
}
@Test
public void validatePublicationDate_dayInvalid2_fails() {
final IdentifierSaveDto request = IdentifierSaveDto.builder()
.publicationYear(2024)
.publicationDay(32)
.build();
/* test */
assertFalse(endpointValidator.validatePublicationDate(request));
}
@Test
public void validatePublicationDate_february29Invalid_fails() {
final IdentifierSaveDto request = IdentifierSaveDto.builder()
.publicationYear(2023)
.publicationMonth(2)
.publicationDay(29)
.build();
/* test */
assertFalse(endpointValidator.validatePublicationDate(request));
}
@Test
public void validatePublicationDate_february29_succeeds() {
final IdentifierSaveDto request = IdentifierSaveDto.builder()
.publicationYear(2024)
.publicationMonth(2)
.publicationDay(29)
.build();
/* test */
assertTrue(endpointValidator.validatePublicationDate(request));
}
}
......@@ -17,6 +17,7 @@ spring.jpa.hibernate.ddl-auto=create
# logging
logging.level.root=error
logging.level.at.tuwien.=debug
logging.level.at.tuwien.validation.=trace
# rabbitmq
spring.rabbitmq.host=localhost
......
......@@ -13,7 +13,7 @@
v-if="!isUpdate"
class="mb-1"
:loading="loading"
:disabled="!formValid || loading"
:disabled="!formValid || !validPublicationMonth || !validPublicationDay || loading"
color="primary"
@click="save">
<v-icon left>mdi-content-save-outline</v-icon> Create PID
......@@ -286,6 +286,7 @@
v-model.number="identifier.publication_day"
type="number"
label="Publication day"
:rules="[validPublicationDay || $t('Invalid day')]"
clearable />
</v-col>
<v-col cols="2">
......@@ -294,6 +295,7 @@
v-model.number="identifier.publication_month"
type="number"
label="Publication month"
:rules="[validPublicationMonth || $t('Invalid month')]"
clearable />
</v-col>
<v-col cols="2">
......@@ -649,6 +651,20 @@ export default {
return 'Table'
}
return ''
},
validPublicationDay () {
const day = this.identifier.publication_day
if (day === null) {
return true
}
return day >= 1 && day <= 31
},
validPublicationMonth () {
const month = this.identifier.publication_month
if (month === null) {
return true
}
return month >= 1 && month <= 12
}
},
watch: {
......
......@@ -97,7 +97,7 @@ import IsniIcon from '@/components/icons/IsniIcon.vue'
import OrcidIcon from '@/components/icons/OrcidIcon.vue'
import RorIcon from '@/components/icons/RorIcon.vue'
import Banner from '@/components/identifier/Banner.vue'
import { formatDateUTC, formatLanguage } from '@/utils'
import { formatLanguage } from '@/utils'
export default {
components: {
......@@ -167,7 +167,9 @@ export default {
if (this.identifier.publication_year && !this.identifier.publication_month && !this.identifier.publication_day) {
return this.identifier.publication_year
} else if (this.identifier.publication_year && this.identifier.publication_month && this.identifier.publication_day) {
return formatDateUTC(this.identifier.publication_year + '-' + this.identifier.publication_month + '-' + this.identifier.publication_day)
const month = this.identifier.publication_month
const day = this.identifier.publication_day
return `${this.identifier.publication_year}-${month < 9 ? '0' + month : month}-${day < 9 ? '0' + day : day}`
} else {
return null
}
......
{
"title": "Database Repository",
"version": "1.4.0",
"version": "1.4.1",
"ssl": {
"force": false
},
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment