Skip to content

Conversation

@elibosley
Copy link
Member

@elibosley elibosley commented May 9, 2025

Summary by CodeRabbit

  • New Features

    • Improved login security by supporting Single Sign-On (SSO) in the login flow.
    • Centralized and enhanced theme management for a more consistent appearance across pages.
  • Refactor

    • Simplified and modularized page layouts and theme handling using helper classes.
    • Moved inline scripts and styles to external files for better maintainability.
    • Replaced legacy notification system with a modern toaster UI component.
    • Streamlined session handling for localhost requests.
    • Updated version checks to conditionally skip modifications for Unraid 7.2 compatibility.
    • Replaced direct version imports with dynamic imports for better load management.
  • Bug Fixes

    • Conditional logic added to prevent applying certain modifications on Unraid 7.2.0 and above for improved compatibility.
  • Chores

    • Introduced a unified Vitest workspace configuration for streamlined testing across multiple projects.
    • Added comprehensive tests for Unraid version comparison logic.
    • Adjusted logging levels for activation-related messages to reduce noise in logs.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 9, 2025

Walkthrough

This change introduces Unraid version checks to multiple file modification classes, ensuring patches are only applied to versions below 7.2.0. It adds a reusable version comparison method, refactors PHP templates to use a ThemeHelper class, and modularizes client-side logic. Session handling, SSO login, and notification UI are also updated.

Changes

File(s) / Path(s) Summary
api/src/unraid-api/unraid-file-modifier/file-modification.ts Adds a protected async method isUnraidVersionGreaterThanOrEqualTo to the abstract FileModification class for semver-based version checks.
api/src/unraid-api/unraid-file-modifier/modifications/default-page-layout.modification.ts
api/src/unraid-api/unraid-file-modifier/modifications/log-viewer.modification.ts
api/src/unraid-api/unraid-file-modifier/modifications/notifications-page.modification.ts
api/src/unraid-api/unraid-file-modifier/modifications/set-password-modal.modification.ts
api/src/unraid-api/unraid-file-modifier/modifications/sso.modification.ts
api/src/unraid-api/unraid-file-modifier/modifications/auth-request.modification.ts
Updates shouldApply methods to skip patching on Unraid 7.2.0 or newer by using the new version check. Existing logic is retained for older versions.
api/src/unraid-api/unraid-file-modifier/modifications/patches/default-page-layout.patch Adds session auto-initialization for localhost, removes legacy jGrowl notification code, updates theme class usage, and modifies notification UI elements.
api/src/unraid-api/unraid-file-modifier/modifications/patches/sso.patch Introduces verifyUsernamePasswordAndSSO for SSO token validation during login, updates login flow, and includes SSO UI logic in the login page.
api/src/unraid-api/unraid-file-modifier/modifications/test/fixtures/downloaded/.login.php
api/src/unraid-api/unraid-file-modifier/modifications/test/snapshots/.login.php.modified.snapshot.php
Refactors theme detection and HTML class assignment to use a ThemeHelper class, centralizing theme logic and updating all theme-dependent CSS and markup.
api/src/unraid-api/unraid-file-modifier/modifications/test/fixtures/downloaded/DefaultPageLayout.php
api/src/unraid-api/unraid-file-modifier/modifications/test/snapshots/DefaultPageLayout.php.modified.snapshot.php
Replaces inline theme/layout logic and JavaScript with a ThemeHelper class and externalized scripts, streamlining HTML structure and modularizing client-side code.
api/src/unraid-api/unraid-file-modifier/modifications/test/fixtures/downloaded/.login.php.last-download-time
api/src/unraid-api/unraid-file-modifier/modifications/test/fixtures/downloaded/DefaultPageLayout.php.last-download-time
api/src/unraid-api/unraid-file-modifier/modifications/test/fixtures/downloaded/Notifications.page.last-download-time
api/src/unraid-api/unraid-file-modifier/modifications/test/fixtures/downloaded/auth-request.php.last-download-time
Adds a newline at the end of each timestamp file; no functional changes.
vitest.workspace.js Adds a Vitest workspace configuration to aggregate and run tests across multiple project subdirectories.
api/src/common/dashboard/get-unraid-version.ts Changes static import of getters to dynamic import inside getUnraidVersion function to defer loading until needed.
api/src/unraid-api/graph/resolvers/customization/customization.service.ts
api/src/unraid-api/graph/resolvers/customization/customization.service.spec.ts
Downgrades log messages about missing activation directory or JSON file from warning to debug level in service and test files.
api/src/unraid-api/unraid-file-modifier/unraid-file-modifier.spec.ts Adds tests for isUnraidVersionGreaterThanOrEqualTo method, verifying version comparison logic including prerelease handling and error cases.

