Skip to content

Stricter Checks on Paths in DataSources #8741

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

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open

Stricter Checks on Paths in DataSources #8741

wants to merge 9 commits into from

Conversation

fm3
Copy link
Member

@fm3 fm3 commented Jul 2, 2025

  • First batch of new checks for datasource edits, as discussed in https://www.notion.so/scalableminds/21bb51644c6380808acefb22460573b0
  • This restricts the add route (used in exploreRemote flow), the update route (used in the dataset settings view) and the finishUpload route (used in ds upload via UI/libs).
  • These changes should work without client changes. @normanrz Can you think of any legitimate workflows that this might break?
  • This PR does not yet touch reserveManualUpload, and it does also not yet introduce reserveAttachmentUpload. I’ll do that in the next iteration.
  • Additionally I switched our usages of Paths.get to the newer and more idiomatic Path.of

Steps to test:

  • Explore and add remote dataset, should work
  • Try to add dataset with forbidden path, should be rejected
  • Same for upload
  • Try to introduce new paths in an existing datasource via the dataset settings page, should be rejected.

Issues:


  • Needs datastore update after deployment

@fm3 fm3 self-assigned this Jul 2, 2025
@fm3 fm3 added the backend label Jul 2, 2025
Copy link
Contributor

coderabbitai bot commented Jul 2, 2025

📝 Walkthrough

Walkthrough

This update standardizes file path handling across the codebase by replacing Paths.get with Path.of. It introduces stricter validation for explicit data source paths, adds new error messages for disallowed path operations, and extends data layer and data source models with methods to aggregate all explicit paths. Additional validation logic is implemented in controllers and services.

Changes

Files/Groups Change Summary
conf/messages Added two new error messages for datasource path validation and update restrictions.
test/e2e/End2EndSpec.scala Replaced Paths.get with Path.of for path construction.
util/src/main/scala/com/scalableminds/util/io/PathUtils.scala
util/src/main/scala/com/scalableminds/util/io/ZipIO.scala
Standardized path creation by replacing Paths.get with Path.of.
webknossos-datastore/app/com/scalableminds/webknossos/datastore/controllers/DataSourceController.scala Added path validation using RemoteSourceDescriptorService; updated method signatures to include preventNewPaths parameter.
webknossos-datastore/app/com/scalableminds/webknossos/datastore/controllers/ExportsController.scala
webknossos-datastore/app/com/scalableminds/webknossos/datastore/datavault/FileSystemDataVault.scala
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/BinaryDataServiceHolder.scala
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/ConnectomeFileService.scala
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/DSUsedStorageService.scala
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mapping/AgglomerateService.scala
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mapping/MappingService.scala
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mesh/Hdf5MeshFileService.scala
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mesh/MeshFileService.scala
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/segmentindex/Hdf5SegmentIndexFileService.scala
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/segmentindex/SegmentIndexFileService.scala
Unified path handling by switching from Paths.get to Path.of in all relevant services and controllers.
webknossos-datastore/app/com/scalableminds/webknossos/datastore/models/datasource/DataLayer.scala Added allExplicitPaths method to aggregate explicit paths from mags, resolutions, and attachments.
webknossos-datastore/app/com/scalableminds/webknossos/datastore/models/datasource/DataSource.scala Added allExplicitPaths method to aggregate all explicit paths from data layers.
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/DataSourceService.scala Updated updateDataSource method to include preventNewPaths parameter and added validation to prevent new explicit paths.
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/uploading/UploadService.scala Injected RemoteSourceDescriptorService, added path validation for uploaded datasources, and updated update logic.
webknossos-datastore/app/com/scalableminds/webknossos/datastore/storage/RemoteSourceDescriptorService.scala Standardized path creation, refactored credential lookup, and added path validation methods including pathIsAllowedToAddDirectly.
webknossos-tracingstore/app/com/scalableminds/webknossos/tracingstore/files/TempFileService.scala Switched to Path.of for temporary directory path creation.
webknossos-tracingstore/app/com/scalableminds/webknossos/tracingstore/tracings/editablemapping/EditableMappingService.scala
webknossos-tracingstore/app/com/scalableminds/webknossos/tracingstore/tracings/volume/VolumeTracingService.scala
Replaced Paths.get with Path.of for root path instantiation in tracing services.

Possibly related PRs

Suggested labels

enhancement, testing

Suggested reviewers

  • normanrz

Poem

