Skip to content

Next release#1615

Merged
jokob-sk merged 7 commits intomainfrom
next_release
Apr 15, 2026
Merged

Next release#1615
jokob-sk merged 7 commits intomainfrom
next_release

Conversation

@jokob-sk
Copy link
Copy Markdown
Collaborator

@jokob-sk jokob-sk commented Apr 14, 2026

Summary by CodeRabbit

  • Improvements
    • Filter options now use distinct value+label entries, are sorted by label, and render safely in dropdowns.
    • Backend filter queries return richer, human-friendly labels (including improved parent-device labeling) and use a unified null/placeholder check.
  • Enhancement
    • Scans backfill missing Sync Hub Node entries when a site node name is configured; scan processing logs this step.
  • Tests
    • Added tests validating hub-node backfill behavior and filter option handling.
  • Documentation
    • Added test-guidance on reusing shared test helpers.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 14, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ab582cbc-2199-4dc3-a124-21fd137f66b0

📥 Commits

Reviewing files that changed from the base of the PR and between 7c7beaa and a5b4f2a.

📒 Files selected for processing (2)
  • .github/skills/code-standards/SKILL.md
  • test/scan/test_sync_hub_node_backfill.py

📝 Walkthrough

Walkthrough

Frontend filter options are converted to {value,label} objects and PHP rendering now supports value/label arrays; backend filter SQL adds columnLabel and adjusts devParentMAC labeling; a scan-time backfill populates missing Devices.devSyncHubNode from SYNC_node_name; tests for the backfill were added.

Changes

Cohort / File(s) Summary
Frontend filter construction
front/devices.php
Filter options now emitted as objects { value, label }; merges compare opt.value to existing entry.columnValue; new groups initialize options with { value, label }; options sorted by label using localeCompare.
PHP rendering
front/php/components/devices_filters.php
renderFilterDropdown() accepts scalar or associative-array values; when an element is an array it uses $item['value'] and $item['label']; escapes value and label independently before emitting <option>.
Backend SQL for filters
server/const.py
sql_devices_filters converted to an f-string interpolating NULL_EQUIVALENTS_SQL; each filter subquery returns columnLabel alongside columnValue; devParentMAC now derives columnLabel via a LEFT JOIN to parent device name with COALESCE and groups using COLLATE NOCASE.
Scan backfill logic
server/scan/device_handling.py, server/scan/session_events.py
Added update_sync_hub_node(db) to backfill Devices.devSyncHubNode from trimmed SYNC_node_name when existing values match NULL_EQUIVALENTS_SQL (commits DB); process_scan now invokes this step with logging.
Tests
test/scan/test_sync_hub_node_backfill.py
New pytest module using in-memory SQLite to verify backfill updates empty/NULL/"null" hub nodes, does not overwrite existing non-empty nodes, and is a no-op when the setting is empty or None.
Repo policy
.github/skills/code-standards/SKILL.md
Added guidance to reuse shared test helpers and avoid duplicating dummy DB mocks or inline DDL in individual tests.

Sequence Diagram

sequenceDiagram
    participant DB as Database
    participant PY as Backend (Python)
    participant PHP as PHP Renderer
    participant JS as Frontend

    DB->>PY: Execute `sql_devices_filters` → rows with `columnValue` + `columnLabel`
    PY->>PHP: Return filter rows (value,label)
    PHP->>JS: Serve page with options represented as `{ value, label }`
    JS->>JS: Deduplicate by `value`, sort by `label` and render dropdown
Loading
sequenceDiagram
    participant Scheduler as Scan Runner
    participant Session as session_events.process_scan
    participant Handler as device_handling.update_sync_hub_node
    participant DB as Database

    Scheduler->>Session: start process_scan()
    Session->>DB: update_devices_data_from_scan()
    Session->>Handler: call update_sync_hub_node(db)
    Handler->>DB: UPDATE Devices SET devSyncHubNode = <SYNC_node_name> WHERE COALESCE(LOWER(TRIM(devSyncHubNode)), '') IN {NULL_EQUIVALENTS_SQL}
    Handler->>DB: db.commitDB()
    Session->>DB: update_devLastConnection_from_CurrentScan()
