Skip to content

Commit

Permalink
Merge 4939627 into 86d78c5
Browse files Browse the repository at this point in the history
  • Loading branch information
fmarco committed Dec 15, 2016
2 parents 86d78c5 + 4939627 commit b825474
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 28 deletions.
5 changes: 4 additions & 1 deletion invitations/admin.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from django.contrib import admin

from .models import Invitation
from .forms import InvitationAdminAddForm, InvitationAdminChangeForm
from .utils import get_invitation_model

Invitation = get_invitation_model()


class InvitationAdmin(admin.ModelAdmin):
Expand All @@ -16,4 +18,5 @@ def get_form(self, request, obj=None, **kwargs):
kwargs['form'].request = request
return super(InvitationAdmin, self).get_form(request, obj, **kwargs)


admin.site.register(Invitation, InvitationAdmin)
8 changes: 8 additions & 0 deletions invitations/app_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,12 @@ def EMAIL_SUBJECT_PREFIX(self):
"""
return self._setting("EMAIL_SUBJECT_PREFIX", None)

@property
def INVITATION_MODEL(self):
"""
Subject-line prefix to use for Invitation model setup
"""
return self._setting("INVITATION_MODEL", "invitations.Invitation")


app_settings = AppSettings('INVITATIONS_')
41 changes: 41 additions & 0 deletions invitations/base_invitation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from django.conf import settings
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _

from .managers import BaseInvitationManager


@python_2_unicode_compatible
class AbstractBaseInvitation(models.Model):
accepted = models.BooleanField(verbose_name=_('accepted'), default=False)
key = models.CharField(verbose_name=_('key'), max_length=64, unique=True)
sent = models.DateTimeField(verbose_name=_('sent'), null=True)
inviter = models.ForeignKey(
settings.AUTH_USER_MODEL, null=True, blank=True)

objects = BaseInvitationManager()

class Meta:
abstract = True

@classmethod
def create(cls, email, inviter=None, **kwargs):
raise NotImplementedError(
'You should implement the create method class'
)

def key_expired(self):
raise NotImplementedError(
'You should implement the key_expired method'
)

def send_invitation(self, request, **kwargs):
raise NotImplementedError(
'You should implement the send_invitation method'
)

def __str__(self):
raise NotImplementedError(
'You should implement the __str__ method'
)
4 changes: 3 additions & 1 deletion invitations/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth import get_user_model

from .models import Invitation
from .adapters import get_invitations_adapter
from .exceptions import AlreadyInvited, AlreadyAccepted, UserRegisteredEmail
from .utils import get_invitation_model

Invitation = get_invitation_model()


class CleanEmailMixin(object):
Expand Down
4 changes: 3 additions & 1 deletion invitations/management/commands/clear_expired_invitations.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from django.core.management.base import BaseCommand
from .. .models import Invitation
from .. .utils import get_invitation_model

Invitation = get_invitation_model()


class Command(BaseCommand):
Expand Down
2 changes: 1 addition & 1 deletion invitations/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from .app_settings import app_settings


class InvitationManager(models.Manager):
class BaseInvitationManager(models.Manager):

def all_expired(self):
return self.filter(self.expired_q())
Expand Down
31 changes: 12 additions & 19 deletions invitations/models.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,36 @@
import datetime

from django.conf import settings
from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.template.context import RequestContext
from django.utils import timezone
from django.utils.crypto import get_random_string
from django.utils.encoding import python_2_unicode_compatible
from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse
from django.conf import settings
from django.template.context import RequestContext
from django.utils.translation import ugettext_lazy as _

from .managers import InvitationManager
from .app_settings import app_settings
from .adapters import get_invitations_adapter
from . import signals
from .adapters import get_invitations_adapter
from .app_settings import app_settings
from .base_invitation import AbstractBaseInvitation


@python_2_unicode_compatible
class Invitation(models.Model):

class Invitation(AbstractBaseInvitation):
email = models.EmailField(unique=True, verbose_name=_('e-mail address'),
max_length=app_settings.EMAIL_MAX_LENGTH)
accepted = models.BooleanField(verbose_name=_('accepted'), default=False)
created = models.DateTimeField(verbose_name=_('created'),
default=timezone.now)
key = models.CharField(verbose_name=_('key'), max_length=64, unique=True)
sent = models.DateTimeField(verbose_name=_('sent'), null=True)
inviter = models.ForeignKey(
settings.AUTH_USER_MODEL, null=True, blank=True)

objects = InvitationManager()

@classmethod
def create(cls, email, inviter=None):
def create(cls, email, inviter=None, **kwargs):
key = get_random_string(64).lower()
instance = cls._default_manager.create(
email=email,
key=key,
inviter=inviter)
inviter=inviter,
**kwargs)
return instance

def key_expired(self):
Expand Down
5 changes: 4 additions & 1 deletion invitations/tests/allauth/test_allauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
from nose_parameterized import parameterized
from allauth.account.models import EmailAddress

from invitations.models import Invitation, InvitationsAdapter
from invitations.models import InvitationsAdapter
from invitations.adapters import get_invitations_adapter
from invitations.utils import get_invitation_model

Invitation = get_invitation_model()


class AllAuthIntegrationTests(TestCase):
Expand Down
8 changes: 5 additions & 3 deletions invitations/tests/basic/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@

from invitations.adapters import (
get_invitations_adapter, BaseInvitationsAdapter)
from invitations.models import Invitation
from invitations.app_settings import app_settings
from invitations.views import AcceptInvite, SendJSONInvite
from invitations.forms import InviteForm
from invitations.utils import get_invitation_model

Invitation = get_invitation_model()


class InvitationModelTests(TestCase):
Expand Down Expand Up @@ -538,6 +540,6 @@ def test_admin_form_change(self):

self.assertEqual(response.status_code, 200)
fields = list(response.context_data['adminform'].form.fields.keys())
expected_fields = ['email', 'accepted', 'created',
'key', 'sent', 'inviter']
expected_fields = ['accepted',
'key', 'sent', 'inviter', 'email', 'created']
self.assertEqual(fields, expected_fields)
22 changes: 22 additions & 0 deletions invitations/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
from django.apps import apps as django_apps
from django.core.exceptions import ImproperlyConfigured
from django.utils import six

from .app_settings import app_settings

try:
import importlib
except:
Expand All @@ -11,3 +15,21 @@ def import_attribute(path):
pkg, attr = path.rsplit('.', 1)
ret = getattr(importlib.import_module(pkg), attr)
return ret


def get_invitation_model():
"""
Returns the Invitation model that is active in this project.
"""
path = app_settings.INVITATION_MODEL
try:
return django_apps.get_model(path)
except ValueError:
raise ImproperlyConfigured(
"path must be of the form 'app_label.model_name'"
)
except LookupError:
raise ImproperlyConfigured(
"path refers to model '%s' that\
has not been installed" % app_settings.INVITATION_MODEL
)
5 changes: 4 additions & 1 deletion invitations/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
from braces.views import LoginRequiredMixin

from .forms import InviteForm, CleanEmailMixin
from .models import Invitation
from .exceptions import AlreadyInvited, AlreadyAccepted, UserRegisteredEmail
from .app_settings import app_settings
from .adapters import get_invitations_adapter
from .signals import invite_accepted
from .utils import get_invitation_model

Invitation = get_invitation_model()


class SendInvite(LoginRequiredMixin, FormView):
Expand Down Expand Up @@ -182,6 +184,7 @@ def accept_invite_after_signup(sender, request, user, **kwargs):
request=request,
signal_sender=Invitation)


if app_settings.ACCEPT_INVITE_AFTER_SIGNUP:
signed_up_signal = get_invitations_adapter().get_user_signed_up_signal()
signed_up_signal.connect(accept_invite_after_signup)

0 comments on commit b825474

Please sign in to comment.