Skip to content

Prefill data based on gitea issue#21

Open
juancolchete wants to merge 61 commits intoteambtcmap:mainfrom
UAIBIT:main
Open

Prefill data based on gitea issue#21
juancolchete wants to merge 61 commits intoteambtcmap:mainfrom
UAIBIT:main

Conversation

@juancolchete
Copy link
Copy Markdown

@juancolchete juancolchete commented Jan 15, 2026

Problem

A lot of data on gitea community creation issue, but this data is not automatic bring to btcmap admin application.

Solution

Prefill this fields on community creation passing a issue id.

How it works

We pass the issue-id as a query parameter as bellow sample.

add_area?issue-id=1103

Implementation

/**
 * With issue data fill forms fields to add community 
 * @param {Object} issueData - The Gitea issue data that comes from fetchIssueData
 * @returns {} 
 * @throws {} 
 */
fillFields(issueData)

/**
 * With contact data that comes from fillFields fill the optional fields on form that are related with community contact 
 * @param {Array<string>} contact - The the field social links with all community contact information 
 * @returns {} 
 * @throws {} 
 */
fillContactFields(contact)

/**
 * With issue id it gets it from gitea parse its data and then fill the required and optional fields on the form based on issue data on Gitea issue body 
 * @param {number} issueId - The Gitea issue ID
 * @returns {} 
 * @throws {Error} If the fetch fails or issue doesn't exist, if a timeout happens or if has an server or API service error. 
 */
