diff --git a/organizations/backends/__init__.py b/organizations/backends/__init__.py index 81ad6270..8f000306 100644 --- a/organizations/backends/__init__.py +++ b/organizations/backends/__init__.py @@ -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(): diff --git a/organizations/backends/defaults.py b/organizations/backends/defaults.py index d0c2f639..ceef671b 100644 --- a/organizations/backends/defaults.py +++ b/organizations/backends/defaults.py @@ -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 @@ -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): @@ -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']) diff --git a/organizations/backends/forms.py b/organizations/backends/forms.py index 0d249bc5..aed6ac83 100644 --- a/organizations/backends/forms.py +++ b/organizations/backends/forms.py @@ -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): """ @@ -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 diff --git a/organizations/utils.py b/organizations/utils.py index 035c647b..2e5ce6a1 100644 --- a/organizations/utils.py +++ b/organizations/utils.py @@ -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): @@ -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. @@ -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 diff --git a/tests/test_backends.py b/tests/test_backends.py index 9163d58b..bd130b31 100644 --- a/tests/test_backends.py +++ b/tests/test_backends.py @@ -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) @@ -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):