Loading

Poem

🐰 I hop through rows and code so spry,
I pair a label where raw strings lie,
I patch the hub when names are thin,
I leave true nodes their place within,
Dropdowns bloom — a joyful nibble 🥕

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Next release' is vague and generic, providing no meaningful information about the specific changes in the pull request. Replace with a descriptive title summarizing the main changes, such as 'Refactor device filters to use labeled object structure' or 'Add sync hub node backfill and improve filter UI'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch next_release

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
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 (1)
front/devices.php (1)

458-460: Consider improving numeric string sorting in filter options.

The current code sorts filter labels using localeCompare(b.label), which sorts numeric strings lexicographically (e.g., "10", "100", "20"). For VLAN IDs and similar numeric-like values, consider using localeCompare(..., undefined, { numeric: true }) for more intuitive sorting. Additionally, wrap the label in String() as a defensive measure:

Suggested improvement
                    transformed.filters.forEach(filter => {
-                      filter.options.sort((a, b) => a.label.localeCompare(b.label));
+                      filter.options.sort((a, b) =>
+                        String(a.label ?? '').localeCompare(
+                          String(b.label ?? ''),
+                          undefined,
+                          { numeric: true, sensitivity: 'base' }
+                        )
+                      );
                    });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@front/devices.php` around lines 458 - 460, The sort currently uses
filter.options.sort((a, b) => a.label.localeCompare(b.label)), which orders
numeric strings lexicographically; update the comparator in the
transformed.filters.forEach loop to call localeCompare with the numeric option
and defend against non-string labels by wrapping labels with String(), e.g., use
String(a.label).localeCompare(String(b.label), undefined, { numeric: true }) so
VLAN-like numeric labels sort intuitively.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@server/const.py`:
- Around line 99-104: The SELECT uses COALESCE(p.devName, d.devParentMAC) which
does not treat empty strings as NULL, producing blank dropdown labels; update
the expression so empty p.devName falls back to d.devParentMAC (e.g., replace
COALESCE(p.devName, d.devParentMAC) with COALESCE(NULLIF(p.devName, ''),
d.devParentMAC) or an equivalent CASE/NULLIF pattern) in the SELECT that builds
columnLabel (the query using aliases p and d and columnLabel).

---

Nitpick comments:
In `@front/devices.php`:
- Around line 458-460: The sort currently uses filter.options.sort((a, b) =>
a.label.localeCompare(b.label)), which orders numeric strings lexicographically;
update the comparator in the transformed.filters.forEach loop to call
localeCompare with the numeric option and defend against non-string labels by
wrapping labels with String(), e.g., use
String(a.label).localeCompare(String(b.label), undefined, { numeric: true }) so
VLAN-like numeric labels sort intuitively.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a74e0c47-7154-4abc-b9d0-3ea76dc74216

📥 Commits

Reviewing files that changed from the base of the PR and between 090b7e0 and 285bd3e.

📒 Files selected for processing (3)
  • front/devices.php
  • front/php/components/devices_filters.php
  • server/const.py

