Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Allow disabling data use terms #3468

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.loculus.backend.config

import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import io.swagger.v3.oas.models.headers.Header
Expand Down Expand Up @@ -146,7 +147,9 @@ internal fun validateEarliestReleaseDateFields(config: BackendConfig): List<Stri
}

fun readBackendConfig(objectMapper: ObjectMapper, configPath: String): BackendConfig {
val config = objectMapper.readValue<BackendConfig>(File(configPath))
val config = objectMapper
.enable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)
.readValue<BackendConfig>(File(configPath))
logger.info { "Loaded backend config from $configPath" }
logger.info { "Config: $config" }
val validationErrors = validateEarliestReleaseDateFields(config)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.loculus.backend.api.Organism
data class BackendConfig(
val organisms: Map<String, InstanceConfig>,
val accessionPrefix: String,
val dataUseTermsEnabled: Boolean,
val dataUseTermsUrls: DataUseTermsUrls?,
) {
fun getInstanceConfig(organism: Organism) = organisms[organism.name] ?: throw IllegalArgumentException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import org.loculus.backend.api.SubmittedProcessedData
import org.loculus.backend.api.UnprocessedData
import org.loculus.backend.auth.AuthenticatedUser
import org.loculus.backend.auth.HiddenParam
import org.loculus.backend.config.BackendConfig
import org.loculus.backend.controller.LoculusCustomHeaders.X_TOTAL_RECORDS
import org.loculus.backend.log.REQUEST_ID_MDC_KEY
import org.loculus.backend.log.RequestIdContext
Expand Down Expand Up @@ -76,33 +77,45 @@ open class SubmissionController(
private val submissionDatabaseService: SubmissionDatabaseService,
private val iteratorStreamer: IteratorStreamer,
private val requestIdContext: RequestIdContext,
private val backendConfig: BackendConfig,
) {

@Operation(description = SUBMIT_DESCRIPTION)
@ApiResponse(responseCode = "200", description = SUBMIT_RESPONSE_DESCRIPTION)
@ApiResponse(responseCode = "400", description = SUBMIT_ERROR_RESPONSE)
@PostMapping("/submit", consumes = ["multipart/form-data"])
fun submit(
@PathVariable @Valid organism: Organism,
@HiddenParam authenticatedUser: AuthenticatedUser,
@Parameter(description = GROUP_ID_DESCRIPTION) @RequestParam groupId: Int,
@Parameter(description = METADATA_FILE_DESCRIPTION) @RequestParam metadataFile: MultipartFile,
@Parameter(description = SEQUENCE_FILE_DESCRIPTION) @RequestParam sequenceFile: MultipartFile?,
@Parameter(description = "Data Use terms under which data is released.") @RequestParam dataUseTermsType:
DataUseTermsType,
@Parameter(
description =
"Data Use terms under which data is released. Mandatory when data use terms are enabled for this Instance.",
) @RequestParam dataUseTermsType: DataUseTermsType?,
@Parameter(
description =
"Mandatory when data use terms are set to 'RESTRICTED'." +
" It is the date when the sequence entries will become 'OPEN'." +
" Format: YYYY-MM-DD",
) @RequestParam restrictedUntil: String?,
): List<SubmissionIdMapping> {
var dataUseTermsKind = DataUseTermsType.OPEN
if (backendConfig.dataUseTermsEnabled) {
if (dataUseTermsType == null) {
throw BadRequestException("the 'dataUseTermsType' needs to be provided.")
} else {
dataUseTermsKind = dataUseTermsType
}
}

val params = SubmissionParams.OriginalSubmissionParams(
organism,
authenticatedUser,
metadataFile,
sequenceFile,
groupId,
DataUseTerms.fromParameters(dataUseTermsType, restrictedUntil),
DataUseTerms.fromParameters(dataUseTermsKind, restrictedUntil),
)
return submitModel.processSubmissions(UUID.randomUUID().toString(), params)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ The accession is the (globally unique) id that the system assigned to the sequen
You can use this response to associate the user provided submissionId with the system assigned accession.
"""

const val SUBMIT_ERROR_RESPONSE = """
The data use terms type have not been provided, even though they are enabled for this Loculus instance.
"""

const val METADATA_FILE_DESCRIPTION = """
A TSV (tab separated values) file containing the metadata of the submitted sequence entries.
The file may be compressed with zstd, xz, zip, gzip, lzma, bzip2 (with common extensions).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.fasterxml.jackson.databind.node.TextNode
import mu.KotlinLogging
import org.loculus.backend.api.DataUseTerms
import org.loculus.backend.api.GeneticSequence
import org.loculus.backend.api.MetadataMap
import org.loculus.backend.api.Organism
import org.loculus.backend.api.ProcessedData
import org.loculus.backend.api.VersionStatus
Expand Down Expand Up @@ -94,6 +95,9 @@ open class ReleasedDataModel(
return "\"$lastUpdateTime\"" // ETag must be enclosed in double quotes
}

private fun conditionalMetadata(condition: Boolean, values: () -> MetadataMap): MetadataMap =
if (condition) values() else emptyMap()

private fun computeAdditionalMetadataFields(
rawProcessedData: RawProcessedData,
latestVersions: Map<Accession, Version>,
Expand All @@ -111,6 +115,13 @@ open class ReleasedDataModel(

val earliestReleaseDate = earliestReleaseDateFinder?.calculateEarliestReleaseDate(rawProcessedData)

val dataUseTermsUrl: String? = backendConfig.dataUseTermsUrls?.let { urls ->
when (currentDataUseTerms) {
DataUseTerms.Open -> urls.open
is DataUseTerms.Restricted -> urls.restricted
}
}

var metadata = rawProcessedData.processedData.metadata +
mapOf(
("accession" to TextNode(rawProcessedData.accession)),
Expand All @@ -126,31 +137,42 @@ open class ReleasedDataModel(
("releasedAtTimestamp" to LongNode(rawProcessedData.releasedAtTimestamp.toTimestamp())),
("releasedDate" to TextNode(rawProcessedData.releasedAtTimestamp.toUtcDateString())),
("versionStatus" to TextNode(versionStatus.name)),
("dataUseTerms" to TextNode(currentDataUseTerms.type.name)),
("dataUseTermsRestrictedUntil" to restrictedDataUseTermsUntil),
("pipelineVersion" to LongNode(rawProcessedData.pipelineVersion)),
) +
if (rawProcessedData.isRevocation) {
mapOf("versionComment" to TextNode(rawProcessedData.versionComment))
} else {
emptyMap()
}.let {
when (backendConfig.dataUseTermsUrls) {
null -> it
else -> {
val url = when (currentDataUseTerms) {
DataUseTerms.Open -> backendConfig.dataUseTermsUrls.open
is DataUseTerms.Restricted -> backendConfig.dataUseTermsUrls.restricted
}
it + ("dataUseTermsUrl" to TextNode(url))
}
}
} +
if (earliestReleaseDate != null) {
mapOf("earliestReleaseDate" to TextNode(earliestReleaseDate.toUtcDateString()))
} else {
emptyMap()
}
// TODO add a test for this change
conditionalMetadata(
backendConfig.dataUseTermsEnabled,
{
mapOf(
"dataUseTerms" to TextNode(currentDataUseTerms.type.name),
"dataUseTermsRestrictedUntil" to restrictedDataUseTermsUntil,
)
},
) +
conditionalMetadata(
rawProcessedData.isRevocation,
{
mapOf(
"versionComment" to TextNode(rawProcessedData.versionComment),
)
},
) +
conditionalMetadata(
earliestReleaseDate != null,
{
mapOf(
"earliestReleaseDate" to TextNode(earliestReleaseDate!!.toUtcDateString()),
)
},
) +
conditionalMetadata(
dataUseTermsUrl != null,
{
mapOf(
"dataUseTermsUrl" to TextNode(dataUseTermsUrl!!),
)
},
)

return ProcessedData(
metadata = metadata,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,6 @@ fun backendConfig(metadataList: List<Metadata>, earliestReleaseDate: EarliestRel
),
),
accessionPrefix = "FOO_",
dataUseTermsEnabled = true,
dataUseTermsUrls = null,
)
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ class SubmitEndpointTest(
organism: Organism,
dataUseTerm: DataUseTerms,
) {
println("Data use terms enabled: ")
println(backendConfig.dataUseTermsEnabled)
submissionControllerClient.submit(
metadataFile,
sequencesFile,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ const val PREFIX = "LOC_"

class GenerateAccessionFromNumberServiceTest {
private val accessionFromNumberService = GenerateAccessionFromNumberService(
BackendConfig(accessionPrefix = PREFIX, organisms = emptyMap(), dataUseTermsUrls = null),
BackendConfig(
accessionPrefix = PREFIX,
organisms = emptyMap(),
dataUseTermsEnabled = true,
dataUseTermsUrls = null,
),
)

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class EmptyProcessedDataProviderTest {
),
),
),
dataUseTermsEnabled = true,
dataUseTermsUrls = null,
),
)
Expand Down
3 changes: 2 additions & 1 deletion backend/src/test/resources/backend_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -225,5 +225,6 @@
]
}
}
}
},
"dataUseTermsEnabled": true
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"accessionPrefix": "LOC_",
"dataUseTermsEnabled": true,
"organisms": {
"dummyOrganism": {
"referenceGenomes": {
Expand Down
3 changes: 3 additions & 0 deletions kubernetes/loculus/templates/_common-metadata.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ fields:
autocomplete: true
displayName: Date released (exact)
columnWidth: 100
# TODO change to be done here - only include these fields if a flag is set
- name: dataUseTerms
type: string
generateIndex: true
Expand Down Expand Up @@ -160,6 +161,7 @@ enableLoginNavigationItem: {{ $.Values.website.websiteConfig.enableLoginNavigati
enableSubmissionNavigationItem: {{ $.Values.website.websiteConfig.enableSubmissionNavigationItem }}
enableSubmissionPages: {{ $.Values.website.websiteConfig.enableSubmissionPages }}
enableSeqSets: {{ $.Values.seqSets.enabled }}
enableDataUseTerms: {{ $.Values.dataUseTermsEnabled }}
accessionPrefix: {{ quote $.Values.accessionPrefix }}
{{- $commonMetadata := (include "loculus.commonMetadata" . | fromYaml).fields }}
organisms:
Expand Down Expand Up @@ -289,6 +291,7 @@ fields:
{{- define "loculus.generateBackendConfig" }}
accessionPrefix: {{ quote $.Values.accessionPrefix }}
name: {{ quote $.Values.name }}
dataUseTermsEnabled: {{$.Values.dataUseTermsEnabled }}
dataUseTermsUrls:
{{$.Values.dataUseTermsUrls | toYaml | nindent 2}}
organisms:
Expand Down
1 change: 1 addition & 0 deletions kubernetes/loculus/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ ingestLimitSeconds: 1800
getSubmissionListLimitSeconds: 600
preprocessingTimeout: 600
accessionPrefix: "LOC_"
dataUseTermsEnabled: false
dataUseTermsUrls:
open: https://#TODO-MVP/open
restricted: https://#TODO-MVP/restricted
Expand Down
Loading
Loading