Skip to content

Conversation

@Boy132
Copy link
Member

@Boy132 Boy132 commented Sep 5, 2025

Better handling for trailing / or empty paths.

@Boy132 Boy132 requested a review from rmartinoscar September 5, 2025 11:46
@Boy132 Boy132 self-assigned this Sep 5, 2025
@coderabbitai
Copy link

coderabbitai bot commented Sep 5, 2025

📝 Walkthrough

Walkthrough

Move actions now use the raw destination location and compute destinations with resolve_path(join_paths(...)) (no leading "./"); per-file and bulk moves emit detailed Activity events and Notifications with old/new paths; join_paths was refactored to trim slashes from base and each segment and drop empty parts, changing how base '' or '/' are handled.

Changes

Cohort / File(s) Summary of Changes
ListFiles move/rename inputs & placeholders
app/Filament/Server/Resources/FileResource/Pages/ListFiles.php
Removed the leading "./" from computed destination (placeholders now use resolve_path(join_paths(...)) instead of resolve_path('./' . join_paths(...))). Location input is no longer trimmed of trailing slashes ($location = $data['location'] vs rtrim(...)).
Per-file move logging & notification
app/Filament/Server/Resources/FileResource/Pages/ListFiles.php
Per-file move computes $oldLocation and $newLocation (using joined path + destination), emits Activity::event('server:file.rename') with directory, files, from, to, and sends a Notification showing the rename (oldLocation -> newLocation).
Bulk move mapping & notification
app/Filament/Server/Resources/FileResource/Pages/ListFiles.php
Bulk move builds the files mapping using the raw location value, emits Activity::event('server:file.rename') with directory and files, and Notification text updated to a bulk message including the moved count and the resolved target directory (resolve_path(join_paths($this->path, $location))).
Header / create file logging
app/Filament/Server/Resources/FileResource/Pages/ListFiles.php
Creating a new file now logs the actual full path ($path) instead of composing join_paths($path, $data['name']).
Path joining normalization
app/helpers.php
Rewrote join_paths(string $base, string ...$paths): trims leading/trailing slashes from the base and each path segment, filters out empty segments, and joins with single '/' between segments. If the trimmed base is empty, returns the joined segments without a leading slash; otherwise returns trimmed_base . '/' . joined_segments. Removed previous special-case handling for base === '/' and removed global double-slash cleanup.

Sequence Diagram(s)

sequenceDiagram
  participant U as User
  participant F as Filament UI
  participant L as ListFiles action
  participant H as join_paths()
  participant RP as resolve_path()
  participant R as Repository (renameFiles)
  participant A as Activity / Notifications

  U->>F: Initiate move (location, files)
  F->>L: Submit payload
  note right of L #f8f9fa: Use location as-provided (no rtrim)
  L->>H: join_paths(this->path, location, filename/paths)
  note right of H #f1f4f8: Trim slashes per segment, drop empties, join with '/'
  H-->>L: normalized path(s)
  L->>RP: resolve_path(normalized path)
  RP-->>L: resolved destination(s)
  L->>R: renameFiles(renamePaths)
  R-->>L: Result
  L->>A: Activity::event('server:file.rename') + Notification(s)
  A-->>F: Trigger UI notifications
  F-->>U: Show outcome
Loading

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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

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

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit 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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

Copy link

@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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
app/Filament/Server/Resources/FileResource/Pages/ListFiles.php (2)

359-371: Same double-slash and relativity issue in bulk move.

Mirrors the per-file action; normalize $location before composing targets to avoid "/dir//name" and unintended absolutes.

Apply:

-                        $location = $data['location'];
-
-                        $files = $files->map(fn ($file) => ['to' => join_paths($location, $file['name']), 'from' => $file['name']])->toArray();
+                        $location = $data['location'];
+                        $files = $files
+                            ->map(fn ($file) => [
+                                'to' => resolve_path(join_paths('', $location, $file['name'])),
+                                'from' => $file['name'],
+                            ])
+                            ->toArray();

If helpful, I can add a small unit test matrix for join_paths covering root/non-root bases, trailing slashes, empty segments, and “/” as a segment.