In the warren of code, a new path we tread,
With Path.of for burrows, old Paths.get is shed.
Data layers checked, explicit and neat,
Only allowed tunnels for rabbits to meet.
If your path’s not allowed, you’ll get a quick scold—
But with these safe routes, our carrots are gold!
🥕🐇


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@fm3 fm3 changed the title WIP: stricter checks on paths in datasources Stricter Checks on Paths in DataSources Jul 3, 2025
@fm3 fm3 marked this pull request as ready for review July 3, 2025 12:35
@fm3 fm3 requested a review from normanrz July 3, 2025 12:35
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
test/e2e/End2EndSpec.scala (1)

67-68: Prefer resolve over string-based Path.of to avoid redundant toString conversion

Path.of(dataDirectory.toPath.toString, "test-dataset") first converts the Path back to a String, then reparses it.
A cleaner and safer variant is to stay in the Path domain:

-        Path.of(dataDirectory.toPath.toString, "test-dataset"),
+        dataDirectory.toPath.resolve("test-dataset"),

This avoids platform-specific path parsing quirks and makes the intent explicit.

webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mesh/MeshFileService.scala (1)

75-75: Normalise the configured base directory once

Storing the raw Path.of(...) may preserve stray ./.. segments or symlinks coming from configuration, which then propagate through every resolve call. Normalising it up-front avoids subtle path mismatches and simplifies debugging.

-  private val dataBaseDir = Path.of(config.Datastore.baseDirectory)
+  private val dataBaseDir = Path
+    .of(config.Datastore.baseDirectory)
+    .toAbsolutePath
+    .normalize()
webknossos-tracingstore/app/com/scalableminds/webknossos/tracingstore/tracings/volume/VolumeTracingService.scala (1)

73-76: Prefer an explicit "." over an empty string when constructing a Path

Path.of("") yields an empty path whose meaning (CWD) is implicit and can be confusing.
A self-describing alternative keeps the intent clear and is immune to corner cases on some platforms:

-  private val binaryDataService = new BinaryDataService(Path.of(""), None, None, None, datasetErrorLoggingService)
+  // Use the current working directory as a dummy path; BinaryDataService never reads from disk here.
+  private val binaryDataService = new BinaryDataService(Path.of("."), None, None, None, datasetErrorLoggingService)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/ConnectomeFileService.scala (1)

255-259: Prefer resolveSibling + FilenameUtils.removeExtension for robustness.

Direct string slicing on the full path (dropRight(connectomeFileExtension.length)) relies on the extension length matching exactly and keeps the trailing dot implicitly. A safer, OS-agnostic approach is to manipulate the filename only and keep the parent path untouched. Proposed refactor:

-import java.nio.file.Path
+import java.nio.file.{Path, Files}
@@
-    val typeNamesPath = Path.of(s"${connectomeFilePath.toString.dropRight(connectomeFileExtension.length)}json")
-    if (new File(typeNamesPath.toString).exists()) {
+    val typeNamesPath = connectomeFilePath
+      .resolveSibling(s"${FilenameUtils.removeExtension(connectomeFilePath.getFileName.toString)}json")
+
+    if (Files.exists(typeNamesPath)) {

Benefits:
• No manual string math
• Works even if the extension ever changes
• Avoids unnecessary new File(...) instantiation by using Files.exists.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4c6b2b2 and 09ccffb.

📒 Files selected for processing (24)
  • conf/messages (1 hunks)
  • test/e2e/End2EndSpec.scala (2 hunks)
  • util/src/main/scala/com/scalableminds/util/io/PathUtils.scala (4 hunks)
  • util/src/main/scala/com/scalableminds/util/io/ZipIO.scala (4 hunks)
  • webknossos-datastore/app/com/scalableminds/webknossos/datastore/controllers/DataSourceController.scala (5 hunks)
  • webknossos-datastore/app/com/scalableminds/webknossos/datastore/controllers/ExportsController.scala (2 hunks)
  • webknossos-datastore/app/com/scalableminds/webknossos/datastore/datavault/FileSystemDataVault.scala (2 hunks)
  • webknossos-datastore/app/com/scalableminds/webknossos/datastore/models/datasource/DataLayer.scala (1 hunks)
  • webknossos-datastore/app/com/scalableminds/webknossos/datastore/models/datasource/DataSource.scala (1 hunks)
  • webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/BinaryDataServiceHolder.scala (2 hunks)
  • webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/ConnectomeFileService.scala (3 hunks)
  • webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/DSUsedStorageService.scala (2 hunks)
  • webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/DataSourceService.scala (4 hunks)
  • webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mapping/AgglomerateService.scala (2 hunks)
  • webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mapping/MappingService.scala (2 hunks)
  • webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mesh/Hdf5MeshFileService.scala (1 hunks)
  • webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mesh/MeshFileService.scala (2 hunks)
  • webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/segmentindex/Hdf5SegmentIndexFileService.scala (1 hunks)
  • webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/segmentindex/SegmentIndexFileService.scala (2 hunks)
  • webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/uploading/UploadService.scala (5 hunks)
  • webknossos-datastore/app/com/scalableminds/webknossos/datastore/storage/RemoteSourceDescriptorService.scala (6 hunks)
  • webknossos-tracingstore/app/com/scalableminds/webknossos/tracingstore/files/TempFileService.scala (2 hunks)
  • webknossos-tracingstore/app/com/scalableminds/webknossos/tracingstore/tracings/editablemapping/EditableMappingService.scala (2 hunks)
  • webknossos-tracingstore/app/com/scalableminds/webknossos/tracingstore/tracings/volume/VolumeTracingService.scala (2 hunks)
🧰 Additional context used
🧠 Learnings (14)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/datavault/FileSystemDataVault.scala (2)
Learnt from: MichaelBuessemeyer
PR: scalableminds/webknossos#8352
File: app/models/organization/CreditTransactionService.scala:0-0
Timestamp: 2025-01-27T12:06:42.865Z
Learning: In Scala's for-comprehension with Fox (Future-like type), the `<-` operator ensures sequential execution. If any step fails, the entire chain short-circuits and returns early, preventing subsequent operations from executing. This makes it safe to perform validation checks before database operations.
Learnt from: frcroth
PR: scalableminds/webknossos#8236
File: webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mesh/NeuroglancerPrecomputedMeshFileService.scala:161-166
Timestamp: 2025-04-28T14:18:04.368Z
Learning: In Scala for-comprehensions with the Fox error handling monad, `Fox.fromBool()` expressions should use the `<-` binding operator instead of the `=` assignment operator to properly propagate error conditions. Using `=` will cause validation failures to be silently ignored.
webknossos-tracingstore/app/com/scalableminds/webknossos/tracingstore/tracings/volume/VolumeTracingService.scala (2)
Learnt from: dieknolle3333
PR: scalableminds/webknossos#8168
File: frontend/javascripts/oxalis/model/sagas/proofread_saga.ts:1039-1039
Timestamp: 2024-11-22T17:18:04.217Z
Learning: In `frontend/javascripts/oxalis/model/sagas/proofread_saga.ts`, when calling `getMagInfo`, the use of `volumeTracingLayer.resolutions` is intentional and should not be changed to `volumeTracingLayer.mags`.
Learnt from: frcroth
PR: scalableminds/webknossos#8202
File: webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/DatasetErrorLoggingService.scala:68-72
Timestamp: 2024-11-25T10:02:03.702Z
Learning: In `DatasetErrorLoggingService.scala`, prefer using `TextUtils.stackTraceAsString(exception)` when logging exceptions instead of passing the exception directly to `logger.error`.
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/DSUsedStorageService.scala (1)
Learnt from: MichaelBuessemeyer
PR: scalableminds/webknossos#8352
File: app/models/organization/CreditTransactionService.scala:0-0
Timestamp: 2025-01-27T12:06:42.865Z
Learning: In Scala's for-comprehension with Fox (Future-like type), the `<-` operator ensures sequential execution. If any step fails, the entire chain short-circuits and returns early, preventing subsequent operations from executing. This makes it safe to perform validation checks before database operations.
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/ConnectomeFileService.scala (1)
Learnt from: MichaelBuessemeyer
PR: scalableminds/webknossos#8352
File: app/models/organization/CreditTransactionService.scala:0-0
Timestamp: 2025-01-27T12:06:42.865Z
Learning: In Scala's for-comprehension with Fox (Future-like type), the `<-` operator ensures sequential execution. If any step fails, the entire chain short-circuits and returns early, preventing subsequent operations from executing. This makes it safe to perform validation checks before database operations.
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mapping/AgglomerateService.scala (2)
Learnt from: frcroth
PR: scalableminds/webknossos#8202
File: webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/DatasetErrorLoggingService.scala:68-72
Timestamp: 2024-11-25T10:02:03.702Z
Learning: In `DatasetErrorLoggingService.scala`, prefer using `TextUtils.stackTraceAsString(exception)` when logging exceptions instead of passing the exception directly to `logger.error`.
Learnt from: frcroth
PR: scalableminds/webknossos#8598
File: webknossos-datastore/app/com/scalableminds/webknossos/datastore/models/datasource/DatasetLayerAttachments.scala:89-95
Timestamp: 2025-06-02T09:49:51.047Z
Learning: In WebKnossos dataset layer attachments, multiple file types can safely use the same directory name (like "agglomerates") because the scanning logic filters by file extension. For example, AgglomerateFileInfo scans for .hdf5 files while CumsumFileInfo scans for .json files in the same "agglomerates" directory without interference.
util/src/main/scala/com/scalableminds/util/io/ZipIO.scala (2)
Learnt from: frcroth
PR: scalableminds/webknossos#8236
File: webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mesh/MeshFileService.scala:170-173
Timestamp: 2025-04-23T08:51:57.756Z
Learning: In the webknossos codebase, classes extending `FoxImplicits` have access to an implicit conversion from `Option[A]` to `Fox[A]`, where `None` is converted to an empty Fox that fails gracefully in for-comprehensions.
Learnt from: MichaelBuessemeyer
PR: scalableminds/webknossos#8352
File: app/models/organization/CreditTransactionService.scala:0-0
Timestamp: 2025-01-27T12:06:42.865Z
Learning: In Scala's for-comprehension with Fox (Future-like type), the `<-` operator ensures sequential execution. If any step fails, the entire chain short-circuits and returns early, preventing subsequent operations from executing. This makes it safe to perform validation checks before database operations.
webknossos-tracingstore/app/com/scalableminds/webknossos/tracingstore/tracings/editablemapping/EditableMappingService.scala (3)
Learnt from: frcroth
PR: scalableminds/webknossos#8236
File: webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mesh/NeuroglancerPrecomputedMeshService.scala:55-66
Timestamp: 2025-04-23T09:22:26.829Z
Learning: In the NeuroglancerMesh class, shardingSpecification is defined as a concrete ShardingSpecification value, not an Option. It uses meshInfo.sharding.getOrElse(ShardingSpecification.empty) to provide a default empty specification if none is present, ensuring that mesh.shardingSpecification is never null.
Learnt from: frcroth
PR: scalableminds/webknossos#8236
File: webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mesh/NeuroglancerPrecomputedMeshService.scala:55-66
Timestamp: 2025-04-23T09:22:26.829Z
Learning: In the NeuroglancerMesh class, shardingSpecification is defined as a concrete ShardingSpecification value, not an Option. It uses meshInfo.sharding.getOrElse(ShardingSpecification.empty) to provide a default empty specification if none is present, ensuring that mesh.shardingSpecification is never null.
Learnt from: frcroth
PR: scalableminds/webknossos#8202
File: webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/DatasetErrorLoggingService.scala:68-72
Timestamp: 2024-11-25T10:02:03.702Z
Learning: In `DatasetErrorLoggingService.scala`, prefer using `TextUtils.stackTraceAsString(exception)` when logging exceptions instead of passing the exception directly to `logger.error`.
webknossos-tracingstore/app/com/scalableminds/webknossos/tracingstore/files/TempFileService.scala (1)
Learnt from: MichaelBuessemeyer
PR: scalableminds/webknossos#8352
File: app/models/organization/CreditTransactionService.scala:0-0
Timestamp: 2025-01-27T12:06:42.865Z
Learning: In Scala's for-comprehension with Fox (Future-like type), the `<-` operator ensures sequential execution. If any step fails, the entire chain short-circuits and returns early, preventing subsequent operations from executing. This makes it safe to perform validation checks before database operations.
conf/messages (1)
Learnt from: MichaelBuessemeyer
PR: scalableminds/webknossos#8393
File: app/controllers/AuthenticationController.scala:566-573
Timestamp: 2025-03-21T16:49:17.956Z
Learning: In the webknossos project, prefer using the ?~> operator for error handling with message keys stored in conf/messages rather than extensive custom error handling.
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/uploading/UploadService.scala (1)
Learnt from: MichaelBuessemeyer
PR: scalableminds/webknossos#8352
File: app/models/organization/CreditTransactionService.scala:0-0
Timestamp: 2025-01-27T12:06:42.865Z
Learning: In Scala's for-comprehension with Fox (Future-like type), the `<-` operator ensures sequential execution. If any step fails, the entire chain short-circuits and returns early, preventing subsequent operations from executing. This makes it safe to perform validation checks before database operations.
webknossos-datastore/app/com/scalableminds/webknossos/datastore/models/datasource/DataLayer.scala (1)
Learnt from: frcroth
PR: scalableminds/webknossos#8609
File: app/models/dataset/Dataset.scala:753-775
Timestamp: 2025-05-12T13:07:29.637Z
Learning: In the `updateMags` method of DatasetMagsDAO (Scala), the code handles different dataset types distinctly:
1. Non-WKW datasets have `magsOpt` populated and use the first branch which includes axisOrder, channelIndex, and credentialId.
2. WKW datasets will have `wkwResolutionsOpt` populated and use the second branch which includes cubeLength.
3. The final branch is a fallback for legacy data.
This ensures appropriate fields are populated for each dataset type.
webknossos-datastore/app/com/scalableminds/webknossos/datastore/controllers/DataSourceController.scala (3)
Learnt from: frcroth
PR: scalableminds/webknossos#8609
File: app/models/dataset/Dataset.scala:753-775
Timestamp: 2025-05-12T13:07:29.637Z
Learning: In the `updateMags` method of DatasetMagsDAO (Scala), the code handles different dataset types distinctly:
1. Non-WKW datasets have `magsOpt` populated and use the first branch which includes axisOrder, channelIndex, and credentialId.
2. WKW datasets will have `wkwResolutionsOpt` populated and use the second branch which includes cubeLength.
3. The final branch is a fallback for legacy data.
This ensures appropriate fields are populated for each dataset type.
Learnt from: frcroth
PR: scalableminds/webknossos#8236
File: webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mesh/NeuroglancerPrecomputedMeshFileService.scala:161-166
Timestamp: 2025-04-28T14:18:04.368Z
Learning: In Scala for-comprehensions with the Fox error handling monad, `Fox.fromBool()` expressions should use the `<-` binding operator instead of the `=` assignment operator to properly propagate error conditions. Using `=` will cause validation failures to be silently ignored.
Learnt from: MichaelBuessemeyer
PR: scalableminds/webknossos#8352
File: app/models/organization/CreditTransactionService.scala:0-0
Timestamp: 2025-01-27T12:06:42.865Z
Learning: In Scala's for-comprehension with Fox (Future-like type), the `<-` operator ensures sequential execution. If any step fails, the entire chain short-circuits and returns early, preventing subsequent operations from executing. This makes it safe to perform validation checks before database operations.
webknossos-datastore/app/com/scalableminds/webknossos/datastore/storage/RemoteSourceDescriptorService.scala (2)
Learnt from: MichaelBuessemeyer
PR: scalableminds/webknossos#8352
File: app/models/organization/CreditTransactionService.scala:0-0
Timestamp: 2025-01-27T12:06:42.865Z
Learning: In Scala's for-comprehension with Fox (Future-like type), the `<-` operator ensures sequential execution. If any step fails, the entire chain short-circuits and returns early, preventing subsequent operations from executing. This makes it safe to perform validation checks before database operations.
Learnt from: frcroth
PR: scalableminds/webknossos#8236
File: webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mesh/MeshFileService.scala:170-173
Timestamp: 2025-04-23T08:51:57.756Z
Learning: In the webknossos codebase, classes extending `FoxImplicits` have access to an implicit conversion from `Option[A]` to `Fox[A]`, where `None` is converted to an empty Fox that fails gracefully in for-comprehensions.
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/DataSourceService.scala (3)
Learnt from: frcroth
PR: scalableminds/webknossos#8609
File: app/models/dataset/Dataset.scala:753-775
Timestamp: 2025-05-12T13:07:29.637Z
Learning: In the `updateMags` method of DatasetMagsDAO (Scala), the code handles different dataset types distinctly:
1. Non-WKW datasets have `magsOpt` populated and use the first branch which includes axisOrder, channelIndex, and credentialId.
2. WKW datasets will have `wkwResolutionsOpt` populated and use the second branch which includes cubeLength.
3. The final branch is a fallback for legacy data.
This ensures appropriate fields are populated for each dataset type.
Learnt from: MichaelBuessemeyer
PR: scalableminds/webknossos#8352
File: app/models/organization/CreditTransactionService.scala:0-0
Timestamp: 2025-01-27T12:06:42.865Z
Learning: In Scala's for-comprehension with Fox (Future-like type), the `<-` operator ensures sequential execution. If any step fails, the entire chain short-circuits and returns early, preventing subsequent operations from executing. This makes it safe to perform validation checks before database operations.
Learnt from: frcroth
PR: scalableminds/webknossos#8236
File: webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mesh/NeuroglancerPrecomputedMeshFileService.scala:161-166
Timestamp: 2025-04-28T14:18:04.368Z
Learning: In Scala for-comprehensions with the Fox error handling monad, `Fox.fromBool()` expressions should use the `<-` binding operator instead of the `=` assignment operator to properly propagate error conditions. Using `=` will cause validation failures to be silently ignored.
🧬 Code Graph Analysis (9)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/datavault/FileSystemDataVault.scala (1)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/models/datasource/DatasetLayerAttachments.scala (1)
  • localPath (43-49)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/segmentindex/Hdf5SegmentIndexFileService.scala (2)
vitest.config.ts (1)
  • config (9-25)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/uploading/UploadService.scala (1)
  • dataBaseDir (158-158)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/segmentindex/SegmentIndexFileService.scala (1)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/uploading/UploadService.scala (1)
  • dataBaseDir (158-158)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/ConnectomeFileService.scala (1)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/DataStoreConfig.scala (1)
  • Datastore (17-64)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mapping/AgglomerateService.scala (2)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/uploading/UploadService.scala (1)
  • dataBaseDir (158-158)
vitest.config.ts (1)
  • config (9-25)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/controllers/ExportsController.scala (2)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/uploading/UploadService.scala (1)
  • dataBaseDir (158-158)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/DataStoreConfig.scala (1)
  • Datastore (17-64)
util/src/main/scala/com/scalableminds/util/io/ZipIO.scala (2)
util/src/main/scala/com/scalableminds/util/io/PathUtils.scala (5)
  • commonPrefix (41-46)
  • commonPrefix (48-51)
  • PathUtils (14-14)
  • cutOffPathAtLastOccurrenceOf (152-168)
  • removeSingleFileNameFromPrefix (171-179)
util/src/main/scala/com/scalableminds/util/tools/Fox.scala (7)
  • map (265-268)
  • map (361-361)
  • empty (56-56)
  • Fox (30-223)
  • Fox (225-289)
  • successful (53-56)
  • shiftBox (296-296)
webknossos-tracingstore/app/com/scalableminds/webknossos/tracingstore/files/TempFileService.scala (2)
app/files/WkTempFileService.scala (1)
  • moduleName (12-12)
webknossos-tracingstore/app/com/scalableminds/webknossos/tracingstore/files/TsTempFileService.scala (1)
  • moduleName (10-10)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/storage/RemoteSourceDescriptorService.scala (4)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/models/datasource/DatasetLayerAttachments.scala (1)
  • localPath (43-49)
util/src/main/scala/com/scalableminds/util/tools/Fox.scala (3)
  • flatMap (268-278)
  • flatMap (363-363)
  • toFox (14-14)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/storage/DataVaultService.scala (2)
  • DataVaultService (22-31)
  • DataVaultService (33-73)
webknossos-datastore/app/com/scalableminds/webknossos/datastore/DataStoreConfig.scala (1)
  • Datastore (17-64)
🔇 Additional comments (43)
test/e2e/End2EndSpec.scala (1)

13-14: Switch to Path import looks good

Migrating from Paths to Path keeps the tests aligned with the production change and removes the deprecated/verbose call sites. No issues here.

webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/BinaryDataServiceHolder.scala (2)

3-3: Confirm build targets Java 11+ before merging
Path.of was introduced in Java 11. If any build, CI, or runtime environment still targets Java 8, this change will break compilation. Double-check your build.sbt / Docker images / CI matrix and bump the tool-chain if necessary.


26-26: No functional change – looks good
Switching from Paths.get to Path.of keeps identical semantics for a single string argument, so there’s no behavioral risk here.

webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/segmentindex/Hdf5SegmentIndexFileService.scala (2)

10-10: Import update aligns with new path-handling policy – looks good.
The switch to java.nio.file.Path is consistent with the project-wide migration and removes the deprecated Paths util.


16-16: Path.of requires JDK 11+ – confirm build/runtime baseline.
Path.of isn’t available on JDK 8. Verify that the CI and production runtime already target ≥ 11; otherwise, this will fail at compile time.

webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/segmentindex/SegmentIndexFileService.scala (2)

29-29: Import cleanup LGTM

java.nio.file.Path is now the only symbol required after dropping Paths.get, so the revised import is correct and avoids the unused Paths import.


44-44: Verify JDK 11+ availability for Path.of

Path.of was introduced in Java 11. If any build/test nodes are still on Java 8, this will fail to compile.
Confirm all build environments (CI and production) target JDK 11 or newer, or revert to Paths.get until the upgrade is complete.

webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/DSUsedStorageService.scala (2)

13-13: LGTM: Import cleanup aligns with modernization.

Removing the unused Paths import after migrating to Path.of is consistent with the codebase modernization effort.


33-33: LGTM: Modernized path creation using Path.of.

The replacement of Paths.get() with Path.of() follows Java 11+ best practices while maintaining identical functionality. This change aligns with the broader codebase modernization described in the PR objectives.

webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mesh/MeshFileService.scala (1)

22-22: Ensure build is on JDK 11+

Path.of only exists since Java 11. Confirm that the CI image, local dev setup and production runtime have all been upgraded from the previous JDK 8 baseline; otherwise this will break compilation.

webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mapping/MappingService.scala (2)

10-10: Confirm JDK 11+ target due to Path.of usage

Path.of is only available from JDK 11 onwards. Please make sure the build toolchain and CI pipelines compile against 11+; otherwise this will fail to compile.


22-24: Path instantiation looks good – verify baseDirectory type

The switch to Path.of(config.Datastore.baseDirectory) is correct and consistent with the migration away from Paths.get.
Just ensure baseDirectory is a String; if it’s already a Path, this will not compile (no Path.of(Path) overload).

webknossos-tracingstore/app/com/scalableminds/webknossos/tracingstore/tracings/volume/VolumeTracingService.scala (1)

33-33: Unused Paths import removed – good catch.

Import scope is now minimal and consistent with the new Path.of idiom.

webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/ConnectomeFileService.scala (2)

4-4: Migration to java.nio.file.Path looks good.

Switching from Paths.get to Path.of is idiomatic since Java 11 and avoids the extra Paths import. No further action required.


87-87: Path construction change is behaviour-preserving.

Path.of(config.Datastore.baseDirectory) is a 1-to-1 replacement for the previous Paths.get(...) call, preserving relative/absolute semantics while staying consistent with the new style.

webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mesh/Hdf5MeshFileService.scala (2)

12-12: Import switch to java.nio.file.Path is fine

The change cleanly removes the java.nio.file.Paths dependency and aligns with the new Path.of usage elsewhere. No issues spotted.


20-21: Verify Java 11+ Toolchain

It looks like we couldn’t find any explicit Java source/target levels or --release flags in your build definitions (e.g. build.sbt, pom.xml). Since Path.of is only available on JDK 11 and above, please double-check that:

  • Your sbt settings (e.g. javacOptions, javaHome) target Java 11+.
  • Any Docker images or CI pipelines are using a JDK ≥ 11.
  • JAVA_HOME in your local and CI environments points to Java 11+.
webknossos-datastore/app/com/scalableminds/webknossos/datastore/datavault/FileSystemDataVault.scala (1)

11-11: LGTM: Clean refactoring to standardize path handling

The changes correctly replace Paths.get with Path.of and remove the unused import. This is functionally equivalent and aligns with the codebase-wide standardization effort.

Also applies to: 99-99

webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/mapping/AgglomerateService.scala (1)

24-24: LGTM: Consistent path handling standardization

The import cleanup and Path.of usage are correct and align with the broader codebase refactoring. The dataBaseDir field maintains its functionality while using the more modern API.

Also applies to: 37-37

util/src/main/scala/com/scalableminds/util/io/PathUtils.scala (1)

4-4: LGTM: Comprehensive path handling standardization

All instances of Paths.get have been correctly replaced with Path.of. The wildcard import is appropriate for the utility class, and the changes maintain identical functionality across all the path manipulation methods.

Also applies to: 45-45, 165-165, 172-172, 183-183

webknossos-tracingstore/app/com/scalableminds/webknossos/tracingstore/files/TempFileService.scala (1)

10-10: LGTM: Correct temporary directory path construction

The refactoring correctly updates the temporary directory path initialization to use Path.of instead of Paths.get. The functionality remains identical while following the standardization pattern.

Also applies to: 24-24

webknossos-datastore/app/com/scalableminds/webknossos/datastore/controllers/ExportsController.scala (1)

3-3: LGTM: Completes the path handling standardization

The import cleanup and Path.of usage for dataBaseDir initialization are correct. This change maintains the same export functionality while following the consistent refactoring pattern across the codebase.

Also applies to: 33-33

util/src/main/scala/com/scalableminds/util/io/ZipIO.scala (4)

4-4: LGTM: Import cleanup aligns with Path.of migration

Removing the unused Paths import after migrating to Path.of is appropriate and maintains clean dependencies.


181-181: LGTM: Consistent migration from Paths.get to Path.of

The standardization from Paths.get to Path.of is correctly applied across all zip entry name processing. Both methods have identical semantics, and this change aligns with the PR's objective to modernize path handling throughout the codebase.

Also applies to: 197-197, 233-233, 251-251


185-185: LGTM: Path.of migration in common prefix computation

The replacement maintains the existing logic for computing common prefixes from zip entry names. The change is consistent with the broader standardization effort.

Also applies to: 237-237


190-190: LGTM: Empty path creation standardized

Using Path.of("") instead of Paths.get("") for creating empty paths is semantically equivalent and follows the modernization pattern.

Also applies to: 242-242

webknossos-datastore/app/com/scalableminds/webknossos/datastore/models/datasource/DataSource.scala (1)

68-68: LGTM: Clean aggregation method for explicit paths

The allExplicitPaths method provides a clean way to collect all explicit paths from data layers using flatMap. This supports the path validation objectives mentioned in the PR and follows functional programming best practices.

conf/messages (1)

129-130: LGTM: Clear error messages for path validation

The new error messages provide clear, actionable feedback for path validation scenarios:

  • Line 129 addresses forbidden paths in datasource addition
  • Line 130 guides users to use compose functionality for adding new paths

Both messages follow existing naming conventions and align with the PR's stricter path validation objectives.

webknossos-datastore/app/com/scalableminds/webknossos/datastore/models/datasource/DataLayer.scala (1)

278-280: LGTM: Comprehensive path aggregation implementation

The allExplicitPaths method correctly aggregates paths from multiple sources:

  • Handles both mag-based and WKW resolution-based layers using the orElse pattern
  • Includes attachment paths by converting Path objects to strings
  • Uses functional programming idioms (flatMap, ++) appropriately
  • Provides fallback to empty sequence when no paths are present

This implementation supports the broader path validation framework introduced in this PR.

webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/uploading/UploadService.scala (4)

25-25: LGTM!

The dependency injection of RemoteSourceDescriptorService is properly implemented.

Also applies to: 116-116


389-391: Good addition of path validation for EXPLORED datasources.

The change from no-op to path validation ensures that uploaded datasources with explicit paths are properly validated, aligning with the PR's objective of stricter path checks.


403-412: Well-implemented path validation method.

The method correctly validates explicit paths in uploaded datasources using proper Fox monad composition and error handling.


510-512: Correct use of preventNewPaths parameter.

Setting preventNewPaths = false is appropriate here as this is part of the upload/add flow where new paths should be allowed after validation.

webknossos-datastore/app/com/scalableminds/webknossos/datastore/services/DataSourceService.scala (3)

49-52: Good modernization to Path.of.

Replacing Paths.get with Path.of aligns with modern Java NIO practices.

Also applies to: 141-141


272-272: Well-designed path restriction logic.

The preventNewPaths parameter correctly enforces path restrictions only during updates when explicitly requested.

Also applies to: 280-280


287-303: Robust implementation of path validation.

The method correctly validates that no new explicit paths are introduced during updates, with proper handling of edge cases and efficient set-based comparison.

webknossos-datastore/app/com/scalableminds/webknossos/datastore/controllers/DataSourceController.scala (3)

25-25: Proper dependency injection.

The RemoteSourceDescriptorService is correctly injected for path validation.

Also applies to: 53-53


395-397: Effective pre-validation of explicit paths.

The validation correctly ensures all explicit paths are allowed before proceeding with datasource creation, providing early failure with a clear error message.


383-385: Correct enforcement of path restrictions.

The preventNewPaths parameter is properly set to true for updates (preventing new paths) and false for additions (allowing new paths), aligning with the PR's objectives.

Also applies to: 413-415

webknossos-datastore/app/com/scalableminds/webknossos/datastore/storage/RemoteSourceDescriptorService.scala (3)

14-14: Consistent modernization to Path.of.

All Paths.get usages properly replaced with Path.of.

Also applies to: 71-71, 117-117, 164-164


129-130: Good refactoring to simplify credential lookup.

Changing findGlobalCredentialFor to return Option instead of Fox is appropriate since it's a synchronous operation. The conversion to Fox at call sites maintains compatibility.

Also applies to: 139-139, 148-148


151-176: Well-designed path validation logic.

The path validation methods provide comprehensive security checks:

  • Prevents path traversal attacks in pathIsDataSourceLocal
  • Ensures remote paths don't use global credentials directly
  • Allows whitelisted local paths for flexibility

The separation of concerns into focused helper methods makes the logic clear and maintainable.

webknossos-tracingstore/app/com/scalableminds/webknossos/tracingstore/tracings/editablemapping/EditableMappingService.scala (1)

44-44: Consistent switch to java.nio.file.Path looks good
Migration away from Paths is in line with the new guidelines across the PR. No further action required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant