예제 #1
0
    def test_authorization_backfill_expiry_date_on_partner_save_with_new_coordinator(
        self,
    ):
        # As above, but this should still work in the case that the coordinator
        # for a partner has changed, so Authorizer is no longer in the coordinators
        # user group.
        initial_partner2_auths_no_expiry_count = 0
        initial_partner2_auths_no_expiry = Authorization.objects.filter(
            partners=self.partner2, date_expires__isnull=True
        )
        for partner2_auth in initial_partner2_auths_no_expiry:
            if partner2_auth.is_valid:
                initial_partner2_auths_no_expiry_count += 1

        # Count partner 2 apps with an expiration date.
        initial_partner2_auths_with_expiry_count = 0
        initial_partner2_auths_with_expiry = Authorization.objects.filter(
            partners=self.partner2, date_expires__isnull=False
        )
        for partner2_auth in initial_partner2_auths_with_expiry:
            if partner2_auth.is_valid:
                initial_partner2_auths_with_expiry_count += 1
                # Clear out the expiration date on those.
                partner2_auth.date_expires = None
                partner2_auth.save()

        # editor4 stops being a coordinator
        get_coordinators().user_set.remove(self.editor4.user)

        # Save partner 2
        self.partner2.save()
        self.partner2.refresh_from_db()
        # Count partner 2 apps with an expiration date post_save.
        post_save_partner2_auths_with_expiry_count = 0
        post_save_partner2_auths_with_expiry = Authorization.objects.filter(
            partners=self.partner2, date_expires__isnull=False
        )
        for partner2_auth in post_save_partner2_auths_with_expiry:
            if partner2_auth.is_valid:
                post_save_partner2_auths_with_expiry_count += 1

        # All valid partner 2 authorizations have expiry set.
        post_save_partner2_auths_no_expiry_count = Authorization.objects.filter(
            partners=self.partner2, date_expires__isnull=True
        ).count()
        self.assertEqual(
            initial_partner2_auths_with_expiry_count
            + initial_partner2_auths_no_expiry_count,
            post_save_partner2_auths_with_expiry_count,
        )
예제 #2
0
def validate_authorizer(authorizer):
    coordinators = get_coordinators()
    authorizer_is_coordinator = authorizer in coordinators.user_set.all()
    if not authorizer or not (authorizer_is_coordinator or authorizer.is_staff
                              or authorizer.username == "TWL Team"):
        raise ValidationError(
            "Authorization authorizer must be a coordinator or staff.")
예제 #3
0
파일: tests.py 프로젝트: Sam-2727/TWLight
    def setUpClass(cls):
        super(GraphsTestCase, cls).setUpClass()
        cls.factory = RequestFactory()

        Request(path="/admin/", ip="127.0.0.1").save()
        Request(path="/admin/", ip="127.0.0.1").save()
        Request(path="/admin/login/", ip="127.0.0.1").save()

        staff_user = User.objects.create_user(username="******", password="******")
        staff_user.is_staff = True
        staff_user.save()
        cls.staff_user = staff_user

        cls.coordinator = EditorFactory(user__email="*****@*****.**").user
        coordinators = get_coordinators()
        coordinators.user_set.add(cls.coordinator)

        user = UserFactory()
        cls.user = user

        cls.partner = PartnerFactory()

        cls.app = ApplicationFactory(partner=cls.partner)
        cls.app.status = Application.APPROVED
        cls.app.save()

        cls.dashboard_url = reverse("dashboard")
예제 #4
0
def coordinators_only(user):
    """Return True if user is in coordinator group (or superuser), else False"""
    is_coordinator = False
    if user:
        coordinators = get_coordinators()
        is_coordinator = coordinators in user.groups.all() or user.is_superuser
    return is_coordinator
예제 #5
0
    def handle(self, *args, **options):
        num_editors = options['num'][0]
        fake = Faker()

        existing_users = User.objects.all()

        # Superuser the only user, per twlight_vagrant README instructions.
        if existing_users.count() == 0:
            raise CommandError('No users present to Superuser. '
                               'Please login first.')
        elif existing_users.count() > 1:
            raise CommandError('More than one user present. '
                               'Please ensure that only one user is present.')
        else:
            user = existing_users[0]
            user.is_superuser = True
            user.is_staff = True
            user.save()

        for _ in range(num_editors):
            user = UserFactory(email=fake.word() + "@example.com")
            editor = EditorFactory(
                user=user,
                real_name=fake.name(),
                country_of_residence=fake.country(),
                occupation=fake.job(),
                affiliation=fake.company(),
                wp_editcount=random.randint(50, 2000),
                wp_registered=fake.date_time_between(start_date="-10y",
                                                     end_date="now",
                                                     tzinfo=None),
                contributions=fake.paragraph(nb_sentences=4))

        # All users who aren't the superuser
        all_users = User.objects.exclude(is_superuser=True)

        # Flag wp_valid correctly if user is valid
        for user in all_users:
            date_valid = datetime.today().date() - timedelta(
                days=182) >= user.editor.wp_registered

            if user.editor.wp_editcount > 500 and date_valid:
                user.editor.wp_valid = True
                user.editor.save()

        # Make 5 random users coordinators
        coordinators = get_coordinators()
        for user in random.sample(all_users, 5):
            user.groups.add(coordinators)
            user.save()

        # Set 5 random non-coordinator users to have restricted data processing
        restricted = get_restricted()
        non_coordinators = all_users.exclude(groups__name='coordinators')
        for user in random.sample(non_coordinators, 5):
            user.groups.add(restricted)
            user.save()
예제 #6
0
    def setUp(self):
        self.editor = EditorFactory(user__email='*****@*****.**').user

        coordinators = get_coordinators()

        self.coordinator1 = EditorFactory(user__email='*****@*****.**',
                                          user__username='******').user
        self.coordinator2 = EditorFactory(user__email='*****@*****.**',
                                          user__username='******').user
        coordinators.user_set.add(self.coordinator1)
        coordinators.user_set.add(self.coordinator2)
예제 #7
0
 def formfield_for_foreignkey(self, db_field, request, **kwargs):
     """
     The coordinator dropdown should limit choices to actual coordinators,
     for admin ease of use.
     """
     if db_field.name == "coordinator":
         return self.CustomModelChoiceField(
             queryset=get_coordinators().user_set.all(), required=False)
     return super(PartnerAdmin,
                  self).formfield_for_foreignkey(db_field, request,
                                                 **kwargs)
예제 #8
0
    def setUp(self):
        super(ApplicationCommentTest, self).setUp()
        self.editor = EditorFactory(user__email='*****@*****.**').user

        coordinators = get_coordinators()

        self.coordinator1 = EditorFactory(user__email='*****@*****.**',
                                          user__username='******').user
        self.coordinator2 = EditorFactory(user__email='*****@*****.**',
                                          user__username='******').user
        coordinators.user_set.add(self.coordinator1)
        coordinators.user_set.add(self.coordinator2)
예제 #9
0
    def setUp(self):
        super(CoordinatorReminderEmailTest, self).setUp()
        editor = EditorFactory()
        self.user = editor.user
        editor2 = EditorFactory()
        self.user2 = editor2.user

        self.coordinator = EditorFactory(user__email="*****@*****.**").user
        coordinators = get_coordinators()
        coordinators.user_set.add(self.coordinator)

        self.partner = PartnerFactory(coordinator=self.coordinator)
        self.partner2 = PartnerFactory(coordinator=self.coordinator)
예제 #10
0
    def setUpTestData(cls):
        super().setUpTestData()
        editor = EditorFactory()
        cls.user = editor.user
        editor2 = EditorFactory()
        cls.user2 = editor2.user

        cls.coordinator = EditorFactory(user__email="*****@*****.**").user
        coordinators = get_coordinators()
        coordinators.user_set.add(cls.coordinator)

        cls.partner = PartnerFactory(coordinator=cls.coordinator)
        cls.partner2 = PartnerFactory(coordinator=cls.coordinator)
예제 #11
0
    def setUpTestData(cls):
        super().setUpTestData()
        cls.editor = EditorFactory(user__email="*****@*****.**").user

        coordinators = get_coordinators()

        cls.coordinator1 = EditorFactory(user__email="*****@*****.**",
                                         user__username="******").user
        cls.coordinator2 = EditorFactory(user__email="*****@*****.**",
                                         user__username="******").user
        coordinators.user_set.add(cls.coordinator1)
        coordinators.user_set.add(cls.coordinator2)

        cls.partner = PartnerFactory()
예제 #12
0
    def form_valid(self, form):
        coordinators = get_coordinators()
        restricted = get_restricted()
        if form.cleaned_data["restricted"]:
            self.request.user.groups.add(restricted)

            # If a coordinator requests we stop processing their data, we
            # shouldn't allow them to continue being one.
            if test_func_coordinators_only(self.request.user):
                self.request.user.groups.remove(coordinators)
        else:
            self.request.user.groups.remove(restricted)

        return HttpResponseRedirect(self.get_success_url())
예제 #13
0
    def setUp(self):
        super(ApplicationCommentTest, self).setUp()
        self.editor = EditorFactory(user__email="*****@*****.**").user

        coordinators = get_coordinators()

        self.coordinator1 = EditorFactory(user__email="*****@*****.**",
                                          user__username="******").user
        self.coordinator2 = EditorFactory(user__email="*****@*****.**",
                                          user__username="******").user
        coordinators.user_set.add(self.coordinator1)
        coordinators.user_set.add(self.coordinator2)

        self.partner = PartnerFactory()
예제 #14
0
    def setUpTestData(cls):
        super().setUpTestData()
        editor = EditorFactory(user__email="*****@*****.**")
        cls.user = editor.user

        cls.coordinator = EditorFactory().user
        coordinators = get_coordinators()
        coordinators.user_set.add(cls.coordinator)

        cls.partner = PartnerFactory()

        cls.authorization = Authorization()
        cls.authorization.user = cls.user
        cls.authorization.authorizer = cls.coordinator
        cls.authorization.date_expires = datetime.today() + timedelta(weeks=1)
        cls.authorization.save()
        cls.authorization.partners.add(cls.partner)
예제 #15
0
    def setUp(self):
        super(UserRenewalNoticeTest, self).setUp()
        editor = EditorFactory(user__email="*****@*****.**")
        self.user = editor.user

        self.coordinator = EditorFactory().user
        coordinators = get_coordinators()
        coordinators.user_set.add(self.coordinator)

        self.partner = PartnerFactory()

        self.authorization = Authorization()
        self.authorization.user = self.user
        self.authorization.authorizer = self.coordinator
        self.authorization.partner = self.partner
        self.authorization.date_expires = datetime.today() + timedelta(weeks=2)
        self.authorization.save()
예제 #16
0
파일: tests.py 프로젝트: nomarie/TWLight
    def setUpClass(cls):
        super(PartnerModelTests, cls).setUpClass()
        cls.lang_en, _ = Language.objects.get_or_create(language='en')
        cls.lang_fr, _ = Language.objects.get_or_create(language='fr')

        editor = EditorFactory()
        coordinators = get_coordinators()
        coordinators.user_set.add(editor.user)
        UserProfileFactory(user=editor.user, terms_of_use=True)

        cls.coordinator = editor.user

        # We should mock out any call to messages call in the view, since
        # RequestFactory (unlike Client) doesn't run middleware. If you
        # actually want to test that messages are displayed, use Client(),
        # and stop/restart the patcher.
        cls.message_patcher = patch('TWLight.applications.views.messages.add_message')
        cls.message_patcher.start()
예제 #17
0
    def test_authorization_authorizer_can_be_updated(self):
        """
        After successfully creating a valid Authorization,
        we should be able to remove the authorizer from
        the expected user groups and still save the object.
        """
        user = UserFactory()
        coordinator_editor = EditorCraftRoom(self, Terms=True, Coordinator=True)

        auth = Authorization(user=user, authorizer=coordinator_editor.user)
        auth.save()

        coordinators = get_coordinators()
        coordinators.user_set.remove(coordinator_editor.user)

        try:
            auth.save()
        except ValidationError:
            self.fail("Authorization authorizer validation failed.")
예제 #18
0
파일: tests.py 프로젝트: nomarie/TWLight
    def test_toggle_waitlist_2(self):
        """
        Posting to the toggle waitlist view sets a WAITLIST partner to
        AVAILABLE.
        """
        # Create needed objects.
        editor = EditorFactory()
        coordinators = get_coordinators()
        coordinators.user_set.add(editor.user)
        UserProfileFactory(user=editor.user, terms_of_use=True)

        partner = PartnerFactory(status=Partner.WAITLIST)

        # Set up request.
        url = reverse('partners:toggle_waitlist', kwargs={'pk': partner.pk})

        request = RequestFactory().post(url)
        request.user = editor.user

        _ = PartnersToggleWaitlistView.as_view()(request, pk=partner.pk)
        partner.refresh_from_db()
        self.assertEqual(partner.status, Partner.AVAILABLE)
예제 #19
0
    def setUpTestData(cls):
        super().setUpTestData()
        editor = EditorFactory(user__email="*****@*****.**")
        cls.user = editor.user

        # The user logged in:
        request = RequestFactory().get("/login")
        signals.user_logged_in.send(sender=cls.user.__class__,
                                    request=request,
                                    user=cls.user)

        cls.coordinator = EditorFactory().user
        coordinators = get_coordinators()
        coordinators.user_set.add(cls.coordinator)

        cls.partner = PartnerFactory()

        cls.authorization = Authorization()
        cls.authorization.user = cls.user
        cls.authorization.authorizer = cls.coordinator
        cls.authorization.date_expires = datetime.today() + timedelta(weeks=1)
        cls.authorization.save()
        cls.authorization.partners.add(cls.partner)
예제 #20
0
    def setUp(self):
        super(ProjectPage2021LaunchTest, self).setUp()
        editor = EditorFactory(user__email="*****@*****.**")
        self.user = editor.user

        # The user logged in:
        request = RequestFactory().get("/login")
        signals.user_logged_in.send(sender=self.user.__class__,
                                    request=request,
                                    user=self.user)

        self.coordinator = EditorFactory().user
        coordinators = get_coordinators()
        coordinators.user_set.add(self.coordinator)

        self.partner = PartnerFactory()

        self.authorization = Authorization()
        self.authorization.user = self.user
        self.authorization.authorizer = self.coordinator
        self.authorization.date_expires = datetime.today() + timedelta(weeks=1)
        self.authorization.save()
        self.authorization.partners.add(self.partner)
예제 #21
0
파일: tests.py 프로젝트: nomarie/TWLight
    def test_toggle_waitlist_access(self):
        """
        Only coordinators can post to the toggle waitlist view.
        """
        # Create needed objects.
        editor = EditorFactory()
        coordinators = get_coordinators()
        coordinators.user_set.add(editor.user)
        UserProfileFactory(user=editor.user, terms_of_use=True)

        partner = PartnerFactory(status=Partner.AVAILABLE)

        # Set up request.
        url = reverse('partners:toggle_waitlist', kwargs={'pk': partner.pk})

        request = RequestFactory().post(url)
        request.user = editor.user

        # This should work and not throw an error.
        resp = PartnersToggleWaitlistView.as_view()(request, pk=partner.pk)

        coordinators.user_set.remove(editor.user)
        with self.assertRaises(PermissionDenied):
            _ = PartnersToggleWaitlistView.as_view()(request, pk=partner.pk)
예제 #22
0
파일: views.py 프로젝트: gaurav7019/TWLight
from django.utils.http import is_safe_url
from django.utils.translation import ugettext_lazy as _
from django_comments.models import Comment

from TWLight.view_mixins import CoordinatorOrSelf, SelfOnly, coordinators
from TWLight.users.groups import get_coordinators, get_restricted

from reversion.models import Version

from .forms import EditorUpdateForm, SetLanguageForm, TermsForm, EmailChangeForm, RestrictDataForm
from .models import Editor, UserProfile
from TWLight.applications.models import Application

import datetime

coordinators = get_coordinators()
restricted = get_restricted()

import logging
logger = logging.getLogger(__name__)


def _is_real_url(url):
    """
    Users might have altered the URL parameters. Let's not just blindly
    redirect; let's actually make sure we can get somewhere first.
    """
    try:
        resolve(url)
        return True
    except Resolver404:
