Skip to content

Next release#1677

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

Next release#1677
jokob-sk wants to merge 4 commits into
mainfrom
next_release

Conversation

@jokob-sk

@jokob-sk jokob-sk commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added REST Import plugin for importing devices from external APIs with configurable field mapping, authentication support, and deterministic MAC address generation.
    • Improved modal dialog responsiveness for larger screens and added scrolling support.
  • Documentation

    • Added plugin development guide and REST Import plugin configuration documentation with usage examples.
  • Tests

    • Added comprehensive test suite for REST Import plugin functionality.

jokob-sk added 3 commits June 17, 2026 06:43
- Implemented the REST Import plugin (rest_import.py) to handle importing data from REST APIs.
- Added functionality for configurable HTTP methods, authentication types, and custom headers.
- Included error handling for various HTTP response statuses and connection issues.
- Created unit tests for the plugin covering header building, path resolution, MAC validation, record mapping, and authentication methods.
- Ensured that module-level side effects are patched during tests to prevent live interactions.
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a new rest_import plugin that fetches device records from configurable REST endpoints, normalizes/validates MACs (or generates fake MACs from IPs), maps fields to CurrentScan, and writes plugin result files. Includes full config.json schema, a Python implementation, a pytest suite, and a README. Also fixes modal dialog layout via CSS, PHP, and JS changes, and adds a Gemini plugin-development skill document.

Changes

REST Import Plugin

Layer / File(s) Summary
Plugin identity, config schema, and README
front/plugins/rest_import/config.json, front/plugins/rest_import/README.md
Defines plugin identity (RSTIMPRT), execution parameters, an imports popup form with auth modes and field mappings, SET_ALWAYS/SET_EMPTY overwrite policies, database column definitions tagging rows with RSTIMPRT, and full README documentation including an OPNsense example.
Python entrypoint and HTTP pipeline
front/plugins/rest_import/rest_import.py
Implements module constants, main(), process_import() orchestration, build_headers(), build_auth(), make_request() with exception handling, and resolve_path() for dot-separated JSON traversal.
Record mapping and MAC validation
front/plugins/rest_import/rest_import.py
Implements map_record(), _resolve_mac() for real/fake MAC derivation from IP, _get_field() for config-driven field extraction, and validate_mac() for normalization and pattern checking.
pytest suite
test/plugins/test_rest_import.py
Tests build_headers, resolve_path, validate_mac, map_record (including fake MAC generation paths), and build_auth across valid, edge-case, and invalid inputs with patched module-level side effects.

Modal UI Fixes and Dev Docs

Layer / File(s) Summary
Modal layout, scroll container, and popup form option logic
front/css/app.css, front/php/templates/modals.php, front/js/modal.js, front/js/settings_utils.js
Adds a responsive CSS rule constraining .modal-dialog to 750px; updates modal-form-plc to cap height at 60vh with vertical scroll; adjusts fieldOptionsOverride to prefer field.options for select-type fields; adds a console.log debug statement in generateFormHtml.
Gemini plugin-development skill doc
.gemini/skills/plugin-development/plugin-skill.md
Adds a skill document describing the plugin development workflow and prefix naming constraints.

Sequence Diagram(s)

sequenceDiagram
  participant main as main()
  participant process_import as process_import()
  participant make_request as make_request()
  participant resolve_path as resolve_path()
  participant map_record as map_record()
  participant Plugin_Objects as Plugin_Objects

  main->>process_import: decoded import cfg (url, auth, field mappings)
  process_import->>make_request: url, method, ssl_verify, auth, headers, post_body
  make_request-->>process_import: parsed JSON response or None
  process_import->>resolve_path: response data, device_list_path
  resolve_path-->>process_import: records list or None
  loop for each record
    process_import->>map_record: record, cfg, mac_field, ip_field, fake_mac
    map_record-->>process_import: mapped fields dict or None
    process_import->>Plugin_Objects: add_object(mapped fields)
  end
  main->>Plugin_Objects: write_result_file()
Loading

Poem

A rabbit hops to REST endpoints with glee,
Fetching devices from each JSON tree.
If MACs are missing, a fake one's derived—
fa:ce: prefixed so nothing's deprived.
The modal scrolls, the dialog is neat,
A new plugin skill makes the workflow complete! 🐇

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.27% 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 this changeset. Replace with a descriptive title that captures the main changes, such as 'Add REST import plugin with field mapping and modal improvements' or similar.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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.

✏️ 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.

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

Caution

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

⚠️ Outside diff range comments (1)
front/plugins/rest_import/README.md (1)

79-85: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use the standard ### Other info section format.

The README currently uses ### Notes; plugin READMEs in this repo should use the standardized ### Other info section and fields for consistency.

📝 Suggested patch
-### Notes
-
-- Version: 1.0.0
-- Author: `jokob-sk`
-- Records with missing or invalid MAC addresses are skipped unless **Generate Fake MAC** is enabled
-- Each import definition executes independently; failed imports do not block others
+### Notes
+
+- Records with missing or invalid MAC addresses are skipped unless **Generate Fake MAC** is enabled
+- Each import definition executes independently; failed imports do not block others
+
+### Other info
+
+- Version: 1.0.0
+- Author: [jokob-sk](https://github.com/jokob-sk)
+- Release Date: 17-Jun-2026

Based on learnings: plugin READMEs under front/plugins/**/README.md should include a ### Other info section with standardized labels.

🤖 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/rest_import/README.md` around lines 79 - 85, Replace the `###
Notes` section header with `### Other info` to align with the standardized
plugin README format used across the repository. Keep all the content (Version,
Author, and the behavioral notes about MAC addresses and import definitions)
exactly as is, only changing the section header name.

Source: Learnings

🧹 Nitpick comments (3)
.gemini/skills/plugin-development/plugin-skill.md (1)

7-7: ⚡ Quick win

Align step 5 with imperative verb pattern for consistency.

Steps 1–4 use imperative verbs ("Assess," "Read," "Confirm," "Ask"), but step 5 uses passive phrasing ("code placed in"). For consistency and clarity, rephrase as an imperative statement.

✨ Proposed fix for consistency
-5. code placed in `front/plugins/<new plugin name>`
+5. Place code in `front/plugins/<new plugin name>`
🤖 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 @.gemini/skills/plugin-development/plugin-skill.md at line 7, In the
plugin-skill.md file at step 5, the phrasing "code placed in" uses passive voice
which is inconsistent with the imperative verb pattern used in steps 1-4
("Assess," "Read," "Confirm," "Ask"). Rephrase step 5 to use an imperative verb
form that matches the pattern of the previous steps, such as starting with an
action verb like "Place" or "Create" instead of the passive construction.
front/js/settings_utils.js (1)

1178-1178: ⚡ Quick win

Remove debug console.log statement.

This debug log will execute on every form field generation, creating unnecessary console output. Please remove or comment it out before merging.

🧹 Proposed cleanup
-  console.log(setType);
🤖 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` at line 1178, Remove the console.log(setType)
debug statement from the code. This statement is executing on every form field
generation and creating unnecessary console output. Simply delete the line
containing console.log(setType) to clean up the debug code before merging.
front/php/templates/modals.php (1)

132-132: 💤 Low value

Consider moving inline styles to a CSS class.

The inline styles work correctly for enabling scroll behavior, but extracting them to a CSS class in app.css would improve maintainability and reusability.

♻️ Proposed refactor

In front/css/app.css, add:

`#modal-form-plc` {
  overflow-y: auto;
  max-height: 60vh;
  padding: 0 15px;
}

Then update this line to:

-<div id="modal-form-plc" style="overflow-y: auto; max-height: 60vh; padding: 0 15px;"></div>
+<div id="modal-form-plc"></div>
🤖 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/php/templates/modals.php` at line 132, The div element with
id="modal-form-plc" contains inline styles for overflow-y, max-height, and
padding that should be externalized for better maintainability and reusability.
Remove the style attribute from the modal-form-plc div element in the modals.php
file and add a corresponding CSS rule in front/css/app.css targeting the
`#modal-form-plc` selector with the three style properties (overflow-y: auto,
max-height: 60vh, and padding: 0 15px).
🤖 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/rest_import/config.json`:
- Around line 470-485: The RSTIMPRT_password and RSTIMPRT_bearer_token input
fields in the configuration are currently rendering as plain text inputs, which
exposes sensitive values during editing. Modify the elementOptions for both the
RSTIMPRT_password function (around line 470) and the RSTIMPRT_bearer_token
function (around line 508) to add an input type property set to "password" in
their respective elementOptions arrays to mask the input values on screen.

In `@front/plugins/rest_import/README.md`:
- Around line 66-77: Add a language identifier to the fenced code block that
contains the OPNsense DHCP configuration example. Change the opening triple
backticks (```) to include a language identifier (```text) to comply with
markdownlint rule MD040, which requires all fenced code blocks to have a
specified language for proper syntax highlighting and linting compliance.

In `@front/plugins/rest_import/rest_import.py`:
- Around line 117-118: Before calling map_record() in the loop that iterates
through records at line 117-118, add a guard check to ensure each record is a
dictionary object. If the record is not a dict (e.g., it's a scalar or list),
skip processing that record or handle it appropriately. Apply the same guard
check to the other location mentioned in the comment around lines 232-235 where
map_record() is also called.
- Around line 59-61: The `decode_settings_base64()` function's return value is
not validated before being passed to `process_import()`, which will cause
failures when cfg.get() is called on malformed or non-dict data. Add validation
after decoding the raw_config in the loop to ensure cfg is a valid dictionary
with expected structure, then either skip invalid configs with appropriate
logging or raise an informative error before calling process_import(cfg,
plugin_objects). Apply this validation consistently to all occurrences mentioned
in the comment including the loop at lines 59-61 and the related code at lines
67-82.
- Around line 206-208: The exception handler catching
requests.exceptions.RequestException is logging the raw exception object `e`
which can leak sensitive endpoint data like URLs and query strings. Replace the
direct logging of the exception in the mylog call with a generic error message
that does not include the exception details, ensuring only safe context
information is logged without exposing the actual request exception content.

---

Outside diff comments:
In `@front/plugins/rest_import/README.md`:
- Around line 79-85: Replace the `### Notes` section header with `### Other
info` to align with the standardized plugin README format used across the
repository. Keep all the content (Version, Author, and the behavioral notes
about MAC addresses and import definitions) exactly as is, only changing the
section header name.

---

Nitpick comments:
In @.gemini/skills/plugin-development/plugin-skill.md:
- Line 7: In the plugin-skill.md file at step 5, the phrasing "code placed in"
uses passive voice which is inconsistent with the imperative verb pattern used
in steps 1-4 ("Assess," "Read," "Confirm," "Ask"). Rephrase step 5 to use an
imperative verb form that matches the pattern of the previous steps, such as
starting with an action verb like "Place" or "Create" instead of the passive
construction.

In `@front/js/settings_utils.js`:
- Line 1178: Remove the console.log(setType) debug statement from the code. This
statement is executing on every form field generation and creating unnecessary
console output. Simply delete the line containing console.log(setType) to clean
up the debug code before merging.

In `@front/php/templates/modals.php`:
- Line 132: The div element with id="modal-form-plc" contains inline styles for
overflow-y, max-height, and padding that should be externalized for better
maintainability and reusability. Remove the style attribute from the
modal-form-plc div element in the modals.php file and add a corresponding CSS
rule in front/css/app.css targeting the `#modal-form-plc` selector with the three
style properties (overflow-y: auto, max-height: 60vh, and padding: 0 15px).
🪄 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: 9d6408b1-c7ba-4825-862e-f4950dab9ea4

📥 Commits

Reviewing files that changed from the base of the PR and between 3752d74 and bb29824.

📒 Files selected for processing (9)
  • .gemini/skills/plugin-development/plugin-skill.md
  • front/css/app.css
  • front/js/modal.js
  • front/js/settings_utils.js
  • front/php/templates/modals.php
  • front/plugins/rest_import/README.md
  • front/plugins/rest_import/config.json
  • front/plugins/rest_import/rest_import.py
  • test/plugins/test_rest_import.py

Comment on lines +470 to +485
"function": "RSTIMPRT_password",
"type": {
"dataType": "string",
"elements": [
{
"elementType": "input",
"elementOptions": [
{
"placeholder": "Password or API Secret"
},
{
"cssClasses": "col-sm-10"
}
],
"transformers": []
}

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Mask secret fields in the popup form.

RSTIMPRT_password and RSTIMPRT_bearer_token are currently plain text inputs, which exposes sensitive values during editing.

🔐 Suggested patch
                   {
                     "function": "RSTIMPRT_password",
                     "type": {
                       "dataType": "string",
                       "elements": [
                         {
                           "elementType": "input",
                           "elementOptions": [
+                            {
+                              "type": "password"
+                            },
                             {
                               "placeholder": "Password or API Secret"
                             },
                             {
                               "cssClasses": "col-sm-10"
                             }
                           ],
                           "transformers": []
                         }
                       ]
                     },
@@
                   {
                     "function": "RSTIMPRT_bearer_token",
                     "type": {
                       "dataType": "string",
                       "elements": [
                         {
                           "elementType": "input",
                           "elementOptions": [
+                            {
+                              "type": "password"
+                            },
                             {
                               "placeholder": "Bearer token"
                             },
                             {
                               "cssClasses": "col-sm-10"
                             }
                           ],
                           "transformers": []
                         }
                       ]
                     },

Also applies to: 508-523

🤖 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/rest_import/config.json` around lines 470 - 485, The
RSTIMPRT_password and RSTIMPRT_bearer_token input fields in the configuration
are currently rendering as plain text inputs, which exposes sensitive values
during editing. Modify the elementOptions for both the RSTIMPRT_password
function (around line 470) and the RSTIMPRT_bearer_token function (around line
508) to add an input type property set to "password" in their respective
elementOptions arrays to mask the input values on screen.

Comment on lines +66 to +77
```
Name: OPNsense DHCP
URL: https://firewall/api/dnsmasq/leases/search
Method: GET
Auth Type: basic
Username: admin
Device List Path: rows
MAC Address: hwaddr
IP Address: address
Device Name: hostname
Vendor: mac_info
```

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a language to the fenced configuration block.

The fenced block at Line 66 has no language identifier, matching the markdownlint MD040 warning.

📝 Suggested patch
-```
+```text
 Name:              OPNsense DHCP
 URL:               https://firewall/api/dnsmasq/leases/search
 Method:            GET
 Auth Type:         basic
 Username:          admin
 Device List Path:  rows
 MAC Address:       hwaddr
 IP Address:        address
 Device Name:       hostname
 Vendor:            mac_info
</details>

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.22.1)</summary>

[warning] 66-66: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

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/rest_import/README.md around lines 66 - 77, Add a language
identifier to the fenced code block that contains the OPNsense DHCP
configuration example. Change the opening triple backticks () to include a language identifier (text) to comply with markdownlint rule MD040, which
requires all fenced code blocks to have a specified language for proper syntax
highlighting and linting compliance.


</details>

<!-- fingerprinting:phantom:poseidon:hawk -->

<!-- cr-comment:v1:3a910b619fdb2af36c9e5dda -->

_Source: Linters/SAST tools_

<!-- This is an auto-generated comment by CodeRabbit -->

Comment on lines +59 to +61
for raw_config in import_configs:
cfg = decode_settings_base64(raw_config)
process_import(cfg, plugin_objects)

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Validate decoded import configs before processing.

If decode_settings_base64() returns malformed/non-dict data, process_import() will fail on cfg.get(...) and abort the run.

🛠️ Suggested patch
-    for raw_config in import_configs:
-        cfg = decode_settings_base64(raw_config)
-        process_import(cfg, plugin_objects)
+    for idx, raw_config in enumerate(import_configs):
+        cfg = decode_settings_base64(raw_config)
+        if not isinstance(cfg, dict):
+            mylog('none', [f'[{pluginName}] Skipping import #{idx + 1} - invalid config payload'])
+            continue
+        process_import(cfg, plugin_objects)

Also applies to: 67-82

🤖 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/rest_import/rest_import.py` around lines 59 - 61, The
`decode_settings_base64()` function's return value is not validated before being
passed to `process_import()`, which will cause failures when cfg.get() is called
on malformed or non-dict data. Add validation after decoding the raw_config in
the loop to ensure cfg is a valid dictionary with expected structure, then
either skip invalid configs with appropriate logging or raise an informative
error before calling process_import(cfg, plugin_objects). Apply this validation
consistently to all occurrences mentioned in the comment including the loop at
lines 59-61 and the related code at lines 67-82.

Comment on lines +117 to +118
for idx, record in enumerate(records):
result = map_record(name, idx, record, cfg, mac_field, ip_field, fake_mac)

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard against non-object records before mapping.

map_record() expects a dict (record.get(...)). If the resolved list contains scalars/lists, this raises and stops processing.

🛠️ Suggested patch
     for idx, record in enumerate(records):
+        if not isinstance(record, dict):
+            mylog('none', [f'[{pluginName}] Skipped record {idx} - record is not an object for "{name}"'])
+            skipped += 1
+            continue
         result = map_record(name, idx, record, cfg, mac_field, ip_field, fake_mac)
         if result is None:
             skipped += 1
             continue

Also applies to: 232-235

🤖 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/rest_import/rest_import.py` around lines 117 - 118, Before
calling map_record() in the loop that iterates through records at line 117-118,
add a guard check to ensure each record is a dictionary object. If the record is
not a dict (e.g., it's a scalar or list), skip processing that record or handle
it appropriately. Apply the same guard check to the other location mentioned in
the comment around lines 232-235 where map_record() is also called.

Comment on lines +206 to +208
except requests.exceptions.RequestException as e:
mylog('none', [f'[{pluginName}] Request error for "{name}": {e}'])
return None

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid logging raw request exception text.

RequestException messages can include full URLs/query strings, which risks leaking sensitive endpoint data into logs.

🔐 Suggested patch
-    except requests.exceptions.RequestException as e:
-        mylog('none', [f'[{pluginName}] Request error for "{name}": {e}'])
+    except requests.exceptions.RequestException as e:
+        mylog('none', [f'[{pluginName}] Request error for "{name}" ({e.__class__.__name__})'])
         return None
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
except requests.exceptions.RequestException as e:
mylog('none', [f'[{pluginName}] Request error for "{name}": {e}'])
return None
except requests.exceptions.RequestException as e:
mylog('none', [f'[{pluginName}] Request error for "{name}" ({e.__class__.__name__})'])
return None
🤖 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/rest_import/rest_import.py` around lines 206 - 208, The
exception handler catching requests.exceptions.RequestException is logging the
raw exception object `e` which can leak sensitive endpoint data like URLs and
query strings. Replace the direct logging of the exception in the mylog call
with a generic error message that does not include the exception details,
ensuring only safe context information is logged without exposing the actual
request exception content.

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