fillFieldsPassingIssue(issueId){

/**
 * Fetches issue data from Gitea API
 * @param {number} issueId - The Gitea issue ID
 * @returns {Promise<Object>} The issue data object
 * @throws {Error} If the fetch fails or issue doesn't exist, if a timeout happens or if has an server or API service error. 
 */
fetchIssueData(issueId) 

/**
 * With issue body, process its data and transform in a base object 
 * @param {string} issueText - The the field social links with all community contact information 
 * @returns {Promise<Object>} The issue body data as a parsed object with the main properties 
 * @throws {} 
 */
parseIssueData(issueText)

 /**
  * The social links string content is tranformed in a string array with contact information  
  * @param {string} contactText - The the field social links with all community contact information 
  * @returns {Array<string>} - Array with contact information 
  * @throws {} 
  */
 fillContact(contactText)

 /**
  * Passing a text without formatation, this text is normalized to get its main data  
  * @param {string} text - Unformated text 
  * @returns {string} - Formatted text 
  * @throws {} 
  */
cleanIssueText(text)

 /**
  * Passing the name of URL parameter we get its value  
  * @param {string} sParam - The search string also known as URL parameter 
  * @returns {string} - The URL parameter content
  * @throws {} 
  */
getURLParameter(sParam)

Summary by CodeRabbit

  • New Features

    • URL-driven auto-fill for area creation from external issue data (name, contacts, description, icon)
    • New client utilities for reading URL parameters and normalizing text
  • Bug Fixes / Validation

    • Stricter validation and length/pattern checks for area fields, tips, description, and many contact/social entries
  • Chores

    • Added environment sample and direnv export, updated ignore rules, reproducible dev shell, and dependency list file

@juancolchete
Copy link
Copy Markdown
Author

Ready for review

@escapedcat
Copy link
Copy Markdown
Contributor

Who's bot is this? :D

@dadofsambonzuki
Copy link
Copy Markdown
Member

dadofsambonzuki commented Feb 20, 2026 via email

@dadofsambonzuki
Copy link
Copy Markdown
Member

Dave got banned 🫠. He's appealing.

Here's what he said:

Looking at this PR #21 (UAIBIT Gitea Integration) and the previous Claude review, here's my take:

My Assessment

The Good:

• The feature itself is genuinely useful — auto-filling forms from Gitea issues will save time for community onboarding
• The contributor (juancolchete) has been responsive and iterating based on feedback
• Leverages the existing form infrastructure well rather than reinventing

The Concerns (mostly echoing Claude's review):

🔴 Critical to fix before merge:

  1. XSS vulnerability — The innerHTML injection on line 474 is a real issue. Untrusted data from Gitea issues gets rendered directly. Even if Gitea is "internal," this is a footgun.
  2. Fragile string parsing — The indexOf() chain parsing approach fails silently when the issue template format changes. This will break later and be hard to debug.
  3. No error handling — If Gitea is down/returns 404, the user gets no feedback. The function just fails silently.

🟡 Should fix:

  1. API endpoint needs timeouts — The Python backend makes an external HTTP call without timeout or proper error handling. This can hang the request.
  2. Use apiFetch() not raw fetch() — Inconsistent with the rest of the codebase, means session expiry isn't handled properly.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 11, 2026

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
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds dev tooling and env integration (direnv, Nix flake, requirements), exposes GITEA_BASE_URL in Flask and tightens many input validators, introduces frontend utilities, and implements a client-side autofill pipeline that fetches and parses a Gitea issue to prepopulate the add_area form.

Changes

Cohort / File(s) Summary
Environment & Dev tooling
\.env.sample, \.envrc, \.gitignore, flake.nix, requirements.txt
Adds env sample and direnv integration (.envrc writing .direnv/.env), updates .gitignore to ignore .direnv/venv, adds a Nix flake.nix devShell (python311, virtualenv, geos, LD_LIBRARY_PATH), and new requirements.txt.
Backend - Config & validation
app.py
Adds app.config['GITEA_BASE_URL'] (env fallback) and tightens validation schema: stricter url_alias, length/pattern constraints for many contact:* fields, tips:lightning_address pattern/length, and description min/max lengths.
Frontend - Utilities
static/js/utils.js
New helpers: getURLParameter(sParam) and cleanIssueText(text) for query parsing and issue-text normalization.
Frontend - add_area form & autofill
templates/add_area.html
Large client-side changes: switched some external script URLs, included utils.js, made DOM init async, introduced MIN_FIELD_LENGTH, preserved tag rows on type change, and added fetch→parse→fill logic to auto-populate fields and contact tags from a Gitea issue when issue-id is present. Review parsing regex/mapping, async ordering, and DOM mutation points.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Browser as Browser / add_area.html
    participant Utils as utils.js
    participant Backend as Flask API
    participant Gitea as Gitea API

    User->>Browser: Open add_area page (with ?issue-id=N)
    Browser->>Utils: getURLParameter('issue-id')
    Utils-->>Browser: issue-id
    Browser->>Backend: GET /api/gitea/get-issue/N
    activate Backend
    Backend->>Gitea: HTTP GET /api/v1/repos/.../issues/N
    activate Gitea
    Gitea-->>Backend: issue JSON
    deactivate Gitea
    Backend-->>Browser: JSON { success, data }
    deactivate Backend
    Browser->>Browser: parseIssueData(issue.body)
    Browser->>Browser: fillFields(parsedData)
    Browser->>Utils: cleanIssueText(contactText)
    Utils-->>Browser: cleaned text
    Browser-->>User: Form inputs and tag rows pre-filled
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • dadofsambonzuki

Poem

🐇 I hopped through flakes and envs tonight,
Fetched issues, parsed fields by soft moonlight,
Trimmed lines, made tags, suggested a name,
Prefilled the form — a rabbit's tiny claim.
Hop in, reviewers, and nibble through the changes!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

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.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Prefill data based on gitea issue' accurately and concisely summarizes the main feature addition—enabling form prefill from Gitea issues via URL parameters.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

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

Caution

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

⚠️ Outside diff range comments (1)
app.py (1)

36-169: ⚠️ Potential issue | 🟠 Major

These new field constraints are not enforced server-side yet.

add_area() and set_area_tag() still only run the type-based validators, so the new pattern, min_length, and max_length entries in this block are currently dead config. Invalid aliases/contact URLs and too-short descriptions can still bypass the backend. Also, contact:matrix uses matrix instead of pattern, so that rule would still be skipped after the generic fix.

As per coding guidelines "Mirror client-side validation logic from static/js/validation.js on the server side".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app.py` around lines 36 - 169, The server-side schema additions (pattern,
min_length, max_length) in the area field definitions are not being enforced
because add_area() and set_area_tag() only run type-based validation; update
those functions to validate string length and regex patterns from the schema for
each field (including treating the contact:matrix entry's "matrix" key as a
pattern), applying min_length, max_length and pattern checks when type ==
'text'/'url'/'email'/'tel' etc., and return/raise the same validation errors the
client expects so the backend mirrors static/js/validation.js.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.envrc:
- Line 3: Replace the unsafe global dump "env > .direnv/.env" with an explicit
export/whitelist approach: remove that line and instead write only the
application-specific variables you need into .direnv/.env (or use direnv's
layout/export commands) — for example, explicitly export APP_VAR1, APP_VAR2, and
any required secrets from a secure source rather than serializing the entire
shell environment; ensure the implementation updates the .env creation step that
currently uses "env > .direnv/.env" so only the named variables are persisted.

In `@app.py`:
- Line 21: The GITEA_BASE_URL is being read from the wrong environment variable
(os.environ.get('SECRET_KEY')), causing the app.config['GITEA_BASE_URL'] to be
set to the secret; update the lookup to read the correct env var name (e.g.,
os.environ.get('GITEA_BASE_URL', 'https://gitea.btcmap.org')) so
app.config['GITEA_BASE_URL'] uses the intended Gitea host; modify the assignment
where app.config['GITEA_BASE_URL'] is set to reference the correct environment
variable name.

In `@requirements.txt`:
- Line 4: Remove standard library packages listed in requirements.txt: delete
the "datetime" and "typing" entries (they are stdlib on Python 3.10) so they are
not treated as PyPI dependencies; update requirements.txt accordingly and run
your dependency resolver/CI check to confirm no remaining stdlib entries cause
resolver noise.

In `@templates/add_area.html`:
- Around line 510-511: The calls to createTagRow(...) are passing untrusted
issue/body values into a function that builds DOM via row.innerHTML, enabling
XSS; update createTagRow to stop using innerHTML and instead construct the row
with createElement/createTextNode and setAttribute/textContent for all
user-controlled values (or otherwise explicitly escape values before insertion),
then ensure callers (the places that call createTagRow such as the lines adding
newRow to tagsTable) continue to append the returned Element; reference
createTagRow and any usage that assigns row.innerHTML and replace that
implementation with safe DOM APIs.
- Around line 420-437: The loop parsing issueText currently uses a default
endKey ("Created at: ") which causes a field to swallow the rest of the issue
when the immediate next marker is missing; change the logic in the for loop that
uses keys/startKey/endKey to search forward from i+1 for the next marker that
actually exists in issueText (use issueText.indexOf(keys[j]) !== -1) and use
that marker as endKey; if no subsequent marker is found, do not take the rest of
the document — instead set issueData[fieldName] to "" (and optionally warn) so
missing intermediate markers don't corrupt following fields; update places
referencing issueTemplate, startKey, endKey, issueText, issueData in the loop
accordingly.
- Around line 473-476: The loop that filters contactRaw using
"if(contactRaw[i].length > MIN_FIELD_LENGTH)" wrongly drops valid short values;
instead trim the value and check for non-empty presence before pushing to the
contact array (e.g., use a trimmed variable like value = contactRaw[i].trim()
and if(value) contact.push(value)), and apply the same change to the similar
block around 541-546 so that length validation is deferred to the form
validators rather than this prefill logic.

---

Outside diff comments:
In `@app.py`:
- Around line 36-169: The server-side schema additions (pattern, min_length,
max_length) in the area field definitions are not being enforced because
add_area() and set_area_tag() only run type-based validation; update those
functions to validate string length and regex patterns from the schema for each
field (including treating the contact:matrix entry's "matrix" key as a pattern),
applying min_length, max_length and pattern checks when type ==
'text'/'url'/'email'/'tel' etc., and return/raise the same validation errors the
client expects so the backend mirrors static/js/validation.js.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e0afce12-6df6-4698-ad73-d22f5fbe8d7d

📥 Commits

Reviewing files that changed from the base of the PR and between f2697ae and aeef449.

⛔ Files ignored due to path filters (1)
  • flake.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • .env.sample
  • .envrc
  • .gitignore
  • app.py
  • flake.nix
  • requirements.txt
  • static/js/utils.js
  • templates/add_area.html

…ils silently when the issue template format changes. This will break later and be hard to debug.
Copy link
Copy Markdown

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

♻️ Duplicate comments (1)
templates/add_area.html (1)

518-527: ⚠️ Potential issue | 🔴 Critical

XSS risk: untrusted issue data flows into innerHTML sink.

contact[i] originates from the Gitea issue body (untrusted) and is passed to createTagRow(), which builds DOM via row.innerHTML at line 235. A crafted value can escape the value="..." attribute and inject arbitrary HTML/script.

The fix requires createTagRow to use safe DOM APIs (createElement, setAttribute, textContent) instead of innerHTML for user-controlled values.

,

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/add_area.html` around lines 518 - 527, The loop is inserting
untrusted contact[i] into the DOM by calling
createTagRow(contactTagsInfo[j].name, contact[i], ...), and createTagRow
currently builds HTML via row.innerHTML (unsafe). Modify createTagRow to stop
using innerHTML and instead build the row using safe DOM APIs: use
document.createElement for elements, element.setAttribute for attributes, and
element.textContent (or createTextNode) to insert contact values so they are not
interpreted as HTML; ensure any values placed into attribute contexts are set
via setAttribute (not interpolated into strings) and remove any use of innerHTML
in the createTagRow implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@templates/add_area.html`:
- Around line 518-527: The loop is inserting untrusted contact[i] into the DOM
by calling createTagRow(contactTagsInfo[j].name, contact[i], ...), and
createTagRow currently builds HTML via row.innerHTML (unsafe). Modify
createTagRow to stop using innerHTML and instead build the row using safe DOM
APIs: use document.createElement for elements, element.setAttribute for
attributes, and element.textContent (or createTextNode) to insert contact values
so they are not interpreted as HTML; ensure any values placed into attribute
contexts are set via setAttribute (not interpolated into strings) and remove any
use of innerHTML in the createTagRow implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 417823c3-b3f9-466b-9d7c-7ae0c26d8f36

📥 Commits

Reviewing files that changed from the base of the PR and between aeef449 and bbeb608.

📒 Files selected for processing (1)
  • templates/add_area.html

Copy link
Copy Markdown

@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

♻️ Duplicate comments (1)
templates/add_area.html (1)

552-558: ⚠️ Potential issue | 🟡 Minor

Off-by-one: > MIN_FIELD_LENGTH excludes exactly 10-character values.

Per the server-side validation in app.py, tips:lightning_address and description have min_length: 10, meaning 10-character values are valid. Using > instead of >= silently drops these.

-      if(prefilledCommunityData?.lightningTips.length > MIN_FIELD_LENGTH){
+      if(prefilledCommunityData?.lightningTips.length >= MIN_FIELD_LENGTH){
           newRow = createTagRow('tips:lightning_address', prefilledCommunityData.lightningTips, false, false);
           tagsTable.appendChild(newRow);
       }
-      if(prefilledCommunityData?.description.length > MIN_FIELD_LENGTH){
+      if(prefilledCommunityData?.description.length >= MIN_FIELD_LENGTH){
           newRow = createTagRow('description', prefilledCommunityData.description, false, false);
           tagsTable.appendChild(newRow);
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/add_area.html` around lines 552 - 558, The client-side checks for
prefilledCommunityData.lightningTips and prefilledCommunityData.description use
strict greater-than against MIN_FIELD_LENGTH which excludes valid
exactly-10-character values; update the conditions in the code that reference
prefilledCommunityData?.lightningTips and prefilledCommunityData?.description to
use >= MIN_FIELD_LENGTH (i.e., change > to >=) so that createTagRow is called
for values of length equal to MIN_FIELD_LENGTH and those rows are appended to
tagsTable.
🧹 Nitpick comments (3)
templates/add_area.html (3)

481-490: Contact length filter may drop valid short entries.

The > MIN_FIELD_LENGTH check on line 485 filters out contact entries ≤10 characters. Valid short entries like "t.me/abc" (9 chars) or short handles would be silently dropped.

Consider using a presence check instead and letting individual contact type validators handle length requirements:

     function fillContact(contactText){ 
         let contactRaw = contactText.split("\n");
         let contact = []
         for(let i=0;i<contactRaw.length;i++){
-          if(contactRaw[i].length > MIN_FIELD_LENGTH){
-            contact.push(contactRaw[i])
+          const trimmed = contactRaw[i].trim();
+          if(trimmed){
+            contact.push(trimmed)
           }
         }
         return contact
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/add_area.html` around lines 481 - 490, The fillContact function
currently filters out entries using "if(contactRaw[i].length >
MIN_FIELD_LENGTH)", which will drop valid short contacts; change this to a
presence check (e.g., trim and check non-empty) so any non-empty line is kept
and let specific contact validators enforce length/format rules later; update
the function name fillContact and the MIN_FIELD_LENGTH usage accordingly so
MIN_FIELD_LENGTH is no longer used for presence filtering and only used where
type-specific validation occurs.

545-548: Add null checks before accessing .value on querySelector results.

If fillFields is invoked before the form type is selected and updateFields() populates the table, these selectors return null, causing a runtime error.

-      tagsTable.querySelector('input[name="name"]').value = prefilledCommunityData.name
+      const nameInput = tagsTable.querySelector('input[name="name"]');
+      if (nameInput) nameInput.value = prefilledCommunityData.name;
       document.getElementById("sugestions").textContent = `suggested logo: ${prefilledCommunityData.icon}`
       let urlAlias = prefilledCommunityData.name.normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-zA-Z0-9\s]/g, "").toLowerCase().trim().replace(/\s+/g, "-");
-      tagsTable.querySelector('input[name="url_alias"]').value = urlAlias
+      const aliasInput = tagsTable.querySelector('input[name="url_alias"]');
+      if (aliasInput) aliasInput.value = urlAlias;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/add_area.html` around lines 545 - 548, The code in fillFields that
does tagsTable.querySelector('input[name="name"]').value and
tagsTable.querySelector('input[name="url_alias"]').value and
document.getElementById("sugestions").textContent assumes those DOM nodes exist;
add null checks (or use optional chaining and defaults) before accessing
.value/.textContent so calling fillFields before the form type is selected won't
throw. Specifically, in the fillFields/updateFields flow ensure you verify the
result of tagsTable.querySelector(...) and document.getElementById("sugestions")
are non-null (or provide fallback elements/strings) before assigning, and only
compute/set urlAlias when the corresponding input element is present.

498-517: Contact regexes with anchors may miss embedded values.

Several patterns use ^...$ anchors (email at line 499, phone at line 515, nostr at line 512), which require the entire string to match. If issue data contains prefixed text like "Email: user@example.com" or "Phone: +1-555-1234", these won't match.

Consider relaxing anchors or pre-extracting the relevant portion:

-          {name:"contact:email", index: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/},
+          {name:"contact:email", index: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/},
           ...
-          {name:"contact:phone", index: /^\+?[\d\s\-()]+$/},
+          {name:"contact:phone", index: /\+[\d\s\-()]{7,}/},

Alternatively, if the issue template guarantees bare values on each line, this is fine as-is.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/add_area.html` around lines 498 - 517, The contactTagsInfo array
uses anchored regexes that only match entire strings (e.g., the email pattern,
phone pattern, and nostr pattern) which will miss embedded values; update the
entries in contactTagsInfo (specifically the objects for "contact:email",
"contact:phone", and "contact:nostr") to use unanchored/looser regexes (remove ^
and $ anchors or add search-friendly patterns) or alternatively run a
pre-extraction step over the input that extracts tokens/URLs before testing so
the existing anchored patterns can still match; ensure other patterns that
expect substrings (like "contact:website" etc.) remain unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@templates/add_area.html`:
- Line 10: Fix the misspelled HTML element id "sugestions" by renaming it to
"suggestions" in the template (the <p> element with id="sugestions") and update
any JavaScript references that use document.getElementById('sugestions') or
querySelector/#sugestions to use 'suggestions' instead so all DOM lookups and
event handlers (e.g., the code that currently references "sugestions") remain
consistent.

---

Duplicate comments:
In `@templates/add_area.html`:
- Around line 552-558: The client-side checks for
prefilledCommunityData.lightningTips and prefilledCommunityData.description use
strict greater-than against MIN_FIELD_LENGTH which excludes valid
exactly-10-character values; update the conditions in the code that reference
prefilledCommunityData?.lightningTips and prefilledCommunityData?.description to
use >= MIN_FIELD_LENGTH (i.e., change > to >=) so that createTagRow is called
for values of length equal to MIN_FIELD_LENGTH and those rows are appended to
tagsTable.

---

Nitpick comments:
In `@templates/add_area.html`:
- Around line 481-490: The fillContact function currently filters out entries
using "if(contactRaw[i].length > MIN_FIELD_LENGTH)", which will drop valid short
contacts; change this to a presence check (e.g., trim and check non-empty) so
any non-empty line is kept and let specific contact validators enforce
length/format rules later; update the function name fillContact and the
MIN_FIELD_LENGTH usage accordingly so MIN_FIELD_LENGTH is no longer used for
presence filtering and only used where type-specific validation occurs.
- Around line 545-548: The code in fillFields that does
tagsTable.querySelector('input[name="name"]').value and
tagsTable.querySelector('input[name="url_alias"]').value and
document.getElementById("sugestions").textContent assumes those DOM nodes exist;
add null checks (or use optional chaining and defaults) before accessing
.value/.textContent so calling fillFields before the form type is selected won't
throw. Specifically, in the fillFields/updateFields flow ensure you verify the
result of tagsTable.querySelector(...) and document.getElementById("sugestions")
are non-null (or provide fallback elements/strings) before assigning, and only
compute/set urlAlias when the corresponding input element is present.
- Around line 498-517: The contactTagsInfo array uses anchored regexes that only
match entire strings (e.g., the email pattern, phone pattern, and nostr pattern)
which will miss embedded values; update the entries in contactTagsInfo
(specifically the objects for "contact:email", "contact:phone", and
"contact:nostr") to use unanchored/looser regexes (remove ^ and $ anchors or add
search-friendly patterns) or alternatively run a pre-extraction step over the
input that extracts tokens/URLs before testing so the existing anchored patterns
can still match; ensure other patterns that expect substrings (like
"contact:website" etc.) remain unchanged.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 85117bcd-2eed-458b-90b0-12a737566867

📥 Commits

Reviewing files that changed from the base of the PR and between bbeb608 and 43fcc34.

📒 Files selected for processing (3)
  • .gitignore
  • app.py
  • templates/add_area.html
✅ Files skipped from review due to trivial changes (1)
  • .gitignore
🚧 Files skipped from review as they are similar to previous changes (1)
  • app.py

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds support for pre-filling the “Add Area” (community) form using data parsed from a Gitea issue body, triggered via an issue-id query parameter, and includes some dev-environment/dependency scaffolding updates.

Changes:

  • Add client-side logic in add_area.html to fetch a Gitea issue, parse its template fields, and prefill form/tag rows.
  • Add shared JS utilities (getURLParameter, cleanIssueText) to support the prefill flow.
  • Introduce dev/dependency files (flake.nix, flake.lock, requirements.txt, .envrc, .env.sample) and adjust validation metadata in app.py.

Reviewed changes

Copilot reviewed 6 out of 9 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
templates/add_area.html Implements issue-id driven fetch/parse/prefill and UI adjustments for community creation.
static/js/utils.js Adds URL param + text normalization helpers used by prefill.
app.py Adds Gitea config and extends AREA_TYPE_REQUIREMENTS validation metadata.
requirements.txt Adds a pip requirements file (currently inconsistent with pyproject.toml).
flake.nix / flake.lock Adds Nix dev shell configuration for local development.
.envrc / .env.sample Adds direnv/Nix usage and a sample env var for Gitea base URL.
.gitignore Updates ignored local/dev directories/files.
Comments suppressed due to low confidence (1)

templates/add_area.html:332

  • updateFields() no longer clears the tags table before appending required fields. Changing the area type (or calling updateFields() multiple times) will now accumulate duplicate required rows (same name=... inputs), which can lead to confusing UI and overwritten values on submit. Reintroduce clearing logic or selectively replace only the required rows for the selected type.
    function updateFields() {
        const selectedType = typeSelect.value;

        if (selectedType && areaTypeRequirements[selectedType]) {
            Object.entries(areaTypeRequirements[selectedType])
                .filter(([key, requirements]) => requirements.required && key !== 'icon:square')
                .forEach(([key, requirements]) => {
                    tagsTable.appendChild(createTagRow(
                        key, 
                        '', 
                        true, 
                        false, 
                        requirements.allowed_values
                    ));
                });
        }
    }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

flake.nix Outdated
Comment on lines +17 to +18
python310
python310Packages.virtualenv
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

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

The dev shell pins python310, but the project declares requires-python = ">=3.11" in pyproject.toml. Using Python 3.10 here will cause dependency resolution/runtime issues. Update the flake to use a 3.11+ interpreter (and matching virtualenv package) to align with the project requirements.

Suggested change
python310
python310Packages.virtualenv
python311
python311Packages.virtualenv

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@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

Caution

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

⚠️ Outside diff range comments (1)
app.py (1)

73-223: ⚠️ Potential issue | 🟠 Major

These new min_length / max_length / pattern entries are currently dead config.

add_area() and set_area_tag() still validate only by requirements['type'], so the new constraints never run server-side. A client can still submit an invalid url_alias, too-short description, malformed lightning address, or mismatched contact URL by bypassing the JS validators.

As per coding guidelines, "Mirror client-side validation logic from static/js/validation.js on the server side."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app.py` around lines 73 - 223, The new min_length/max_length/pattern
constraints in the requirements dict are not enforced because server-side
validation in add_area() and set_area_tag() only checks requirements['type'];
update those functions to validate all present constraint keys (min_length,
max_length, pattern, allowed_values, etc.) against the incoming value using the
same rules as static/js/validation.js and reject/raise on violations; ensure you
reference the requirements lookup by field name (e.g., requirements[field]) and
apply pattern matching for regex entries, numeric/date checks for type
'number'/'date', and length checks for text fields so server-side validation
mirrors the client.
♻️ Duplicate comments (3)
templates/add_area.html (2)

481-489: ⚠️ Potential issue | 🟡 Minor

Don’t filter autofill values with > MIN_FIELD_LENGTH.

This still drops exact-10-character values and short-but-valid contact entries before the normal validators run. tips:lightning_address and description already use a minimum length of 10 in app.py, so the strict > check is off by one.

Suggested fix
 function fillContact(contactText){ 
-    let contactRaw = contactText.split("\n");
-    let contact = []
-    for(let i=0;i<contactRaw.length;i++){
-      if(contactRaw[i].length > MIN_FIELD_LENGTH){
-        contact.push(contactRaw[i])
-      }
-    }
+    let contactRaw = contactText.split("\n");
+    let contact = []
+    for(let i=0;i<contactRaw.length;i++){
+      const value = contactRaw[i].trim()
+      if(value){
+        contact.push(value)
+      }
+    }
     return contact
 }
 ...
-      if(prefilledCommunityData?.lightningTips.length > MIN_FIELD_LENGTH){
+      if(prefilledCommunityData?.lightningTips.trim()){
           newRow = createTagRow('tips:lightning_address', prefilledCommunityData.lightningTips, false, false);
           tagsTable.appendChild(newRow);
       }
-      if(prefilledCommunityData?.description.length > MIN_FIELD_LENGTH){
+      if(prefilledCommunityData?.description.trim()){
           newRow = createTagRow('description', prefilledCommunityData.description, false, false);
           tagsTable.appendChild(newRow);
       }

Also applies to: 552-558

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/add_area.html` around lines 481 - 489, The autofill filter in
fillContact is using a strict greater-than check (contactRaw[i].length >
MIN_FIELD_LENGTH) which drops valid values equal to MIN_FIELD_LENGTH; change the
condition to allow lengths >= MIN_FIELD_LENGTH. Update the same off-by-one check
in the other similar helper (the block around the second occurrence) so both
functions use >= MIN_FIELD_LENGTH to match the validators in app.py.

521-522: ⚠️ Potential issue | 🔴 Critical

Issue-controlled strings still flow into createTagRow()’s innerHTML sink.

These calls pass Gitea body values into createTagRow(), and that helper still renders rows with row.innerHTML earlier in the file. A crafted issue value can break out of the value="..." context and execute script in the admin page.

Also applies to: 553-558

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/add_area.html` around lines 521 - 522, The calls passing
Gitea-controlled strings (e.g., contactTagsInfo[j].name and similar values at
the other call sites) into createTagRow() still end up in a row.innerHTML sink;
modify createTagRow to stop using innerHTML and instead build the row via
document.createElement, setAttribute, and element.textContent (or element.value
for inputs) so all values are inserted as text/attributes rather than raw HTML;
then keep the existing call sites (contacts loop and the other block) unchanged
or optionally pre-validate, making sure any dynamic strings are never
concatenated into HTML before being appended.
requirements.txt (1)

4-4: ⚠️ Potential issue | 🟡 Minor

Drop stdlib modules from requirements.txt.

datetime and typing come from the Python standard library, so declaring them here only adds resolver noise and can pull unintended packages/backports into the environment.

Suggested cleanup
 flask
 flask_session
 requests
-datetime
 geojson_rewind
 shapely
 pyproj
-typing
 nostr-sdk
 cryptography

Also applies to: 8-8

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@requirements.txt` at line 4, Remove standard-library modules from
requirements.txt: delete the entries "datetime" and "typing" (and any other
stdlib names) so the requirements file only lists external packages; this
prevents resolver noise and accidental installation of backports—ensure only
third-party packages remain in requirements.txt.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app.py`:
- Line 25: The route is currently ignoring app.config['GITEA_BASE_URL'] and
indiscriminately turning upstream HTTP errors into a generic 502 via a broad
RequestException handling around response.raise_for_status(); update the route
handler that calls requests.get (use the configured base URL from
app.config['GITEA_BASE_URL'] when building the Gitea URL) and change error
handling to detect requests.exceptions.HTTPError (or inspect
response.status_code) so upstream 404s are returned as Flask 404s (or returned
with the same status code) instead of being collapsed into the generic exception
branch; ensure you still handle non-HTTP network errors as 502 but preserve and
propagate upstream HTTP status codes for clarity.

In `@requirements.txt`:
- Around line 1-10: Update requirements.txt to include the third-party package
Flask-Login (the project imports flask_login in app.py) and remove entries for
Python standard-library modules datetime and typing; ensure the added dependency
uses the correct PyPI package name "Flask-Login" so installs succeed.

In `@templates/add_area.html`:
- Around line 705-749: The code calls fillFieldsPassingIssue() twice and before
validating the issue-id, causing duplicate fetches and timing issues; remove the
early unvalidated call and ensure you validate issue-id first (use
getURLParameter("issue-id"), normalize/trim and test /^\d+$/), show errors via
showIssueIdToast when invalid, and only call
fillFieldsPassingIssue(Number.parseInt(...,10)) once after validation and after
form initialization is complete.

---

Outside diff comments:
In `@app.py`:
- Around line 73-223: The new min_length/max_length/pattern constraints in the
requirements dict are not enforced because server-side validation in add_area()
and set_area_tag() only checks requirements['type']; update those functions to
validate all present constraint keys (min_length, max_length, pattern,
allowed_values, etc.) against the incoming value using the same rules as
static/js/validation.js and reject/raise on violations; ensure you reference the
requirements lookup by field name (e.g., requirements[field]) and apply pattern
matching for regex entries, numeric/date checks for type 'number'/'date', and
length checks for text fields so server-side validation mirrors the client.

---

Duplicate comments:
In `@requirements.txt`:
- Line 4: Remove standard-library modules from requirements.txt: delete the
entries "datetime" and "typing" (and any other stdlib names) so the requirements
file only lists external packages; this prevents resolver noise and accidental
installation of backports—ensure only third-party packages remain in
requirements.txt.

In `@templates/add_area.html`:
- Around line 481-489: The autofill filter in fillContact is using a strict
greater-than check (contactRaw[i].length > MIN_FIELD_LENGTH) which drops valid
values equal to MIN_FIELD_LENGTH; change the condition to allow lengths >=
MIN_FIELD_LENGTH. Update the same off-by-one check in the other similar helper
(the block around the second occurrence) so both functions use >=
MIN_FIELD_LENGTH to match the validators in app.py.
- Around line 521-522: The calls passing Gitea-controlled strings (e.g.,
contactTagsInfo[j].name and similar values at the other call sites) into
createTagRow() still end up in a row.innerHTML sink; modify createTagRow to stop
using innerHTML and instead build the row via document.createElement,
setAttribute, and element.textContent (or element.value for inputs) so all
values are inserted as text/attributes rather than raw HTML; then keep the
existing call sites (contacts loop and the other block) unchanged or optionally
pre-validate, making sure any dynamic strings are never concatenated into HTML
before being appended.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: ee5493af-b0bf-4fac-8c79-e77fec2f2872

📥 Commits

Reviewing files that changed from the base of the PR and between 6dc9302 and 5dc3d10.

📒 Files selected for processing (5)
  • .envrc
  • app.py
  • flake.nix
  • requirements.txt
  • templates/add_area.html
🚧 Files skipped from review as they are similar to previous changes (2)
  • .envrc
  • flake.nix

@dadofsambonzuki
Copy link
Copy Markdown
Member

How are we looking here? Ready for a human to review/test?!

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.

5 participants