Comment thread server/const.py
Copy link
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@server/scan/device_handling.py`:
- Around line 249-259: Normalize the retrieved setting and existing DB values
before backfilling: call get_setting_value and immediately trim whitespace and
normalize case (e.g., node_name = get_setting_value(...).strip().lower()), then
return if node_name is empty; in the UPDATE statement for Devices (the
devSyncHubNode column referenced in the COALESCE(...) condition), compare
against trimmed/lowercased DB values (use SQL functions like TRIM/LOWER on
devSyncHubNode) and the normalized literals ('' and 'null') so values like "
NULL " or whitespace-only settings are treated as empty and won't be persisted
as node names.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2cbf4548-00d3-4050-a2c1-bd531ff86754

📥 Commits

Reviewing files that changed from the base of the PR and between 285bd3e and 89139fe.

📒 Files selected for processing (3)
  • server/scan/device_handling.py
  • server/scan/session_events.py
  • test/scan/test_sync_hub_node_backfill.py

Comment thread server/scan/device_handling.py Outdated
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Copy link
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@server/scan/device_handling.py`:
- Around line 243-263: In update_sync_hub_node, the SQL IN clause uses
NULL_EQUIVALENTS_SQL without surrounding parentheses causing invalid SQL; update
the f-string in the sql.execute call inside update_sync_hub_node to wrap
NULL_EQUIVALENTS_SQL in parentheses (i.e. use IN ({NULL_EQUIVALENTS_SQL})) so
the comma-separated list is a valid SQL tuple, then run db.commitDB() as before.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: df40f25f-0a10-440d-9605-6c54ade28bd8

📥 Commits

Reviewing files that changed from the base of the PR and between 89139fe and c046298.

📒 Files selected for processing (2)
  • server/const.py
  • server/scan/device_handling.py

Comment thread server/scan/device_handling.py
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Copy link
Copy Markdown
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.

Caution

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

⚠️ Outside diff range comments (1)
server/scan/device_handling.py (1)

403-412: ⚠️ Potential issue | 🔴 Critical

Parameterize default_icon in the SELECT filter.

Line 404 interpolates a user-configurable setting directly into SQL ('{default_icon}'). That can break query semantics and is an injection vector.

🔧 Proposed fix
     if get_setting_value("NEWDEV_replace_preset_icon"):
         query = f"""SELECT * FROM Devices
-                    WHERE devIcon in ({NULL_EQUIVALENTS_SQL}, '{default_icon}')
+                    WHERE devIcon in ({NULL_EQUIVALENTS_SQL}, ?)
                         OR devIcon IS NULL"""
+        params = (default_icon,)
     else:
         query = f"""SELECT * FROM Devices
                     WHERE devIcon in ({NULL_EQUIVALENTS_SQL})
                         OR devIcon IS NULL"""
+        params = ()

-    for device in sql.execute(query):
+    for device in sql.execute(query, params):
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/scan/device_handling.py` around lines 403 - 412, The SELECT currently
injects default_icon into the SQL string (devIcon in (..., '{default_icon}')),
which is an injection risk; change the code that builds the query to use a bound
parameter for default_icon (e.g., a placeholder like ? or %s depending on the DB
driver) and pass default_icon as an argument to sql.execute instead of
interpolating it. Locate the branch that references NULL_EQUIVALENTS_SQL and
default_icon in device_handling.py (the query variable and the subsequent
sql.execute loop) and replace the inline '{default_icon}' with a parameter
placeholder and include default_icon in the execute call so the DB driver
handles escaping/typing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@server/scan/device_handling.py`:
- Around line 403-412: The SELECT currently injects default_icon into the SQL
string (devIcon in (..., '{default_icon}')), which is an injection risk; change
the code that builds the query to use a bound parameter for default_icon (e.g.,
a placeholder like ? or %s depending on the DB driver) and pass default_icon as
an argument to sql.execute instead of interpolating it. Locate the branch that
references NULL_EQUIVALENTS_SQL and default_icon in device_handling.py (the
query variable and the subsequent sql.execute loop) and replace the inline
'{default_icon}' with a parameter placeholder and include default_icon in the
execute call so the DB driver handles escaping/typing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f3ee545d-e5dc-48d2-a971-2b786c842fa2

📥 Commits

Reviewing files that changed from the base of the PR and between c046298 and 7c7beaa.

📒 Files selected for processing (1)
  • server/scan/device_handling.py

@jokob-sk
Copy link
Copy Markdown
Collaborator Author

review @coderabbitai

@jokob-sk jokob-sk merged commit a4b494b into main Apr 15, 2026
6 checks passed
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 15, 2026

@jokob-sk Sure, I'll review the changes in this PR now!

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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.

1 participant