Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature] Added intergration with openwisp-monitoring #488

Open
wants to merge 48 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
73d69c6
[feature] Added intergraion with openwisp-monitoring
pandafy Aug 18, 2023
6b4846c
[req-changes] Fixed colours for RADIUS charts
pandafy Aug 31, 2023
e8b7990
[chores] Refactored code
pandafy Aug 31, 2023
6c12595
[tests] Added tests for RADIUS monitoring
pandafy Aug 31, 2023
e18f1b3
[chores] Updated requirements-test.txt
pandafy Aug 31, 2023
c4d1e7a
[ci] Added stylelint and jshint
pandafy Aug 31, 2023
e8901f5
[tests] Fixed test suite
pandafy Aug 31, 2023
978e7e9
[ci] Updated system dependencies
pandafy Aug 31, 2023
3ab942f
[tests] Fixed coverage
pandafy Sep 8, 2023
cc6c330
[docs] Added documentation
pandafy Sep 8, 2023
9139946
[feature] Added dashboard pie charts for radius monitoring
pandafy Sep 13, 2023
ce5755a
[docs] Added dashboard pie chart screenshot
pandafy Sep 14, 2023
de4af91
[fix] Removed precision from Round() which is not support on Django 3.2
pandafy Sep 30, 2023
dee1af5
[chores] Upgraded openwisp-utils dependency
pandafy Sep 30, 2023
88eeda3
[fix] Handle called_station_id uses "-" instead of ":"
pandafy Feb 16, 2024
38eab47
[req-changes] Updated colors for the user registration page
pandafy Mar 8, 2024
a453f4f
[req-changes] Don't discard accounting metrics if related device is n…
pandafy Mar 8, 2024
3dd0901
[req-changes] Updated colours
pandafy Mar 12, 2024
b0c41f3
[tests] Added test for changes in post_save_radiusaccounting
pandafy Mar 12, 2024
fd91f6f
[req-changes] Use a separate metric for storing total registered users
pandafy Mar 14, 2024
45554ef
[req-changes] Moved "RADIUS Sessions" tab on the device page after "C…
pandafy Mar 15, 2024
c232b7f
[change] Create a separate metric and chart for total registered users
pandafy Mar 15, 2024
460d679
[tests] Fixed test suite
pandafy Mar 15, 2024
8db674d
[change] Updated colours
pandafy Mar 15, 2024
12259cc
[change] Exclude users in write_user_signup_metrics which registered …
pandafy Mar 15, 2024
7e0cf00
[revert] Revert "[change] Updated colours"
pandafy Mar 15, 2024
7cc8dc0
[change] Added fill operation in influxDB query
pandafy Mar 15, 2024
a511ec4
[change] Removed fill from user registration graph
pandafy Mar 18, 2024
a706e4c
[tests] Fixed tests
pandafy Mar 18, 2024
869e4db
[fix] Fixed called_station_id and calling_station_id lookup for Radiu…
pandafy Mar 19, 2024
6cf1fd8
[fix] Fixed view all radius sessions button in device change page
pandafy Mar 19, 2024
810593c
[fix] Fixed alignment of RADIUS Session text
pandafy Mar 19, 2024
ccad33c
[req-changes] Fixed inconsistencies in UI
pandafy Mar 21, 2024
2f2b956
[req-changes] Updated order of RADIUS charts in device page
pandafy Apr 1, 2024
a0c81c1
[req-change] Use verbose label for SAML in radius monitoring charts
pandafy Apr 4, 2024
338ede3
[req-change] Use verbose name for all registration methods
pandafy Apr 4, 2024
5d86050
[fix] Fixed date formatting for RADIUS sessions on device page
pandafy Apr 17, 2024
c16cb22
[chores] Changed openwisp-monitoring branch from radius-monitoring to…
pandafy Apr 17, 2024
b008b25
[fix] Fixed metric not writing when RegisteredUser does not exist
pandafy Apr 17, 2024
8d1717c
[fix] Fixed test
pandafy Apr 17, 2024
db2756e
[req-changes] Removed fill from User Registration form
pandafy Apr 18, 2024
17909e6
[req-changes] Renamed labels of RADIUS monitoring charts
pandafy Apr 18, 2024
c862fba
[change] Hash calling_station_id
pandafy May 6, 2024
938c492
[req-changes] Added setting for disable org lookup for device
pandafy May 7, 2024
f8dfab6
[req-changes] Renamed setting
pandafy May 7, 2024
c73ee88
[change] Use device.organization_id for RADIUS metric if SHARED_ACCOU…
pandafy May 8, 2024
193ac59
[req-change] Don't overwrite the organization of RadiusAccounting
pandafy May 8, 2024
1bdf7b6
[chores] Removed changes to .gitignore and setup.cfg
pandafy May 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,18 @@ jobs:
- name: Install system libraries
run: |
sudo apt update
sudo apt-get -qq -y install xmlsec1 gettext
sudo apt-get -qq -y install xmlsec1 gettext \
sqlite3 \
fping \
gdal-bin \
libproj-dev \
libgeos-dev \
libspatialite-dev \
spatialite-bin \
libsqlite3-mod-spatialite

- name: Start InfluxDB and Redis container
run: docker-compose up -d influxdb redis

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
Expand All @@ -47,7 +58,7 @@ jobs:
pip install -U -r requirements-test.txt

- name: Install npm dependencies
run: sudo npm install -g jslint
run: sudo npm install -g jslint stylelint jshint

- name: Install openwisp-radius
run: |
Expand All @@ -61,6 +72,7 @@ jobs:
- name: Tests
run: |
coverage run --source=openwisp_radius runtests.py
MONITORING_INTEGRATION=1 coverage run --append --source=openwisp_radius runtests.py
# SAMPLE tests do not influence coverage, so we can speed up tests with --parallel
SAMPLE_APP=1 ./runtests.py --parallel --keepdb

Expand Down
7 changes: 7 additions & 0 deletions .jshintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"unused": true,
"esversion": 6,
"curly": true,
"strict": "global",
"browser": true
}
22 changes: 22 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: "3"

services:
influxdb:
image: influxdb:1.8-alpine
volumes:
- influxdb-data:/var/lib/influxdb
ports:
- "8086:8086"
environment:
INFLUXDB_DB: openwisp2
INFLUXDB_USER: openwisp
INFLUXDB_USER_PASSWORD: openwisp

redis:
image: redis:alpine
ports:
- "6379:6379"
entrypoint: redis-server --appendonly yes

volumes:
influxdb-data: {}
Binary file added docs/source/images/radius-dashboard-charts.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/images/radius-traffic-chart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/images/user-registration-chart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ that are common in WiFi and ISP deployments.
/user/registration
/user/social_login
/user/saml
/user/radius_monitoring
/user/change_of_authorization
/user/api
/developer/signals
Expand Down
81 changes: 81 additions & 0 deletions docs/source/user/radius_monitoring.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
Integration with OpenWISP Monitoring
------------------------------------

OpenWISP RADIUS includes an optional Django sub-app that adds integration with
`OpenWISP Monitoring <https://github.com/openwisp/openwisp-monitoring#openwisp-monitoring>`_
to provide RADIUS metrics.

.. image:: /images/radius-dashboard-charts.png
:alt: RADIUS session dashboard charts

RADIUS metrics
==============

1. User registrations
~~~~~~~~~~~~~~~~~~~~~

.. image:: /images/user-registration-chart.png
:alt: User registration chart

This chart shows number of users signed up using different registration methods.

2. Total user registrations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Copy link
Member

Choose a reason for hiding this comment

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

this line is longer than the title, let's also update the charts images once we are done with everything else


.. image:: /images/total-user-registration-chart.png
:alt: Total user registration chart

This chart shows total users registered using different registration methods
in the system on a given date.

3. Unique RADIUS Sessions
~~~~~~~~~~~~~~~~~~~~~~~~~

.. image:: /images/unique-radius-session-chart.png
:alt: Unique RADIUS session chart

This chart shows unique RADIUS sessions. It is helpful to know how many
unique users has used the system in a given time.

4. RADIUS traffic
~~~~~~~~~~~~~~~~~

.. image:: /images/radius-traffic-chart.png
:alt: RADIUS traffic chart

This chart shows the RADIUS traffic generated by user sessions.

Enabling RADIUS metrics in Django project
=========================================

You can enable the monitoring integration by including ``openwisp_radius.integrations.monitoring``
in ``INSTALLED_APPS`` of your Django project's settings as following:


.. code-block:: python

# In your_project/settings.py

INSTALLED_APPS = [
# ...
'openwisp_radius',
'openwisp_radius.integrations.monitoring' # <--- add the app after openwisp_radius
# ...
]

.. note::

Ensure your Django project is correctly configured to utilize OpenWISP Monitoring as
outlined in the `OpenWISP Monitoring's documentation <https://github.com/openwisp/openwisp-monitoring#setup-integrate-in-an-existing-django-project>`_.
For production environments, it is advisable to deploy OpenWISP using
`Ansible OpenWISP2 <https://github.com/openwisp/ansible-openwisp2>`_ or
`Docker OpenWISP <https://github.com/openwisp/docker-openwisp>`_, as they simplify
the deployment process considerably.

.. important::

If you are registering a :ref:`"registration method" <register_registration_method>`
in any other Django application, then ``openwisp_radius.integrations.monitoring``
should come after that app in the ``INSTALLED_APPS``. Otherwise, the
registration method would not appear in the chart.

8 changes: 5 additions & 3 deletions docs/source/user/settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ or Cameroon (``+237``).

OpenWISP RADIUS only allow using mobile phone numbers for user registration.
This can cause issues in regions where fixed line and mobile phone numbers
uses the same pattern (e.g. USA). Setting the value to ``True``
uses the same pattern (e.g. USA). Setting the value to ``True``
would make phone number type checking less strict.

.. _openwisp_radius_optional_registration_fields:
Expand Down Expand Up @@ -643,8 +643,8 @@ If this is enabled, each registered user should be verified using a verification
The following choices are available by default:

- ``''`` (empty string): unspecified
- ``manual``: manually created
- ``email``: Email (No Identity Verification)
- ``manual``: Manually created
- ``email``: Email
- ``mobile_phone``: Mobile phone number
:ref:`verification via SMS <openwisp_radius_sms_verification_enabled>`
- ``social_login``: :ref:`social login feature <social_login>`
Expand All @@ -665,6 +665,8 @@ The following choices are available by default:
**Disclaimer:** these are just suggestions on possible configurations
of OpenWISP RADIUS and must not be considered as legal advice.

.. _register_registration_method:

Adding support for more registration/verification methods
#########################################################

Expand Down
5 changes: 5 additions & 0 deletions openwisp_radius/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ def get_api_urls(api_views=None):
api_views.download_rad_batch_pdf,
name='download_rad_batch_pdf',
),
path(
'radius/sessions/',
api_views.radius_accounting,
name='radius_accounting_list',
),
]
else:
return []
47 changes: 46 additions & 1 deletion openwisp_radius/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@
from django.contrib.sites.shortcuts import get_current_site
from django.core.cache import cache
from django.core.exceptions import ValidationError
from django.db.models import Q
from django.db.utils import IntegrityError
from django.http import Http404, HttpResponse
from django.utils import timezone
from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _
from django.utils.translation.trans_real import get_language_from_request
from django.views.decorators.csrf import csrf_exempt
from django_filters.rest_framework import DjangoFilterBackend
from django_filters.rest_framework import CharFilter, DjangoFilterBackend
from drf_yasg.utils import no_body, swagger_auto_schema
from rest_framework import serializers, status
from rest_framework.authentication import SessionAuthentication
Expand All @@ -41,6 +42,7 @@

from openwisp_radius.api.serializers import RadiusUserSerializer
from openwisp_users.api.authentication import BearerAuthentication, SesameAuthentication
from openwisp_users.api.mixins import FilterByOrganizationManaged, ProtectedAPIMixin
from openwisp_users.api.permissions import IsOrganizationManager
from openwisp_users.api.views import ChangePasswordView as BasePasswordChangeView
from openwisp_users.backends import UsersAuthenticationBackend
Expand Down Expand Up @@ -801,3 +803,46 @@ def create_phone_token(self, *args, **kwargs):


change_phone_number = ChangePhoneNumberView.as_view()


class RadiusAccountingFilter(AccountingFilter):
called_station_id = CharFilter(
field_name='called_station_id', method='filter_mac_address'
)
calling_station_id = CharFilter(
field_name='calling_station_id', method='filter_mac_address'
)

def filter_mac_address(self, queryset, name, value):
"""
The input MAC address in any of these two formats:
- AA-BB-CC-DD-EE-FF (quadrants separated by hyphen)
- AA:BB:CC:DD:EE:FF (quadrants separated by colon)
The below lookup ensures that the filtering is
case-insensitive and works across different formats.
"""
lookup = f'{name}__iexact'
return queryset.filter(
Q(**{lookup: value.replace(':', '-')})
| Q(**{lookup: value.replace('-', ':')})
)


@method_decorator(
name='get',
decorator=swagger_auto_schema(
operation_description="""
Returns all RADIUS sessions of user managed organizations.
""",
),
)
class RadiusAccountingView(ProtectedAPIMixin, FilterByOrganizationManaged, ListAPIView):
throttle_scrope = 'radius_accounting_list'
serializer_class = RadiusAccountingSerializer
pagination_class = AccountingViewPagination
filter_backends = (DjangoFilterBackend,)
filterset_class = RadiusAccountingFilter
queryset = RadiusAccounting.objects.all().order_by('-start_time')


radius_accounting = RadiusAccountingView.as_view()
Empty file.
Empty file.
40 changes: 40 additions & 0 deletions openwisp_radius/integrations/monitoring/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from django.contrib import admin
from django.urls import reverse
from swapper import load_model

Device = load_model('config', 'Device')
RadiusAccounting = load_model('openwisp_radius', 'RadiusAccounting')

BaseDeviceAdmin = admin.site._registry[Device].__class__


class DeviceAdmin(BaseDeviceAdmin):
change_form_template = 'admin/config/radius-monitoring/device/change_form.html'

class Media:
js = tuple(BaseDeviceAdmin.Media.js) + (
'radius-monitoring/js/device-change.js',
)
css = {
'all': ('radius-monitoring/css/device-change.css',)
+ BaseDeviceAdmin.Media.css['all']
}

def get_extra_context(self, pk=None):
ctx = super().get_extra_context(pk)
ctx.update(
{
'radius_accounting_api_endpoint': reverse(
'radius:radius_accounting_list'
),
'radius_accounting': reverse(
f'admin:{RadiusAccounting._meta.app_label}'
f'_{RadiusAccounting._meta.model_name}_changelist'
),
}
)
return ctx


admin.site.unregister(Device)
admin.site.register(Device, DeviceAdmin)
Loading
Loading