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, )
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.")
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")
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
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()
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)
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)
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)
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)
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)
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()
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())
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()
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)
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()
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()
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.")
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)
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)
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)
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)
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:
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):
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)
def setUpTestData(cls): super().setUpTestData() cls.coordinator = EditorFactory().user coordinators = get_coordinators() coordinators.user_set.add(cls.coordinator)
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)
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
def setUp(self): super(ApplicationStatusTest, self).setUp() self.coordinator = EditorFactory().user coordinators = get_coordinators() coordinators.user_set.add(self.coordinator)
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, )