diff --git a/commons/commons-util/src/main/kotlin/ebi/ac/uk/util/date/Instant.kt b/commons/commons-util/src/main/kotlin/ebi/ac/uk/util/date/Instant.kt index b686e01e0..26ad6a8c2 100644 --- a/commons/commons-util/src/main/kotlin/ebi/ac/uk/util/date/Instant.kt +++ b/commons/commons-util/src/main/kotlin/ebi/ac/uk/util/date/Instant.kt @@ -7,4 +7,6 @@ import java.time.temporal.ChronoUnit.DAYS fun Instant.asOffsetAtStartOfDay(): OffsetDateTime = atOffset(UTC).toLocalDate().atStartOfDay().atOffset(UTC) +fun OffsetDateTime.atStartOfDay(): OffsetDateTime = toInstant().asOffsetAtStartOfDay() + fun Instant.asOffsetAtEndOfDay(): OffsetDateTime = plus(1, DAYS).atOffset(UTC).toLocalDate().atStartOfDay().minusSeconds(1).atOffset(UTC) diff --git a/submission/submission-core/src/main/kotlin/ac/uk/ebi/biostd/submission/exceptions/InvalidPermissionsException.kt b/submission/submission-core/src/main/kotlin/ac/uk/ebi/biostd/submission/exceptions/InvalidPermissionsException.kt index 09b4401b6..2b9518012 100644 --- a/submission/submission-core/src/main/kotlin/ac/uk/ebi/biostd/submission/exceptions/InvalidPermissionsException.kt +++ b/submission/submission-core/src/main/kotlin/ac/uk/ebi/biostd/submission/exceptions/InvalidPermissionsException.kt @@ -7,12 +7,12 @@ sealed class InvalidPermissionsException(message: String) : RuntimeException(mes class UserCanNotProvideAccessNumber( user: String, -) : InvalidPermissionsException("The user {$user} is not allowed to provide accession number directly") +) : InvalidPermissionsException("The user $user is not allowed to provide accession number directly") class UserCanNotUpdateSubmit( accNo: String, user: String, -) : InvalidPermissionsException("The user {$user} is not allowed to update the submission $accNo") +) : InvalidPermissionsException("The user $user is not allowed to update the submission $accNo") class UserCanNotSubmitCollectionsException( user: String, diff --git a/submission/submission-core/src/main/kotlin/ac/uk/ebi/biostd/submission/exceptions/InvalidPublicSubmissionException.kt b/submission/submission-core/src/main/kotlin/ac/uk/ebi/biostd/submission/exceptions/InvalidPublicSubmissionException.kt index 43647a438..d6fd61b3e 100644 --- a/submission/submission-core/src/main/kotlin/ac/uk/ebi/biostd/submission/exceptions/InvalidPublicSubmissionException.kt +++ b/submission/submission-core/src/main/kotlin/ac/uk/ebi/biostd/submission/exceptions/InvalidPublicSubmissionException.kt @@ -2,6 +2,6 @@ package ac.uk.ebi.biostd.submission.exceptions class PastReleaseDateException : RuntimeException("Release date cannot be in the past") -class InvalidReleaseDateException : RuntimeException("The release date of a public study cannot be changed") +class InvalidReleaseException : RuntimeException("The release date of a public study cannot be changed") class UnreleasedSubmissionException : RuntimeException("Can't generate FTP links for a private submission") diff --git a/submission/submission-core/src/main/kotlin/ac/uk/ebi/biostd/submission/service/TimesService.kt b/submission/submission-core/src/main/kotlin/ac/uk/ebi/biostd/submission/service/TimesService.kt index 0b5ffcb4c..c30634cc0 100644 --- a/submission/submission-core/src/main/kotlin/ac/uk/ebi/biostd/submission/service/TimesService.kt +++ b/submission/submission-core/src/main/kotlin/ac/uk/ebi/biostd/submission/service/TimesService.kt @@ -1,13 +1,13 @@ package ac.uk.ebi.biostd.submission.service import ac.uk.ebi.biostd.submission.exceptions.InvalidDateFormatException -import ac.uk.ebi.biostd.submission.exceptions.InvalidReleaseDateException +import ac.uk.ebi.biostd.submission.exceptions.InvalidReleaseException import ac.uk.ebi.biostd.submission.exceptions.PastReleaseDateException import ac.uk.ebi.biostd.submission.model.SubmitRequest import ebi.ac.uk.base.orFalse import ebi.ac.uk.model.extensions.releaseDate import ebi.ac.uk.security.integration.components.IUserPrivilegesService -import ebi.ac.uk.util.date.asOffsetAtStartOfDay +import ebi.ac.uk.util.date.atStartOfDay import ebi.ac.uk.util.date.isBeforeOrEqual import java.time.Instant import java.time.LocalDate @@ -19,46 +19,30 @@ import java.time.ZoneOffset.UTC * Calculates the submission release date based on current state of the submission in the system. Calculation rules. */ class TimesService( - private val privilegesService: IUserPrivilegesService, + private val privileges: IUserPrivilegesService, ) { - internal fun getTimes(request: SubmitRequest): Times { + internal fun getTimes(rqt: SubmitRequest): Times { val now = OffsetDateTime.now() - val creationTime = request.previousVersion?.creationTime ?: now - val releaseTime = request.submission.releaseDate?.let { releaseTime(now, it, request) } + val creationTime = rqt.previousVersion?.creationTime ?: now + val releaseTime = rqt.submission.releaseDate?.let { parseDate(it) } val released = releaseTime?.isBeforeOrEqual(now).orFalse() + val submitter = rqt.submitter.email + if (releaseTime != null && privileges.canUpdateReleaseDate(submitter).not()) checkReleaseTime(rqt, releaseTime) return Times(creationTime, now, releaseTime, released) } - private fun releaseTime( - now: OffsetDateTime, - releaseDate: String, - request: SubmitRequest, - ): OffsetDateTime { - val releaseTime = parseDate(releaseDate) - val user = request.submitter.email - val today = now.toInstant().asOffsetAtStartOfDay() - val isReleased = request.previousVersion?.released.orFalse() - val previousReleaseTime = request.previousVersion?.releaseTime?.toInstant()?.asOffsetAtStartOfDay() - - fun checkFutureReleaseTime() = - when { - isReleased && privilegesService.canSuppress(user).not() -> throw InvalidReleaseDateException() - else -> releaseTime - } - - fun checkPastReleaseTime() = - when { - isReleased -> throw InvalidReleaseDateException() - previousReleaseTime == null -> throw PastReleaseDateException() - else -> releaseTime - } - - return when { - previousReleaseTime?.isEqual(releaseTime).orFalse() -> releaseTime - releaseTime.isAfter(today) -> checkFutureReleaseTime() - releaseTime.isBefore(today) -> checkPastReleaseTime() - else -> releaseTime + @Suppress("ThrowsCount") + private fun checkReleaseTime( + rqt: SubmitRequest, + releaseTime: OffsetDateTime, + ) { + val today = OffsetDateTime.now().atStartOfDay() + + when (val previous = rqt.previousVersion) { + null -> if (releaseTime < today) throw PastReleaseDateException() + else -> + if (previous.released && releaseTime != previous.releaseTime) throw InvalidReleaseException() } } diff --git a/submission/submission-core/src/test/kotlin/ac/uk/ebi/biostd/submission/service/AccNoServiceTest.kt b/submission/submission-core/src/test/kotlin/ac/uk/ebi/biostd/submission/service/AccNoServiceTest.kt index 990f5f741..7ab4a3888 100644 --- a/submission/submission-core/src/test/kotlin/ac/uk/ebi/biostd/submission/service/AccNoServiceTest.kt +++ b/submission/submission-core/src/test/kotlin/ac/uk/ebi/biostd/submission/service/AccNoServiceTest.kt @@ -79,7 +79,7 @@ class AccNoServiceTest( val error = assertThrows { testInstance.calculateAccNo(request) } assertThat(error.message) - .isEqualTo("The user {submiter@email.com} is not allowed to provide accession number directly") + .isEqualTo("The user submiter@email.com is not allowed to provide accession number directly") } @Test @@ -155,7 +155,7 @@ class AccNoServiceTest( val error = assertThrows { testInstance.calculateAccNo(request) } assertThat(error.message) - .isEqualTo("The user {$SUBMITTER} is not allowed to update the submission $ACC_NO") + .isEqualTo("The user $SUBMITTER is not allowed to update the submission $ACC_NO") } @Test @@ -188,7 +188,7 @@ class AccNoServiceTest( val error = assertThrows { testInstance.calculateAccNo(request) } assertThat(error.message).isEqualTo( - "The user {submiter@email.com} is not allowed to update the submission AAB12", + "The user submiter@email.com is not allowed to update the submission AAB12", ) } } diff --git a/submission/submission-core/src/test/kotlin/ac/uk/ebi/biostd/submission/service/TimesServiceTest.kt b/submission/submission-core/src/test/kotlin/ac/uk/ebi/biostd/submission/service/TimesServiceTest.kt deleted file mode 100644 index cf0285bd7..000000000 --- a/submission/submission-core/src/test/kotlin/ac/uk/ebi/biostd/submission/service/TimesServiceTest.kt +++ /dev/null @@ -1,173 +0,0 @@ -package ac.uk.ebi.biostd.submission.service - -import ac.uk.ebi.biostd.submission.exceptions.InvalidDateFormatException -import ac.uk.ebi.biostd.submission.exceptions.InvalidReleaseDateException -import ac.uk.ebi.biostd.submission.exceptions.PastReleaseDateException -import ac.uk.ebi.biostd.submission.model.SubmitRequest -import ebi.ac.uk.model.extensions.releaseDate -import ebi.ac.uk.security.integration.components.IUserPrivilegesService -import io.mockk.clearAllMocks -import io.mockk.every -import io.mockk.impl.annotations.MockK -import io.mockk.junit5.MockKExtension -import io.mockk.mockkStatic -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Nested -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertThrows -import org.junit.jupiter.api.extension.ExtendWith -import java.time.OffsetDateTime -import java.time.ZoneOffset.UTC - -@ExtendWith(MockKExtension::class) -class TimesServiceTest( - @MockK private val request: SubmitRequest, - @MockK private val privilegesService: IUserPrivilegesService, -) { - private val testInstance = TimesService(privilegesService) - private val testTime = OffsetDateTime.of(2018, 10, 10, 0, 0, 0, 0, UTC) - private val mockNow = OffsetDateTime.of(2018, 12, 31, 0, 0, 0, 0, UTC) - - @BeforeEach - fun beforeEach() { - mockkStatic(OffsetDateTime::class) - every { OffsetDateTime.now() } returns mockNow - every { request.previousVersion } returns null - every { request.submission.releaseDate } returns null - } - - @AfterEach - fun afterEach() = clearAllMocks() - - @Nested - inner class ModificationTime { - @Test - fun `calculate modification time`() { - val times = testInstance.getTimes(request) - assertThat(times.modificationTime).isEqualTo(mockNow) - } - } - - @Nested - inner class CreationTime { - @Test - fun `when exists`() { - every { request.previousVersion?.creationTime } returns testTime - - val times = testInstance.getTimes(request) - assertThat(times.createTime).isEqualTo(testTime) - } - - @Test - fun `when is new`() { - val times = testInstance.getTimes(request) - assertThat(times.createTime).isEqualTo(mockNow) - } - } - - @Nested - inner class ReleaseTime { - private val previousReleaseTime = OffsetDateTime.of(2016, 10, 10, 0, 0, 0, 0, UTC) - - @BeforeEach - fun beforeEach() { - every { request.accNo } returns "S-BSST1" - every { request.submitter.email } returns "user@test.org" - every { request.previousVersion?.released } returns true - every { privilegesService.canSuppress("user@test.org") } returns false - every { request.previousVersion?.releaseTime } returns previousReleaseTime - every { request.previousVersion?.creationTime } returns previousReleaseTime - } - - @Test - fun `when release date has invalid format`() { - every { request.submission.releaseDate } returns "2018/10/10" - - val exception = assertThrows { testInstance.getTimes(request) } - assertThat(exception.message).isEqualTo( - "Provided date 2018/10/10 could not be parsed. Expected format is YYYY-MM-DD", - ) - } - - @Test - fun `when no release date`() { - val times = testInstance.getTimes(request) - assertThat(times.released).isFalse() - assertThat(times.releaseTime).isNull() - } - - @Test - fun `when release date is in the past`() { - every { request.previousVersion } returns null - every { request.submission.releaseDate } returns "2016-10-10T09:27:04.000Z" - - val error = assertThrows { testInstance.getTimes(request) } - assertThat(error.message).isEqualTo("Release date cannot be in the past") - } - - @Test - fun `when updating existing submission`() { - every { request.submission.releaseDate } returns "2016-10-10T21:16:36.000Z" - - val times = testInstance.getTimes(request) - assertThat(times.released).isTrue() - assertThat(times.releaseTime).isEqualTo(previousReleaseTime) - } - - @Test - fun `when publishing private submission`() { - every { request.previousVersion?.released } returns false - every { request.submission.releaseDate } returns "2018-12-31T09:27:04.000Z" - - val times = testInstance.getTimes(request) - assertThat(times.released).isTrue() - assertThat(times.releaseTime).isEqualTo(mockNow) - } - - @Test - fun `when updating private submission release date`() { - val releaseTime = OffsetDateTime.of(2019, 10, 10, 0, 0, 0, 0, UTC) - val previousReleaseTime = OffsetDateTime.of(2020, 10, 10, 0, 0, 0, 0, UTC) - - every { request.previousVersion?.released } returns false - every { request.previousVersion?.releaseTime } returns previousReleaseTime - every { request.submission.releaseDate } returns "2019-10-10T09:27:04.000Z" - - val times = testInstance.getTimes(request) - assertThat(times.released).isFalse() - assertThat(times.releaseTime).isEqualTo(releaseTime) - } - - @Test - fun `when updating public submission release date`() { - every { request.submission.releaseDate } returns "2015-10-10T21:16:36.000Z" - - val error = assertThrows { testInstance.getTimes(request) } - assertThat(error.message).isEqualTo("The release date of a public study cannot be changed") - } - - @Test - fun `when submitter cant suppress`() { - every { request.previousVersion?.released } returns true - every { request.submission.releaseDate } returns "2020-10-10T09:27:04.000Z" - - val error = assertThrows { testInstance.getTimes(request) } - assertThat(error.message).isEqualTo("The release date of a public study cannot be changed") - } - - @Test - fun `when submitter can suppress`() { - val releaseTime = OffsetDateTime.of(2020, 10, 10, 0, 0, 0, 0, UTC) - - every { request.previousVersion?.released } returns true - every { privilegesService.canSuppress("user@test.org") } returns true - every { request.submission.releaseDate } returns "2020-10-10T09:27:04.000Z" - - val times = testInstance.getTimes(request) - assertThat(times.released).isFalse() - assertThat(times.releaseTime).isEqualTo(releaseTime) - } - } -} diff --git a/submission/submission-security/src/main/kotlin/ebi/ac/uk/security/integration/components/IUserPrivilegesService.kt b/submission/submission-security/src/main/kotlin/ebi/ac/uk/security/integration/components/IUserPrivilegesService.kt index 4678653d2..802a9b629 100644 --- a/submission/submission-security/src/main/kotlin/ebi/ac/uk/security/integration/components/IUserPrivilegesService.kt +++ b/submission/submission-security/src/main/kotlin/ebi/ac/uk/security/integration/components/IUserPrivilegesService.kt @@ -31,5 +31,9 @@ interface IUserPrivilegesService { fun canRelease(email: String): Boolean - fun canSuppress(email: String): Boolean + /** + * Permission to indicate the given user is able to release in the past, make a submission private or change a + * public study release date. + */ + fun canUpdateReleaseDate(email: String): Boolean } diff --git a/submission/submission-security/src/main/kotlin/ebi/ac/uk/security/service/UserPrivilegesService.kt b/submission/submission-security/src/main/kotlin/ebi/ac/uk/security/service/UserPrivilegesService.kt index 1151a3ad8..8e05a6704 100644 --- a/submission/submission-security/src/main/kotlin/ebi/ac/uk/security/service/UserPrivilegesService.kt +++ b/submission/submission-security/src/main/kotlin/ebi/ac/uk/security/service/UserPrivilegesService.kt @@ -17,7 +17,7 @@ internal class UserPrivilegesService( private val userRepository: UserDataRepository, private val tagsDataRepository: AccessTagDataRepo, private val submissionQueryService: SubmissionMetaQueryService, - private val userPermissionsService: UserPermissionsService, + private val permissionsService: UserPermissionsService, ) : IUserPrivilegesService { override fun canProvideAccNo(email: String) = isSuperUser(email) @@ -41,7 +41,7 @@ internal class UserPrivilegesService( when { isSuperUser(email) -> tagsDataRepository.findAll().map { it.name } else -> - userPermissionsService + permissionsService .allowedTags(email, accessType) .map { it.accessTag.name } .distinct() @@ -67,7 +67,7 @@ internal class UserPrivilegesService( override fun canRelease(email: String): Boolean = isSuperUser(email) - override fun canSuppress(email: String): Boolean = isSuperUser(email) + override fun canUpdateReleaseDate(email: String): Boolean = isSuperUser(email) private suspend fun hasPermissions( user: String, @@ -75,8 +75,8 @@ internal class UserPrivilegesService( accessType: AccessType, ): Boolean { val collections = submissionQueryService.getCollections(accNo) - return userPermissionsService.hasPermission(user, accNo, accessType) || - (collections.isNotEmpty() && collections.all { userPermissionsService.hasPermission(user, it, accessType) }) + return permissionsService.hasPermission(user, accNo, accessType) || + (collections.isNotEmpty() && collections.all { permissionsService.hasPermission(user, it, accessType) }) } private fun isSuperUser(email: String) = getUser(email).superuser @@ -86,7 +86,7 @@ internal class UserPrivilegesService( accNo: String, ): Boolean { val collections = submissionQueryService.getCollections(accNo) - return collections.isNotEmpty() && collections.all { userPermissionsService.isAdmin(email, it) } + return collections.isNotEmpty() && collections.all { permissionsService.isAdmin(email, it) } } private fun isAuthor( diff --git a/submission/submission-security/src/test/kotlin/ebi/ac/uk/security/service/UserPrivilegesServiceTest.kt b/submission/submission-security/src/test/kotlin/ebi/ac/uk/security/service/UserPrivilegesServiceTest.kt index b91a2a871..c07178981 100644 --- a/submission/submission-security/src/test/kotlin/ebi/ac/uk/security/service/UserPrivilegesServiceTest.kt +++ b/submission/submission-security/src/test/kotlin/ebi/ac/uk/security/service/UserPrivilegesServiceTest.kt @@ -203,13 +203,13 @@ class UserPrivilegesServiceTest( @Test fun `super user suppress`() { - assertThat(testInstance.canSuppress("superuser@mail.com")).isTrue() + assertThat(testInstance.canUpdateReleaseDate("superuser@mail.com")).isTrue() } @Test fun `regular user suppress`() { every { superuser.superuser } returns false - assertThat(testInstance.canSuppress("superuser@mail.com")).isFalse() + assertThat(testInstance.canUpdateReleaseDate("superuser@mail.com")).isFalse() } private fun initUsers() { diff --git a/submission/submission-security/src/test/kotlin/ebi/ac/uk/security/util/SecurityUtilTest.kt b/submission/submission-security/src/test/kotlin/ebi/ac/uk/security/util/SecurityUtilTest.kt index 44c42a222..179482da0 100644 --- a/submission/submission-security/src/test/kotlin/ebi/ac/uk/security/util/SecurityUtilTest.kt +++ b/submission/submission-security/src/test/kotlin/ebi/ac/uk/security/util/SecurityUtilTest.kt @@ -98,7 +98,7 @@ class SecurityUtilTest( } @Test - fun `check password is set as invalid when normal user security token is used`() { + fun `check password is set as invalid when Regular user security token is used`() { val userToken = testInstance.createToken(simpleUser) every { userRepository.getReferenceById(SecurityTestEntities.USER_ID) } returns simpleUser diff --git a/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/common/SecurityTestService.kt b/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/common/SecurityTestService.kt index a3e86a111..7f283ab37 100644 --- a/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/common/SecurityTestService.kt +++ b/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/common/SecurityTestService.kt @@ -1,6 +1,8 @@ package ac.uk.ebi.biostd.itest.common import ac.uk.ebi.biostd.itest.entities.TestUser +import ac.uk.ebi.biostd.persistence.model.DbSequence +import ac.uk.ebi.biostd.persistence.repositories.SequenceDataRepository import ac.uk.ebi.biostd.persistence.repositories.UserDataRepository import ebi.ac.uk.security.integration.model.api.SecurityUser import ebi.ac.uk.security.service.SecurityService @@ -8,7 +10,16 @@ import ebi.ac.uk.security.service.SecurityService class SecurityTestService( private val securityService: SecurityService, private val userDataRepository: UserDataRepository, + private val sequenceRepository: SequenceDataRepository, ) { + fun ensureSequence(prefix: String) { + if (sequenceRepository.existsByPrefix(prefix).not()) sequenceRepository.save(DbSequence(prefix)) + } + + suspend fun ensureUserRegistration(testUser: TestUser) { + if (userDataRepository.existsByEmail(testUser.email).not()) registerUser(testUser) + } + private suspend fun registerUser(testUser: TestUser): SecurityUser { val user = securityService.registerUser(testUser.asRegisterRequest()) if (testUser.superUser) { @@ -19,8 +30,4 @@ class SecurityTestService( return user } - - suspend fun ensureUserRegistration(testUser: TestUser) { - if (userDataRepository.existsByEmail(testUser.email).not()) registerUser(testUser) - } } diff --git a/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/common/TestConfig.kt b/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/common/TestConfig.kt index 066b8e107..af7d008d1 100644 --- a/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/common/TestConfig.kt +++ b/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/common/TestConfig.kt @@ -1,5 +1,6 @@ package ac.uk.ebi.biostd.itest.common +import ac.uk.ebi.biostd.persistence.repositories.SequenceDataRepository import ac.uk.ebi.biostd.persistence.repositories.UserDataDataRepository import ac.uk.ebi.biostd.persistence.repositories.UserDataRepository import ebi.ac.uk.security.service.SecurityService @@ -11,8 +12,9 @@ class TestConfig { @Bean fun securityTestService( userDataRepository: UserDataRepository, + sequenceDataRepository: SequenceDataRepository, securityService: SecurityService, - ) = SecurityTestService(securityService, userDataRepository) + ) = SecurityTestService(securityService, userDataRepository, sequenceDataRepository) @Bean(name = ["TestCollectionValidator"]) fun testCollectionValidator(): TestCollectionValidator = TestCollectionValidator() diff --git a/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/security/SubmitPermissionTest.kt b/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/security/SubmitPermissionTest.kt index 88576bd50..e1ccfd39e 100644 --- a/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/security/SubmitPermissionTest.kt +++ b/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/security/SubmitPermissionTest.kt @@ -260,7 +260,7 @@ class SubmitPermissionTest( assertThatExceptionOfType(WebClientException::class.java) .isThrownBy { regularUserWebClient.submitSingle(resubmission, SubmissionFormat.TSV) } .withMessageContaining( - "The user {register_user@ebi.ac.uk} is not allowed to update the submission S-SBMT1", + "The user register_user@ebi.ac.uk is not allowed to update the submission S-SBMT1", ) } diff --git a/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/submission/submit/ResubmissionApiTest.kt b/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/submission/submit/ResubmissionApiTest.kt index 25e2c74f1..49d9ae4f5 100644 --- a/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/submission/submit/ResubmissionApiTest.kt +++ b/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/submission/submit/ResubmissionApiTest.kt @@ -1,9 +1,7 @@ package ac.uk.ebi.biostd.itest.test.submission.submit -import ac.uk.ebi.biostd.client.exception.WebClientException import ac.uk.ebi.biostd.client.integration.commons.SubmissionFormat.TSV import ac.uk.ebi.biostd.client.integration.web.BioWebClient -import ac.uk.ebi.biostd.client.integration.web.SecurityWebClient import ac.uk.ebi.biostd.itest.common.SecurityTestService import ac.uk.ebi.biostd.itest.entities.RegularUser import ac.uk.ebi.biostd.itest.entities.SuperUser @@ -28,7 +26,6 @@ import kotlinx.coroutines.reactor.awaitSingleOrNull import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.Assertions.assertThatExceptionOfType import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -212,42 +209,7 @@ class ResubmissionApiTest( } @Test - fun `5-4 regular user suppresses own submission`() { - val version1 = - tsv { - line("Submission", "S-RSTST4") - line("Title", "Public Submission") - line("ReleaseDate", OffsetDateTime.now().toStringDate()) - line() - line("Study") - line() - }.toString() - - val regularUser = RegularUser.email - val onBehalfClient = - SecurityWebClient - .create("http://localhost:$serverPort") - .getAuthenticatedClient(SuperUser.email, SuperUser.password, regularUser) - - assertThat(onBehalfClient.submitSingle(version1, TSV)).isSuccessful() - - val version2 = - tsv { - line("Submission", "S-RSTST4") - line("Title", "Suppressed Submission") - line("ReleaseDate", "2050-05-22") - line() - line("Study") - line() - }.toString() - - assertThatExceptionOfType(WebClientException::class.java) - .isThrownBy { getWebClient(serverPort, RegularUser).submitSingle(version2, TSV) } - .withMessageContaining("The release date of a public study cannot be changed") - } - - @Test - fun `5-5 super user suppresses submission from another user`() = + fun `5-4 Make a public submission private should remove FTP files`() = runTest { val version1 = tsv { @@ -263,14 +225,9 @@ class ResubmissionApiTest( line() }.toString() - val onBehalfClient = - SecurityWebClient - .create("http://localhost:$serverPort") - .getAuthenticatedClient(SuperUser.email, SuperUser.password, RegularUser.email) - webClient.uploadFile(tempFolder.createFile("file_5-5-1.txt", "5-5-1 file content")) webClient.uploadFile(tempFolder.createFile("file_5-5-2.txt", "5-5-2 file content")) - assertThat(onBehalfClient.submitSingle(version1, TSV)).isSuccessful() + assertThat(webClient.submitSingle(version1, TSV)).isSuccessful() val subV1 = submissionRepository.getExtByAccNo("S-RSTST5") val ftpFilesV1 = FileUtils.listAllFiles(File("$ftpPath/${subV1.relPath}/Files")) @@ -295,7 +252,7 @@ class ResubmissionApiTest( line() }.toString() - assertThat(onBehalfClient.submitSingle(version2, TSV)).isSuccessful() + assertThat(webClient.submitSingle(version2, TSV)).isSuccessful() val subV2 = submissionRepository.getExtByAccNo("S-RSTST5") @@ -348,39 +305,4 @@ class ResubmissionApiTest( }.toString() assertThat(webClient.submitSingle(version2, TSV)).isSuccessful() } - - @Test - fun `5-7 change the release date of a public submission`() { - val version1 = - tsv { - line("Submission", "S-RSTST7") - line("Title", "Release date change test") - line("ReleaseDate", OffsetDateTime.now().toStringDate()) - line() - line("Study") - line() - }.toString() - - assertThat(webClient.submitSingle(version1, TSV)).isSuccessful() - - mongoTemplate.updateMulti( - Query(where(SUB_ACC_NO).`in`("S-RSTST7").andOperator(where(SUB_VERSION).gt(0))), - ExtendedUpdate().set(SUB_RELEASE_TIME, OffsetDateTime.of(2018, 10, 10, 0, 0, 0, 0, UTC).toInstant()), - DocSubmission::class.java, - ) - - val version2 = - tsv { - line("Submission", "S-RSTST7") - line("Title", "Release date change test") - line("ReleaseDate", "2019-11-20") - line() - line("Study") - line() - }.toString() - - assertThatExceptionOfType(WebClientException::class.java) - .isThrownBy { webClient.submitSingle(version2, TSV) } - .withMessageContaining("The release date of a public study cannot be changed") - } } diff --git a/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/submission/submit/SpecialSubmissionAttributesTest.kt b/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/submission/submit/SpecialSubmissionAttributesTest.kt index 8471bb174..3373fa5f1 100644 --- a/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/submission/submit/SpecialSubmissionAttributesTest.kt +++ b/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/submission/submit/SpecialSubmissionAttributesTest.kt @@ -1,6 +1,5 @@ package ac.uk.ebi.biostd.itest.test.submission.submit -import ac.uk.ebi.biostd.client.exception.WebClientException import ac.uk.ebi.biostd.client.integration.commons.SubmissionFormat.TSV import ac.uk.ebi.biostd.client.integration.web.BioWebClient import ac.uk.ebi.biostd.itest.common.SecurityTestService @@ -35,7 +34,6 @@ import ebi.ac.uk.util.collections.second import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.Assertions.assertThatExceptionOfType import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -66,21 +64,6 @@ class SpecialSubmissionAttributesTest( tagsRefRepository.save(DbTag(classifier = "classifier", name = "tag")) } - @Test - fun `15-1 new submission with past release date`() { - val submission = - tsv { - line("Submission", "S-RLSD123") - line("Title", "Test Public Submission") - line("ReleaseDate", "2000-01-31") - line() - }.toString() - - assertThatExceptionOfType(WebClientException::class.java) - .isThrownBy { webClient.submitSingle(submission, TSV) } - .withMessageContaining("Release date cannot be in the past") - } - @Test fun `15-2 submission with tags`() = runTest { diff --git a/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/submission/submit/SubmissionApiTest.kt b/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/submission/submit/SubmissionApiTest.kt index 6ac1e7803..6ce814054 100644 --- a/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/submission/submit/SubmissionApiTest.kt +++ b/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/submission/submit/SubmissionApiTest.kt @@ -12,8 +12,6 @@ import ac.uk.ebi.biostd.itest.itest.ITestListener.Companion.submissionPath import ac.uk.ebi.biostd.itest.itest.ITestListener.Companion.tempFolder import ac.uk.ebi.biostd.itest.itest.getWebClient import ac.uk.ebi.biostd.persistence.common.service.SubmissionPersistenceQueryService -import ac.uk.ebi.biostd.persistence.model.DbSequence -import ac.uk.ebi.biostd.persistence.repositories.SequenceDataRepository import ac.uk.ebi.biostd.submission.config.FilePersistenceConfig import ebi.ac.uk.asserts.assertThat import ebi.ac.uk.dsl.file @@ -55,7 +53,6 @@ import kotlin.test.assertFailsWith class SubmissionApiTest( @Autowired val securityTestService: SecurityTestService, @Autowired val submissionRepository: SubmissionPersistenceQueryService, - @Autowired val sequenceRepository: SequenceDataRepository, @Autowired val toSubmissionMapper: ToSubmissionMapper, @LocalServerPort val serverPort: Int, ) { @@ -65,9 +62,9 @@ class SubmissionApiTest( fun init(): Unit = runBlocking { securityTestService.ensureUserRegistration(SuperUser) - webClient = getWebClient(serverPort, SuperUser) + securityTestService.ensureSequence("S-BSST") - sequenceRepository.save(DbSequence("S-BSST")) + webClient = getWebClient(serverPort, SuperUser) } @Test diff --git a/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/submission/submit/SubmissionDatesTest.kt b/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/submission/submit/SubmissionDatesTest.kt new file mode 100644 index 000000000..7a3a33b69 --- /dev/null +++ b/submission/submission-webapp/src/itest/kotlin/ac/uk/ebi/biostd/itest/test/submission/submit/SubmissionDatesTest.kt @@ -0,0 +1,369 @@ +package ac.uk.ebi.biostd.itest.test.submission.submit + +import ac.uk.ebi.biostd.client.exception.WebClientException +import ac.uk.ebi.biostd.client.integration.commons.SubmissionFormat.TSV +import ac.uk.ebi.biostd.client.integration.web.BioWebClient +import ac.uk.ebi.biostd.itest.common.SecurityTestService +import ac.uk.ebi.biostd.itest.entities.DefaultUser +import ac.uk.ebi.biostd.itest.entities.SuperUser +import ac.uk.ebi.biostd.itest.itest.getWebClient +import ac.uk.ebi.biostd.persistence.common.service.SubmissionPersistenceQueryService +import ac.uk.ebi.biostd.submission.config.FilePersistenceConfig +import ebi.ac.uk.asserts.assertThat +import ebi.ac.uk.dsl.tsv.line +import ebi.ac.uk.dsl.tsv.tsv +import ebi.ac.uk.extended.mapping.to.ToSubmissionMapper +import ebi.ac.uk.util.date.toStringDate +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.test.runTest +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatExceptionOfType +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT +import org.springframework.boot.test.web.server.LocalServerPort +import org.springframework.context.annotation.Import +import org.springframework.test.context.junit.jupiter.SpringExtension +import java.time.OffsetDateTime + +@Import(FilePersistenceConfig::class) +@ExtendWith(SpringExtension::class) +@SpringBootTest(webEnvironment = RANDOM_PORT) +class SubmissionDatesTest( + @Autowired val securityTestService: SecurityTestService, + @Autowired val submissionRepository: SubmissionPersistenceQueryService, + @Autowired val toSubmissionMapper: ToSubmissionMapper, + @LocalServerPort val serverPort: Int, +) { + private lateinit var adminWebClient: BioWebClient + private lateinit var userWebClient: BioWebClient + + @BeforeAll + fun init(): Unit = + runBlocking { + securityTestService.ensureUserRegistration(DefaultUser) + securityTestService.ensureUserRegistration(SuperUser) + securityTestService.ensureSequence("S-BSST") + + userWebClient = getWebClient(serverPort, DefaultUser) + adminWebClient = getWebClient(serverPort, SuperUser) + } + + @Nested + inner class DatesCases() { + @Test + fun `28-1 Creation date is not changed beetween re submissions`() = + runTest { + val v1 = + tsv { + line("Submission", "CREATE-0010") + line("Title", "Sample Submission") + line() + + line("Study") + line() + }.toString() + + assertThat(adminWebClient.submitSingle(v1, TSV)).isSuccessful() + val creationTime = submissionRepository.getExtByAccNoAndVersion("CREATE-0010", 1).creationTime + + val v2 = + tsv { + line("Submission", "CREATE-0010") + line("Title", "Sample Submission UPDATED") + line() + + line("Study") + line() + }.toString() + assertThat(adminWebClient.submitSingle(v2, TSV)).isSuccessful() + val v2Extended = submissionRepository.getExtByAccNoAndVersion("CREATE-0010", 2) + assertThat(v2Extended.creationTime).isEqualTo(creationTime) + } + + @Test + fun `28-2 Modification date is changed beetween re submissions`() = + runTest { + val v1 = + tsv { + line("Submission", "MOD-0010") + line("Title", "Sample Submission") + line() + + line("Study") + line() + }.toString() + + assertThat(adminWebClient.submitSingle(v1, TSV)).isSuccessful() + val modificationTime = submissionRepository.getExtByAccNoAndVersion("MOD-0010", 1).modificationTime + + val v2 = + tsv { + line("Submission", "MOD-0010") + line("Title", "Sample Submission UPDATED") + line() + + line("Study") + line() + }.toString() + assertThat(adminWebClient.submitSingle(v2, TSV)).isSuccessful() + val v2Extended = submissionRepository.getExtByAccNoAndVersion("MOD-0010", 2) + assertThat(v2Extended.modificationTime).isAfter(modificationTime) + } + } + + @Nested + inner class WhenRegularUser { + @Test + fun `28-3 Regular user submit with release date in the past`() = + runTest { + val submission = + tsv { + line("Submission") + line("Title", "Sample Submission") + line("ReleaseDate", "2020-04-24") + line() + + line("Study") + line() + }.toString() + + assertThatExceptionOfType(WebClientException::class.java) + .isThrownBy { userWebClient.submitSingle(submission, TSV) } + .withMessage( + """ + { + "log": { + "level": "ERROR", + "message": "Submission validation errors", + "subnodes": [{ + "level": "ERROR", + "message": "Release date cannot be in the past", + "subnodes": [] + }] + }, + "status": "FAIL" + } + """.trimIndent(), + ) + } + + @Test + fun `28-4 Regular user re-submit a public submission with a new release date in the future`() = + runTest { + val v1 = + tsv { + line("Submission") + line("Title", "Sample Submission") + line("ReleaseDate", OffsetDateTime.now().toStringDate()) + line() + + line("Study") + line() + }.toString() + + val submitted = userWebClient.submitSingle(v1, TSV) + assertThat(submitted).isSuccessful() + + val v2 = + tsv { + line("Submission", submitted.body.accNo) + line("Title", "Sample Submission") + line("ReleaseDate", "2040-04-24") + line() + + line("Study") + line() + }.toString() + + assertThatExceptionOfType(WebClientException::class.java) + .isThrownBy { userWebClient.submitSingle(v2, TSV) } + .withMessage( + """ + { + "log": { + "level": "ERROR", + "message": "Submission validation errors", + "subnodes": [{ + "level": "ERROR", + "message": "The release date of a public study cannot be changed", + "subnodes": [] + }] + }, + "status": "FAIL" + } + """.trimIndent(), + ) + } + + @Test + fun `28-5 Regular user re-submit a private submission with a new release date in the past`() = + runTest { + fun submission(releaseDate: String): String { + return tsv { + line("Submission") + line("Title", "Sample Submission") + line("ReleaseDate", releaseDate) + line() + + line("Study") + line() + }.toString() + } + + val v1 = + tsv { + line("Submission") + line("Title", "Sample Submission") + line("ReleaseDate", "2010-04-24") + line() + + line("Study") + line() + }.toString() + + val submitted = adminWebClient.submitSingle(v1, TSV) + assertThat(submitted).isSuccessful() + + val v2 = + tsv { + line("Submission", submitted.body.accNo) + line("Title", "Sample Submission") + line("ReleaseDate", "2011-04-24") + line() + + line("Study") + line() + }.toString() + + assertThatExceptionOfType(WebClientException::class.java) + .isThrownBy { userWebClient.submitSingle(v2, TSV) } + .withMessage( + """ + { + "log": { + "level": "ERROR", + "message": "Submission validation errors", + "subnodes": [{ + "level": "ERROR", + "message": "The release date of a public study cannot be changed", + "subnodes": [] + }] + }, + "status": "FAIL" + } + """.trimIndent(), + ) + } + } + + @Nested + inner class AdminUser { + @Test + fun `28-6 Admin submits and re submit in the past`() = + runTest { + val v1 = + tsv { + line("Submission", "RELEASE-0010") + line("Title", "Sample Submission") + line("ReleaseDate", "2020-04-24") + line() + + line("Study") + line() + }.toString() + + assertThat(adminWebClient.submitSingle(v1, TSV)).isSuccessful() + val v1Extended = submissionRepository.getExtByAccNoAndVersion("RELEASE-0010", 1) + assertThat(v1Extended.releaseTime).isEqualTo(OffsetDateTime.parse("2020-04-24T00:00+00:00")) + + val v2 = + tsv { + line("Submission", "RELEASE-0010") + line("Title", "Sample Submission") + line("ReleaseDate", "1985-04-24") + line() + + line("Study") + line() + }.toString() + assertThat(adminWebClient.submitSingle(v2, TSV)).isSuccessful() + val v2Extended = submissionRepository.getExtByAccNoAndVersion("RELEASE-0010", 2) + assertThat(v2Extended.releaseTime).isEqualTo(OffsetDateTime.parse("1985-04-24T00:00+00:00")) + } + + @Test + fun `28-7 Admin make a public submission private`() = + runTest { + val v1 = + tsv { + line("Submission", "RELEASE-0020") + line("Title", "Sample Submission") + line("ReleaseDate", "2020-04-24") + line() + + line("Study") + line() + }.toString() + + assertThat(adminWebClient.submitSingle(v1, TSV)).isSuccessful() + val v1Extended = submissionRepository.getExtByAccNoAndVersion("RELEASE-0020", 1) + assertThat(v1Extended.released).isTrue() + assertThat(v1Extended.releaseTime).isEqualTo(OffsetDateTime.parse("2020-04-24T00:00+00:00")) + + val v2 = + tsv { + line("Submission", "RELEASE-0020") + line("Title", "Sample Submission") + line("ReleaseDate", "2050-04-24") + line() + + line("Study") + line() + }.toString() + assertThat(adminWebClient.submitSingle(v2, TSV)).isSuccessful() + val v2Extended = submissionRepository.getExtByAccNoAndVersion("RELEASE-0020", 2) + assertThat(v2Extended.released).isFalse() + assertThat(v2Extended.releaseTime).isEqualTo(OffsetDateTime.parse("2050-04-24T00:00+00:00")) + } + + @Test + fun `28-8 Admin make a Regular user public submission private`() = + runTest { + val v1 = + tsv { + line("Submission") + line("Title", "Sample Submission") + line("ReleaseDate", OffsetDateTime.now().toStringDate()) + line() + + line("Study") + line() + }.toString() + + val submitted = userWebClient.submitSingle(v1, TSV) + assertThat(submitted).isSuccessful() + val accNo = submitted.body.accNo + + val v2 = + tsv { + line("Submission", accNo) + line("Title", "Sample Submission") + line("ReleaseDate", "2050-04-24") + line() + + line("Study") + line() + }.toString() + + assertThat(adminWebClient.submitSingle(v2, TSV)).isSuccessful() + val v2Extended = submissionRepository.getExtByAccNoAndVersion(accNo, 2) + assertThat(v2Extended.released).isFalse() + assertThat(v2Extended.releaseTime).isEqualTo(OffsetDateTime.parse("2050-04-24T00:00+00:00")) + } + } +} diff --git a/submission/submission-webapp/src/itest/resources/itestsInventory/itestsInventory.md b/submission/submission-webapp/src/itest/resources/itestsInventory/itestsInventory.md index 2edb59136..17bf74f21 100644 --- a/submission/submission-webapp/src/itest/resources/itestsInventory/itestsInventory.md +++ b/submission/submission-webapp/src/itest/resources/itestsInventory/itestsInventory.md @@ -1,166 +1,172 @@ -| Class | Test No | Test name | Description | -|---------------------------------|---------|------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------| -| DeletePermissionTest | 1-1 | superuser deletes private submission | Shows who users can delete submissions, and which permissions let them delete. | -| DeletePermissionTest | 1-2 | superuser deletes public submission | | -| DeletePermissionTest | 1-3 | regular user deletes private submission | | -| DeletePermissionTest | 1-4 | regular user deletes public submission | | -| DeletePermissionTest | 1-5 | regular user with access tag permission deletes private submission | | -| DeletePermissionTest | 1-6 | regular user with access tag permission deletes public submission | | -| DeletePermissionTest | 1-7 | regular user with admin permission deletes private submission | | -| DeletePermissionTest | 1-8 | regular user with admin permission deletes public submission | | -| DeletePermissionTest | 1-9 | delete own public submission | | -| DeletePermissionTest | 1-10 | delete own private submission | | -| DeletePermissionTest | 1-11 | delete own public submissions | | -| DeletePermissionTest | 1-12 | delete own private submissions | | -| DeletePermissionTest | 1-13 | resubmit deleted submission | | -| AllInOneSubmissionTest | 2-1 | submit all in one TSV submission | Submits three completely filled submissions (TSV, JSON, XML). Files previously uploaded. | -| AllInOneSubmissionTest | 2-2 | submit all in one JSON submission | | -| FileListSubmissionTest | 3-1 | JSON submission with TSV file list | Submits submissions considering different formats on the file list file. | -| FileListSubmissionTest | 3-2 | JSON submission with XLS file list | | -| FileListSubmissionTest | 3-3 | JSON submission with invalid file list format | | -| FileListSubmissionTest | 3-4 | list referenced files | | -| FileListSubmissionTest | 3-5 | reuse previous version file list | | -| FileListSubmissionTest | 3-6 | empty file list | | -| SubmitPermissionTest | 4-1 | create collection with superuser | Shows under which permissions a user could perform a submission | -| SubmitPermissionTest | 4-2 | create collection with regular user | | -| SubmitPermissionTest | 4-3 | submit without attach permission | | -| SubmitPermissionTest | 4-4 | submit with attach permission access tag | | -| SubmitPermissionTest | 4-5 | registering user and submit to default project | | -| SubmitPermissionTest | 4-6 | submit with collection admin permission | | -| SubmitPermissionTest | 4-7 | resubmit with collection admin permission | | -| SubmitPermissionTest | 4-8 | owner resubmits without attach permission | | -| SubmitPermissionTest | 4-9 | not owner user resubmits without the update permission | | -| SubmitPermissionTest | 4-10 | not owner user resubmits with the update permission | | -| ResubmissionApiTest | 5-1 | resubmit existing submission | Shows the system behaves when resubmissions occurs | -| ResubmissionApiTest | 5-2 | resubmit existing submission with the same files | | -| ResubmissionApiTest | 5-3 | re submit a submission with rootPath | | -| ResubmissionApiTest | 5-4 | regular user suppresses own submission | Verifies that a regular user can't suppress (make private) a public submission | -| ResubmissionApiTest | 5-5 | super user suppresses submission from another user | Verifies that a superuser can suppress (make private) a public submission and that files are private | -| SubmissionFileSourceTest | 6-1 | resubmission with SUBMISSION file source as priority over USER_SPACE | Considers submission with different source files, user space, fire, bypassing files with fire | -| SubmissionFileSourceTest | 6-3-1 | submission with directory with files on FIRE | | -| SubmissionFileSourceTest | 6-3-2-1 | re-submission with directory with files on FIRE | | -| SubmissionFileSourceTest | 6-3-2-1 | re-submission with directory with files on FIRE using submission source only | | -| SubmissionFileSourceTest | 6-3-3 | re-submission on FIRE, User folder should be prioritized | | -| SubmissionFileSourceTest | 6-3-4 | submission with directories with the same name on FIRE | | -| SubmissionFileSourceTest | 6-3-5 | submission with directory with files on NFS | | -| SubmissionFileSourceTest | 6-3-6 | submission with directories with the same name on NFS | | -| SubmissionFileSourceTest | 6-4 | multiple file references | | -| SubmissionFileSourceTest | 6-5 | submission with group file | | -| SubmissionFileSourceTest | 6-6 | Submission bypassing fire | | -| SubmissionFileSourceTest | 6-7 | resubmission with SUBMISSION source ONLY | | -| SubmissionFileSourceTest | 6-8 | submission with files with the same md5 and different path | | -| ExtCollectionSubmitTest | 7-1 | submit private project | Creates public and private collection project | -| ExtCollectionSubmitTest | 7-2 | submit public project | | -| ExtCollectionSubmitTest | 7-3 | submit duplicated accNo template | | -| SubmissionToCollectionsTest | 8-1 | accNo generation from collection template | Considers different test cases on submission attached to project | -| SubmissionToCollectionsTest | 8-2 | direct submission overriding collection | | -| SubmissionToCollectionsTest | 8-3 | no release date to private collection | | -| SubmissionToCollectionsTest | 8-4 | public submission to private collection | | -| SubmissionToCollectionsTest | 8-5 | private submission to public collection | | -| SubmissionToCollectionsTest | 8-6 | no release date to public collection | | -| SubmissionToCollectionsTest | 8-7 | submit to collection with validator | | -| SubmissionToCollectionsTest | 8-8 | submit to collection with failling validator | | -| MultipartFileSubmissionApiTest | 9-1 | XLS submission | Submits submissions and files at the same time | -| MultipartFileSubmissionApiTest | 9-2 | TSV submission | | -| MultipartFileSubmissionApiTest | 9-3 | JSON submission | | -| MultipartFileSubmissionApiTest | 9-4 | direct submission with overriden attributes | | -| MultipartFileSubmissionApiTest | 9-5 | invalid format file | | -| SubmissionStorageModeTest | 10-1 | Fire to Nfs | Submit in Fire storage mode, resubmit in Nfs mode, and vice versa. | -| SubmissionStorageModeTest | 10-2 | Nfs to Fire | | -| FileListValidationTest | 11-1 | blank file list | Different cases in which a submission can be performed with a fileList | -| FileListValidationTest | 11-2 | empty file list | | -| FileListValidationTest | 11-3 | unsupported file list format | | -| FileListValidationTest | 11-4 | valid file list | | -| FileListValidationTest | 11-6 | valid file list with root path | | -| FileListValidationTest | 11-7 | file list with missing files on NFS mode | | -| FileListValidationTest | 11-8 | file list with missing files on FIRE mode | | -| FileListValidationTest | 11-9 | valid file list on behalf another user | | -| SubmissionDraftApiTest | 12-1 | get draft submission when draft does not exist but submission does | How the system behaves with respect on drafts | -| SubmissionDraftApiTest | 12-2 | create and get submission draft | | -| SubmissionDraftApiTest | 12-3 | create and update submission draft | | -| SubmissionDraftApiTest | 12-4 | delete submission draft after submission | | -| SubmissionDraftApiTest | 12-5 | get draft submission when neither draft nor submission exists | | -| SubmissionDraftApiTest | 12-6 | delete a draft directly | | -| SubmissionDraftApiTest | 12-7 | re submit from draft | | -| SubmissionDraftApiTest | 12-8 | update a submission already submitted draft | | -| SubmissionListApiTest | 13-1 | get submission list | Get all submissions that satisfies filters | -| SubmissionListApiTest | 13-2 | get submission list by accession | | -| SubmissionListApiTest | 13-3 | get direct submission list by accession | | -| SubmissionListApiTest | 13-4 | get submission list by keywords | | -| SubmissionListApiTest | 13-5 | get submission list by release date | | -| SubmissionListApiTest | 13-6 | get submission list pagination | | -| SubmissionListApiTest | 13-7 | get submissions with submission title | | -| SubmissionListApiTest | 13-8 | get submissions with section title | | -| SubmissionListApiTest | 13-9 | submission with spaces | | -| SubmissionListApiTest | 13-10 | latest updated submission should appear firs | | -| SubmissionOnBehalfTest | 14-1 | submission on behalf another user | Performs differents submissions on behalf other user | -| SubmissionOnBehalfTest | 14-2 | submission on behalf new user | | -| SubmissionOnBehalfTest | 14-3 | submission on behalf created user with files in his folder | | -| SubmissionOnBehalfTest | 14-4 | submission on behalf when owner and submitter has the same file | | -| SpecialSubmissionAttributesTest | 15-1 | new submission with past release date | Considers submissions with special attribute cases as empty attributes, empty section tables, tags , and others | -| SpecialSubmissionAttributesTest | 15-2 | submission with tags | | -| SpecialSubmissionAttributesTest | 15-3 | new submission with empty accNo subsection table | | -| SpecialSubmissionAttributesTest | 15-4 | new submission with empty-null attributes | | -| SpecialSubmissionAttributesTest | 15-5 | new submission with empty-null table attributes | | -| SpecialSubmissionAttributesTest | 15-6 | submission with DOI | | -| SpecialSubmissionAttributesTest | 15-7 | submission with DOI and incomplete name | The DOI is registered without contributors when the author name is incomplete | -| SpecialSubmissionAttributesTest | 15-8 | submission with DOI and no name | The DOI is registered without contributors when the author name is not present | -| SubmissionApiTest | 16-1 | submit with submission object | Performs different simple submission cases, no accNo, invalid link url, rootPath, and others. | -| SubmissionApiTest | 16-2 | empty accNo | | -| SubmissionApiTest | 16-3 | submission with root path | | -| SubmissionApiTest | 16-4 | submission with generic root section | | -| SubmissionApiTest | 16-5 | submit with invalid link Url | | -| SubmissionApiTest | 16-6 | submission with validation error | | -| SubmissionApiTest | 16-7 | submission for checking ftp files | | -| SubmissionApiTest | 16-8 | submission released makes files public | | -| SubmissionApiTest | 16-9 | submission not released makes files private | | -| SubmissionApiTest | 16-10 | submission containing invalid file path | | -| SubmissionApiTest | 16-11 | submission containing folder with trailing slash | | -| SubmissionApiTest | 16-12 | submission containing file list with invalid name | | -| SubmissionApiTest | 16-13 | User with Ftp based folder submission | | -| SubmissionApiTest | 16-14 | submission when the system has the basePath property configured | | -| UserFileApiTest | 17-1 | upload download delete file and retrieve in user root folder | Shows behaviour of filesApi for user considering different user folder names re | -| UserFileApiTest | 17-2 | upload download delete file and retrieve in user folder | | -| UserFileApiTest | 17-3 | upload download delete file and retrieve in user folder with space | | -| GroupFilesApiTest | 18-1 | upload download delete file and retrieve in user root folder | Shows behaviour of filesApi for groups considering different folder names | -| GroupFilesApiTest | 18-2 | upload download delete file and retrieve in user folder | | -| SubmissionAsyncTest | 19-1 | simple submit async | Performs a simple submit async and checks each stages in the process | -| SubmissionAsyncTest | 19-2 | check submission stages | | -| CollectionsListTest | 20-1 | list collections for super user | Shows which collections users can see | -| CollectionsListTest | 20-2 | list collections for regular user | | -| CollectionsListTest | 20-3 | list collections for default user | | -| CollectionsListTest | 20-4 | list collections for collection admin user | | -| PermissionApiTest | 21-1 | grant permission to a user by superuser | Gives permission to read to a user by superuser, consider its exceptions | -| PermissionApiTest | 21-2 | grant permission to a user by regular user | | -| PermissionApiTest | 21-3 | grant permission to non-existing user | | -| PermissionApiTest | 21-4 | grant permission to non-existing submission | | -| SecurityApiTest | 22-1 | register with invalid email | Shows registration user behaviour | -| SecurityApiTest | 22-2 | register when activation is not enable | | -| SecurityApiTest | 22-3 | login when inactive | | -| SecurityApiTest | 22-4 | case insensitive user registration | | -| SecurityApiTest | 22-5 | case insensitive inactive registration | | -| SecurityApiTest | 22-6 | check ftp home type user | | -| SecurityApiTest | 22-7 | check Nfs home type user | | -| SubmissionDraftListApiTest | 23-1 | get draft by key | Shows how to get drafts, paginated or not. | -| SubmissionDraftListApiTest | 23-2 | get drafts without pagination | | -| SubmissionDraftListApiTest | 23-3 | get drafts with pagination | | -| UserGroupsApiTest | 24-1 | get user groups | Shows belonging behaviour of users in groups, and exceptions | -| UserGroupsApiTest | 24-2 | trying to add a user to un-existing group | | -| UserGroupsApiTest | 24-3 | trying to add a user that does not exist | | -| UserGroupsApiTest | 24-4 | trying to add a user by regularUser | | -| SubmissionRefreshApiTest | 25-1 | Refresh when submission title is updated | | -| SubmissionRefreshApiTest | 25-2 | Refresh when submission release date is updated | | -| SubmissionRefreshApiTest | 25-3 | Refresh when submission attribute is updated | | -| SubmissionRefreshApiTest | 25-4 | Refresh when submission fileListFile attribute is updated | | -| SubmissionStatsTest | 26-1 | files size stat calculation on submit over FIRE | | -| SubmissionStatsTest | 26-2 | files size stat calculation on submit over NFS | | -| SubmissionStatsTest | 26-3 | find stats by accNo | | -| SubmissionStatsTest | 26-4 | find stats by type | | -| SubmissionStatsTest | 26-5 | find stats by type and AccNo | | -| SubmissionStatsTest | 26-6 | register stats by file | | -| SubmissionStatsTest | 26-7 | increment stats by file | | -| SubmissionReleaseTest | 27-1 | public submission without secret key and HARD_LINKS release mode | | -| SubmissionReleaseTest | 27-2 | private submission without secret key and HARD_LINKS release mode | | -| SubmissionReleaseTest | 27-3 | public submission with secret key and MOVE release mode | | -| SubmissionReleaseTest | 27-4 | private submission with secret key and MOVE release mode | | -| SubmissionReleaseTest | 27-5 | release already submitted submission using release operation | | +| Class | Test No | Test name | Description | +|---------------------------------|---------|----------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------| +| DeletePermissionTest | 1-1 | superuser deletes private submission | Shows who users can delete submissions, and which permissions let them delete. | +| DeletePermissionTest | 1-2 | superuser deletes public submission | | +| DeletePermissionTest | 1-3 | regular user deletes private submission | | +| DeletePermissionTest | 1-4 | regular user deletes public submission | | +| DeletePermissionTest | 1-5 | regular user with access tag permission deletes private submission | | +| DeletePermissionTest | 1-6 | regular user with access tag permission deletes public submission | | +| DeletePermissionTest | 1-7 | regular user with admin permission deletes private submission | | +| DeletePermissionTest | 1-8 | regular user with admin permission deletes public submission | | +| DeletePermissionTest | 1-9 | delete own public submission | | +| DeletePermissionTest | 1-10 | delete own private submission | | +| DeletePermissionTest | 1-11 | delete own public submissions | | +| DeletePermissionTest | 1-12 | delete own private submissions | | +| DeletePermissionTest | 1-13 | resubmit deleted submission | | +| AllInOneSubmissionTest | 2-1 | submit all in one TSV submission | Submits three completely filled submissions (TSV, JSON, XML). Files previously uploaded. | +| AllInOneSubmissionTest | 2-2 | submit all in one JSON submission | | +| FileListSubmissionTest | 3-1 | JSON submission with TSV file list | Submits submissions considering different formats on the file list file. | +| FileListSubmissionTest | 3-2 | JSON submission with XLS file list | | +| FileListSubmissionTest | 3-3 | JSON submission with invalid file list format | | +| FileListSubmissionTest | 3-4 | list referenced files | | +| FileListSubmissionTest | 3-5 | reuse previous version file list | | +| FileListSubmissionTest | 3-6 | empty file list | | +| SubmitPermissionTest | 4-1 | create collection with superuser | Shows under which permissions a user could perform a submission | +| SubmitPermissionTest | 4-2 | create collection with regular user | | +| SubmitPermissionTest | 4-3 | submit without attach permission | | +| SubmitPermissionTest | 4-4 | submit with attach permission access tag | | +| SubmitPermissionTest | 4-5 | registering user and submit to default project | | +| SubmitPermissionTest | 4-6 | submit with collection admin permission | | +| SubmitPermissionTest | 4-7 | resubmit with collection admin permission | | +| SubmitPermissionTest | 4-8 | owner resubmits without attach permission | | +| SubmitPermissionTest | 4-9 | not owner user resubmits without the update permission | | +| SubmitPermissionTest | 4-10 | not owner user resubmits with the update permission | | +| ResubmissionApiTest | 5-1 | resubmit existing submission | Shows the system behaves when resubmissions occurs | +| ResubmissionApiTest | 5-2 | resubmit existing submission with the same files | | +| ResubmissionApiTest | 5-3 | re submit a submission with rootPath | | +| ResubmissionApiTest | 5-4 | Make a public submission private should remove FTP files | | +| SubmissionFileSourceTest | 6-1 | resubmission with SUBMISSION file source as priority over USER_SPACE | Considers submission with different source files, user space, fire, bypassing files with fire | +| SubmissionFileSourceTest | 6-3-1 | submission with directory with files on FIRE | | +| SubmissionFileSourceTest | 6-3-2-1 | re-submission with directory with files on FIRE | | +| SubmissionFileSourceTest | 6-3-2-1 | re-submission with directory with files on FIRE using submission source only | | +| SubmissionFileSourceTest | 6-3-3 | re-submission on FIRE, User folder should be prioritized | | +| SubmissionFileSourceTest | 6-3-4 | submission with directories with the same name on FIRE | | +| SubmissionFileSourceTest | 6-3-5 | submission with directory with files on NFS | | +| SubmissionFileSourceTest | 6-3-6 | submission with directories with the same name on NFS | | +| SubmissionFileSourceTest | 6-4 | multiple file references | | +| SubmissionFileSourceTest | 6-5 | submission with group file | | +| SubmissionFileSourceTest | 6-6 | Submission bypassing fire | | +| SubmissionFileSourceTest | 6-7 | resubmission with SUBMISSION source ONLY | | +| SubmissionFileSourceTest | 6-8 | submission with files with the same md5 and different path | | +| ExtCollectionSubmitTest | 7-1 | submit private project | Creates public and private collection project | +| ExtCollectionSubmitTest | 7-2 | submit public project | | +| ExtCollectionSubmitTest | 7-3 | submit duplicated accNo template | | +| SubmissionToCollectionsTest | 8-1 | accNo generation from collection template | Considers different test cases on submission attached to project | +| SubmissionToCollectionsTest | 8-2 | direct submission overriding collection | | +| SubmissionToCollectionsTest | 8-3 | no release date to private collection | | +| SubmissionToCollectionsTest | 8-4 | public submission to private collection | | +| SubmissionToCollectionsTest | 8-5 | private submission to public collection | | +| SubmissionToCollectionsTest | 8-6 | no release date to public collection | | +| SubmissionToCollectionsTest | 8-7 | submit to collection with validator | | +| SubmissionToCollectionsTest | 8-8 | submit to collection with failling validator | | +| MultipartFileSubmissionApiTest | 9-1 | XLS submission | Submits submissions and files at the same time | +| MultipartFileSubmissionApiTest | 9-2 | TSV submission | | +| MultipartFileSubmissionApiTest | 9-3 | JSON submission | | +| MultipartFileSubmissionApiTest | 9-4 | direct submission with overriden attributes | | +| MultipartFileSubmissionApiTest | 9-5 | invalid format file | | +| SubmissionStorageModeTest | 10-1 | Fire to Nfs | Submit in Fire storage mode, resubmit in Nfs mode, and vice versa. | +| SubmissionStorageModeTest | 10-2 | Nfs to Fire | | +| FileListValidationTest | 11-1 | blank file list | Different cases in which a submission can be performed with a fileList | +| FileListValidationTest | 11-2 | empty file list | | +| FileListValidationTest | 11-3 | unsupported file list format | | +| FileListValidationTest | 11-4 | valid file list | | +| FileListValidationTest | 11-6 | valid file list with root path | | +| FileListValidationTest | 11-7 | file list with missing files on NFS mode | | +| FileListValidationTest | 11-8 | file list with missing files on FIRE mode | | +| FileListValidationTest | 11-9 | valid file list on behalf another user | | +| SubmissionDraftApiTest | 12-1 | get draft submission when draft does not exist but submission does | How the system behaves with respect on drafts | +| SubmissionDraftApiTest | 12-2 | create and get submission draft | | +| SubmissionDraftApiTest | 12-3 | create and update submission draft | | +| SubmissionDraftApiTest | 12-4 | delete submission draft after submission | | +| SubmissionDraftApiTest | 12-5 | get draft submission when neither draft nor submission exists | | +| SubmissionDraftApiTest | 12-6 | delete a draft directly | | +| SubmissionDraftApiTest | 12-7 | re submit from draft | | +| SubmissionDraftApiTest | 12-8 | update a submission already submitted draft | | +| SubmissionListApiTest | 13-1 | get submission list | Get all submissions that satisfies filters | +| SubmissionListApiTest | 13-2 | get submission list by accession | | +| SubmissionListApiTest | 13-3 | get direct submission list by accession | | +| SubmissionListApiTest | 13-4 | get submission list by keywords | | +| SubmissionListApiTest | 13-5 | get submission list by release date | | +| SubmissionListApiTest | 13-6 | get submission list pagination | | +| SubmissionListApiTest | 13-7 | get submissions with submission title | | +| SubmissionListApiTest | 13-8 | get submissions with section title | | +| SubmissionListApiTest | 13-9 | submission with spaces | | +| SubmissionListApiTest | 13-10 | latest updated submission should appear firs | | +| SubmissionOnBehalfTest | 14-1 | submission on behalf another user | Performs differents submissions on behalf other user | +| SubmissionOnBehalfTest | 14-2 | submission on behalf new user | | +| SubmissionOnBehalfTest | 14-3 | submission on behalf created user with files in his folder | | +| SubmissionOnBehalfTest | 14-4 | submission on behalf when owner and submitter has the same file | | +| SpecialSubmissionAttributesTest | 15-2 | submission with tags | | +| SpecialSubmissionAttributesTest | 15-3 | new submission with empty accNo subsection table | | +| SpecialSubmissionAttributesTest | 15-4 | new submission with empty-null attributes | | +| SpecialSubmissionAttributesTest | 15-5 | new submission with empty-null table attributes | | +| SpecialSubmissionAttributesTest | 15-6 | submission with DOI | | +| SpecialSubmissionAttributesTest | 15-7 | submission with DOI and incomplete name | The DOI is registered without contributors when the author name is incomplete | +| SpecialSubmissionAttributesTest | 15-8 | submission with DOI and no name | The DOI is registered without contributors when the author name is not present | +| SubmissionApiTest | 16-1 | submit with submission object | Performs different simple submission cases, no accNo, invalid link url, rootPath, and others. | +| SubmissionApiTest | 16-2 | empty accNo | | +| SubmissionApiTest | 16-3 | submission with root path | | +| SubmissionApiTest | 16-4 | submission with generic root section | | +| SubmissionApiTest | 16-5 | submit with invalid link Url | | +| SubmissionApiTest | 16-6 | submission with validation error | | +| SubmissionApiTest | 16-7 | submission for checking ftp files | | +| SubmissionApiTest | 16-8 | submission released makes files public | | +| SubmissionApiTest | 16-9 | submission not released makes files private | | +| SubmissionApiTest | 16-10 | submission containing invalid file path | | +| SubmissionApiTest | 16-11 | submission containing folder with trailing slash | | +| SubmissionApiTest | 16-12 | submission containing file list with invalid name | | +| SubmissionApiTest | 16-13 | User with Ftp based folder submission | | +| SubmissionApiTest | 16-14 | submission when the system has the basePath property configured | | +| UserFileApiTest | 17-1 | upload download delete file and retrieve in user root folder | Shows behaviour of filesApi for user considering different user folder names re | +| UserFileApiTest | 17-2 | upload download delete file and retrieve in user folder | | +| UserFileApiTest | 17-3 | upload download delete file and retrieve in user folder with space | | +| GroupFilesApiTest | 18-1 | upload download delete file and retrieve in user root folder | Shows behaviour of filesApi for groups considering different folder names | +| GroupFilesApiTest | 18-2 | upload download delete file and retrieve in user folder | | +| SubmissionAsyncTest | 19-1 | simple submit async | Performs a simple submit async and checks each stages in the process | +| SubmissionAsyncTest | 19-2 | check submission stages | | +| CollectionsListTest | 20-1 | list collections for super user | Shows which collections users can see | +| CollectionsListTest | 20-2 | list collections for regular user | | +| CollectionsListTest | 20-3 | list collections for default user | | +| CollectionsListTest | 20-4 | list collections for collection admin user | | +| PermissionApiTest | 21-1 | grant permission to a user by superuser | Gives permission to read to a user by superuser, consider its exceptions | +| PermissionApiTest | 21-2 | grant permission to a user by regular user | | +| PermissionApiTest | 21-3 | grant permission to non-existing user | | +| PermissionApiTest | 21-4 | grant permission to non-existing submission | | +| SecurityApiTest | 22-1 | register with invalid email | Shows registration user behaviour | +| SecurityApiTest | 22-2 | register when activation is not enable | | +| SecurityApiTest | 22-3 | login when inactive | | +| SecurityApiTest | 22-4 | case insensitive user registration | | +| SecurityApiTest | 22-5 | case insensitive inactive registration | | +| SecurityApiTest | 22-6 | check ftp home type user | | +| SecurityApiTest | 22-7 | check Nfs home type user | | +| SubmissionDraftListApiTest | 23-1 | get draft by key | Shows how to get drafts, paginated or not. | +| SubmissionDraftListApiTest | 23-2 | get drafts without pagination | | +| SubmissionDraftListApiTest | 23-3 | get drafts with pagination | | +| UserGroupsApiTest | 24-1 | get user groups | Shows belonging behaviour of users in groups, and exceptions | +| UserGroupsApiTest | 24-2 | trying to add a user to un-existing group | | +| UserGroupsApiTest | 24-3 | trying to add a user that does not exist | | +| UserGroupsApiTest | 24-4 | trying to add a user by regularUser | | +| SubmissionRefreshApiTest | 25-1 | Refresh when submission title is updated | | +| SubmissionRefreshApiTest | 25-2 | Refresh when submission release date is updated | | +| SubmissionRefreshApiTest | 25-3 | Refresh when submission attribute is updated | | +| SubmissionRefreshApiTest | 25-4 | Refresh when submission fileListFile attribute is updated | | +| SubmissionStatsTest | 26-1 | files size stat calculation on submit over FIRE | | +| SubmissionStatsTest | 26-2 | files size stat calculation on submit over NFS | | +| SubmissionStatsTest | 26-3 | find stats by accNo | | +| SubmissionStatsTest | 26-4 | find stats by type | | +| SubmissionStatsTest | 26-5 | find stats by type and AccNo | | +| SubmissionStatsTest | 26-6 | register stats by file | | +| SubmissionStatsTest | 26-7 | increment stats by file | | +| SubmissionReleaseTest | 27-1 | public submission without secret key and HARD_LINKS release mode | | +| SubmissionReleaseTest | 27-2 | private submission without secret key and HARD_LINKS release mode | | +| SubmissionReleaseTest | 27-3 | public submission with secret key and MOVE release mode | | +| SubmissionReleaseTest | 27-4 | private submission with secret key and MOVE release mode | | +| SubmissionReleaseTest | 27-5 | release already submitted submission using release operation | | +| SubmissionDatesTest | 28-1 | Creation date is not changed beetween re submissions | | +| SubmissionDatesTest | 28-2 | Modification date is changed beetween re submissions | | +| SubmissionDatesTest | 28-3 | Regular user submit with release date in the past | | +| SubmissionDatesTest | 28-4 | Regular user re-submit a public submission with a new release date in the future | | +| SubmissionDatesTest | 28-5 | Regular user re-submit a private submission with a new release date in the past | | +| SubmissionDatesTest | 28-6 | Admin submit and re Submit in the past | | +| SubmissionDatesTest | 28-7 | Admin make a public submission private | | +| SubmissionDatesTest | 28-8 | Admin make a Regular user public submission private | | diff --git a/submission/submission-webapp/src/test/kotlin/ac/uk/ebi/biostd/submission/domain/service/SubmissionDraftServiceTest.kt b/submission/submission-webapp/src/test/kotlin/ac/uk/ebi/biostd/submission/domain/service/SubmissionDraftServiceTest.kt index 1ed38a397..b990cb6cf 100644 --- a/submission/submission-webapp/src/test/kotlin/ac/uk/ebi/biostd/submission/domain/service/SubmissionDraftServiceTest.kt +++ b/submission/submission-webapp/src/test/kotlin/ac/uk/ebi/biostd/submission/domain/service/SubmissionDraftServiceTest.kt @@ -133,7 +133,7 @@ class SubmissionDraftServiceTest( val error = assertThrows { testInstance.getOrCreateSubmissionDraft(USER_ID, DRAFT_KEY) } - assertThat(error.message).isEqualTo("The user {$USER_ID} is not allowed to update the submission $DRAFT_KEY") + assertThat(error.message).isEqualTo("The user $USER_ID is not allowed to update the submission $DRAFT_KEY") coVerify(exactly = 1) { userPrivilegesService.canResubmit(USER_ID, DRAFT_KEY)