def test_registered_higher_deselections_on_change_status(self): self.login_registrar() # Make a RR so the registrar can change status items = [self.item1.id, self.item2.id] self.create_review_request(items) # Register item1 as candidate models.Status.objects.create(concept=self.item1, registrationAuthority=self.ra, registrationDate=timezone.now(), state=STATES.standard) # Register item2 as standard models.Status.objects.create(concept=self.item2, registrationAuthority=self.ra, registrationDate=timezone.now(), state=STATES.preferred) self.assertTrue( perms.user_can_change_status(self.registrar, self.item1)) self.assertTrue( perms.user_can_change_status(self.registrar, self.item2)) response = self.review_changes(items, STATES.standard) self.assertTrue(response.context['deselections']) form = response.context['form'] extra_info = form.fields['selected_list'].widget.extra_info self.assertTrue(extra_info[self.item1.id]['perm']) self.assertFalse(extra_info[self.item1.id]['checked']) self.assertTrue(extra_info[self.item2.id]['perm']) self.assertFalse(extra_info[self.item2.id]['checked'])
def test_registered_higher_deselections_on_change_status(self): self.login_registrar() # Make a RR so the registrar can change status items = [self.item1.id, self.item2.id] self.create_review_request(items) # Register item1 as candidate models.Status.objects.create( concept=self.item1, registrationAuthority=self.ra, registrationDate=timezone.now(), state=STATES.standard ) # Register item2 as standard models.Status.objects.create( concept=self.item2, registrationAuthority=self.ra, registrationDate=timezone.now(), state=STATES.preferred ) self.assertTrue(perms.user_can_change_status(self.registrar, self.item1)) self.assertTrue(perms.user_can_change_status(self.registrar, self.item2)) response = self.review_changes(items, STATES.standard) self.assertTrue(response.context['deselections']) form = response.context['form'] extra_info = form.fields['selected_list'].widget.extra_info self.assertTrue(extra_info[self.item1.id]['perm']) self.assertFalse(extra_info[self.item1.id]['checked']) self.assertTrue(extra_info[self.item2.id]['perm']) self.assertFalse(extra_info[self.item2.id]['checked'])
def test_bulk_status_change_on_permitted_items(self): self.login_registrar() review = models.ReviewRequest.objects.create( requester=self.su, registration_authority=self.ra) review.concepts.add(self.item1) review.concepts.add(self.item2) self.assertTrue( perms.user_can_change_status(self.registrar, self.item1)) self.assertTrue( perms.user_can_change_status(self.registrar, self.item2)) self.assertFalse(self.item1.is_registered) self.assertFalse(self.item2.is_registered) response = self.client.post( reverse('aristotle:bulk_action'), { 'bulkaction': 'change_state', 'state': 1, 'items': [self.item1.id, self.item2.id], 'registrationDate': "2014-10-27", 'cascadeRegistration': 0, 'registrationAuthorities': [self.ra.id], 'confirmed': 'confirmed', }) self.assertTrue(self.item1.is_registered) self.assertTrue(self.item2.is_registered)
def test_bulk_status_change_on_forbidden_items(self): self.login_registrar() self.make_review_request(self.item1, self.registrar) self.assertTrue( perms.user_can_change_status(self.registrar, self.item1)) self.assertFalse( perms.user_can_change_status(self.registrar, self.item4)) self.assertFalse(self.item1.is_registered) self.assertFalse(self.item2.is_registered) self.assertFalse(self.item4.is_registered) reg_date = datetime.date(2014, 10, 27) new_state = self.ra.locked_state items = [self.item1.id, self.item2.id, self.item4.id] action_response = self.client.post( reverse('aristotle:bulk_action'), { 'bulkaction': 'aristotle_mdr.forms.bulk_actions.ChangeStateForm', 'items': items, }) self.assertRedirects(action_response, reverse('aristotle:change_state_bulk_action')) get_response = self.client.get( reverse('aristotle:change_state_bulk_action')) self.assertEqual(get_response.context['form'].initial['items'], [str(a) for a in items]) response = self.client.post( reverse('aristotle:change_state_bulk_action'), { 'change_state-state': new_state, 'change_state-items': [str(a) for a in items], 'change_state-registrationDate': reg_date, 'change_state-cascadeRegistration': 0, 'change_state-registrationAuthorities': [self.ra.id], 'change_state-confirmed': 'confirmed', 'submit_skip': 'value', 'change_status_bulk_action_view-current_step': 'change_state', }, follow=True) self.assertEqual(200, response.status_code) self.assertTrue(self.item1.is_registered) self.assertFalse(self.item2.is_registered) self.assertFalse(self.item4.is_registered) self.assertTrue( self.item1.current_statuses().first().registrationDate == reg_date) self.assertTrue( self.item1.current_statuses().first().state == new_state) self.assertTrue(self.item1.current_statuses().first(). registrationAuthority == self.ra) self.assertEqual(len(response.redirect_chain), 1) self.assertEqual(response.redirect_chain[0][1], 302)
def test_bulk_status_change_on_forbidden_items(self): self.login_registrar() self.make_review_request(self.item1, self.registrar) self.assertTrue(perms.user_can_change_status(self.registrar, self.item1)) self.assertFalse(perms.user_can_change_status(self.registrar, self.item4)) self.assertFalse(self.item1.is_registered) self.assertFalse(self.item2.is_registered) self.assertFalse(self.item4.is_registered) reg_date = datetime.date(2014,10,27) new_state = self.ra.locked_state items = [self.item1.id, self.item2.id, self.item4.id] action_response = self.client.post( reverse('aristotle:bulk_action'), { 'bulkaction': 'aristotle_mdr.forms.bulk_actions.ChangeStateForm', 'items': items, } ) self.assertRedirects(action_response, reverse('aristotle:change_state_bulk_action')) get_response = self.client.get(reverse('aristotle:change_state_bulk_action')) self.assertEqual(get_response.context['form'].initial['items'], [str(a) for a in items]) response = self.client.post( reverse('aristotle:change_state_bulk_action'), { 'change_state-state': new_state, 'change_state-items': [str(a) for a in items], 'change_state-registrationDate': reg_date, 'change_state-cascadeRegistration': 0, 'change_state-registrationAuthorities': [self.ra.id], 'change_state-confirmed': 'confirmed', 'submit_skip': 'value', 'change_status_bulk_action_view-current_step': 'change_state', }, follow=True ) self.assertEqual(200, response.status_code) self.assertTrue(self.item1.is_registered) self.assertFalse(self.item2.is_registered) self.assertFalse(self.item4.is_registered) self.assertTrue(self.item1.current_statuses().first().registrationDate == reg_date) self.assertTrue(self.item1.current_statuses().first().state == new_state) self.assertTrue(self.item1.current_statuses().first().registrationAuthority == self.ra) self.assertEqual(len(response.redirect_chain), 1) self.assertEqual(response.redirect_chain[0][1], 302)
def test_bulk_status_change_on_forbidden_items(self): self.login_registrar() review = models.ReviewRequest.objects.create( requester=self.su, registration_authority=self.ra, registration_date=datetime.date(2010, 1, 1), state=self.ra.locked_state) review.concepts.add(self.item1) # review.concepts.add(self.item4) self.assertTrue( perms.user_can_change_status(self.registrar, self.item1)) self.assertFalse( perms.user_can_change_status(self.registrar, self.item4)) self.assertFalse(self.item1.is_registered) self.assertFalse(self.item2.is_registered) self.assertFalse(self.item4.is_registered) reg_date = datetime.date(2014, 10, 27) new_state = self.ra.locked_state response = self.client.post( reverse('aristotle:bulk_action'), { 'bulkaction': 'aristotle_mdr.forms.bulk_actions.ChangeStateForm', 'state': new_state, 'items': [self.item1.id, self.item2.id, self.item4.id], 'registrationDate': reg_date, 'cascadeRegistration': 0, 'registrationAuthorities': [self.ra.id], 'confirmed': 'confirmed', }, follow=True) self.assertEqual(200, response.status_code) self.assertTrue(self.item1.is_registered) self.assertFalse(self.item2.is_registered) self.assertFalse(self.item4.is_registered) self.assertTrue( self.item1.current_statuses().first().registrationDate == reg_date) self.assertTrue( self.item1.current_statuses().first().state == new_state) self.assertTrue(self.item1.current_statuses().first(). registrationAuthority == self.ra) from django.utils.html import escape err1 = "Some items failed" err2 = "s: %s" % ','.join( sorted([str(self.item2.id), str(self.item4.id)])) self.assertContains(response, err1) self.assertContains(response, err2) self.assertEqual(len(response.redirect_chain), 1) self.assertEqual(response.redirect_chain[0][1], 302)
def test_registrar_can_change_status(self): self.login_registrar() self.assertFalse(perms.user_can_view(self.registrar,self.item1)) self.item1.readyToReview = True self.item1.save() self.item1 = self.itemType.objects.get(pk=self.item1.pk) self.assertTrue(perms.user_can_view(self.registrar,self.item1)) self.assertTrue(perms.user_can_change_status(self.registrar,self.item1)) response = self.client.get(reverse('aristotle:changeStatus',args=[self.item1.id])) self.assertEqual(response.status_code,200) self.assertEqual(self.item1.statuses.count(),0) response = self.client.post( reverse('aristotle:changeStatus',args=[self.item1.id]), { 'registrationAuthorities': [str(self.ra.id)], 'state': self.ra.public_state, 'changeDetails': "testing", 'cascadeRegistration': 0, # no } ) self.assertRedirects(response,url_slugify_concept(self.item1)) self.item1 = self.itemType.objects.get(pk=self.item1.pk) self.assertEqual(self.item1.statuses.count(),1) self.assertTrue(self.item1.is_registered) self.assertTrue(self.item1.is_public())
def cascaded_register(self, item, state, user, **kwargs): all_items = [item] + item.registry_cascade_items if not perms.user_can_change_status(user, item): # Return a failure as this item isn't allowed return {'success': [], 'failed': all_items} revision_message = _( "Cascade registration of item '%(name)s' (id:%(iid)s)\n") % { 'name': item.name, 'iid': item.id } if 'change_details' in kwargs: revision_message += kwargs['change_details'] seen_items = {'success': [], 'failed': []} with transaction.atomic(), reversion.revisions.create_revision(): reversion.revisions.set_user(user) reversion.revisions.set_comment(revision_message) for child_item in all_items: self._register(child_item, state, **kwargs) seen_items['success'] += [child_item] return seen_items
def changeStatus(request, iid): item = get_object_or_404(MDR._concept,pk=iid) item = MDR._concept.objects.get_subclass(pk=iid) if not (item and user_can_change_status(request.user,item)): if request.user.is_anonymous(): return redirect('/accounts/login?next=%s' % request.path) else: raise PermissionDenied # There would be an else here, but both branches above return, # so we've chopped it out to prevent an arrow anti-pattern. ras=request.user.profile.registrarAuthorities if request.method == 'POST': # If the form has been submitted... form = MDRForms.ChangeStatusForm(request.POST,ras=ras) # A form bound to the POST data if form.is_valid(): # process the data in form.cleaned_data as required ras = form.cleaned_data['registrationAuthorities'] state = form.cleaned_data['state'] regDate = form.cleaned_data['registrationDate'] cascade = form.cleaned_data['cascadeRegistration'] if regDate is None: regDate = timezone.now().date() for ra in ras: ra = MDR.RegistrationAuthority.objects.get(id=int(ra)) ra.register(item,state,request.user,regDate,cascade) return HttpResponseRedirect(reverse("aristotle:%s"%item.url_name(),args=[item.id])) else: form = MDRForms.ChangeStatusForm(ras=ras) return render(request,"aristotle_mdr/actions/changeStatus.html", {"item":item, "form":form, } )
def build_extra_info(self, queryset, ra, user, static_content): (extra_info, deselections) = get_status_change_details(queryset, ra, static_content['new_state']) for key, item in extra_info.items(): item['checked'] = not item['has_higher_status'] item['perm'] = perms.user_can_change_status(user, item['concept']) return (extra_info, deselections)
def test_registrar_can_change_status(self): self.login_registrar() self.assertFalse(perms.user_can_view(self.registrar,self.item1)) self.item1.readyToReview = True self.item1.save() self.item1 = self.itemType.objects.get(pk=self.item1.pk) self.assertTrue(perms.user_can_view(self.registrar,self.item1)) self.assertTrue(perms.user_can_change_status(self.registrar,self.item1)) response = self.client.get(reverse('aristotle:changeStatus',args=[self.item1.id])) self.assertEqual(response.status_code,200) self.assertEqual(self.item1.statuses.count(),0) response = self.client.post(reverse('aristotle:changeStatus',args=[self.item1.id]), { 'registrationAuthorities': [str(self.ra.id)], 'state': self.ra.public_state, 'changeDetails': "testing", 'cascadeRegistration': 0, #no } ) self.assertRedirects(response,url_slugify_concept(self.item1)) self.item1 = self.itemType.objects.get(pk=self.item1.pk) self.assertEqual(self.item1.statuses.count(),1) self.assertTrue(self.item1.is_registered) self.assertTrue(self.item1.is_public())
def test_registrar_cannot_use_faulty_statuses(self): self.login_registrar() self.assertFalse(perms.user_can_view(self.registrar,self.item1)) self.item1.readyToReview = True self.item1.save() self.item1 = self.itemType.objects.get(pk=self.item1.pk) self.assertTrue(perms.user_can_view(self.registrar,self.item1)) self.assertTrue(perms.user_can_change_status(self.registrar,self.item1)) response = self.client.get(reverse('aristotle:changeStatus',args=[self.item1.id])) self.assertEqual(response.status_code,200) self.assertEqual(self.item1.statuses.count(),0) response = self.client.post(reverse('aristotle:changeStatus',args=[self.item1.id]), { 'registrationAuthorities': [str(self.ra.id)], 'state': "Not a number",#obviously wrong 'changeDetails': "testing", 'cascadeRegistration': 0, #no } ) self.assertFormError(response, 'form', 'state', 'Select a valid choice. Not a number is not one of the available choices.') response = self.client.post(reverse('aristotle:changeStatus',args=[self.item1.id]), { 'registrationAuthorities': [str(self.ra.id)], 'state': "343434", #also wrong 'changeDetails': "testing", 'cascadeRegistration': 0, #no } ) self.assertFormError(response, 'form', 'state', 'Select a valid choice. 343434 is not one of the available choices.')
def test_bulk_status_change_on_permitted_items(self): self.login_registrar() review = models.ReviewRequest.objects.create( requester=self.su, registration_authority=self.ra, state=self.ra.locked_state, registration_date=datetime.date(2013, 4, 2)) review.concepts.add(self.item1) review.concepts.add(self.item2) self.assertTrue( perms.user_can_change_status(self.registrar, self.item1)) self.assertTrue( perms.user_can_change_status(self.registrar, self.item2)) self.assertFalse(self.item1.is_registered) self.assertFalse(self.item2.is_registered) reg_date = datetime.date(2014, 10, 27) new_state = self.ra.locked_state response = self.client.post(reverse('aristotle:bulk_action'), { 'bulkaction': 'aristotle_mdr.forms.bulk_actions.ChangeStateForm', 'state': new_state, 'items': [self.item1.id, self.item2.id], 'registrationDate': reg_date, 'cascadeRegistration': 0, 'registrationAuthorities': [self.ra.id], 'confirmed': 'confirmed', }, follow=True) self.assertTrue(self.item1.is_registered) self.assertTrue(self.item2.is_registered) self.assertTrue( self.item1.current_statuses().first().registrationDate == reg_date) self.assertTrue( self.item2.current_statuses().first().registrationDate == reg_date) self.assertTrue( self.item1.current_statuses().first().state == new_state) self.assertTrue( self.item2.current_statuses().first().state == new_state) self.assertTrue(self.item1.current_statuses().first(). registrationAuthority == self.ra) self.assertTrue(self.item2.current_statuses().first(). registrationAuthority == self.ra) self.assertNotContains(response, "Some items failed")
def build_extra_info(self, queryset, ra, user, static_content): extra_info = {} subclassed_queryset = queryset.select_subclasses() statuses = Status.objects.filter( concept__in=queryset, registrationAuthority=ra).select_related('concept') statuses = status_filter(statuses).order_by("-registrationDate", "-created") new_state_num = static_content['new_state'] new_state = str(STATES[new_state_num]) # Build a dict mapping concepts to their status data # So that no additional status queries need to be made states_dict = {} for status in statuses: state_name = str(STATES[status.state]) reg_date = status.registrationDate if status.concept.id not in states_dict: states_dict[status.concept.id] = { 'name': state_name, 'reg_date': reg_date, 'state': status.state } deselections = False for concept in subclassed_queryset: url = reverse('aristotle:registrationHistory', kwargs={'iid': concept.id}) innerdict = {} # Get class name innerdict['type'] = concept.__class__.get_verbose_name() innerdict['checked'] = True try: state_info = states_dict[concept.id] except KeyError: state_info = None if state_info: innerdict['old'] = { 'url': url, 'text': state_info['name'], 'old_reg_date': state_info['reg_date'] } if state_info['state'] >= new_state_num: innerdict['checked'] = False deselections = True innerdict['perm'] = perms.user_can_change_status(user, concept) innerdict['new_state'] = {'url': url, 'text': new_state} extra_info[concept.id] = innerdict return (extra_info, deselections)
def build_extra_info(self, queryset, ra, user, static_content): extra_info = {} subclassed_queryset = queryset.select_subclasses() statuses = MDR.Status.objects.filter( concept__in=queryset, registrationAuthority=ra).select_related('concept') statuses = status_filter(statuses).order_by("-registrationDate", "-created") # Build a dict mapping concepts to their status data # So that no additional status queries need to be made states_dict = {} for status in statuses: state_name = str(MDR.STATES[status.state]) reg_date = status.registrationDate if status.concept.id not in states_dict: states_dict[status.concept.id] = { 'name': state_name, 'reg_date': reg_date } for concept in subclassed_queryset: url = reverse('aristotle:registrationHistory', kwargs={'iid': concept.id}) innerdict = {} # Get class name innerdict.update({'type': concept.__class__.get_verbose_name()}) try: state_info = states_dict[concept.id] except KeyError: state_info = None if state_info: innerdict.update({ 'old': { 'url': url, 'text': state_info['name'] }, 'old_reg_date': state_info['reg_date'] }) innerdict.update( {'perm': perms.user_can_change_status(user, concept)}) innerdict.update({ 'new_state': { 'url': url, 'text': static_content['new_state'] } }) extra_info.update({concept.id: innerdict}) return extra_info
def has_change_permission(self, request,obj=None): if obj is None: return True else: if perms.user_can_edit(request.user,obj): return True if perms.user_can_change_status(request.user,obj): return True else: return super(ConceptAdmin, self).has_change_permission(request,obj=None)
def dispatch(self, request, *args, **kwargs): # Check for keyError here self.item = get_object_or_404(MDR._concept, pk=kwargs['iid']).item if not (self.item and user_can_change_status(request.user, self.item)): if request.user.is_anonymous(): return redirect(reverse('friendly_login') + '?next=%s' % request.path) else: raise PermissionDenied return super().dispatch(request, *args, **kwargs)
def register(self, item, state, user, *args, **kwargs): if not perms.user_can_change_status(user, item): # Return a failure as this item isn't allowed return {'success': [], 'failed': [item]} revision_message = kwargs.get('changeDetails', "") with transaction.atomic(), reversion.revisions.create_revision(): reversion.revisions.set_user(user) reversion.revisions.set_comment(revision_message) self._register(item, state, user, *args, **kwargs) return {'success': [item], 'failed': []}
def can_change_status(item, user): """ A filter that acts as a wrapper around ``aristotle_mdr.perms.user_can_supersede``. Returns true if the user has permission to supersede the item, otherwise it returns False. If calling ``user_can_supersede`` throws an exception it safely returns False. For example:: {% if myItem|can_supersede:request.user %} {{ item }} {% endif %} """ return perms.user_can_change_status(user, item)
def test_bulk_status_change_on_forbidden_items(self): self.login_registrar() review = models.ReviewRequest.objects.create( requester=self.su, registration_authority=self.ra) review.concepts.add(self.item1) # review.concepts.add(self.item4) self.assertTrue( perms.user_can_change_status(self.registrar, self.item1)) self.assertFalse( perms.user_can_change_status(self.registrar, self.item4)) self.assertFalse(self.item1.is_registered) self.assertFalse(self.item2.is_registered) self.assertFalse(self.item4.is_registered) response = self.client.post( reverse('aristotle:bulk_action'), { 'bulkaction': 'change_state', 'state': 1, 'items': [self.item1.id, self.item2.id, self.item4.id], 'registrationDate': "2014-10-27", 'cascadeRegistration': 0, 'registrationAuthorities': [self.ra.id], 'confirmed': 'confirmed', }, follow=True) self.assertEqual(200, response.status_code) self.assertTrue(self.item1.is_registered) self.assertFalse(self.item2.is_registered) self.assertFalse(self.item4.is_registered) from django.utils.html import escape err1 = "Some items failed" err2 = "s: %s" % ','.join( sorted([str(self.item2.id), str(self.item4.id)])) self.assertTrue(err1 in response.content) self.assertTrue(err2 in response.content) self.assertEqual(len(response.redirect_chain), 1) self.assertEqual(response.redirect_chain[0][1], 302)
def register(self,item,state,user,registrationDate=timezone.now(),cascade=False,changeDetails=""): if not perms.user_can_change_status(user,item): # Should raise something here instead of quietly failing return None reg,created = Status.objects.get_or_create( concept=item, registrationAuthority=self, defaults ={ "registrationDate" : registrationDate, "state" : state, "changeDetails":changeDetails } ) if not created: reg.changeDetails = changeDetails reg.state = state reg.registrationDate = registrationDate reg.save() if cascade: for i in item.registry_cascade_items: if i is not None and perms.user_can_change_status(user,i): self.register(i,state,user,registrationDate=registrationDate,cascade=cascade,changeDetails=changeDetails) return reg
def test_bulk_status_change_on_forbidden_items(self): self.login_registrar() review = models.ReviewRequest.objects.create(requester=self.su,registration_authority=self.ra) review.concepts.add(self.item1) # review.concepts.add(self.item4) self.assertTrue(perms.user_can_change_status(self.registrar, self.item1)) self.assertFalse(perms.user_can_change_status(self.registrar, self.item4)) self.assertFalse(self.item1.is_registered) self.assertFalse(self.item2.is_registered) self.assertFalse(self.item4.is_registered) response = self.client.post( reverse('aristotle:bulk_action'), { 'bulkaction': 'change_state', 'state': 1, 'items': [self.item1.id, self.item2.id, self.item4.id], 'registrationDate': "2014-10-27", 'cascadeRegistration': 0, 'registrationAuthorities': [self.ra.id], 'confirmed': 'confirmed', }, follow=True ) self.assertEqual(200, response.status_code) self.assertTrue(self.item1.is_registered) self.assertFalse(self.item2.is_registered) self.assertFalse(self.item4.is_registered) from django.utils.html import escape err1 = "Some items failed" err2 = "s: %s" % ','.join(sorted([str(self.item2.id), str(self.item4.id)])) self.assertTrue(err1 in response.content) self.assertTrue(err2 in response.content) self.assertEqual(len(response.redirect_chain), 1) self.assertEqual(response.redirect_chain[0][1], 302)
def test_deslections_on_first_registration(self): self.login_registrar() # Make a RR so the registrar can change status items = [self.item1.id] self.create_review_request(items) self.assertTrue(perms.user_can_change_status(self.registrar, self.item1)) response = self.review_changes(items, STATES.standard) self.assertFalse(response.context['deselections']) form = response.context['form'] extra_info = form.fields['selected_list'].widget.extra_info self.assertTrue(extra_info[self.item1.id]['perm']) self.assertTrue(extra_info[self.item1.id]['checked'])
def test_bulk_status_change_on_permitted_items(self): self.login_registrar() review = models.ReviewRequest.objects.create(requester=self.su,registration_authority=self.ra) review.concepts.add(self.item1) review.concepts.add(self.item2) self.assertTrue(perms.user_can_change_status(self.registrar, self.item1)) self.assertTrue(perms.user_can_change_status(self.registrar, self.item2)) self.assertFalse(self.item1.is_registered) self.assertFalse(self.item2.is_registered) response = self.client.post( reverse('aristotle:bulk_action'), { 'bulkaction': 'change_state', 'state': 1, 'items': [self.item1.id, self.item2.id], 'registrationDate': "2014-10-27", 'cascadeRegistration': 0, 'registrationAuthorities': [self.ra.id], 'confirmed': 'confirmed', } ) self.assertTrue(self.item1.is_registered) self.assertTrue(self.item2.is_registered)
def changeStatus(request, iid): item = get_object_or_404(MDR._concept, pk=iid).item if not (item and user_can_change_status(request.user, item)): if request.user.is_anonymous(): return redirect(reverse('friendly_login') + '?next=%s' % request.path) else: raise PermissionDenied # There would be an else here, but both branches above return, # so we've chopped it out to prevent an arrow anti-pattern. if request.method == 'POST': # If the form has been submitted... form = MDRForms.ChangeStatusForm(request.POST, user=request.user) # A form bound to the POST data if form.is_valid(): # process the data in form.cleaned_data as required ras = form.cleaned_data['registrationAuthorities'] state = form.cleaned_data['state'] regDate = form.cleaned_data['registrationDate'] cascade = form.cleaned_data['cascadeRegistration'] changeDetails = form.cleaned_data['changeDetails'] with transaction.atomic(), reversion.revisions.create_revision(): reversion.revisions.set_user(request.user) for ra in ras: if cascade: register_method = ra.cascaded_register else: register_method = ra.register register_method( item, state, request.user, changeDetails=changeDetails, registrationDate=regDate, ) # TODO: notification and message on success/failure return HttpResponseRedirect(url_slugify_concept(item)) else: form = MDRForms.ChangeStatusForm(user=request.user) import json return render( request, "aristotle_mdr/actions/changeStatus.html", { "item": item, "form": form, "status_matrix": json.dumps(generate_visibility_matrix(request.user)), } )
def test_deslections_on_first_registration(self): self.login_registrar() # Make a RR so the registrar can change status items = [self.item1.id] self.create_review_request(items) self.assertTrue( perms.user_can_change_status(self.registrar, self.item1)) response = self.review_changes(items, STATES.standard) self.assertFalse(response.context['deselections']) form = response.context['form'] extra_info = form.fields['selected_list'].widget.extra_info self.assertTrue(extra_info[self.item1.id]['perm']) self.assertTrue(extra_info[self.item1.id]['checked'])
def can_change_status(item, user): """ A filter that acts as a wrapper around ``aristotle_mdr.perms.can_change_status``. Returns true if the user has permission to change status the item, otherwise it returns False. If calling ``user_can_change_status`` throws an exception it safely returns False. For example:: {% if myItem|can_change_status:request.user %} {{ item }} {% endif %} """ # return perms.can_change_status(user, item) try: return perms.user_can_change_status(user, item) except: # pragma: no cover -- passing a bad item or user is the template authors fault return None
def _register(self,item,state,user,*args,**kwargs): changeDetails=kwargs.get('changeDetails',"") # If registrationDate is None (like from a form), override it with todays date registrationDate= kwargs.get('registrationDate',None) or timezone.now().date() until_date=kwargs.get('until_date',None) if not perms.user_can_change_status(user,item): # Return a failure as this item isn't allowed return False Status.objects.create( concept=item, registrationAuthority=self, registrationDate=registrationDate, state=state, changeDetails=changeDetails, until_date=until_date ) return True
def register(self,item,state,user,regDate=timezone.now(),cascade=False): reg,created = Status.objects.get_or_create( concept=item, registrationAuthority=self, defaults ={ "registrationDate" : regDate, "state" : state } ) if not created: reg.state = state reg.registrationDate = regDate reg.save() if cascade: for i in item.registryCascadeItems: if i is not None and perms.user_can_change_status(user,i): self.register(i,state,user,regDate,cascade) return reg
def make_review_request(self, item, user, requester=None): if not requester: requester = self.su self.assertFalse(perms.user_can_view(user, item)) item.save() item = item.__class__.objects.get(pk=item.pk) review = ReviewRequest.objects.create( requester=requester, registration_authority=self.ra, target_registration_state=self.ra.public_state, due_date=datetime.date(2010, 1, 1), registration_date=datetime.date(2010, 1, 1)) review.concepts.add(item) self.assertTrue(perms.user_can_view(user, item)) self.assertTrue(perms.user_can_change_status(user, item)) return review
def make_review_request(self, item, user, requester=None): if not requester: requester = self.su self.assertFalse(perms.user_can_view(user,item)) item.save() item = item.__class__.objects.get(pk=item.pk) review = ReviewRequest.objects.create( requester=requester,registration_authority=self.ra, target_registration_state=self.ra.public_state, due_date=datetime.date(2010,1,1), registration_date=datetime.date(2010,1,1) ) review.concepts.add(item) self.assertTrue(perms.user_can_view(user,item)) self.assertTrue(perms.user_can_change_status(user,item)) return review
def register(self, item, state, user, **kwargs): if not perms.user_can_change_status(user, item): # Return a failure as this item isn't allowed return {'success': [], 'failed': [item]} revision_message = _( "Registration of item '%(name)s' (id:%(iid)s)\n") % { 'name': item.name, 'iid': item.id } if 'change_details' in kwargs: revision_message = kwargs['change_details'] with transaction.atomic(), reversion.revisions.create_revision(): reversion.revisions.set_user(user) reversion.revisions.set_comment(revision_message) self._register(item, state, **kwargs) return {'success': [item], 'failed': []}
def test_glossary_ajax_list(self): import json gitem = models.GlossaryItem(name="Glossary item",workgroup=self.wg1) response = self.client.get(reverse('aristotle:glossaryAjaxlist')) data = json.loads(str(response.content)) self.assertEqual(data,[]) gitem.readyToReview = True gitem.save() self.assertTrue(perms.user_can_change_status(self.registrar,gitem)) self.ra.register(gitem,models.STATES.standard,self.registrar) self.assertTrue(gitem.is_public()) response = self.client.get(reverse('aristotle:glossaryAjaxlist')) data = json.loads(str(response.content)) self.assertEqual(len(data),1) self.assertEqual(data[0]['id'],gitem.id)
def test_bulk_status_change_on_permitted_items(self): self.login_registrar() self.item1.readyToReview = True self.item2.readyToReview = True self.item1.save() self.item2.save() self.assertTrue(perms.user_can_change_status(self.registrar,self.item1)) self.assertFalse(self.item1.is_registered) response = self.client.post(reverse('aristotle:bulk_action'), { 'bulkaction': 'change_state', 'state' : 1, 'items' : [self.item1.id,self.item2.id], 'registrationDate' : "2014-10-27", 'cascadeRegistration': 0, 'registrationAuthorities' : [self.ra.id], 'confirmed':'confirmed', } ) self.assertTrue(self.item1.is_registered) self.assertTrue(self.item2.is_registered)
def test_glossary_ajax_list_public(self): self.logout() import json gitem = gmodels.GlossaryItem.objects.create(name="Glossary item", workgroup=self.wg1) response = self.client.get( reverse('aristotle_glossary:json_list') + '?items=%s' % gitem.id) data = json.loads(str(response.content))['items'] self.assertEqual(data, []) gitem.readyToReview = True self.assertTrue(perms.user_can_change_status(self.registrar, gitem)) self.ra.register(gitem, models.STATES.standard, self.registrar) gitem = gmodels.GlossaryItem.objects.get(pk=gitem.pk) self.assertTrue(gitem.is_public()) response = self.client.get( reverse('aristotle_glossary:json_list') + '?items=%s' % gitem.id) data = json.loads(str(response.content))['items'] self.assertEqual(len(data), 1) self.assertEqual(data[0]['id'], gitem.pk)
def changeStatus(request, iid): item = get_object_or_404(MDR._concept, pk=iid).item if not (item and user_can_change_status(request.user, item)): if request.user.is_anonymous(): return redirect(reverse("friendly_login") + "?next=%s" % request.path) else: raise PermissionDenied # There would be an else here, but both branches above return, # so we've chopped it out to prevent an arrow anti-pattern. if request.method == "POST": # If the form has been submitted... form = MDRForms.ChangeStatusForm(request.POST, user=request.user) # A form bound to the POST data if form.is_valid(): # process the data in form.cleaned_data as required ras = form.cleaned_data["registrationAuthorities"] state = form.cleaned_data["state"] regDate = form.cleaned_data["registrationDate"] cascade = form.cleaned_data["cascadeRegistration"] changeDetails = form.cleaned_data["changeDetails"] with transaction.atomic(), reversion.revisions.create_revision(): reversion.revisions.set_user(request.user) for ra in ras: if cascade: register_method = ra.cascaded_register else: register_method = ra.register register_method(item, state, request.user, changeDetails=changeDetails, registrationDate=regDate) # TODO: notification and message on success/failure return HttpResponseRedirect(url_slugify_concept(item)) else: form = MDRForms.ChangeStatusForm(user=request.user) import json return render( request, "aristotle_mdr/actions/changeStatus.html", {"item": item, "form": form, "status_matrix": json.dumps(generate_visibility_matrix(request.user))}, )
def test_bulk_status_change_on_permitted_items(self): self.login_registrar() self.item1.readyToReview = True self.item2.readyToReview = True self.item1.save() self.item2.save() self.assertTrue(perms.user_can_change_status(self.registrar, self.item1)) self.assertFalse(self.item1.is_registered) response = self.client.post( reverse('aristotle:bulk_action'), { 'bulkaction': 'change_state', 'state': 1, 'items': [self.item1.id, self.item2.id], 'registrationDate': "2014-10-27", 'cascadeRegistration': 0, 'registrationAuthorities': [self.ra.id], 'confirmed': 'confirmed', } ) self.assertTrue(self.item1.is_registered) self.assertTrue(self.item2.is_registered)
def changeStatus(request, iid): item = get_object_or_404(MDR._concept,pk=iid).item if not (item and user_can_change_status(request.user,item)): if request.user.is_anonymous(): return redirect(reverse('django.contrib.auth.views.login')+'?next=%s' % request.path) else: raise PermissionDenied # There would be an else here, but both branches above return, # so we've chopped it out to prevent an arrow anti-pattern. if request.method == 'POST': # If the form has been submitted... form = MDRForms.ChangeStatusForm(request.POST,user=request.user) # A form bound to the POST data if form.is_valid(): # process the data in form.cleaned_data as required ras = form.cleaned_data['registrationAuthorities'] state = form.cleaned_data['state'] regDate = form.cleaned_data['registrationDate'] cascade = form.cleaned_data['cascadeRegistration'] changeDetails = form.cleaned_data['changeDetails'] for ra in ras: if cascade: register_method = ra.cascaded_register else: register_method = ra.register register_method(item,state,request.user, changeDetails=changeDetails, registrationDate=regDate, ) # TODO: notification and message on success/failure return HttpResponseRedirect(url_slugify_concept(item)) else: form = MDRForms.ChangeStatusForm(user=request.user) return render(request,"aristotle_mdr/actions/changeStatus.html", {"item":item, "form":form, } )
def test_registrar_cannot_use_faulty_statuses(self): self.login_registrar() self.assertFalse(perms.user_can_view(self.registrar,self.item1)) self.item1.readyToReview = True self.item1.save() self.item1 = self.itemType.objects.get(pk=self.item1.pk) self.assertTrue(perms.user_can_view(self.registrar,self.item1)) self.assertTrue(perms.user_can_change_status(self.registrar,self.item1)) response = self.client.get(reverse('aristotle:changeStatus',args=[self.item1.id])) self.assertEqual(response.status_code,200) self.assertEqual(self.item1.statuses.count(),0) response = self.client.post( reverse('aristotle:changeStatus', args=[self.item1.id]), { 'registrationAuthorities': [str(self.ra.id)], 'state': "Not a number", # obviously wrong 'changeDetails': "testing", 'cascadeRegistration': 0, # no } ) self.assertFormError(response, 'form', 'state', 'Select a valid choice. Not a number is not one of the available choices.') response = self.client.post( reverse('aristotle:changeStatus',args=[self.item1.id]), { 'registrationAuthorities': [str(self.ra.id)], 'state': "343434", # also wrong 'changeDetails': "testing", 'cascadeRegistration': 0, # no } ) self.assertFormError(response, 'form', 'state', 'Select a valid choice. 343434 is not one of the available choices.')
def cascaded_register(self, item, state, user, *args, **kwargs): if not perms.user_can_change_status(user, item): # Return a failure as this item isn't allowed return {'success': [], 'failed': [item] + item.registry_cascade_items} revision_message = _( "Cascade registration of item '%(name)s' (id:%(iid)s)\n" ) % { 'name': item.name, 'iid': item.id } revision_message = revision_message + kwargs.get('changeDetails', "") seen_items = {'success': [], 'failed': []} with transaction.atomic(), reversion.revisions.create_revision(): reversion.revisions.set_user(user) reversion.revisions.set_comment(revision_message) for child_item in [item] + item.registry_cascade_items: self._register( child_item, state, user, *args, **kwargs ) seen_items['success'] = seen_items['success'] + [child_item] return seen_items
def register_many(self, items, state, user, *args, **kwargs): # Change the registration status of many items # the items argument should be a queryset revision_message = _("Bulk registration of %i items\n") % (items.count()) revision_message = revision_message + kwargs.get('changeDetails', "") seen_items = {'success': [], 'failed': []} with transaction.atomic(), reversion.revisions.create_revision(): reversion.revisions.set_user(user) reversion.revisions.set_comment(revision_message) # can use bulk_create here when background reindex is setup for child_item in items: if perms.user_can_change_status(user, child_item): self._register( child_item, state, user, *args, **kwargs ) seen_items['success'].append(child_item.id) else: seen_items['failed'].append(child_item.id) return seen_items
def test_can_change_status(self): self.assertTrue(perms.user_can_change_status(self.su,None))
def has_change_permission(self, request, obj=None): if obj is not None: return perms.user_can_change_status(request.user, obj) return super().has_change_permission(request, obj=None)
def bulk_status_change_on_permitted_items(self, review_changes): self.login_registrar() review = models.ReviewRequest.objects.create( requester=self.su, registration_authority=self.ra, state=self.ra.locked_state, registration_date=datetime.date(2013, 4, 2)) review.concepts.add(self.item1) review.concepts.add(self.item2) self.assertTrue( perms.user_can_change_status(self.registrar, self.item1)) self.assertTrue( perms.user_can_change_status(self.registrar, self.item2)) self.assertFalse(self.item1.is_registered) self.assertFalse(self.item2.is_registered) reg_date = datetime.date(2014, 10, 27) new_state = self.ra.locked_state items = [self.item1.id, self.item2.id] response = self.client.post( reverse('aristotle:bulk_action'), { 'bulkaction': 'aristotle_mdr.forms.bulk_actions.ChangeStateForm', 'items': items, }) self.assertRedirects(response, reverse('aristotle:change_state_bulk_action')) change_state_get_response = self.client.get( reverse('aristotle:change_state_bulk_action')) self.assertEqual( change_state_get_response.context['form'].initial['items'], [str(a) for a in items]) postdata = { 'change_state-state': new_state, 'change_state-items': [str(a) for a in items], 'change_state-registrationDate': reg_date, 'change_state-cascadeRegistration': 0, 'change_state-registrationAuthorities': [self.ra.id], 'submit_skip': 'value', 'change_status_bulk_action_view-current_step': 'change_state', } if review_changes: selected_list = [str(self.item1.id)] change_state_response = self.perform_state_review( postdata, selected_list) else: change_state_response = self.client.post( reverse('aristotle:change_state_bulk_action'), postdata, ) self.assertEqual(change_state_response.status_code, 302) item2_changed = not review_changes self.assertTrue(self.item1.is_registered) self.assertEqual(self.item2.is_registered, item2_changed) self.assertTrue( self.item1.current_statuses().first().registrationDate == reg_date) self.assertTrue( self.item1.current_statuses().first().state == new_state) self.assertTrue(self.item1.current_statuses().first(). registrationAuthority == self.ra) if item2_changed: self.assertTrue(self.item2.current_statuses().first(). registrationDate == reg_date) self.assertTrue( self.item2.current_statuses().first().state == new_state) self.assertTrue(self.item2.current_statuses().first(). registrationAuthority == self.ra) else: self.assertEqual(len(self.item2.current_statuses()), 0)
def has_change_permission(self, request, obj=None): if obj is not None: return perms.user_can_change_status(request.user, obj) return super(StatusInline, self).has_change_permission(request, obj=None)
def changeStatus(request, iid): item = get_object_or_404(MDR._concept, pk=iid).item if not (item and user_can_change_status(request.user, item)): if request.user.is_anonymous(): return redirect(reverse('friendly_login') + '?next=%s' % request.path) else: raise PermissionDenied # There would be an else here, but both branches above return, # so we've chopped it out to prevent an arrow anti-pattern. if request.method == 'POST': # If the form has been submitted... form = MDRForms.ChangeStatusForm(request.POST, user=request.user) # A form bound to the POST data if form.is_valid(): # process the data in form.cleaned_data as required ras = form.cleaned_data['registrationAuthorities'] state = form.cleaned_data['state'] regDate = form.cleaned_data['registrationDate'] cascade = form.cleaned_data['cascadeRegistration'] changeDetails = form.cleaned_data['changeDetails'] with transaction.atomic(), reversion.revisions.create_revision(): reversion.revisions.set_user(request.user) for ra in ras: if cascade: register_method = ra.cascaded_register else: register_method = ra.register register_method( item, state, request.user, changeDetails=changeDetails, registrationDate=regDate, ) # TODO: notification and message on success/failure return HttpResponseRedirect(url_slugify_concept(item)) else: form = MDRForms.ChangeStatusForm(user=request.user) matrix={} visibility = "hidden" if item._is_locked: visibility = "locked" if item._is_public: visibility = "public" from aristotle_mdr.models import WORKGROUP_OWNERSHIP, STATES import json for ra in request.user.profile.registrarAuthorities: if item.workgroup.ownership == WORKGROUP_OWNERSHIP.authority: owner = ra in item.workgroup.registrationAuthorities.all() elif item.workgroup.ownership == WORKGROUP_OWNERSHIP.registry: owner = True ra_matrix = {'name': ra.name, 'states': {}} for s, _ in STATES: if s > ra.public_state: ra_matrix['states'][s] = [visibility, "public"][owner] elif s > ra.locked_state: ra_matrix['states'][s] = [visibility, "locked"][owner] else: ra_matrix['states'][s] = [visibility, "hidden"][owner] matrix[ra.id] = ra_matrix return render( request, "aristotle_mdr/actions/changeStatus.html", { "item": item, "form": form, "status_matrix": json.dumps(matrix), "visibility": visibility } )
def bulk_status_change_on_permitted_items(self, review_changes): self.login_registrar() self.create_review_request([self.item1, self.item2]) self.assertTrue(perms.user_can_change_status(self.registrar, self.item1)) self.assertTrue(perms.user_can_change_status(self.registrar, self.item2)) self.assertFalse(self.item1.is_registered) self.assertFalse(self.item2.is_registered) reg_date = datetime.date(2014,10,27) new_state = self.ra.locked_state items = [self.item1.id, self.item2.id] response = self.client.post( reverse('aristotle:bulk_action'), { 'bulkaction': 'aristotle_mdr.forms.bulk_actions.ChangeStateForm', 'items': items, } ) self.assertRedirects(response, reverse('aristotle:change_state_bulk_action')) change_state_get_response = self.client.get(reverse('aristotle:change_state_bulk_action')) self.assertEqual(change_state_get_response.context['form'].initial['items'], [str(a) for a in items]) postdata = { 'change_state-state': new_state, 'change_state-items': [str(a) for a in items], 'change_state-registrationDate': reg_date, 'change_state-cascadeRegistration': 0, 'change_state-registrationAuthorities': [self.ra.id], 'submit_skip': 'value', 'change_status_bulk_action_view-current_step': 'change_state', } if review_changes: selected_list = [str(self.item1.id)] change_state_response = self.perform_state_review(postdata, selected_list) else: change_state_response = self.client.post( reverse('aristotle:change_state_bulk_action'), postdata, ) self.assertEqual(change_state_response.status_code, 302) item2_changed = not review_changes self.assertTrue(self.item1.is_registered) self.assertEqual(self.item2.is_registered, item2_changed) self.assertTrue(self.item1.current_statuses().first().registrationDate == reg_date) self.assertTrue(self.item1.current_statuses().first().state == new_state) self.assertTrue(self.item1.current_statuses().first().registrationAuthority == self.ra) if item2_changed: self.assertTrue(self.item2.current_statuses().first().registrationDate == reg_date) self.assertTrue(self.item2.current_statuses().first().state == new_state) self.assertTrue(self.item2.current_statuses().first().registrationAuthority == self.ra) else: self.assertEqual(len(self.item2.current_statuses()), 0)