예제 #23
0
Note that these do *not* use something like django-braces' UserPassesTestMixin,
because we may need to use multiple tests in one view (e.g. must be a
coordinator AND must have agreed to the terms of use). If we used that mixin,
test functions and login URLs would overwrite each other. Using the dispatch
function and super() means we can chain as many access tests as we'd like.
"""

from django.contrib import messages
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse_lazy
from django.http import HttpResponseRedirect

from TWLight.users.groups import get_coordinators


coordinators = get_coordinators()


class CoordinatorsOrSelf(object):
    """
    Restricts visibility to:
    * Coordinators; or
    * The Editor who owns (or is) the object in the view; or
    * Superusers.

    This mixin assumes that the decorated view has a get_object method, and that
    the object in question has a ForeignKey, 'user', to the User model, or else
    is an instance of User.
    """

    def test_func_coordinators_or_self(self, user):
예제 #24
0
def coordinators_only(user):
    """Return True if user is in coordinator group (or superuser), else False"""
    coordinators = get_coordinators()
    return (coordinators in user.groups.all() or
            user.is_superuser)
예제 #25
0
 def setUpTestData(cls):
     super().setUpTestData()
     cls.coordinator = EditorFactory().user
     coordinators = get_coordinators()
     coordinators.user_set.add(cls.coordinator)
예제 #26
0
class Authorization(models.Model):
    """
    Authorizations track editor access to partner resources. The approval or
    sending of an application triggers the creation of an authorization for the
    relevant editor to access the approved resource. Authorizations may be
    created manually for testing.
    """
    class Meta:
        app_label = "users"
        verbose_name = "authorization"
        verbose_name_plural = "authorizations"

    coordinators = get_coordinators()

    # Users may have multiple authorizations.
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        blank=False,
        null=True,
        on_delete=models.SET_NULL,
        related_name="authorizations",
        help_text="The authorized user.",
    )

    # Authorizers may authorize many users.
    authorizer = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        blank=False,
        null=True,
        on_delete=models.SET_NULL,
        help_text="The authorizing user.",
    )

    date_authorized = models.DateField(auto_now_add=True)

    date_expires = models.DateField(
        blank=True,
        null=True,
        help_text="The date this authorization expires.")

    partners = models.ManyToManyField(
        Partner,
        blank=True,
        # Limit to available partners.
        limit_choices_to=(models.Q(
            status__in=[Partner.AVAILABLE, Partner.WAITLIST])),
        help_text="The partner(s) for which the editor is authorized.",
    )

    stream = models.ForeignKey(
        Stream,
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
        # Limit to available partners.
        limit_choices_to=(models.Q(
            partner__status__in=[Partner.AVAILABLE, Partner.WAITLIST])),
        help_text="The stream for which the editor is authorized.",
    )

    reminder_email_sent = models.BooleanField(
        default=False,
        help_text="Have we sent a reminder email about this authorization?",
    )

    @property
    def is_valid(self):
        """
        Gives Boolean response regarding the current validity of this authorization.
        """
        # We assume the authorization is invalid unless we know better.
        valid = False
        today = datetime.today().date()
        # When updating this logic, please also update the filter in
        # TWLight.applications.helpers.get_active_authorizations function,
        # so that they remain in sync and return the same type of authorizations.
        if (
                # Valid authorizations always have an authorizer, and user and a partner_id.
                self.authorizer and self.user and self.partners.all().exists()
                # and a valid authorization date that is now or in the past
                and self.date_authorized and self.date_authorized <= today
                # and an expiration date in the future (or no expiration date).
                and ((self.date_expires and self.date_expires >= today)
                     or not self.date_expires)):
            valid = True
        return valid

    # Try to return a useful object name, if fields were set appropriately.
    def __str__(self):
        if self.stream:
            stream_name = self.stream.name
        else:
            stream_name = None

        company_name = get_company_name(self)

        # In reality, we should always have an authorized user.
        if self.user:
            try:
                authorized_user = self.user.editor.wp_username
            except Editor.DoesNotExist:
                try:
                    authorized_user = self.user.username
                except User.DoesNotExist:
                    authorized_user = self.user
        else:
            authorized_user = None

        # In reality, we should always have an authorizer,
        # but we need to enhance the sample data commands so they don't
        # break the admin site in dev.
        if self.authorizer:
            try:
                authorizer = self.authorizer.editor.wp_username
            except Editor.DoesNotExist:
                try:
                    authorizer = self.authorizer.username
                except User.DoesNotExist:
                    authorizer = self.authorizer
        else:
            authorizer = None

        return "authorized: {authorized_user} - authorizer: {authorizer} - date_authorized: {date_authorized} - " "company_name: {company_name} - stream_name: {stream_name}".format(
            authorized_user=authorized_user,
            authorizer=authorizer,
            date_authorized=self.date_authorized,
            company_name=company_name,
            stream_name=stream_name,
        )

    def get_latest_app(self):
        """
        Returns the latest app corresponding to this auth in which the the status is *NOT* NOT_APPROVED.
        """
        from TWLight.applications.models import Application

        if self.partners.all().count() == 1 and self.user and self.user.editor:
            partner = self.partners.all()
            try:
                if self.stream:
                    return Application.objects.filter(
                        ~Q(status=Application.NOT_APPROVED),
                        partner__in=partner,
                        specific_stream=self.stream,
                        editor=self.user.editor,
                    ).latest("id")
                else:
                    return Application.objects.filter(
                        ~Q(status=Application.NOT_APPROVED),
                        partner__in=partner,
                        editor=self.user.editor,
                    ).latest("id")
            except Application.DoesNotExist:
                return None

    def get_latest_sent_app(self):
        """
        Returns the latest app corresponding to this auth in which the the status is SENT.
        """
        from TWLight.applications.models import Application

        if self.partners.all().count() == 1 and self.user and self.user.editor:
            try:
                return Application.objects.filter(
                    status=Application.SENT,
                    partner__in=self.partners.all(),
                    editor=self.user.editor,
                ).latest("id")
            except Application.DoesNotExist:
                return None

    @property
    def about_to_expire(self):
        # less than 30 days but greater than -1 day is when we consider an authorization about to expire
        today = date.today()
        if (self.date_expires
                and self.date_expires - today < timedelta(days=30)
                and not self.date_expires < today):
            return True
        else:
            return False

    def get_authorization_method(self):
        """
        For this authorization, returns the linked authorization
        method of the partner or stream, as applicable
        """
        if self.stream:
            authorization_method = self.stream.authorization_method
        elif self.pk and self.partners.exists():
            # Even if there is more than one partner, there should only be one authorization_method.
            authorization_method = (self.partners.all().values_list(
                "authorization_method", flat=True).distinct().get())
        else:
            authorization_method = None

        return authorization_method

    @property
    def is_bundle(self):
        """
        Returns True if this authorization is to a Bundle partner
        or stream and False otherwise.
        """
        authorization_method = self.get_authorization_method()

        if authorization_method == Partner.BUNDLE:
            return True
        else:
            return False

    def is_accessed_via_proxy(self):
        """
        Do users access the collection for this authorization via the proxy, or not?
        Returns True if the partner or stream has an authorization_method of Proxy or Bundle.
        """
        authorization_method = self.get_authorization_method()

        if authorization_method in [Partner.PROXY, Partner.BUNDLE]:
            return True
        else:
            return False

    def clean(self):
        """
        Run custom validations for Authorization objects, both when the
        object is created and updated, separately
        """
        # Run custom validation for ManyToMany Partner relationship.
        # This only works on updates to existing instances because ManyToMany relationships only exist
        # if the instance is in the db. Those will have a pk.
        # The admin form calls validate_partners before saving, so we are covered between the two.
        if self.pk:
            validate_partners(self.partners)

        # If the Authorization *is* being created, then we want to validate
        # that the authorizer field is a user in expected groups.
        # A user can stop being in one of these groups later, so we
        # only verify this on object creation.
        else:
            validate_authorizer(self.authorizer)
예제 #27
0
파일: models.py 프로젝트: ssd71/TWLight
class Authorization(models.Model):
    """
    Authorizations track editor access to partner resources. The approval or
    sending of an application triggers the creation of an authorization for the
    relevant editor to access the approved resource. Authorizations may be
    created manually for testing.
    """
    class Meta:
        app_label = "users"
        verbose_name = "authorization"
        verbose_name_plural = "authorizations"
        unique_together = ("user", "partner", "stream")

    coordinators = get_coordinators()

    # Users may have multiple authorizations.
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        blank=False,
        null=True,
        on_delete=models.SET_NULL,
        related_name="authorizations",
        # Translators: In the administrator interface, this text is help text for a field where staff can specify the username of the authorized editor.
        help_text=_("The authorized user."),
    )

    # Authorizers may authorize many users.
    authorizer = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        blank=False,
        null=True,
        on_delete=models.SET_NULL,
        # Really this should be limited to superusers or the associated partner coordinator instead of any coordinator. This object structure needs to change a bit for that to be possible.
        limit_choices_to=(models.Q(is_superuser=True)
                          | models.Q(groups__name="coordinators")),
        # Translators: In the administrator interface, this text is help text for a field where staff can specify the user who authorized the editor.
        help_text=_("The authorizing user."),
    )

    date_authorized = models.DateField(auto_now_add=True)

    date_expires = models.DateField(
        blank=True,
        null=True,
        # Translators: This field records the date the authorization expires.
        help_text=_("The date this authorization expires."),
    )

    partner = models.ForeignKey(
        Partner,
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
        # Limit to available partners.
        limit_choices_to=(models.Q(status=0)),
        # Translators: In the administrator interface, this text is help text for a field where staff can specify the partner for which the editor is authorized.
        help_text=_("The partner for which the editor is authorized."),
    )

    stream = models.ForeignKey(
        Stream,
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
        # Limit to available partners.
        limit_choices_to=(models.Q(partner__status=0)),
        # Translators: In the administrator interface, this text is help text for a field where staff can specify the partner for which the editor is authoried.
        help_text=_("The stream for which the editor is authorized."),
    )

    reminder_email_sent = models.BooleanField(
        default=False,
        # Translators: In the administrator interface, this text is help text for a field which tracks whether a reminder has been sent about this authorization yet.
        help_text=_("Have we sent a reminder email about this authorization?"),
    )

    @property
    def is_valid(self):
        """
        Gives Boolean response regarding the current validity of this authorization.
        """
        # We assume the authorization is invalid unless we know better.
        valid = False
        today = datetime.today().date()
        # When updating this logic, please also update the filter in
        # TWLight.applications.helpers.get_active_authorizations function,
        # so that they remain in sync and return the same type of authorizations.
        if (
                # Valid authorizations always have an authorizer, and user and a partner_id.
                self.authorizer and self.user and self.partner_id
                # and a valid authorization date that is now or in the past
                and self.date_authorized and self.date_authorized <= today
                # and an expiration date in the future (or no expiration date).
                and ((self.date_expires and self.date_expires >= today)
                     or not self.date_expires)):
            valid = True
        return valid

    # Try to return a useful object name, if fields were set appropriately.
    def __str__(self):
        if self.stream:
            stream_name = self.stream.name
        else:
            stream_name = None

        if self.partner:
            company_name = self.partner.company_name
        else:
            company_name = None

        # In reality, we should always have an authorized user.
        if self.user:
            try:
                authorized_user = self.user.editor.wp_username
            except Editor.DoesNotExist:
                try:
                    authorized_user = self.user.username
                except User.DoesNotExist:
                    authorized_user = self.user
        else:
            authorized_user = None

        # In reality, we should always have an authorizer,
        # but we need to enhance the sample data commands so they don't
        # break the admin site in dev.
        if self.authorizer:
            try:
                authorizer = self.authorizer.editor.wp_username
            except Editor.DoesNotExist:
                try:
                    authorizer = self.authorizer.username
                except User.DoesNotExist:
                    authorizer = self.authorizer
        else:
            authorizer = None

        return (
            "authorized: {authorized_user} - authorizer: {authorizer} - date_authorized: {date_authorized} - "
            "company_name: {company_name} - stream_name: {stream_name}".format(
                authorized_user=authorized_user,
                authorizer=authorizer,
                date_authorized=self.date_authorized,
                company_name=company_name,
                stream_name=stream_name,
            ))

    def get_latest_app(self):
        """
        Returns the latest application for a corresponding authorization,
        except when the status of the application is NOT_APPROVED, in which
        case returns the previous not NOT_APPROVED application.
        """
        from TWLight.applications.models import Application

        try:
            if self.stream:
                return Application.objects.filter(
                    ~Q(status=Application.NOT_APPROVED),
                    specific_stream=self.stream,
                    editor=self.user.editor,
                ).latest("id")
            else:
                return Application.objects.filter(
                    ~Q(status=Application.NOT_APPROVED),
                    partner=self.partner,
                    editor=self.user.editor,
                ).latest("id")
        except Application.DoesNotExist:
            return None

    def get_latest_sent_app(self):
        from TWLight.applications.models import Application

        try:
            return Application.objects.filter(
                status=Application.SENT,
                partner=self.partner,
                editor=self.user.editor).latest("id")
        except Application.DoesNotExist:
            return None

    def about_to_expire(self):
        # less than 30 days but greater than -1 day is when we consider an authorization about to expire
        today = date.today()
        if (self.date_expires
                and self.date_expires - today < timedelta(days=30)
                and not self.date_expires < today):
            return True
        else:
            return False

    def is_renewable(self):
        partner = self.partner
        if (
                # We consider an authorization renewable, if the partner is PROXY and
                # about to expire or has already expired (is_valid returns false on expiry)
                # or if the partner isn't PROXY or BUNDLE, in which case the authorization
                # would have an empty date_expires field. The first would check still cover for
                # non-PROXY and non-BUNDLE partners with expiry dates.
                self.about_to_expire() or not self.is_valid
                or not partner.authorization_method == partner.PROXY
                and not partner.authorization_method == partner.BUNDLE):
            return True
        else:
            return False
예제 #28
0
파일: tests.py 프로젝트: rv-raman/TWLight
 def setUp(self):
     super(ApplicationStatusTest, self).setUp()
     self.coordinator = EditorFactory().user
     coordinators = get_coordinators()
     coordinators.user_set.add(self.coordinator)
예제 #29
0
class Authorization(models.Model):
    """
    Authorizations track editor access to partner resources. The approval or
    sending of an application triggers the creation of an authorization for the
    relevant editor to access the approved resource. Authorizations may be
    created manually for testing.
    """
    class Meta:
        app_label = 'users'
        verbose_name = 'authorization'
        verbose_name_plural = 'authorizations'
        unique_together = ('authorized_user', 'partner', 'stream',
                           'date_authorized')

    coordinators = get_coordinators()

    # Users may have multiple authorizations.
    authorized_user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        blank=False,
        null=True,
        on_delete=models.SET_NULL,
        related_name="authorizations",
        # Translators: In the administrator interface, this text is help text for a field where staff can specify the username of the authorized editor.
        help_text=_('The authorized user.'))

    # Authorizers may authorize many users.
    authorizer = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        blank=False,
        null=True,
        on_delete=models.SET_NULL,
        # Really this should be limited to superusers or the associated partner coordinator instead of any coordinator. This object structure needs to change a bit for that to be possible.
        limit_choices_to=(models.Q(is_superuser=True)
                          | models.Q(groups__name='coordinators')),
        # Translators: In the administrator interface, this text is help text for a field where staff can specify the user who authorized the editor.
        help_text=_('The authorizing user.'))

    date_authorized = models.DateField(auto_now_add=True)

    date_expires = models.DateField(
        blank=True,
        null=True,
        #Translators: This field records the date the authorization expires.
        help_text=_("The date this authorization expires."))

    partner = models.ForeignKey(
        Partner,
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
        # Limit to available partners.
        limit_choices_to=(models.Q(status=0)),
        # Translators: In the administrator interface, this text is help text for a field where staff can specify the partner for which the editor is authorized.
        help_text=_('The partner for which the editor is authorized.'))

    stream = models.ForeignKey(
        Stream,
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
        # Limit to available partners.
        limit_choices_to=(models.Q(partner__status=0)),
        # Translators: In the administrator interface, this text is help text for a field where staff can specify the partner for which the editor is authoried.
        help_text=_('The stream for which the editor is authorized.'))

    reminder_email_sent = models.BooleanField(
        default=False,
        # Translators: In the administrator interface, this text is help text for a field which tracks whether a reminder has been sent about this authorization yet.
        help_text=_("Have we sent a reminder email about this authorization?"))

    # Try to return a useful object name, if fields were set appropriately.
    def __unicode__(self):
        if self.stream:
            stream_name = self.stream.name
        else:
            stream_name = None

        if self.partner:
            company_name = self.partner.company_name
        else:
            stream_name = None

        try:
            authorized_user = self.authorized_user.editor.wp_username
        except:
            authorized_user = self.authorized_user.username

        # In reality, we should always have an authorizer,
        # but we need to enhance the sample data commands so they don't
        # break the admin site in dev.
        if self.authorizer:
            try:
                authorizer = self.authorizer.editor.wp_username
            except:
                authorizer = self.authorizer.username
        else:
            authorizer = None

        return u'authorized: {authorized_user} - authorizer: {authorizer} - date_authorized: {date_authorized} - company_name: {company_name} - stream_name: {stream_name}'.format(
            authorized_user=authorized_user,
            authorizer=authorizer,
            date_authorized=self.date_authorized,
            company_name=company_name,
            stream_name=stream_name,
        )