Skip to content

FE: Notifications sorting fix #1713#1714

Open
jokob-sk wants to merge 15 commits into
mainfrom
next_release
Open

FE: Notifications sorting fix #1713#1714
jokob-sk wants to merge 15 commits into
mainfrom
next_release

Conversation

@jokob-sk

@jokob-sk jokob-sk commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • Bug Fixes
    • Fixed DataTables timestamp sorting by preserving the raw timezone-trimmed value for sort while keeping localized display.
  • Improvements
    • Strengthened Telegram notifications with size-safe truncation and more reliable request handling.
    • Ensured webhook payloads are serialized once for consistent logging and signature generation.
    • Improved notification database cleanup by retaining only the newest entries.
    • Expanded notification templates/placeholders (VLAN/site/SSID) and updated related settings to use multiline text.
    • Updated Omada SDN OpenAPI plugin to v0.5; normalized missing client IP values to null, and extended “always override” imports to include VLAN.
  • Documentation
    • Updated the public contact email address used in security, donations, and conduct/disclosure materials.

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • ✅ Review completed - (🔄 Check again to review again)
📝 Walkthrough

Walkthrough

Notification rendering, publisher delivery, notification fields, cleanup SQL, Omada normalization, import configuration, and project contact information were updated.

Changes

Notification timestamp rendering

Layer / File(s) Summary
Timestamp render logic
front/userNotifications.php
Sorting and non-display timestamp renders now return the timezone-trimmed value before display rendering applies localization.

Publisher delivery

Layer / File(s) Summary
Telegram request execution
front/plugins/_publisher_telegram/tg.py
Telegram messages account for the truncation marker, use JSON payloads and non-shell curl arguments with timeouts, log stdout, and raise errors for failed responses.
Webhook payload consistency
front/plugins/_publisher_webhook/webhook.py
One compact JSON serialization is reused for logging, HMAC signing, and both request paths.

Notification field propagation

Layer / File(s) Summary
Notification field selection and templates
server/messaging/notification_sections.py, front/plugins/notification_processing/config.json
Notification queries and template descriptions now include devVlan, devSite, and devSSID.
Import field configuration
front/plugins/rest_import/config.json
devVlan was added to the SET_ALWAYS options.

Plugin maintenance

Layer / File(s) Summary
Notification retention query
front/plugins/db_cleanup/script.py
Notification cleanup now retains the newest configured rows using descending creation time and a limit subquery.
Omada normalization
front/plugins/omada_sdn_openapi/script.py
The plugin version is 0.5, and missing IP values are normalized to "null".

Project contact updates

Layer / File(s) Summary
Contact and reporting information
.github/ISSUE_TEMPLATE/security-report.yml, CODE_OF_CONDUCT.md, README.md, docs/SECURITY.md, back/update_vendors.sh, front/css/app.css, front/js/*, front/php/..., install/production-filesystem/services/scripts/update_vendors.sh, server/__main__.py
Contact references now use netalertx@gmail.com; security guidance also references GitHub security advisories.

Sequence Diagram(s)

sequenceDiagram
  participant Publisher as Telegram publisher
  participant Curl as curl subprocess
  participant Telegram as Telegram API
  Publisher->>Publisher: Truncate and serialize message
  Publisher->>Curl: Execute curl with JSON request
  Curl->>Telegram: Send message
  Telegram-->>Curl: Return response
  Curl-->>Publisher: Return stdout or process error
  Publisher->>Publisher: Raise error for unsuccessful response
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main functional change: fixing notification timestamp sorting.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@front/userNotifications.php`:
- Around line 91-93: Update the conditional in the DataTables rendering callback
around the sort/type handling to return the raw value whenever type is not
"display". Replace the limited sort/type check with a type !== "display" check
so filter uses the unlocalized value as well.
🪄 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: 319f419c-5a35-4fb3-b8a9-6da928d0ff44

📥 Commits

Reviewing files that changed from the base of the PR and between 2924b4c and 05e0f69.

📒 Files selected for processing (1)
  • front/userNotifications.php

Comment thread front/userNotifications.php Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@front/plugins/_publisher_telegram/tg.py`:
- Line 109: Update the debug logging around the Telegram command in the
publisher flow to avoid including the bot token embedded in the API URL. Log
only the operation name or a URL with the token redacted, while preserving the
existing command execution behavior.
- Around line 88-91: Update the truncation logic in the payload construction
block to ensure the final payload, including " (text was truncated)", never
exceeds TELEGRAM_SIZE. Reduce the text slice by the marker length before
appending it, while preserving the existing unmodified text path when no
truncation is needed.
- Around line 99-118: Add curl connection and total request timeouts to the
command assembled in the Telegram publisher flow before subprocess.run, using
values both below RUN_TIMEOUT. Update the cmd construction associated with the
sendMessage request while preserving the existing subprocess behavior and
logging.
🪄 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: 5cb31b82-0f48-4585-80fd-a7ad5baeb671

📥 Commits

Reviewing files that changed from the base of the PR and between 84bc713 and 30df63b.

📒 Files selected for processing (1)
  • front/plugins/_publisher_telegram/tg.py

Comment thread front/plugins/_publisher_telegram/tg.py
Comment thread front/plugins/_publisher_telegram/tg.py
Comment thread front/plugins/_publisher_telegram/tg.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@front/plugins/_publisher_telegram/tg.py`:
- Around line 116-118: Remove the standalone stray period immediately before the
mylog("debug", ["Executing: Telegram sendMessage", "--data <json>"]) call,
leaving the surrounding list or statement structure valid so tg.py parses and
runs successfully.
🪄 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: 552e935e-1710-42ec-b6ea-cda26f2375f8

📥 Commits

Reviewing files that changed from the base of the PR and between 30df63b and 776a415.

📒 Files selected for processing (1)
  • front/plugins/_publisher_telegram/tg.py

Comment thread front/plugins/_publisher_telegram/tg.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (3)
front/plugins/db_cleanup/script.py (3)

132-138: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Parameterize the SQL query to prevent potential injection or syntax errors.

Using string formatting for query construction (flagged by Ruff S608) can lead to SQL syntax errors if histCount evaluates to an empty string, or pose an injection risk if the setting is tampered with. Parameterizing the LIMIT clause and casting to int ensures type safety. Additionally, using "index" (lowercase) perfectly matches the table schema.

🛡️ Proposed fix
-    delete_query = f"""DELETE FROM Notifications
-                        WHERE "Index" NOT IN (
-                            SELECT "Index" FROM Notifications
-                            ORDER BY dateTimeCreated DESC
-                            LIMIT {histCount}
-                        );"""
-    cursor.execute(delete_query)
+    delete_query = """DELETE FROM Notifications
+                        WHERE "index" NOT IN (
+                            SELECT "index" FROM Notifications
+                            ORDER BY dateTimeCreated DESC
+                            LIMIT ?
+                        );"""
+    # Provide a safe integer fallback to avoid runtime errors
+    cursor.execute(delete_query, (int(histCount) if str(histCount).isdigit() else 100,))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@front/plugins/db_cleanup/script.py` around lines 132 - 138, Update the delete
query construction and cursor.execute call in the cleanup flow to remove
f-string interpolation, cast histCount to int, and bind it as a SQL parameter
for the LIMIT clause. Use the schema-matching lowercase "index" identifier in
both column references while preserving the existing notification-retention
behavior.

132-138: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Parameterize the SQL query to prevent injection and syntax errors.

Using string formatting for query construction (flagged by Ruff S608) can lead to SQL syntax errors if histCount evaluates to an empty string (the default when the setting is missing), or pose an injection risk if the setting is tampered with. Parameterizing the LIMIT clause and safely casting to int ensures type safety and stability.

Additionally, using "index" (lowercase) perfectly matches the table schema.

🛡️ Proposed fix
-    delete_query = f"""DELETE FROM Notifications
-                        WHERE "Index" NOT IN (
-                            SELECT "Index" FROM Notifications
-                            ORDER BY dateTimeCreated DESC
-                            LIMIT {histCount}
-                        );"""
-    cursor.execute(delete_query)
+    delete_query = """DELETE FROM Notifications
+                        WHERE "index" NOT IN (
+                            SELECT "index" FROM Notifications
+                            ORDER BY dateTimeCreated DESC
+                            LIMIT ?
+                        );"""
+    # Provide a safe integer fallback in case `histCount` is empty/None
+    cursor.execute(delete_query, (int(histCount or 100),))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@front/plugins/db_cleanup/script.py` around lines 132 - 138, Update the
delete_query construction and cursor.execute call to parameterize the LIMIT
value instead of interpolating histCount. Safely convert the configured
histCount to an integer, including handling its missing or empty default, and
pass it as the query parameter; also use the schema-matching lowercase "index"
identifier in both column references.

Source: Linters/SAST tools


132-138: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Parameterize the SQL query to prevent injection and syntax errors.

Static analysis tools (Ruff S608) flag this string-based query construction as a potential SQL injection vector. Since histCount is fetched from database settings, parameterizing the limit clause avoids potential injection or syntax errors (e.g., if histCount evaluates to an empty string). Additionally, it's safer to use "index" (lowercase) to strictly match the table schema.

🛡️ Proposed fix to parameterize the query
-    delete_query = f"""DELETE FROM Notifications
-                        WHERE "Index" NOT IN (
-                            SELECT "Index" FROM Notifications
-                            ORDER BY dateTimeCreated DESC
-                            LIMIT {histCount}
-                        );"""
-    cursor.execute(delete_query)
+    delete_query = """DELETE FROM Notifications
+                        WHERE "index" NOT IN (
+                            SELECT "index" FROM Notifications
+                            ORDER BY dateTimeCreated DESC
+                            LIMIT ?
+                        );"""
+    # Cast to int to ensure type safety; provide a safe fallback if empty
+    cursor.execute(delete_query, (int(histCount) if str(histCount).isdigit() else 1000,))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@front/plugins/db_cleanup/script.py` around lines 132 - 138, Update the
delete_query construction before cursor.execute to parameterize histCount in the
LIMIT clause instead of interpolating it into the SQL string, ensuring the value
is validated or converted to the expected numeric type and handling an empty
setting safely. Use the schema’s lowercase "index" identifier consistently in
both the DELETE and subquery references.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@front/plugins/omada_sdn_openapi/script.py`:
- Around line 172-175: Update the missing-IP handling in the entry-processing
logic to assign Python None rather than the string "null" when
entry["ip_address"] is absent or equals "None". Preserve this value through
serialization so the plugin contract emits JSON null, without introducing a
sentinel string.

---

Nitpick comments:
In `@front/plugins/db_cleanup/script.py`:
- Around line 132-138: Update the delete query construction and cursor.execute
call in the cleanup flow to remove f-string interpolation, cast histCount to
int, and bind it as a SQL parameter for the LIMIT clause. Use the
schema-matching lowercase "index" identifier in both column references while
preserving the existing notification-retention behavior.
- Around line 132-138: Update the delete_query construction and cursor.execute
call to parameterize the LIMIT value instead of interpolating histCount. Safely
convert the configured histCount to an integer, including handling its missing
or empty default, and pass it as the query parameter; also use the
schema-matching lowercase "index" identifier in both column references.
- Around line 132-138: Update the delete_query construction before
cursor.execute to parameterize histCount in the LIMIT clause instead of
interpolating it into the SQL string, ensuring the value is validated or
converted to the expected numeric type and handling an empty setting safely. Use
the schema’s lowercase "index" identifier consistently in both the DELETE and
subquery references.
🪄 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: 72963693-2d2b-46ad-beea-e14b4e91f997

📥 Commits

Reviewing files that changed from the base of the PR and between 776a415 and d8e8939.

📒 Files selected for processing (3)
  • front/plugins/_publisher_telegram/tg.py
  • front/plugins/db_cleanup/script.py
  • front/plugins/omada_sdn_openapi/script.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • front/plugins/_publisher_telegram/tg.py

Comment thread front/plugins/omada_sdn_openapi/script.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (2)
front/plugins/_publisher_telegram/tg.py (2)

102-115: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Keep the bot token and notification body out of curl arguments.

The argv list removes shell-injection risk, but it still exposes the bot token and full notification payload through process listings such as /proc and ps. Pass the JSON body through stdin and use a protected mechanism for the token instead of embedding either value in cmd.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@front/plugins/_publisher_telegram/tg.py` around lines 102 - 115, Update the
curl invocation in the command-building flow so neither the Telegram bot token
nor the notification payload appears in cmd: pass the JSON payload through
subprocess stdin and supply the token via a protected non-argv mechanism
supported by curl, while preserving the existing endpoint, headers, and timeout
behavior.

120-135: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Propagate failed Telegram sends instead of returning them as normal results.

check=False ignores curl failures, and the code never checks proc.returncode or Telegram’s ok response field. OSError is also converted into an ordinary string. Since main() unconditionally writes the returned value to watched2, failed deliveries can become indistinguishable from successful publisher results.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@front/plugins/_publisher_telegram/tg.py` around lines 120 - 135, Update the
Telegram send subprocess flow around subprocess.run so nonzero curl return codes
and Telegram responses with ok=false are treated as failures and propagated to
main() rather than returned as successful output. Ensure OSError exceptions are
likewise propagated instead of converted to strings, while preserving normal
return behavior for successful deliveries.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@front/plugins/_publisher_telegram/tg.py`:
- Around line 102-115: Update the curl invocation in the command-building flow
so neither the Telegram bot token nor the notification payload appears in cmd:
pass the JSON payload through subprocess stdin and supply the token via a
protected non-argv mechanism supported by curl, while preserving the existing
endpoint, headers, and timeout behavior.
- Around line 120-135: Update the Telegram send subprocess flow around
subprocess.run so nonzero curl return codes and Telegram responses with ok=false
are treated as failures and propagated to main() rather than returned as
successful output. Ensure OSError exceptions are likewise propagated instead of
converted to strings, while preserving normal return behavior for successful
deliveries.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 23329338-72fd-43e2-beeb-72cc89637f55

📥 Commits

Reviewing files that changed from the base of the PR and between d8e8939 and 123fe32.

📒 Files selected for processing (1)
  • front/plugins/_publisher_telegram/tg.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@front/js/settings_utils.js`:
- Around line 1108-1123: The JSON.parse catch in collectSetting must propagate
validation failure instead of returning the invalid input, preventing it from
being saved as valid. Preserve valid JSON string contents by removing the
regex-based replacements and, only if required by the backend, perform
Python-literal conversion structurally rather than altering serialized text.
🪄 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 Plus

Run ID: acbe33d5-26a1-4a7b-8f77-a0994e642c97

📥 Commits

Reviewing files that changed from the base of the PR and between 056f5ed and 02987fa.

📒 Files selected for processing (20)
  • .github/ISSUE_TEMPLATE/security-report.yml
  • CODE_OF_CONDUCT.md
  • README.md
  • back/update_vendors.sh
  • docs/SECURITY.md
  • front/css/app.css
  • front/js/app-init.js
  • front/js/cache.js
  • front/js/common.js
  • front/js/settings_utils.js
  • front/js/ui_components.js
  • front/php/server/db.php
  • front/php/server/util.php
  • front/php/templates/header.php
  • front/php/templates/modals.php
  • front/plugins/notification_processing/config.json
  • front/settings.php
  • install/production-filesystem/services/scripts/update_vendors.sh
  • server/__main__.py
  • server/models/device_instance.py
🚧 Files skipped from review as they are similar to previous changes (14)
  • front/php/templates/header.php
  • .github/ISSUE_TEMPLATE/security-report.yml
  • front/js/app-init.js
  • README.md
  • front/js/common.js
  • front/php/templates/modals.php
  • back/update_vendors.sh
  • front/css/app.css
  • front/php/server/util.php
  • front/js/cache.js
  • server/main.py
  • install/production-filesystem/services/scripts/update_vendors.sh
  • docs/SECURITY.md
  • front/js/ui_components.js

Comment on lines +1108 to +1123
try {
value = JSON.parse(value);
} catch (e) {
console.error(`[collectSetting] Invalid JSON for ${setCodeName}`, e);
return value;
}

value = JSON.stringify(value, null, 2)
.replace(/\btrue\b/g, "True")
.replace(/\bfalse\b/g, "False")
.replace(/\bnull\b/g, "None");

console.log("---------------")
console.log(value)

return value;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Reject invalid JSON without mutating valid JSON values.

Line 1112 returns invalid input, so collectSetting() saves it as valid. Also, the regex replacements alter string content—for example {"label":"true"} becomes {"label":"True"}. Propagate a validation failure from this handler, and use a structure-aware conversion only if the backend truly requires Python-style literals.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@front/js/settings_utils.js` around lines 1108 - 1123, The JSON.parse catch in
collectSetting must propagate validation failure instead of returning the
invalid input, preventing it from being saved as valid. Preserve valid JSON
string contents by removing the regex-based replacements and, only if required
by the backend, perform Python-literal conversion structurally rather than
altering serialized text.

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