Skip to content

Commit 4781572

Browse files
Merge branch 'master' into ci/changelog-bot
2 parents 0041ee2 + d203490 commit 4781572

85 files changed

Lines changed: 5220 additions & 88 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/backport.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Backport fixes to stable branch
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
- main
8+
issue_comment:
9+
types: [created]
10+
11+
concurrency:
12+
group: backport-${{ github.workflow }}-${{ github.ref }}
13+
cancel-in-progress: false
14+
15+
permissions:
16+
contents: write
17+
pull-requests: write
18+
19+
jobs:
20+
backport-on-push:
21+
if: github.event_name == 'push'
22+
uses: openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@master
23+
with:
24+
commit_sha: ${{ github.sha }}
25+
secrets:
26+
app_id: ${{ secrets.OPENWISP_BOT_APP_ID }}
27+
private_key: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }}
28+
29+
backport-on-comment:
30+
if: >
31+
github.event_name == 'issue_comment' &&
32+
github.event.issue.pull_request &&
33+
github.event.issue.pull_request.merged_at != null &&
34+
github.event.issue.state == 'closed' &&
35+
contains(fromJSON('["MEMBER", "OWNER"]'), github.event.comment.author_association) &&
36+
startsWith(github.event.comment.body, '/backport')
37+
uses: openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@master
38+
with:
39+
pr_number: ${{ github.event.issue.number }}
40+
comment_body: ${{ github.event.comment.body }}
41+
secrets:
42+
app_id: ${{ secrets.OPENWISP_BOT_APP_ID }}
43+
private_key: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
name: CI Failure Bot
2+
3+
on:
4+
workflow_run:
5+
workflows: ["OpenWISP Controller CI Build"]
6+
types:
7+
- completed
8+
9+
permissions:
10+
pull-requests: write
11+
actions: read
12+
contents: read
13+
14+
concurrency:
15+
group: ci-failure-${{ github.repository }}-${{ github.event.workflow_run.pull_requests[0].number || github.event.workflow_run.head_branch }}
16+
cancel-in-progress: true
17+
18+
jobs:
19+
find-pr:
20+
runs-on: ubuntu-latest
21+
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
22+
outputs:
23+
pr_number: ${{ steps.pr.outputs.number }}
24+
pr_author: ${{ steps.pr.outputs.author }}
25+
steps:
26+
- name: Find PR Number
27+
id: pr
28+
env:
29+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30+
REPO: ${{ github.repository }}
31+
PR_NUMBER_PAYLOAD: ${{ github.event.workflow_run.pull_requests[0].number }}
32+
EVENT_HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
33+
run: |
34+
emit_pr() {
35+
local pr_number="$1"
36+
local pr_author
37+
pr_author=$(gh pr view "$pr_number" --repo "$REPO" --json author --jq '.author.login // empty' 2>/dev/null || echo "")
38+
if [ -z "$pr_author" ]; then
39+
pr_author="${{ github.event.workflow_run.actor.login }}"
40+
echo "::warning::Could not fetch PR author for PR #$pr_number; falling back to @$pr_author"
41+
fi
42+
echo "number=$pr_number" >> "$GITHUB_OUTPUT"
43+
echo "author=$pr_author" >> "$GITHUB_OUTPUT"
44+
}
45+
PR_NUMBER="$PR_NUMBER_PAYLOAD"
46+
if [ -n "$PR_NUMBER" ]; then
47+
echo "Found PR #$PR_NUMBER from workflow payload."
48+
emit_pr "$PR_NUMBER"
49+
exit 0
50+
fi
51+
HEAD_SHA="$EVENT_HEAD_SHA"
52+
echo "Payload empty. Searching for PR via Commits API..."
53+
PR_NUMBER=$(gh api repos/$REPO/commits/$HEAD_SHA/pulls -q '.[0].number' 2>/dev/null || true)
54+
if [ -n "$PR_NUMBER" ] && [ "$PR_NUMBER" != "null" ]; then
55+
echo "Found PR #$PR_NUMBER using Commits API."
56+
emit_pr "$PR_NUMBER"
57+
exit 0
58+
fi
59+
echo "API lookup failed/empty. Scanning open PRs for matching head SHA..."
60+
PR_NUMBER=$(gh pr list --repo "$REPO" --state open --limit 100 --json number,headRefOid --jq ".[] | select(.headRefOid == \"$HEAD_SHA\") | .number" | head -n 1)
61+
if [ -n "$PR_NUMBER" ]; then
62+
echo "Found PR #$PR_NUMBER by scanning open PRs."
63+
emit_pr "$PR_NUMBER"
64+
exit 0
65+
fi
66+
echo "::warning::No open PR found. This workflow run might not be attached to an open PR."
67+
exit 0
68+
69+
call-ci-failure-bot:
70+
needs: find-pr
71+
if: ${{ needs.find-pr.outputs.pr_number != '' }}
72+
uses: openwisp/openwisp-utils/.github/workflows/reusable-bot-ci-failure.yml@master
73+
with:
74+
pr_number: ${{ needs.find-pr.outputs.pr_number }}
75+
head_sha: ${{ github.event.workflow_run.head_sha }}
76+
head_repo: ${{ github.event.workflow_run.head_repository.full_name }}
77+
base_repo: ${{ github.repository }}
78+
run_id: ${{ github.event.workflow_run.id }}
79+
pr_author: ${{ needs.find-pr.outputs.pr_author }}
80+
actor: ${{ github.event.workflow_run.actor.login }}
81+
secrets:
82+
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
83+
APP_ID: ${{ secrets.OPENWISP_BOT_APP_ID }}
84+
PRIVATE_KEY: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }}

.github/workflows/ci.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ on:
99
branches:
1010
- master
1111
- "1.1"
12-
- gsoc25-map
13-
- gsoc25-whois
12+
- "1.2"
1413

1514
jobs:
1615
build:
@@ -99,6 +98,7 @@ jobs:
9998
format: cobertura
10099
flag-name: python-${{ matrix.env.env }}
101100
github-token: ${{ secrets.GITHUB_TOKEN }}
101+
fail-on-error: false
102102

103103
coveralls:
104104
needs: build
@@ -108,3 +108,4 @@ jobs:
108108
uses: coverallsapp/github-action@v2
109109
with:
110110
parallel-finished: true
111+
fail-on-error: false

CHANGES.rst

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,30 @@ Version 1.3.0 [unreleased]
66

77
Work in progress.
88

9+
Version 1.2.2 [2026-03-06]
10+
--------------------------
11+
12+
Changes
13+
~~~~~~~
14+
15+
Other changes
16+
+++++++++++++
17+
18+
- Improved help text of configuration variable fields
19+
- Minor fixes in the test suite
20+
21+
Version 1.2.1 [2026-03-04]
22+
--------------------------
23+
24+
Bugfixes
25+
~~~~~~~~
26+
27+
- Use context variables in Vpn.auto_client for OpenVPN backend
28+
- Fixed 500 FieldError in DeviceLocationView `#1110
29+
<https://github.com/openwisp/openwisp-controller/issues/1110>`_
30+
- Fixed MultiValueDictKeyError on empty device form submission `#1057
31+
<https://github.com/openwisp/openwisp-controller/issues/1057>`_
32+
933
Version 1.2.0 [2025-10-24]
1034
--------------------------
1135

docs/developer/extending.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ Once you have created the models, add the following to your
344344
CONFIG_VPNCLIENT_MODEL = "sample_config.VpnClient"
345345
CONFIG_ORGANIZATIONCONFIGSETTINGS_MODEL = "sample_config.OrganizationConfigSettings"
346346
CONFIG_ORGANIZATIONLIMITS_MODEL = "sample_config.OrganizationLimits"
347+
CONFIG_WHOISINFO_MODEL = "sample_config.WHOISInfo"
347348
DJANGO_X509_CA_MODEL = "sample_pki.Ca"
348349
DJANGO_X509_CERT_MODEL = "sample_pki.Cert"
349350
GEO_LOCATION_MODEL = "sample_geo.Location"

docs/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ the OpenWISP architecture.
4747
user/vxlan-wireguard.rst
4848
user/zerotier.rst
4949
user/openvpn.rst
50+
user/whois.rst
51+
user/estimated-location.rst
5052
user/subnet-division-rules.rst
5153
user/rest-api.rst
5254
user/settings.rst

docs/user/estimated-location.rst

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
Estimated Location
2+
==================
3+
4+
.. image:: https://raw.githubusercontent.com/openwisp/openwisp-controller/docs/docs/1.3/estimated-locations/is-estimated-flag.png
5+
:target: https://raw.githubusercontent.com/openwisp/openwisp-controller/docs/docs/1.3/estimated-locations/is-estimated-flag.png
6+
:alt: Estimated location flag
7+
8+
.. important::
9+
10+
The **Estimated Location** feature is **disabled by default**.
11+
12+
Before enabling it, the :ref:`WHOIS Lookup feature
13+
<controller_setup_whois_lookup>` must be enabled.
14+
15+
Then set :ref:`OPENWISP_CONTROLLER_ESTIMATED_LOCATION_ENABLED` to
16+
``True``.
17+
18+
.. contents:: **Table of contents**:
19+
:depth: 1
20+
:local:
21+
22+
Overview
23+
--------
24+
25+
This feature automatically creates or updates a device's location based on
26+
latitude and longitude information retrieved from the :doc:`whois`
27+
feature.
28+
29+
It is very useful for those users who have devices scattered across
30+
different geographic regions and would like some help to place the devices
31+
on the map, while being gently reminded to improve the precision of the
32+
location with a direct link for doing so.
33+
34+
It also significantly reduces the effort required to assign a geographic
35+
location manually when many devices are deployed in large buildings like
36+
schools, offices, hospitals, libraries, etc. Improve the precision of the
37+
estimated location just once and all the other devices sharing the same
38+
public IP will automatically inherit the same location.
39+
40+
The feature is not useful in the following scenarios:
41+
42+
- Most devices are deployed in one single location.
43+
- Most devices are mobile (e.g. moving vehicles).
44+
45+
Visibility of Estimated Status
46+
------------------------------
47+
48+
The estimated status of a location is visible in the admin interface in
49+
several ways:
50+
51+
- The location name will mention the *IP address* from which it was
52+
estimated.
53+
- A *warning message* appears at the top of the location list page as in
54+
the image below.
55+
56+
.. image:: https://raw.githubusercontent.com/openwisp/openwisp-controller/docs/docs/1.3/estimated-locations/estimated-warning.png
57+
:target: https://raw.githubusercontent.com/openwisp/openwisp-controller/docs/docs/1.3/estimated-locations/estimated-warning.png
58+
:alt: Estimated location warning
59+
60+
- The *Is Estimated?* flag is displayed both in the location list page and
61+
in the location detail page, as in the images below.
62+
63+
.. image:: https://raw.githubusercontent.com/openwisp/openwisp-controller/docs/docs/1.3/estimated-locations/admin-list.png
64+
:target: https://raw.githubusercontent.com/openwisp/openwisp-controller/docs/docs/1.3/estimated-locations/admin-list.png
65+
:alt: Estimated location admin list
66+
67+
.. image:: https://raw.githubusercontent.com/openwisp/openwisp-controller/docs/docs/1.3/estimated-locations/is-estimated-flag.png
68+
:target: https://raw.githubusercontent.com/openwisp/openwisp-controller/docs/docs/1.3/estimated-locations/is-estimated-flag.png
69+
:alt: Estimated location flag
70+
71+
- The device list page also allows filtering devices which are associated
72+
with estimated locations as shown in the image below.
73+
74+
.. image:: https://raw.githubusercontent.com/openwisp/openwisp-controller/docs/docs/1.3/estimated-locations/filter-devices-by-estimated-location.png
75+
:target: https://raw.githubusercontent.com/openwisp/openwisp-controller/docs/docs/1.3/estimated-locations/filter-devices-by-estimated-location.png
76+
:alt: Filter devices associated to estimated locations
77+
78+
Any change to the geographic coordinates of an estimated location will set
79+
the ``is_estimated`` field to ``False``.
80+
81+
When manually increasing the precision of estimated locations, it is
82+
highly recommended to also change the auto-generated location name.
83+
84+
In the REST API, the ``is_estimated`` field is visible in the :ref:`Device
85+
Location <device_location_estimated>`, :ref:`Location list
86+
<location_list_estimated>`, :ref:`Location Detail
87+
<location_detail_estimated>` and :ref:`Location list (GeoJSON)
88+
<location_geojson_estimated>` endpoints if the feature is enabled. The
89+
field can also be used for filtering in the location list endpoints,
90+
including the GeoJSON endpoint, and in the :ref:`Device List
91+
<device_list_estimated_filters>`.
92+
93+
Triggers and Record Management
94+
------------------------------
95+
96+
The feature is triggered automatically when all the following conditions
97+
are met:
98+
99+
- A WHOIS lookup is performed.
100+
- The last IP is a public IP address.
101+
- Both WHOIS lookup and Estimated Location features are enabled for the
102+
device's organization.
103+
104+
If no matching location exists, a new estimated location is created using
105+
coordinates from the WHOIS record. If an estimated location already
106+
exists, it will be updated with the new coordinates.
107+
108+
If another device with the same IP already has a location, the system will
109+
assign the same location for any device having the same IP and not being
110+
assigned to any other location.
111+
112+
If two devices share the same IP and are assigned to the same location,
113+
and one of them updates its last IP, the system will create a new
114+
estimated location for that device.
115+
116+
When multiple devices with the same IP already have a location assigned
117+
but the locations differ, the system will send a notification to network
118+
administrators asking to manually resolve the ambiguity.
119+
120+
When WHOIS records are updated as described in :ref:`the WHOIS Lookup
121+
section <controller_whois_auto_management>`, any related estimated
122+
location will also be updated, if needed and only if the estimated
123+
location has not been manually modified to increase precision.

docs/user/intro.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ following features:
3535
- **VPN management**: automatically provision VPN tunnel configurations,
3636
including cryptographic keys and IP addresses, e.g.: :doc:`OpenVPN
3737
</user/vpn>`, :doc:`WireGuard <wireguard>`
38+
- :doc:`whois`: display information about the public IP address used by
39+
devices to communicate with OpenWISP
3840
- :doc:`import-export`
3941

4042
It exposes various :doc:`REST API endpoints <rest-api>`.
@@ -96,6 +98,9 @@ The geographic app is based on `django-loci
9698
geographic coordinates of the devices, as well as their indoor coordinates
9799
on floor plan images.
98100

101+
It also provides an :doc:`estimated-location` feature which automatically
102+
creates or updates device locations based on WHOIS data.
103+
99104
It exposes various :doc:`REST API endpoints <rest-api>`.
100105

101106
Subnet Division App

docs/user/organization-limits.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ To set these limits:
88
1. Navigate to **USERS & ORGANIZATIONS** on the left-hand navigation menu.
99
2. Go to **Organizations**.
1010
3. Click on the specific organization you want to limit.
11-
4. In the **CONTROLLER LIMIT** section, set the desired limit.
11+
4. In the **CONTROLLER LIMITS** section, set the desired limit.
1212

1313
Refer to the screenshot below for guidance:
1414

0 commit comments

Comments
 (0)