199-206: Normalize and sanitize the “to” path before calling renameFiles
renameFiles sends your $this->path as root and expects each to entry to be relative—passing the raw $location can introduce leading slashes or “//” and allow absolute or traversal paths. Wrap it in resolve_path(join_paths('', $location, $file->name)):

-                            $location = $data['location'];
-                            $files = [['to' => join_paths($location, $file->name), 'from' => $file->name]];
+                            $location = $data['location'];
+                            $to = resolve_path(join_paths('', $location, $file->name));
+                            $files = [['to' => $to, 'from' => $file->name]];
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 925ab26 and 8c6490b.

📒 Files selected for processing (2)
  • app/Filament/Server/Resources/FileResource/Pages/ListFiles.php (2 hunks)
  • app/helpers.php (1 hunks)

@pelican-dev pelican-dev deleted a comment from coderabbitai bot Sep 5, 2025
Copy link

@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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
app/Filament/Server/Resources/FileResource/Pages/ListFiles.php (3)

438-440: Fix duplicated filename in Activity “file” property after new file creation.

$path already includes the filename; joining again appends it twice.

-                        Activity::event('server:file.write')
-                            ->property('file', join_paths($path, $data['name']))
+                        Activity::event('server:file.write')
+                            ->property('file', $path)
                             ->log();

190-206: Canonicalize user input before rename; align preview default
Normalize $data['location with resolve_path($data['location'] ?? '') before building the 'to' entries, and change the placeholder’s default from '/' to '' (i.e. ->content(fn(Get $get…) => resolve_path(join_paths($this->path, $get('location') ?? '', $file->name)))) so the UI preview and daemon payload remain consistent.


356-373: Normalize bulk move location
In the bulk move action callback (app/Filament/Server/Resources/FileResource/Pages/ListFiles.php around line 359), replace

$location = $data['location'];

with

$location = resolve_path($data['location'] ?? '');

to ensure the target directory is normalized before use.

♻️ Duplicate comments (1)
app/helpers.php (1)

55-65: Confirm intent: join_paths now drops leading “/” from $base (absolute → relative).

This changes join_paths('/dir', 'a') from '/dir/a' to 'dir/a'. Verify all call sites (URLs vs daemon repo) expect this. If you meant to only trim trailing slashes while preserving absolute bases, apply the rtrim + root-case approach (previously suggested) and reindex $paths.

-        $base = trim($base, '/');
+        // Preserve absolute bases ("/foo") but normalize trailing "/".
+        $isRoot = ($base === '/');
+        $base = $isRoot ? '' : rtrim($base, '/');

-        $paths = array_map(fn (string $path) => trim($path, '/'), $paths);
-        $paths = array_filter($paths, fn (string $path) => strlen($path) > 0);
+        $paths = array_map(fn (string $path) => trim($path, '/'), $paths);
+        $paths = array_values(array_filter($paths, fn (string $path) => $path !== ''));

-        if (empty($base)) {
+        if ($isRoot || $base === '') {
             return implode('/', $paths);
         }
 
         return $base . '/' . implode('/', $paths);

To verify impact:

#!/bin/bash
# Find join_paths($this->path, ...) usages and show contexts.
rg -nP -C2 'join_paths\(\s*\$this->path\s*,'
# Inspect DaemonFileRepository expectations for absolute vs relative paths.
rg -nP -C3 'class\s+DaemonFileRepository|function\s+(copyFile|putContent|renameFiles)\b'
🧹 Nitpick comments (2)
app/helpers.php (2)

57-58: Minor: reindex after filtering.

array_filter preserves keys; implode works, but reindexing helps consistency and avoids surprises if array operations are added later.

-        $paths = array_filter($paths, fn (string $path) => strlen($path) > 0);
+        $paths = array_values(array_filter($paths, fn (string $path) => $path !== ''));

53-54: Add a short docblock clarifying absolute/relative semantics.

Explicitly document that base '' or '/' yields a relative result (no leading slash), and that segments are trimmed and empty parts removed.

-    function join_paths(string $base, string ...$paths): string
+    /**
+     * Joins path segments with single slashes.
+     * - base '' or '/' => returns a relative path (no leading slash).
+     * - Each segment is trim($seg, '/'); empty parts are dropped.
+     */
+    function join_paths(string $base, string ...$paths): string
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5b36220 and 3fc4cda.

📒 Files selected for processing (2)
  • app/Filament/Server/Resources/FileResource/Pages/ListFiles.php (2 hunks)
  • app/helpers.php (1 hunks)

Copy link

@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: 0

🧹 Nitpick comments (3)
app/Filament/Server/Resources/FileResource/Pages/ListFiles.php (3)

196-196: Normalize preview input (handle backslashes/whitespace).

Users often paste Windows-style paths. Normalize before joining so the preview is accurate.

-                                ->content(fn (Get $get, File $file) => resolve_path(join_paths($this->path, $get('location') ?? '/', $file->name))),
+                                ->content(fn (Get $get, File $file) => resolve_path(
+                                    join_paths(
+                                        $this->path,
+                                        str_replace('\\', '/', trim((string) ($get('location') ?? '/'))),
+                                        $file->name
+                                    )
+                                )),

356-356: Unify bulk preview behavior with per-file and normalize input.

Use the same default “/” and handle backslashes/whitespace so root previews don’t render empty at “/”.

-                            ->content(fn (Get $get) => resolve_path(join_paths($this->path, $get('location') ?? ''))),
+                            ->content(fn (Get $get) => resolve_path(
+                                join_paths(
+                                    $this->path,
+                                    str_replace('\\', '/', trim((string) ($get('location') ?? '/')))
+                                )
+                            )),

359-371: Sanitize bulk $location and optionally pre-normalize each “to”.

This avoids odd paths if users type “.\” or include spaces and keeps Activity/Notification aligned with actual ops.

-                        $location = $data['location'];
+                        $location = str_replace('\\', '/', trim((string) ($data['location'] ?? '')));
@@
-                        $files = $files->map(fn ($file) => ['to' => join_paths($location, $file['name']), 'from' => $file['name']])->toArray();
+                        $files = $files->map(
+                            fn ($file) => ['to' => resolve_path(join_paths($location, $file['name'])), 'from' => $file['name']]
+                        )->toArray();

If the daemon requires raw relative paths (and does its own normalization), skip resolving “to” above and keep only the $location sanitation.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3fc4cda and 7b8ee25.

📒 Files selected for processing (1)
  • app/Filament/Server/Resources/FileResource/Pages/ListFiles.php (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
app/Filament/Server/Resources/FileResource/Pages/ListFiles.php (4)
app/helpers.php (2)
  • resolve_path (69-87)
  • join_paths (53-65)
app/Filament/Server/Resources/FileResource/Pages/EditFiles.php (1)
  • getDaemonFileRepository (232-239)
app/Repositories/Daemon/DaemonFileRepository.php (1)
  • putContent (52-64)
app/Services/Activity/ActivityLogService.php (1)
  • property (108-116)
🔇 Additional comments (2)
app/Filament/Server/Resources/FileResource/Pages/ListFiles.php (2)

441-441: LGTM: log the exact file path used.

Using the computed $path in the activity record is clearer and avoids drift.


199-206: Sanitize and normalize $location before use

Trim whitespace, convert backslashes to forward slashes, and normalize dot-segments via resolve_path() so both the client logs and daemon API receive a consistent, safe path.

@@ app/Filament/Server/Resources/FileResource/Pages/ListFiles.php Lines 199-206
-                            $location = $data['location'];
-                            $files = [['to' => join_paths($location, $file->name), 'from' => $file->name]];
+                            $locationRaw = (string) ($data['location'] ?? '');
+                            $location    = str_replace('\\', '/', trim($locationRaw));
+                            $to          = resolve_path(join_paths($location, $file->name));
+                            $files       = [['to' => $to, 'from' => $file->name]];

@@
-                            $newLocation = resolve_path(join_paths($this->path, $location, $file->name));
+                            $newLocation = resolve_path(join_paths($this->path, $to));

Confirm the daemon’s /files/rename endpoint does its own path normalization and prevents directory-traversal before merging.

@Boy132 Boy132 merged commit 32eb1ab into main Sep 8, 2025
25 checks passed
@Boy132 Boy132 deleted the boy132/fix-move-preview branch September 8, 2025 07:03
@github-actions github-actions bot locked and limited conversation to collaborators Sep 8, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants