Skip to content

Commit

Permalink
[openwisp-utils] Moved shared logic to openwisp-utils
Browse files Browse the repository at this point in the history
  • Loading branch information
nemesifier committed Jun 28, 2017
1 parent c7fe513 commit c75fa68
Show file tree
Hide file tree
Showing 11 changed files with 27 additions and 168 deletions.
17 changes: 10 additions & 7 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ If you want to contribute, install your cloned fork:
Setup (integrate in an existing django project)
-----------------------------------------------

``INSTALLED_APPS`` in ``settings.py`` should look like the following (ordering is important):
``INSTALLED_APPS`` and ``EXTENDED_APPS`` (an internal openwisp2 setting) in ``settings.py``
should look like the following (ordering is important):

.. code-block:: python
Expand All @@ -99,18 +100,20 @@ Setup (integrate in an existing django project)
'sortedm2m',
'reversion',
]
EXTENDED_APPS = ('django_netjsonconfig', 'django_x509')
Add ``openwisp_controller.staticfiles.DependencyFinder`` to ``STATICFILES_FINDERS`` in your ``settings.py``
Add ``openwisp_utils.staticfiles.DependencyFinder`` to ``STATICFILES_FINDERS`` in your ``settings.py``

.. code-block:: python
STATICFILES_FINDERS = [
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'openwisp_controller.staticfiles.DependencyFinder',
'openwisp_utils.staticfiles.DependencyFinder',
]
Add ``openwisp_controller.loaders.DependencyLoader`` to ``TEMPLATES`` in your ``settings.py``
Add ``openwisp_utils.loaders.DependencyLoader`` to ``TEMPLATES`` in your ``settings.py``

.. code-block:: python
Expand All @@ -123,7 +126,7 @@ Add ``openwisp_controller.loaders.DependencyLoader`` to ``TEMPLATES`` in your ``
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
# add the following line
'openwisp_controller.loaders.DependencyLoader'
'openwisp_utils.loaders.DependencyLoader'
],
'context_processors': [
'django.template.context_processors.debug',
Expand All @@ -149,8 +152,8 @@ Add the following settings to ``settings.py``:
from django.conf import settings
from django.conf.urls import include, url
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django_netjsonconfig.admin_theme.admin import admin, openwisp_admin
from openwisp_utils.admin_theme.admin import admin, openwisp_admin
openwisp_admin()
Expand Down
11 changes: 0 additions & 11 deletions openwisp_controller/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,3 @@ def get_version():
suffix = 0
version = '%s%s%s' % (version, first_letter, suffix)
return version


# openwisp-controller extends and depends on these apps which
# cannot be listed in ``settings.INSTALLED_APPS``
# this variable is used by:
# - openwisp_controller.staticfiles.DependencyFinder
# - openwisp_controller.loaders.DependencyLoader
__dependencies__ = (
'django_x509',
'django_netjsonconfig'
)
86 changes: 5 additions & 81 deletions openwisp_controller/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _

from openwisp_utils.admin import MultitenantAdminMixin as BaseMultitenantAdminMixin


class OrgVersionMixin(object):
"""
Expand All @@ -18,89 +20,11 @@ def recoverlist_view(self, request, extra_context=None):
return super(OrgVersionMixin, self).recoverlist_view(request, extra_context)


class MultitenantAdminMixin(OrgVersionMixin):
"""
Mixin that makes a ModelAdmin class multitenant:
users will see only the objects related to the organizations
they are associated with.
"""
multitenant_shared_relations = []

def get_repr(self, obj):
return str(obj)

get_repr.short_description = _('name')

def get_queryset(self, request):
"""
If current user is not superuser, show only the
objects associated to organizations she's associated with
"""
qs = super(MultitenantAdminMixin, self).get_queryset(request)
if request.user.is_superuser:
return qs
organizations = request.user.organizations_pk
return qs.filter(organization__in=organizations)

def _edit_form(self, request, form):
"""
Modifies the form querysets as follows;
if current user is not superuser:
* show only relevant organizations
* show only relations associated to relevant organizations
or shared relations
else show everything
"""
fields = form.base_fields
if not request.user.is_superuser:
orgs_pk = request.user.organizations_pk
# organizations relation;
# may be readonly and not present in field list
if 'organization' in fields:
org_field = fields['organization']
org_field.queryset = org_field.queryset.filter(pk__in=orgs_pk)
# other relations
q = Q(organization__in=orgs_pk) | Q(organization=None)
for field_name in self.multitenant_shared_relations:
# each relation may be readonly
# and not present in field list
if field_name not in fields:
continue
field = fields[field_name]
field.queryset = field.queryset.filter(q)

def get_form(self, request, obj=None, **kwargs):
form = super(MultitenantAdminMixin, self).get_form(request, obj, **kwargs)
self._edit_form(request, form)
return form

def get_formset(self, request, obj=None, **kwargs):
formset = super(MultitenantAdminMixin, self).get_formset(request, obj=None, **kwargs)
self._edit_form(request, formset.form)
return formset


class MultitenantOrgFilter(admin.RelatedFieldListFilter):
"""
Admin filter that shows only organizations the current
user is associated with in its available choices
"""
multitenant_lookup = 'pk__in'

def field_choices(self, field, request, model_admin):
if request.user.is_superuser:
return super(MultitenantOrgFilter, self).field_choices(field, request, model_admin)
organizations = request.user.organizations_pk
return field.get_choices(include_blank=False,
limit_choices_to={self.multitenant_lookup: organizations})


class MultitenantTemplateFilter(MultitenantOrgFilter):
class MultitenantAdminMixin(OrgVersionMixin, BaseMultitenantAdminMixin):
"""
Admin filter that shows only templates of
organizations the current user is associated with
openwisp_utils.admin.MultitenantAdminMixin + OrgVersionMixin
"""
multitenant_lookup = 'organization__in'
pass


class AlwaysHasChangedMixin(object):
Expand Down
8 changes: 3 additions & 5 deletions openwisp_controller/config/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@
AbstractTemplateAdmin,
AbstractVpnAdmin, AbstractVpnForm,
BaseForm)
from openwisp_controller.admin import (AlwaysHasChangedMixin,
MultitenantAdminMixin,
MultitenantOrgFilter,
MultitenantTemplateFilter)
from openwisp_controller.admin import AlwaysHasChangedMixin, MultitenantAdminMixin
from openwisp_users.admin import OrganizationAdmin as BaseOrganizationAdmin
from openwisp_users.models import Organization
from openwisp_utils.admin import MultitenantOrgFilter, MultitenantRelatedOrgFilter

from .models import Config, Device, OrganizationConfigSettings, Template, Vpn

Expand All @@ -42,7 +40,7 @@ class DeviceAdmin(MultitenantAdminMixin, AbstractDeviceAdmin):
inlines = [ConfigInline]
list_filter = [('organization', MultitenantOrgFilter),
'config__backend',
('config__templates', MultitenantTemplateFilter),
('config__templates', MultitenantRelatedOrgFilter),
'config__status',
'created']
list_select_related = ('config', 'organization')
Expand Down
20 changes: 0 additions & 20 deletions openwisp_controller/loaders.py

This file was deleted.

4 changes: 2 additions & 2 deletions openwisp_controller/pki/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

from django_x509.base.admin import CaAdmin as BaseCaAdmin
from django_x509.base.admin import CertAdmin as BaseCertAdmin
from openwisp_controller.admin import (MultitenantAdminMixin,
MultitenantOrgFilter)
from openwisp_controller.admin import MultitenantAdminMixin
from openwisp_utils.admin import MultitenantOrgFilter

from .models import Ca, Cert

Expand Down
28 changes: 0 additions & 28 deletions openwisp_controller/staticfiles.py

This file was deleted.

9 changes: 0 additions & 9 deletions openwisp_controller/tests/test_staticfinders.py

This file was deleted.

2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
django-netjsonconfig>=0.5.8,<0.7.0
openwisp-users<0.2
openwisp-utils[users]<0.2
8 changes: 5 additions & 3 deletions tests/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
'django.contrib.staticfiles',
# openwisp2 admin theme
# (must be loaded here)
'django_netjsonconfig.admin_theme',
'openwisp_utils.admin_theme',
# all-auth
'django.contrib.sites',
'allauth',
Expand All @@ -41,13 +41,15 @@
'reversion',
]

EXTENDED_APPS = ('django_netjsonconfig', 'django_x509')

AUTH_USER_MODEL = 'openwisp_users.User'
SITE_ID = '1'

STATICFILES_FINDERS = [
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'openwisp_controller.staticfiles.DependencyFinder',
'openwisp_utils.staticfiles.DependencyFinder',
]

MIDDLEWARE_CLASSES = [
Expand Down Expand Up @@ -77,7 +79,7 @@
'loaders': [
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
'openwisp_controller.loaders.DependencyLoader'
'openwisp_utils.loaders.DependencyLoader'
],
'context_processors': [
'django.template.context_processors.debug',
Expand Down
2 changes: 1 addition & 1 deletion tests/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from django.core.urlresolvers import reverse_lazy
from django.views.generic import RedirectView

from django_netjsonconfig.admin_theme.admin import admin, openwisp_admin
from openwisp_utils.admin_theme.admin import admin, openwisp_admin

openwisp_admin()

Expand Down

0 comments on commit c75fa68

Please sign in to comment.