Sequence Diagram(s)

sequenceDiagram
    participant FileModification
    participant ModificationClass
    participant UnraidSystem

    ModificationClass->>FileModification: shouldApply()
    FileModification->>UnraidSystem: getUnraidVersion()
    FileModification->>FileModification: isUnraidVersionGreaterThanOrEqualTo('7.2.0')
    alt Version >= 7.2.0
        ModificationClass-->>FileModification: Return shouldApply: false (skip)
    else Version < 7.2.0
        ModificationClass-->>FileModification: Continue with patch logic
    end
Loading

Possibly related PRs

Suggested reviewers

  • mdatelle
  • pujitm

Poem

Versions checked with care and grace,
Patches skip when newer’s in place.
Themes aligned with helper’s art,
Sessions start with localhost heart.
SSO tokens dance and gleam,
Notifications toast the dream.
Code refined, a seamless stream! 🎉✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between 31df6bf and 09f0323.

📒 Files selected for processing (1)
  • api/src/unraid-api/unraid-file-modifier/file-modification.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • api/src/unraid-api/unraid-file-modifier/file-modification.ts
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: Test API
  • GitHub Check: Build Web App
  • GitHub Check: Build API
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Cloudflare Pages

🪧 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 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.

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: 3

🔭 Outside diff range comments (4)
api/src/unraid-api/unraid-file-modifier/modifications/patches/sso.patch (3)

20-24: 🛠️ Refactor suggestion

Escape literal dots in JWT-style regex

. in a regex matches any character; here you want to require literal dots between the three base-64url segments.
Suggestion:

-        if (!preg_match('/^[A-Za-z0-9-_]+.[A-Za-z0-9-_]+.[A-Za-z0-9-_]+$/', $password)) {
+        if (!preg_match('/^[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+$/', $password)) {

This prevents malformed tokens such as abc%def from bypassing the format check.


25-33: ⚠️ Potential issue

Avoid logging sensitive SSO validation output

$output may contain user-specific details returned by the validator. Persisting it in plain logs (my_logger(...)) risks leaking PII or session data.

-        my_logger("SSO Login Attempt Response: " . print_r($output, true));
+        // Log only debug code – omit token-specific response to avoid leaking PII.
+        my_logger("SSO Login Attempt Response: <omitted>");

Alternatively, wrap the log behind a debug flag.


10-18: 🛠️ Refactor suggestion

password_verify result ignored on error path

If getent shadow unexpectedly returns no second field, explode(':', $output)[1] yields null, causing password_verify() to raise a warning. Add a sanity check before verifying:

$credentials = explode(":", $output);
if (count($credentials) < 2 || empty($credentials[1])) {
    return false;
}
api/src/unraid-api/unraid-file-modifier/modifications/patches/default-page-layout.patch (1)

12-18: 🛠️ Refactor suggestion

is_localhost() check may be bypassed via reverse-proxy / SSRF

Relying solely on REMOTE_ADDR === 127.0.0.1/::1 can be unsafe when:

  1. The GUI is behind nginx/Traefik which terminates TLS on the same host — REMOTE_ADDR becomes 127.0.0.1.
  2. An internal SSRF hits the endpoint, gaining a root GUI session.

Mitigate by additionally verifying that HTTP_X_FORWARDED_FOR/HTTP_FORWARDED headers are absent, or restrict to SERVER_ADDR equality.

♻️ Duplicate comments (1)
api/src/unraid-api/unraid-file-modifier/modifications/__test__/snapshots/DefaultPageLayout.php.modified.snapshot.php (1)

75-92: Same localhost-session logic duplicated

The code block duplicates logic reviewed in DefaultPageLayout.patch. Please extract to a shared helper to avoid drift.

🧹 Nitpick comments (5)
api/src/unraid-api/unraid-file-modifier/modifications/patches/sso.patch (1)

20-21: Magic length constant lacks context

strlen($password) > 800 is arbitrary and undocumented. If token size changes, valid tokens may be rejected.

Consider:

// JWTs are typically < 5 KB; treat anything longer than 5 KB as suspicious
define('MAX_SSO_TOKEN_LENGTH', 5120);
if (strlen($password) > MAX_SSO_TOKEN_LENGTH) return false;

Add a comment referencing the spec or internal limit.

api/src/unraid-api/unraid-file-modifier/modifications/patches/default-page-layout.patch (2)

19-28: Session auto-creation may clobber an active session

Destroying an existing session (session_destroy()) then starting a fresh one discards CSRF tokens and user data unexpectedly when the first localhost request arrives.

Safer:

if (!is_good_session()) {
    session_regenerate_id(true); // keep data, rotate ID
    $_SESSION['unraid_login'] = time();
    $_SESSION['unraid_user']  = 'root';
}

Keeps data while still authenticating root.


40-41: $notify['position'] not sanitized before echo

The value ultimately lands in HTML and could break markup if maliciously crafted. Wrap with htmlspecialchars():

position="<?= htmlspecialchars(($notify['position'] === 'center') ? 'top-center' : $notify['position'], ENT_QUOTES) ?>"
api/src/unraid-api/unraid-file-modifier/modifications/__test__/snapshots/DefaultPageLayout.php.modified.snapshot.php (1)

118-129: Inline CSS could live in dedicated stylesheet

Embedding large :root CSS in a snapshot file hampers caching and theming overrides. Consider moving to default-custom-vars.css and enqueueing it.

api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/DefaultPageLayout.php (1)

128-151: Replace short open tags with full <?php … ?> for portability

The includes and body sections use the short form <? … ?>.
If short_open_tag is disabled (common in modern PHP installations), these blocks will be sent to the client as raw text.

-<? require_once "$docroot/webGui/include/DefaultPageLayout/HeadInlineJS.php"; ?>
+<?php require_once "$docroot/webGui/include/DefaultPageLayout/HeadInlineJS.php"; ?>

(and similarly for the other includes)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a5f48da and ee39fc2.

📒 Files selected for processing (17)
  • api/dev/Unraid.net/myservers.cfg (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/file-modification.ts (2 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/.login.php (4 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/.login.php.last-download-time (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/DefaultPageLayout.php (4 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/DefaultPageLayout.php.last-download-time (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/Notifications.page.last-download-time (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/auth-request.php.last-download-time (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/snapshots/.login.php.modified.snapshot.php (4 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/snapshots/DefaultPageLayout.php.modified.snapshot.php (5 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/default-page-layout.modification.ts (2 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/log-viewer.modification.ts (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/notifications-page.modification.ts (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/patches/default-page-layout.patch (2 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/patches/sso.patch (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/set-password-modal.modification.ts (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/sso.modification.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
api/src/unraid-api/unraid-file-modifier/modifications/patches/default-page-layout.patch (2)
Learnt from: elibosley
PR: unraid/api#1101
File: api/src/unraid-api/unraid-file-modifier/modifications/patches/default-page-layout.patch:6-20
Timestamp: 2025-01-31T22:01:41.842Z
Learning: The default-page-layout.patch is used to remove the old jGrowl notification system from Unraid pages, as notifications are handled by a new system implemented on a different page.
Learnt from: elibosley
PR: unraid/api#1101
File: api/src/unraid-api/unraid-file-modifier/modifications/patches/default-page-layout.patch:6-20
Timestamp: 2025-01-31T22:01:41.842Z
Learning: The default-page-layout.patch removes the old jGrowl notification system and is complemented by the unraid-toaster component implementation. The new system is added through the DefaultPageLayout modification which inserts the toaster component with proper position configuration based on user preferences.
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Test API
  • GitHub Check: Build Web App
  • GitHub Check: Build API
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (22)
api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/.login.php.last-download-time (1)

1-1: Fixture timestamp refresh
Updated the .login.php last-download-time to align with the new snapshot. This keeps the test fixture in sync after refactoring.

api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/auth-request.php.last-download-time (1)

1-1: Fixture timestamp refresh
Updated the auth-request.php last-download-time to the new value, matching the refreshed fixture state.

api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/Notifications.page.last-download-time (1)

1-1: Fixture timestamp refresh
Bumped the Notifications.page last-download-time to reflect the latest refactored output.

api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/DefaultPageLayout.php.last-download-time (1)

1-1: Fixture timestamp refresh
Updated the DefaultPageLayout.php last-download-time to sync with the newly modularized layout snapshot.

api/dev/Unraid.net/myservers.cfg (1)

2-2: Verify API version change
The [api] section version was downgraded from 4.7.0 to 4.4.1. Please confirm this rollback is intentional and ensure any version-dependent logic or documentation is updated accordingly.

api/src/unraid-api/unraid-file-modifier/modifications/log-viewer.modification.ts (1)

44-49: Appropriate version check for Unraid 7.2 compatibility

The addition of this version check ensures that LogViewer modifications are skipped on Unraid 7.2.0 or newer, which aligns with the PR objective of disabling file changes for this version.

api/src/unraid-api/unraid-file-modifier/modifications/notifications-page.modification.ts (1)

21-26: Consistent version check implementation

This implementation properly skips NotificationsPage modifications on Unraid 7.2.0 and higher, maintaining compatibility as required by the PR.

api/src/unraid-api/unraid-file-modifier/modifications/set-password-modal.modification.ts (1)

22-27: Version check correctly implemented

The version check follows the same pattern as other modification files, ensuring consistent behavior across the codebase for Unraid 7.2 compatibility.

api/src/unraid-api/unraid-file-modifier/modifications/__test__/snapshots/.login.php.modified.snapshot.php (4)

218-220: Improved theme handling with ThemeHelper

Good implementation of the ThemeHelper class to centralize theme logic and improve code maintainability.


224-224: Refactored HTML class attribution

Using getThemeHtmlClass() from ThemeHelper provides a cleaner approach to setting theme-based HTML classes.


258-259: Simplified theme color logic

The use of $isDarkTheme boolean makes the CSS color selection more readable and maintainable than direct theme checks.


435-435: Consistent theme handling in media queries

Theme handling is consistently updated in the media query section, ensuring unified behavior across different viewport sizes.

api/src/unraid-api/unraid-file-modifier/modifications/default-page-layout.modification.ts (2)

3-5: Added necessary imports for version checking.

The new imports for semver's gte function and the getUnraidVersion utility support the version comparison functionality being added to this class.


99-107:

✅ Verification successful

Good implementation of version-based skipping for Unraid 7.2+.

This change properly implements the PR's goal of disabling file modifications on Unraid 7.2 or newer versions. The method appropriately checks the version and returns early with a clear reason when needed.


🏁 Script executed:

#!/bin/bash
# Check for consistent version checking across modification files
echo "Checking for consistent version checking in modification files..."
rg -A 10 "isUnraidVersionGreaterThanOrEqualTo" api/src/unraid-api/unraid-file-modifier/modifications/

Length of output: 7713


Consistent Unraid 7.2+ version checks in all modifications
I’ve verified that each file under api/src/unraid-api/unraid-file-modifier/modifications implements the same early-return check for Unraid 7.2+, disabling their changes appropriately:

• sso.modification.ts
• set-password-modal.modification.ts
• notifications-page.modification.ts
• log-viewer.modification.ts
• default-page-layout.modification.ts

No further action required.

api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/.login.php (3)

167-169: Improved theme handling with ThemeHelper.

Good refactoring - replacing direct theme checks with a dedicated ThemeHelper class improves maintainability and code organization.


173-173: Enhanced theme application to HTML element.

Using the theme helper's method to set the HTML class attribute provides a more consistent approach to theming.


207-208: Consistently applied theme variables throughout the file.

All theme-dependent styling has been properly updated to use the ThemeHelper's isDarkTheme variable instead of direct checks.

Also applies to: 292-292, 384-384

api/src/unraid-api/unraid-file-modifier/modifications/sso.modification.ts (1)

94-101: Added version check to skip SSO modifications on Unraid 7.2+.

This change correctly implements the PR's goal by checking for Unraid 7.2+ before applying SSO modifications. The early return pattern keeps the code clean and maintains the existing SSO configuration check as a secondary condition.

api/src/unraid-api/unraid-file-modifier/file-modification.ts (2)

7-9: Added imports for version comparison functionality.

These imports properly support the new version checking capability being added to the FileModification class.


243-253: Well-implemented version comparison utility method.

This is a solid implementation of the version comparison functionality:

  • Takes an optional version parameter with sensible default (7.2.0)
  • Includes options for handling prerelease versions
  • Properly coerces version strings to semver objects
  • Includes appropriate error handling
  • Uses standard semver comparison

This reusable method provides a consistent way for all modification classes to implement version-based conditional logic.

api/src/unraid-api/unraid-file-modifier/modifications/patches/sso.patch (1)

68-71: Graceful fallback if legacy function remains in codebase

You replaced verifyUsernamePassword with verifyUsernamePasswordAndSSO. If any old call sites remain, they will fatal-error. Recommend keeping a thin wrapper:

function verifyUsernamePassword($u, $p) {
    return verifyUsernamePasswordAndSSO($u, $p);
}
api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/DefaultPageLayout.php (1)

14-19: Verify $docroot is initialised and non-user-controlled before file inclusion

require_once "$docroot/plugins/dynamix/include/ThemeHelper.php"; implicitly trusts $docroot.
If a malicious request (or mis-configuration) can influence this variable you could end up loading arbitrary PHP, leading to RCE.
Please ensure $docroot is set server-side only and never derived from request data, or wrap it in a whitelist check.

@elibosley elibosley marked this pull request as ready for review May 19, 2025 16:18
@elibosley elibosley requested review from mdatelle and pujitm as code owners May 19, 2025 16:18
@elibosley elibosley force-pushed the feat/page-modifications-for-7.2 branch from ee39fc2 to fe2a708 Compare May 20, 2025 13:07
@elibosley elibosley requested a review from zackspear as a code owner May 20, 2025 13:07
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

🔭 Outside diff range comments (1)
api/src/unraid-api/unraid-file-modifier/modifications/__test__/snapshots/DefaultPageLayout.php.modified.snapshot.php (1)

698-700: ⚠️ Potential issue

Escape shell paths before exec / pkill.

$script is interpolated directly into a shell command.
A page or plugin author could (accidentally or maliciously) register a script name containing spaces or shell-meta characters, resulting in command-injection.

-    $script = explode(':',$row)[0];
-    exec("$docroot/$script &>/dev/null &");
+    $script = escapeshellcmd(explode(':', $row)[0]);
+    exec("$docroot/$script &>/dev/null &");
...
-      exec("pkill -f $docroot/$script &>/dev/null &");
+      $cmd = escapeshellcmd("$docroot/$script");
+      exec("pkill -f $cmd &>/dev/null &");

Using escapeshellcmd() (or, better, proc_open without a shell) eliminates that risk.

Also applies to: 703-706

♻️ Duplicate comments (4)
api/src/unraid-api/unraid-file-modifier/modifications/__test__/snapshots/DefaultPageLayout.php.modified.snapshot.php (1)

713-713: Sanitise $display['rtl'] before dumping into the <html> tag.
See earlier review – value should be limited to '' or dir="rtl".

api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/DefaultPageLayout.php (3)

698-706: Duplicate of the shell-command issue noted in the snapshot file – please apply the same fix here.


739-747: Duplicate of the CSS-injection concern – same validation logic recommended.


713-713: Duplicate of the $display['rtl'] sanitisation note.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between ee39fc2 and fe2a708.

📒 Files selected for processing (18)
  • api/src/unraid-api/unraid-file-modifier/file-modification.ts (2 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/.login.php (4 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/.login.php.last-download-time (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/DefaultPageLayout.php (4 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/DefaultPageLayout.php.last-download-time (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/Notifications.page.last-download-time (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/auth-request.php.last-download-time (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/snapshots/.login.php.modified.snapshot.php (4 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/snapshots/DefaultPageLayout.php.modified.snapshot.php (4 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/auth-request.modification.ts (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/default-page-layout.modification.ts (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/log-viewer.modification.ts (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/notifications-page.modification.ts (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/patches/default-page-layout.patch (2 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/patches/sso.patch (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/set-password-modal.modification.ts (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/sso.modification.ts (1 hunks)
  • vitest.workspace.js (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • vitest.workspace.js
🚧 Files skipped from review as they are similar to previous changes (13)
  • api/src/unraid-api/unraid-file-modifier/modifications/test/fixtures/downloaded/.login.php.last-download-time
  • api/src/unraid-api/unraid-file-modifier/modifications/test/fixtures/downloaded/DefaultPageLayout.php.last-download-time
  • api/src/unraid-api/unraid-file-modifier/modifications/test/fixtures/downloaded/auth-request.php.last-download-time
  • api/src/unraid-api/unraid-file-modifier/modifications/test/fixtures/downloaded/Notifications.page.last-download-time
  • api/src/unraid-api/unraid-file-modifier/modifications/notifications-page.modification.ts
  • api/src/unraid-api/unraid-file-modifier/modifications/log-viewer.modification.ts
  • api/src/unraid-api/unraid-file-modifier/modifications/default-page-layout.modification.ts
  • api/src/unraid-api/unraid-file-modifier/file-modification.ts
  • api/src/unraid-api/unraid-file-modifier/modifications/set-password-modal.modification.ts
  • api/src/unraid-api/unraid-file-modifier/modifications/sso.modification.ts
  • api/src/unraid-api/unraid-file-modifier/modifications/test/snapshots/.login.php.modified.snapshot.php
  • api/src/unraid-api/unraid-file-modifier/modifications/test/fixtures/downloaded/.login.php
  • api/src/unraid-api/unraid-file-modifier/modifications/patches/default-page-layout.patch
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: Build Web App
  • GitHub Check: Test API
  • GitHub Check: Build API
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (5)
api/src/unraid-api/unraid-file-modifier/modifications/auth-request.modification.ts (2)

67-72: Good implementation of version-based conditional application

The version check nicely prevents applying modifications to Unraid 7.2.0+ where the feature is already built-in. This helps avoid duplicating functionality in newer OS versions.


75-75: Clear reason message updated for consistency

The updated reason message clearly explains why the patch is being applied for versions below 7.2.0.

api/src/unraid-api/unraid-file-modifier/modifications/patches/sso.patch (3)

9-57: Well-structured SSO authentication function

The new function properly handles both traditional password verification and SSO token validation with good security practices:

  • Proper shell argument escaping
  • Token format validation with regex
  • Comprehensive error logging
  • Exception handling for JSON parsing

The implementation follows a sensible fallback approach - first trying normal password verification before attempting SSO validation.


70-70: Appropriate function replacement

Correctly updated to use the new SSO-enabled authentication function.


82-82: SSO login UI integration

The inclusion of the SSO login PHP file properly integrates the UI components needed for the SSO functionality.

Copy link
Contributor

@zackspear zackspear left a comment

Choose a reason for hiding this comment

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

generally looks good, but it might make sense to have a consts file of unraid versions for version control. Since 7.2.0 has fundamental changes, we could explain in just one place why 7.2.0 is the "magic" version.

either way, approved if you feel like it's not relevant

@github-actions
Copy link
Contributor

This plugin has been deployed to Cloudflare R2 and is available for testing.
Download it at this URL:

https://preview.dl.unraid.net/unraid-api/tag/PR1382/dynamix.unraid.net.plg

@elibosley elibosley merged commit 02de89d into main May 20, 2025
12 checks passed
@elibosley elibosley deleted the feat/page-modifications-for-7.2 branch May 20, 2025 19:14
pujitm pushed a commit that referenced this pull request Jul 8, 2025
🤖 I have created a release *beep* *boop*
---


## [4.9.0](v4.8.0...v4.9.0)
(2025-07-08)


### Features

* add graphql resource for API plugins
([#1420](#1420))
([642a220](642a220))
* add management page for API keys
([#1408](#1408))
([0788756](0788756))
* add rclone ([#1362](#1362))
([5517e75](5517e75))
* API key management
([#1407](#1407))
([d37dc3b](d37dc3b))
* api plugin management via CLI
([#1416](#1416))
([3dcbfbe](3dcbfbe))
* build out docker components
([#1427](#1427))
([711cc9a](711cc9a))
* docker and info resolver issues
([#1423](#1423))
([9901039](9901039))
* fix shading in UPC to be less severe
([#1438](#1438))
([b7c2407](b7c2407))
* info resolver cleanup
([#1425](#1425))
([1b279bb](1b279bb))
* initial codeql setup
([#1390](#1390))
([2ade7eb](2ade7eb))
* initialize claude code in codebse
([#1418](#1418))
([b6c4ee6](b6c4ee6))
* move api key fetching to use api key service
([#1439](#1439))
([86bea56](86bea56))
* move to cron v4 ([#1428](#1428))
([b8035c2](b8035c2))
* move to iframe for changelog
([#1388](#1388))
([fcd6fbc](fcd6fbc))
* native slackware package
([#1381](#1381))
([4f63b4c](4f63b4c))
* send active unraid theme to docs
([#1400](#1400))
([f71943b](f71943b))
* slightly better watch mode
([#1398](#1398))
([881f1e0](881f1e0))
* upgrade nuxt-custom-elements
([#1461](#1461))
([345e83b](345e83b))
* use bigint instead of long
([#1403](#1403))
([574d572](574d572))


### Bug Fixes

* activation indicator removed
([5edfd82](5edfd82))
* alignment of settings on ManagementAccess settings page
([#1421](#1421))
([70c790f](70c790f))
* allow rclone to fail to initialize
([#1453](#1453))
([7c6f02a](7c6f02a))
* always download 7.1 versioned files for patching
([edc0d15](edc0d15))
* api `pnpm type-check`
([#1442](#1442))
([3122bdb](3122bdb))
* **api:** connect config `email` validation
([#1454](#1454))
([b9a1b9b](b9a1b9b))
* backport
unraid/webgui[#2269](https://github.com/unraid/api/issues/2269) rc.nginx
update ([#1436](#1436))
([a7ef06e](a7ef06e))
* bigint
([e54d27a](e54d27a))
* config migration from `myservers.cfg`
([#1440](#1440))
([c4c9984](c4c9984))
* **connect:** fatal race-condition in websocket disposal
([#1462](#1462))
([0ec0de9](0ec0de9))
* **connect:** mothership connection
([#1464](#1464))
([7be8bc8](7be8bc8))
* console hidden
([9b85e00](9b85e00))
* debounce is too long
([#1426](#1426))
([f12d231](f12d231))
* delete legacy connect keys and ensure description
([22fe91c](22fe91c))
* **deps:** pin dependencies
([#1465](#1465))
([ba75a40](ba75a40))
* **deps:** pin dependencies
([#1470](#1470))
([412b329](412b329))
* **deps:** storybook v9
([#1476](#1476))
([45bb49b](45bb49b))
* **deps:** update all non-major dependencies
([#1366](#1366))
([291ee47](291ee47))
* **deps:** update all non-major dependencies
([#1379](#1379))
([8f70326](8f70326))
* **deps:** update all non-major dependencies
([#1389](#1389))
([cb43f95](cb43f95))
* **deps:** update all non-major dependencies
([#1399](#1399))
([68df344](68df344))
* **deps:** update dependency @types/diff to v8
([#1393](#1393))
([00da27d](00da27d))
* **deps:** update dependency cache-manager to v7
([#1413](#1413))
([9492c2a](9492c2a))
* **deps:** update dependency commander to v14
([#1394](#1394))
([106ea09](106ea09))
* **deps:** update dependency diff to v8
([#1386](#1386))
([e580f64](e580f64))
* **deps:** update dependency dotenv to v17
([#1474](#1474))
([d613bfa](d613bfa))
* **deps:** update dependency lucide-vue-next to ^0.509.0
([#1383](#1383))
([469333a](469333a))
* **deps:** update dependency marked to v16
([#1444](#1444))
([453a5b2](453a5b2))
* **deps:** update dependency shadcn-vue to v2
([#1302](#1302))
([26ecf77](26ecf77))
* **deps:** update dependency vue-sonner to v2
([#1401](#1401))
([53ca414](53ca414))
* disable file changes on Unraid 7.2
([#1382](#1382))
([02de89d](02de89d))
* do not start API with doinst.sh
([7d88b33](7d88b33))
* do not uninstall fully on 7.2
([#1484](#1484))
([2263881](2263881))
* drop console with terser
([a87d455](a87d455))
* error logs from `cloud` query when connect is not installed
([#1450](#1450))
([719f460](719f460))
* flash backup integration with Unraid Connect config
([#1448](#1448))
([038c582](038c582))
* header padding regression
([#1477](#1477))
([e791cc6](e791cc6))
* incorrect state merging in redux store
([#1437](#1437))
([17b7428](17b7428))
* lanip copy button not present
([#1459](#1459))
([a280786](a280786))
* move to bigint scalar
([b625227](b625227))
* node_modules dir removed on plugin update
([#1406](#1406))
([7b005cb](7b005cb))
* omit Connect actions in UPC when plugin is not installed
([#1417](#1417))
([8c8a527](8c8a527))
* parsing of `ssoEnabled` in state.php
([#1455](#1455))
([f542c8e](f542c8e))
* pin ranges ([#1460](#1460))
([f88400e](f88400e))
* pr plugin promotion workflow
([#1456](#1456))
([13bd9bb](13bd9bb))
* proper fallback if missing paths config modules
([7067e9e](7067e9e))
* rc.unraid-api now cleans up older dependencies
([#1404](#1404))
([83076bb](83076bb))
* remote access lifecycle during boot & shutdown
([#1422](#1422))
([7bc583b](7bc583b))
* sign out correctly on error
([#1452](#1452))
([d08fc94](d08fc94))
* simplify usb listing
([#1402](#1402))
([5355115](5355115))
* theme issues when sent from graph
([#1424](#1424))
([75ad838](75ad838))
* **ui:** notifications positioning regression
([#1445](#1445))
([f73e5e0](f73e5e0))
* use some instead of every for connect detection
([9ce2fee](9ce2fee))


### Reverts

* revert package.json dependency updates from commit 711cc9a for api and
packages/*
([94420e4](94420e4))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants