Skip to content

Commit

Permalink
Encapsulate organization.Organization model imports
Browse files Browse the repository at this point in the history
These should be made such that they are avoidable if explicit class arguments
are provided to avoid unnecessarily importing concrete models which may not be
installed.

bennylopegh-131
  • Loading branch information
bennylope committed Jul 8, 2017
1 parent cf3ce55 commit b9afc95
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 38 deletions.
4 changes: 2 additions & 2 deletions organizations/backends/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@

from importlib import import_module

from organizations.app_settings import (ORGS_INVITATION_BACKEND,
ORGS_REGISTRATION_BACKEND)
from organizations.app_settings import ORGS_INVITATION_BACKEND
from organizations.app_settings import ORGS_REGISTRATION_BACKEND


def invitation_backend():
Expand Down
29 changes: 16 additions & 13 deletions organizations/backends/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,32 @@

from django.conf import settings
from django.conf.urls import url
from django.contrib.auth import authenticate, login, get_user_model
from django.core.urlresolvers import reverse
from django.contrib.auth import authenticate
from django.contrib.auth import get_user_model
from django.contrib.auth import login
from django.core.mail import EmailMessage
from django.core.urlresolvers import reverse
from django.http import Http404
from django.shortcuts import render, redirect
from django.shortcuts import redirect
from django.shortcuts import render
from django.template import loader
from django.utils.translation import ugettext as _

from ..utils import create_organization
from ..utils import model_field_attr
from .forms import UserRegistrationForm, OrganizationRegistrationForm
from .tokens import RegistrationTokenGenerator
from organizations.backends.forms import UserRegistrationForm
from organizations.backends.forms import org_registration_form
from organizations.backends.tokens import RegistrationTokenGenerator
from organizations.utils import create_organization
from organizations.utils import default_org_model
from organizations.utils import model_field_attr


class BaseBackend(object):
"""
Base backend class for registering and inviting users to an organization
"""
org_model = None

def __init__(self, org_model=None, *args, **kwargs):
def __init__(self, org_model=None):
self.user_model = get_user_model()
self.org_model = org_model
self.org_model = org_model or default_org_model()

def get_urls(self):
raise NotImplementedError
Expand Down Expand Up @@ -92,7 +95,7 @@ def activate_organizations(self, user):
relation_name = self.org_model().user_relation_name
except TypeError:
# No org_model specified, raises a TypeError because NoneType is
# not callable. Thiis the most sensible default
# not callable. This the most sensible default:
relation_name = "organizations_organization"
organization_set = getattr(user, relation_name)
for org in organization_set.filter(is_active=False):
Expand Down Expand Up @@ -215,7 +218,7 @@ def create_view(self, request):
"""
if request.user.is_authenticated():
return redirect("organization_add")
form = OrganizationRegistrationForm(request.POST or None)
form = org_registration_form(self.org_model)(request.POST or None)
if form.is_valid():
try:
user = self.user_model.objects.get(email=form.cleaned_data['email'])
Expand Down
27 changes: 16 additions & 11 deletions organizations/backends/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@
from django.contrib.auth import get_user_model
from django.utils.translation import ugettext_lazy as _

from ..models import Organization


class UserRegistrationForm(forms.ModelForm):
"""
Expand Down Expand Up @@ -61,14 +59,21 @@ class Meta:
'date_joined', 'groups', 'user_permissions')


class OrganizationRegistrationForm(forms.ModelForm):
"""Form class for creating new organizations owned by new users."""
email = forms.EmailField()
def org_registration_form(org_model):
"""
Generates a registration ModelForm for the given organization model class
"""

class OrganizationRegistrationForm(forms.ModelForm):
"""Form class for creating new organizations owned by new users."""
email = forms.EmailField()

class Meta:
model = org_model
exclude = ('is_active', 'users')

class Meta:
model = Organization
exclude = ('is_active', 'users')
def save(self, *args, **kwargs):
self.instance.is_active = False
super(OrganizationRegistrationForm, self).save(*args, **kwargs)

def save(self, *args, **kwargs):
self.instance.is_active = False
super(OrganizationRegistrationForm, self).save(*args, **kwargs)
return OrganizationRegistrationForm
11 changes: 7 additions & 4 deletions organizations/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@

from itertools import chain

from .models import Organization

def default_org_model():
"""Encapsulates importing the concrete model"""
from organizations.models import Organization
return Organization


def model_field_names(model):
Expand All @@ -41,8 +45,7 @@ def model_field_names(model):
)))


def create_organization(user, name, slug=None, is_active=None,
org_defaults=None, org_user_defaults=None, **kwargs):
def create_organization(user, name, slug=None, is_active=None, org_defaults=None, org_user_defaults=None, **kwargs):
"""
Returns a new organization, also creating an initial organization user who
is the owner.
Expand All @@ -56,7 +59,7 @@ def create_organization(user, name, slug=None, is_active=None,
>>> create_account = partial(create_organization, model=Account)
"""
org_model = kwargs.pop('model', None) or kwargs.pop('org_model', None) or Organization
org_model = kwargs.pop('model', None) or kwargs.pop('org_model', None) or default_org_model()
kwargs.pop('org_user_model', None) # Discard deprecated argument

org_owner_model = org_model.owner.related.related_model
Expand Down
33 changes: 25 additions & 8 deletions tests/test_backends.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
from django.contrib.auth.models import User
from django.core import mail
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
from django.http import Http404, QueryDict
from django.http import Http404
from django.http import QueryDict
from django.test import TestCase
from django.test.client import RequestFactory
from django.test.utils import override_settings

from test_vendors.models import Vendor
from test_abstract.models import CustomOrganization

from organizations.backends.defaults import (BaseBackend, InvitationBackend,
RegistrationBackend)
from organizations.backends.defaults import BaseBackend
from organizations.backends.defaults import InvitationBackend
from organizations.backends.defaults import RegistrationBackend
from organizations.backends.tokens import RegistrationTokenGenerator
from organizations.models import Organization
from .utils import request_factory_login
from test_abstract.models import CustomOrganization
from test_vendors.models import Vendor
from tests.utils import request_factory_login


@override_settings(USE_TZ=True)
Expand All @@ -23,6 +24,22 @@ def test_generate_username(self):
self.assertTrue(BaseBackend().get_username())


@override_settings(INSTALLED_APPS=["django.contrib.auth", "django.contrib.contenttypes",
"django.contrib.sites", "test_accounts"], USE_TZ=True)
class TestSansOrganizations(TestCase):

def test_verify_the_world(self):
"""Verify the test environment is set up correctly"""
from django.conf import settings
self.assertFalse('organizations' in settings.INSTALLED_APPS)

def test_generate_username(self):
self.assertTrue(BaseBackend().get_username())

def test_backend_urls(self):
self.assertTrue(InvitationBackend().get_urls())


@override_settings(USE_TZ=True)
class InvitationTests(TestCase):

Expand Down

0 comments on commit b9afc95

Please sign in to comment.