Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
00c295a
WIP: make organization name its id, drop the mongo id
fm3 Oct 15, 2023
b1228d9
Merge branch 'master' into organization-id-vs-name
fm3 Oct 17, 2023
2d2c4fb
more usages
fm3 Oct 17, 2023
239031c
Update LokiClient.scala
normanrz Mar 12, 2024
d12ce47
Merge branch 'master' into organization-id-vs-name
fm3 Jun 12, 2024
8dfb65b
fix compiler errors after merge
fm3 Jun 12, 2024
2c7aa18
prune scala usages of organizationName
fm3 Jun 12, 2024
fb108c0
fix migration guide
fm3 Jun 12, 2024
c514a15
prune frontend usages of organizationName
fm3 Jun 12, 2024
6d5ff61
prune frontend usages of organization.name
fm3 Jun 12, 2024
46c89fa
fix data type of orga references
fm3 Jun 12, 2024
d30e53b
sql check, fix delete organization
fm3 Jun 13, 2024
cc8bff0
Merge branch 'master' into organization-id-vs-name
fm3 Jul 4, 2024
05ccfae
Merge branch 'master' into organization-id-vs-name
fm3 Aug 5, 2024
75c232c
WIP: Add migration and revision
MichaelBuessemeyer Aug 12, 2024
90b451a
Merge branch 'master' of github.com:scalableminds/webknossos into org…
MichaelBuessemeyer Aug 12, 2024
c717721
format backend
MichaelBuessemeyer Aug 13, 2024
4ecd993
enable backend to parse old analytics schema for ingest events
MichaelBuessemeyer Aug 13, 2024
374cae3
format backend
MichaelBuessemeyer Aug 13, 2024
96f5d3d
update schema version
MichaelBuessemeyer Aug 13, 2024
61c438d
finish first version of migration and revision
MichaelBuessemeyer Aug 13, 2024
9ce7852
fix schema & migration
MichaelBuessemeyer Aug 13, 2024
3fd41b7
Merge branch 'master' of github.com:scalableminds/webknossos into org…
MichaelBuessemeyer Aug 16, 2024
1caf5d0
add migration for analyticsEvents' eventProperties
MichaelBuessemeyer Aug 16, 2024
96a6bd0
Merge branch 'master' of github.com:scalableminds/webknossos into org…
MichaelBuessemeyer Aug 19, 2024
971b5a0
add organizationName to LinkedLayerIdentifier to make it backwards co…
MichaelBuessemeyer Aug 19, 2024
c6e62bb
add legacy route to list datasets supporting the old get param organi…
MichaelBuessemeyer Aug 19, 2024
289f69a
dont use direct get on box and throw jserror when no orgaid or organa…
MichaelBuessemeyer Aug 19, 2024
d8b281e
format backend
MichaelBuessemeyer Aug 19, 2024
d515c07
Merge branch 'master' of github.com:scalableminds/webknossos into org…
MichaelBuessemeyer Aug 20, 2024
9f647df
remove comments from evolution files & fix schema version
MichaelBuessemeyer Aug 20, 2024
041cb02
fix migration, remove old now duplicate unique index
MichaelBuessemeyer Aug 21, 2024
fa11937
readd unique contraint in reversion
MichaelBuessemeyer Aug 21, 2024
66429a9
in reversion: migrate local join orga, open dataset & uplaod dataset …
MichaelBuessemeyer Aug 21, 2024
89332ee
in reversion: fix fk constraints and views
MichaelBuessemeyer Aug 21, 2024
a658f0e
in reversion: fix user infos view
MichaelBuessemeyer Aug 21, 2024
773a223
Merge branch 'master' of github.com:scalableminds/webknossos into org…
MichaelBuessemeyer Aug 27, 2024
873a455
migrate new code pulled in by merge to use orgaId and not name
MichaelBuessemeyer Aug 27, 2024
4a04e5f
Merge branch 'master' of github.com:scalableminds/webknossos into org…
MichaelBuessemeyer Aug 28, 2024
500f294
format backend
MichaelBuessemeyer Aug 28, 2024
b8a93ba
update schema version & include warning in reversion
MichaelBuessemeyer Aug 28, 2024
8b7de38
rename organizationDisplayName to organizationName
MichaelBuessemeyer Aug 28, 2024
68af06e
add changelog entry
MichaelBuessemeyer Aug 28, 2024
f0643a6
add migration entry
MichaelBuessemeyer Aug 28, 2024
4d431ea
remove auto generated message files for data and tracingstore
MichaelBuessemeyer Aug 28, 2024
7780ba4
Merge branch 'master' of github.com:scalableminds/webknossos into org…
MichaelBuessemeyer Aug 28, 2024
02c4661
update e2e db fixtures / initial db data
MichaelBuessemeyer Aug 28, 2024
a62d83d
rename left over orgDisplayName variable to orgName
MichaelBuessemeyer Aug 28, 2024
01693f8
update snapshots to use new e2e your name last names
MichaelBuessemeyer Aug 28, 2024
68d6d4b
fix typo and format code
MichaelBuessemeyer Aug 28, 2024
15bf4c5
more relaxed analytics json reads
fm3 Aug 29, 2024
5fbf7f1
drop default for id column
fm3 Aug 29, 2024
7a469ad
add missing redirect to versioned.routes
fm3 Aug 29, 2024
5043f6d
rename migration, undo changing worker job args
fm3 Aug 29, 2024
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
1 change: 1 addition & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
- The warning about a mismatch between the scale of a pre-computed mesh and the dataset scale's factor now also considers all supported mags of the active segmentation layer. This reduces the false posive rate regarding this warning. [#7921](https://github.com/scalableminds/webknossos/pull/7921/)
- It is no longer allowed to edit annotations of other organizations, even if they are set to public and to others-may-edit. [#7923](https://github.com/scalableminds/webknossos/pull/7923)
- When proofreading segmentations, the user can now interact with super-voxels directly in the data viewports. Additionally, proofreading is significantly faster because the segmentation data doesn't have to be re-downloaded after each merge/split operation. [#7654](https://github.com/scalableminds/webknossos/pull/7654)
- Changed internal data model changing an organization's name to id and its displayName to name. The previously existing id was removed. [#7386](https://github.com/scalableminds/webknossos/pull/7386)
- Because of the way our models are trained, AI analysis and training is disabled for 2D and ND datasets, as well as for color layers with data type uInt24. [#7957](https://github.com/scalableminds/webknossos/pull/7957)
- The overall performance was improved (especially for the segments tab). [#7958](https://github.com/scalableminds/webknossos/pull/7958)
- The performance for the skeleton tab was improved. [#7989](https://github.com/scalableminds/webknossos/pull/7989)
Expand Down
1 change: 1 addition & 0 deletions MIGRATIONS.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ User-facing changes are documented in the [changelog](CHANGELOG.released.md).

### Postgres Evolutions:
- [119-add-metadata-to-folders-and-datasets.sql](conf/evolutions/119-add-metadata-to-folders-and-datasets.sql)
- [120-remove-old-organization-id.sql](conf/evolutions/120-remove-old-organization-id.sql)
4 changes: 2 additions & 2 deletions app/controllers/AiModelController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class AiModelController @Inject()(
jobCommand = JobCommand.train_model
commandArgs = Json.obj(
"training_annotations" -> Json.toJson(trainingAnnotations),
"organization_name" -> organization.name,
"organization_name" -> organization._id,
"model_id" -> modelId,
"custom_workflow_provided_by_user" -> request.body.workflowYaml
)
Expand Down Expand Up @@ -171,7 +171,7 @@ class AiModelController @Inject()(
jobCommand = JobCommand.infer_with_model
boundingBox <- BoundingBox.fromLiteral(request.body.boundingBox).toFox
commandArgs = Json.obj(
"organization_name" -> organization.name,
"organization_name" -> organization._id,
"dataset_name" -> dataset.name,
"color_layer_name" -> request.body.colorLayerName,
"bounding_box" -> boundingBox.toLiteral,
Expand Down
16 changes: 8 additions & 8 deletions app/controllers/AnnotationController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ class AnnotationController @Inject()(
newLayerName = request.body.name.getOrElse(AnnotationLayer.defaultNameForType(request.body.typ))
_ <- bool2Fox(!annotation.annotationLayers.exists(_.name == newLayerName)) ?~> "annotation.addLayer.nameInUse"
organization <- organizationDAO.findOne(request.identity._organization)
_ <- annotationService.addAnnotationLayer(annotation, organization.name, request.body)
_ <- annotationService.addAnnotationLayer(annotation, organization._id, request.body)
updated <- provider.provideAnnotation(typ, id, request.identity)
json <- annotationService.publicWrites(updated, Some(request.identity)) ?~> "annotation.write.failed"
} yield JsonOk(json)
Expand Down Expand Up @@ -242,12 +242,12 @@ class AnnotationController @Inject()(
} yield result
}

def createExplorational(organizationName: String, datasetName: String): Action[List[AnnotationLayerParameters]] =
def createExplorational(organizationId: String, datasetName: String): Action[List[AnnotationLayerParameters]] =
sil.SecuredAction.async(validateJson[List[AnnotationLayerParameters]]) { implicit request =>
for {
organization <- organizationDAO.findOneByName(organizationName)(GlobalAccessContext) ?~> Messages(
organization <- organizationDAO.findOne(organizationId)(GlobalAccessContext) ?~> Messages(
"organization.notFound",
organizationName) ~> NOT_FOUND
organizationId) ~> NOT_FOUND
dataset <- datasetDAO.findOneByNameAndOrganization(datasetName, organization._id) ?~> Messages(
"dataset.notFound",
datasetName) ~> NOT_FOUND
Expand All @@ -262,16 +262,16 @@ class AnnotationController @Inject()(
} yield JsonOk(json)
}

def getSandbox(organizationName: String,
def getSandbox(organization: String,
datasetName: String,
typ: String,
sharingToken: Option[String]): Action[AnyContent] =
sil.UserAwareAction.async { implicit request =>
val ctx = URLSharing.fallbackTokenAccessContext(sharingToken) // users with dataset sharing token may also get a sandbox annotation
for {
organization <- organizationDAO.findOneByName(organizationName)(GlobalAccessContext) ?~> Messages(
organization <- organizationDAO.findOne(organization)(GlobalAccessContext) ?~> Messages(
"organization.notFound",
organizationName) ~> NOT_FOUND
organization) ~> NOT_FOUND
dataset <- datasetDAO.findOneByNameAndOrganization(datasetName, organization._id)(ctx) ?~> Messages(
"dataset.notFound",
datasetName) ~> NOT_FOUND
Expand Down Expand Up @@ -301,7 +301,7 @@ class AnnotationController @Inject()(
_ <- restrictions.allowUpdate(request.identity) ?~> "notAllowed" ~> FORBIDDEN
annotation <- provider.provideAnnotation(typ, id, request.identity)
organization <- organizationDAO.findOne(request.identity._organization)
_ <- annotationService.makeAnnotationHybrid(annotation, organization.name, fallbackLayerName) ?~> "annotation.makeHybrid.failed"
_ <- annotationService.makeAnnotationHybrid(annotation, organization._id, fallbackLayerName) ?~> "annotation.makeHybrid.failed"
updated <- provider.provideAnnotation(typ, id, request.identity)
json <- annotationService.publicWrites(updated, Some(request.identity)) ?~> "annotation.write.failed"
} yield JsonOk(json)
Expand Down
54 changes: 26 additions & 28 deletions app/controllers/AnnotationIOController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,14 @@ class AnnotationIOController @Inject()(
request.body.dataParts("createGroupForEachFile").headOption.contains("true")
val overwritingDatasetName: Option[String] =
request.body.dataParts.get("datasetName").flatMap(_.headOption)
val overwritingOrganizationName: Option[String] =
request.body.dataParts.get("organizationName").flatMap(_.headOption)
val overwritingOrganizationId: Option[String] =
request.body.dataParts.get("organizationId").flatMap(_.headOption)
val attachedFiles = request.body.files.map(f => (f.ref.path.toFile, f.filename))
val parsedFiles =
annotationUploadService.extractFromFiles(attachedFiles,
useZipName = true,
overwritingDatasetName,
overwritingOrganizationName)
overwritingOrganizationId)
val parsedFilesWrapped =
annotationUploadService.wrapOrPrefixGroups(parsedFiles.parseResults, shouldCreateGroupForEachFile)
val parseResultsFiltered: List[NmlParseResult] = parsedFilesWrapped.filter(_.succeeded)
Expand Down Expand Up @@ -225,15 +225,15 @@ class AnnotationIOController @Inject()(
wkUrl: String)(implicit mp: MessagesProvider, ctx: DBAccessContext): Fox[Dataset] =
for {
datasetName <- assertAllOnSameDataset(skeletonTracings, volumeTracings) ?~> "nml.file.differentDatasets"
organizationNameOpt <- assertAllOnSameOrganization(skeletonTracings, volumeTracings) ?~> "nml.file.differentDatasets"
organizationIdOpt <- Fox.runOptional(organizationNameOpt) {
organizationDAO.findOneByName(_)(GlobalAccessContext).map(_._id)
organizationIdOpt <- assertAllOnSameOrganization(skeletonTracings, volumeTracings) ?~> "nml.file.differentDatasets"
organizationIdOpt <- Fox.runOptional(organizationIdOpt) {
organizationDAO.findOne(_)(GlobalAccessContext).map(_._id)
} ?~> (if (wkUrl.nonEmpty && conf.Http.uri != wkUrl) {
Messages("organization.notFound.wrongHost", organizationNameOpt.getOrElse(""), wkUrl, conf.Http.uri)
} else { Messages("organization.notFound", organizationNameOpt.getOrElse("")) }) ~>
Messages("organization.notFound.wrongHost", organizationIdOpt.getOrElse(""), wkUrl, conf.Http.uri)
} else { Messages("organization.notFound", organizationIdOpt.getOrElse("")) }) ~>
NOT_FOUND
organizationId <- Fox.fillOption(organizationIdOpt) {
datasetDAO.getOrganizationForDataset(datasetName)(GlobalAccessContext)
datasetDAO.getOrganizationIdForDataset(datasetName)(GlobalAccessContext)
} ?~> Messages("dataset.noAccess", datasetName) ~> FORBIDDEN
dataset <- datasetDAO.findOneByNameAndOrganization(datasetName, organizationId) ?~> (if (wkUrl.nonEmpty && conf.Http.uri != wkUrl) {
Messages(
Expand Down Expand Up @@ -277,11 +277,11 @@ class AnnotationIOController @Inject()(

private def assertAllOnSameOrganization(skeletons: List[SkeletonTracing],
volumes: List[VolumeTracing]): Fox[Option[String]] = {
// Note that organizationNames are optional. Tracings with no organization attribute are ignored here
val organizationNames = skeletons.flatMap(_.organizationName) ::: volumes.flatMap(_.organizationName)
// Note that organizationIds are optional. Tracings with no organization attribute are ignored here
val organizationIds = skeletons.flatMap(_.organizationId) ::: volumes.flatMap(_.organizationId)
for {
_ <- Fox.runOptional(organizationNames.headOption)(name => bool2Fox(organizationNames.forall(_ == name)))
} yield organizationNames.headOption
_ <- Fox.runOptional(organizationIds.headOption)(name => bool2Fox(organizationIds.forall(_ == name)))
} yield organizationIds.headOption
}

private def adaptVolumeTracingsToFallbackLayer(volumeLayersGrouped: List[List[UploadedVolumeLayer]],
Expand All @@ -297,7 +297,7 @@ class AnnotationIOController @Inject()(
adaptedTracing <- adaptPropertiesToFallbackLayer(volumeLayer.tracing,
dataSource,
dataset,
organization.name,
organization._id,
remoteDataStoreClient)
adaptedAnnotationLayer = volumeLayer.copy(tracing = adaptedTracing)
} yield adaptedAnnotationLayer
Expand All @@ -309,7 +309,7 @@ class AnnotationIOController @Inject()(
volumeTracing: VolumeTracing,
dataSource: GenericDataSource[T],
dataset: Dataset,
organizationName: String,
organizationId: String,
remoteDataStoreClient: WKRemoteDataStoreClient): Fox[VolumeTracing] = {
val fallbackLayerOpt = dataSource.dataLayers.flatMap {
case layer: SegmentationLayer if volumeTracing.fallbackLayer contains layer.name => Some(layer)
Expand All @@ -323,7 +323,7 @@ class AnnotationIOController @Inject()(
.map(layer => elementClassToProto(layer.elementClass))
.getOrElse(elementClassToProto(VolumeTracingDefaults.elementClass))
for {
tracingCanHaveSegmentIndex <- canHaveSegmentIndex(organizationName,
tracingCanHaveSegmentIndex <- canHaveSegmentIndex(organizationId,
dataset.name,
fallbackLayerOpt.map(_.name),
remoteDataStoreClient)
Expand All @@ -341,13 +341,13 @@ class AnnotationIOController @Inject()(
}

private def canHaveSegmentIndex(
organizationName: String,
organizationId: String,
datasetName: String,
fallbackLayerName: Option[String],
remoteDataStoreClient: WKRemoteDataStoreClient)(implicit ec: ExecutionContext): Fox[Boolean] =
fallbackLayerName match {
case Some(layerName) =>
remoteDataStoreClient.hasSegmentIndexFile(organizationName, datasetName, layerName)
remoteDataStoreClient.hasSegmentIndexFile(organizationId, datasetName, layerName)
case None =>
Fox.successful(true)
}
Expand Down Expand Up @@ -411,9 +411,7 @@ class AnnotationIOController @Inject()(

// Note: volumeVersion cannot currently be supplied per layer, see https://github.com/scalableminds/webknossos/issues/5925

def skeletonToTemporaryFile(dataset: Dataset,
annotation: Annotation,
organizationName: String): Fox[TemporaryFile] =
def skeletonToTemporaryFile(dataset: Dataset, annotation: Annotation, organizationId: String): Fox[TemporaryFile] =
for {
tracingStoreClient <- tracingStoreService.clientFor(dataset)
fetchedAnnotationLayers <- Fox.serialCombined(annotation.skeletonAnnotationLayers)(
Expand All @@ -426,7 +424,7 @@ class AnnotationIOController @Inject()(
Some(annotation),
dataset.voxelSize,
None,
organizationName,
organizationId,
conf.Http.uri,
dataset.name,
Some(user),
Expand All @@ -443,7 +441,7 @@ class AnnotationIOController @Inject()(
def volumeOrHybridToTemporaryFile(dataset: Dataset,
annotation: Annotation,
name: String,
organizationName: String): Fox[TemporaryFile] =
organizationId: String): Fox[TemporaryFile] =
for {
tracingStoreClient <- tracingStoreService.clientFor(dataset)
fetchedVolumeLayers: List[FetchedAnnotationLayer] <- Fox.serialCombined(annotation.volumeAnnotationLayers) {
Expand All @@ -466,7 +464,7 @@ class AnnotationIOController @Inject()(
Some(annotation),
dataset.voxelSize,
None,
organizationName,
organizationId,
conf.Http.uri,
dataset.name,
Some(user),
Expand All @@ -491,11 +489,11 @@ class AnnotationIOController @Inject()(
def annotationToTemporaryFile(dataset: Dataset,
annotation: Annotation,
name: String,
organizationName: String): Fox[TemporaryFile] =
organizationId: String): Fox[TemporaryFile] =
if (annotation.tracingType == TracingType.skeleton)
skeletonToTemporaryFile(dataset, annotation, organizationName) ?~> "annotation.download.skeletonToFile.failed"
skeletonToTemporaryFile(dataset, annotation, organizationId) ?~> "annotation.download.skeletonToFile.failed"
else
volumeOrHybridToTemporaryFile(dataset, annotation, name, organizationName) ?~> "annotation.download.hybridToFile.failed"
volumeOrHybridToTemporaryFile(dataset, annotation, name, organizationId) ?~> "annotation.download.hybridToFile.failed"

def exportExtensionForAnnotation(annotation: Annotation): String =
if (annotation.tracingType == TracingType.skeleton)
Expand All @@ -519,7 +517,7 @@ class AnnotationIOController @Inject()(
_ <- restrictions.allowDownload(issuingUser) ?~> "annotation.download.notAllowed" ~> FORBIDDEN
dataset <- datasetDAO.findOne(annotation._dataset)(GlobalAccessContext) ?~> "dataset.notFoundForAnnotation" ~> NOT_FOUND
organization <- organizationDAO.findOne(dataset._organization)(GlobalAccessContext) ?~> "organization.notFound" ~> NOT_FOUND
temporaryFile <- annotationToTemporaryFile(dataset, annotation, name, organization.name) ?~> "annotation.writeTemporaryFile.failed"
temporaryFile <- annotationToTemporaryFile(dataset, annotation, name, organization._id) ?~> "annotation.writeTemporaryFile.failed"
} yield {
Ok.sendFile(temporaryFile, inline = false)
.as(mimeType)
Expand Down
3 changes: 1 addition & 2 deletions app/controllers/Application.scala
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ class Application @Inject()(actorSystem: ActorSystem,
for {
organization <- organizationDAO.findOne(request.identity._organization)
userEmail <- userService.emailFor(request.identity)
_ = Mailer ! Send(
defaultMails.helpMail(request.identity, userEmail, organization.displayName, message, currentUrl))
_ = Mailer ! Send(defaultMails.helpMail(request.identity, userEmail, organization.name, message, currentUrl))
} yield Ok
}

Expand Down
Loading