def test_unpriviledged_access_prohibited(self): self.assertFalse(has_transition_perm(self.model.publish, self.unpriviledged)) self.assertFalse(has_transition_perm(self.model.remove, self.unpriviledged)) transitions = self.model.get_available_user_state_transitions(self.unpriviledged) self.assertEquals(set(['moderate']), set(transition.name for transition in transitions))
def test_proviledged_access_succed(self): self.assertTrue(has_transition_perm(self.model.publish, self.priviledged)) self.assertTrue(has_transition_perm(self.model.remove, self.priviledged)) transitions = self.model.get_available_user_state_transitions(self.priviledged) self.assertEquals(set(['publish', 'remove', 'moderate']), set(transition.name for transition in transitions))
def get_context_data(self, **kwargs): context = super(TaskDetailView, self).get_context_data(**kwargs) task = self.object if self.request.user.has_perm('indigo_api.change_task'): context['change_task_permission'] = True if has_transition_perm(task.submit, self): context['submit_task_permission'] = True if has_transition_perm(task.reopen, self): context['reopen_task_permission'] = True if has_transition_perm(task.unsubmit, self): context['unsubmit_task_permission'] = True if has_transition_perm(task.close, self): context['close_task_permission'] = True context['possible_workflows'] = Workflow.objects.unclosed().filter( country=task.country, locality=task.locality).all() Task.decorate_potential_assignees([task], self.country) return context
def test_cancel_permissions(self): application = ApplicationFactory.create( owner=self.resident, shift=self.shift, state=ApplicationStateEnum.APPROVED) # Resident can cancel approved application self.assertTrue( has_transition_perm(application.cancel, self.resident.user_ptr)) # Scheduler can cancel approved applications self.assertTrue( has_transition_perm(application.cancel, self.scheduler.user_ptr)) application = ApplicationFactory.create( owner=self.resident, shift=self.shift, state=ApplicationStateEnum.CONFIRMED) # Resident can cancel confirmed application self.assertTrue( has_transition_perm(application.cancel, self.resident.user_ptr)) # Scheduler can cancel confirmed applications self.assertTrue( has_transition_perm(application.cancel, self.scheduler.user_ptr))
def set_transition_permissions(self, user): self.can_submit = has_transition_perm(self.submit, user) self.can_accept = has_transition_perm(self.accept, user) self.can_reject = has_transition_perm(self.reject, user) self.can_appeal = has_transition_perm(self.appeal, user) self.can_pay = has_transition_perm(self.pay, user) self.can_edit = self.requested_by == user and self.is_editable self.button_comment = "Edit" if self.can_edit else "Review"
def test_reject_permissions(self): application = ApplicationFactory.create(owner=self.resident, shift=self.shift) # Resident can't reject application self.assertFalse( has_transition_perm(application.reject, self.resident.user_ptr)) # Scheduler can reject own shift's applications self.assertTrue( has_transition_perm(application.reject, self.scheduler.user_ptr))
def decorate_permissions(cls, tasks, view): for task in tasks: task.change_task_permission = view.request.user.has_perm( 'indigo_api.change_task') task.submit_task_permission = has_transition_perm( task.submit, view) task.reopen_task_permission = has_transition_perm( task.reopen, view) task.unsubmit_task_permission = has_transition_perm( task.unsubmit, view) task.close_task_permission = has_transition_perm(task.close, view) return tasks
def test_reject_permission(self): resident = ResidentFactory.create( state=ResidentStateEnum.PROFILE_FILLED) # Scheduler (not account manager) can't approve resident scheduler = SchedulerFactory.create() self.assertFalse(has_transition_perm( resident.reject, scheduler)) # Account manager can approve resident self.assertTrue(has_transition_perm( resident.reject, self.account_manager))
def check_transition_permission(self, transition, user): try: if not can_proceed(transition) or not has_transition_perm( transition, user): raise PermissionDenied except CoreValidationError as exc: raise ValidationError(dict([error for error in exc]))
def post(self, request, *args, **kwargs): task = self.get_object() user = self.request.user task.updated_by_user = user if task.customised: # redirect to custom close url, if necessary if self.change == 'close' and task.customised.close_url(): return redirect(task.customised.close_url()) for change, verb in Task.VERBS.items(): if self.change == change: state_change = getattr(task, change) if not has_transition_perm(state_change, self): raise PermissionDenied state_change(user) if change == 'submit': verb = 'submitted for review' if change == 'unsubmit': verb = 'returned with changes requested' messages.success(request, "Task '%s' has been %s" % (task.title, verb)) task.save() return redirect(self.get_redirect_url())
def transition_action(self, request, *args, **kwargs): instance = self.get_object() transition_method = getattr(instance, transition_name) if not can_proceed(transition_method, self.request.user): raise exceptions.ValidationError( {'detail': _('Conditions not met')}) if not has_transition_perm(transition_method, self.request.user): raise exceptions.PermissionDenied if hasattr(self, 'get_{0}_kwargs'.format(transition_name)): transition_kwargs = getattr( self, 'get_{0}_kwargs'.format(transition_name))() else: transition_kwargs = {} if 'by' in inspect.signature(transition_method).parameters.keys( ) and 'by' not in transition_kwargs: transition_kwargs['by'] = self.request.user transition_method(**transition_kwargs) if self.save_after_transition: instance.save() if getattr(instance, '_prefetched_objects_cache', None): # If 'prefetch_related' has been applied to a queryset, we need to # forcibly invalidate the prefetch cache on the instance. instance._prefetched_objects_cache = {} serializer = self.get_serializer(instance) return Response(serializer.data)
def post(self, request, **kwargs): if 'transition' in request.POST: with transaction.atomic(): self.object = self.get_object( self.get_queryset().select_for_update()) if request.POST.get( 'transition') in self.available_transitions: transition = getattr(self.object, request.POST['transition']) if not has_transition_perm(transition, request.user): raise PermissionDenied transition_kwargs = self.get_transition_kwargs( request.POST['transition']) or {} transition(**transition_kwargs) self.object.save() return redirect( request.POST.get('next') or self.request.build_absolute_uri()) else: return HttpResponseBadRequest() else: try: method = super().post except AttributeError: return HttpResponseBadRequest() else: return method(request, **kwargs)
def get(self, request, *args, **kwargs): action = request.GET.get('action', None) pk = request.GET.get('pk', None) if pk is None or action is None: raise Http404() record = self.model.objects.filter(pk=pk).first() action = getattr(record, 'set_' + action) # check if user has permission to execute the method if not has_transition_perm(action, request.user): messages.warning(request, "Permission Denied") else: # try to transition and catchese if not allowed try: action(by=request.user) record.state_date = dt.datetime.now() record.save() except TransitionNotAllowed: messages.warning(request, "Transition Not Allowed") return redirect( reverse(self.url_redirect_workflow_table) + '?pk=%s' % pk)
def get(self, request, *args, **kwargs): action = request.GET.get('action', None) pk = request.GET.get('pk', None) if pk is None or action is None: raise Http404() record = self.model.objects.filter(pk=pk).first() action = getattr(record, 'set_' + action) # check if user has permission to execute the method if not can_proceed(action): if action.__name__ == 'set_verify_invoices': messages.warning(request, "Task Must Be Work in Progress or Higher") else: messages.warning(request, "Transistion is not Allowed") elif not has_transition_perm(action, request.user): messages.warning(request, "Permission Denied") else: action(by=request.user) record.save() return redirect( reverse(self.url_redirect_workflow_table) + '?pk=%s' % pk)
def get_context_data(self, **kwargs): context = super(TaskEditView, self).get_context_data(**kwargs) work = None task = self.object if task.work: work = json.dumps( WorkSerializer(instance=task.work, context={ 'request': self.request }).data) context['work_json'] = work document = None if task.document: document = json.dumps( DocumentSerializer(instance=task.document, context={ 'request': self.request }).data) context['document_json'] = document context['task_labels'] = TaskLabel.objects.all() context['place_workflows'] = self.place.workflows.filter(closed=False) if has_transition_perm(task.cancel, self): context['cancel_task_permission'] = True return context
def test_complete_permissions(self): self.shift.date_start = timezone.now() - timedelta(hours=2) self.shift.date_end = timezone.now() - timedelta(hours=1) self.shift.save() application = ApplicationFactory.create( owner=self.resident, shift=self.shift, state=ApplicationStateEnum.CONFIRMED) # Resident can't complete confirmed application self.assertFalse( has_transition_perm(application.complete, self.resident.user_ptr)) # Scheduler can complete confirmed applications self.assertTrue( has_transition_perm(application.complete, self.scheduler.user_ptr))
def transition(self, request, *args, **kwargs): """ Change status of FSM controlled object """ action = kwargs.get('action', False) instance = self.get_object() instance_action = getattr(instance, action, None) if not instance_action or not hasattr(instance_action, '_django_fsm'): raise Http404 try: if not can_proceed(instance_action) or not has_transition_perm( instance_action, request.user): raise PermissionDenied except CoreValidationError as ex: raise ValidationError(dict([error for error in ex])) fsm_meta = instance_action._django_fsm field_name = fsm_meta.field if isinstance( fsm_meta.field, six.string_types) else fsm_meta.field.name transition_serializer = fsm_meta.get_transition( getattr(instance, field_name)).custom.get('serializer') if transition_serializer: serializer = transition_serializer(data=request.data) serializer.is_valid(raise_exception=True) instance_action(**serializer.validated_data) else: instance_action() instance.save() return self.retrieve(request, *args, **kwargs)
def test_approve_permissions(self): application = ApplicationFactory.create(owner=self.resident, shift=self.shift) # Resident can't approve application self.assertFalse( has_transition_perm(application.approve, self.resident.user_ptr)) # Scheduler can accept own shift's applications self.assertTrue( has_transition_perm(application.approve, self.scheduler.user_ptr)) another_application = ApplicationFactory.create() # Scheduler can't approve now own shift's applications self.assertFalse( has_transition_perm(another_application.approve, self.scheduler.user_ptr))
def save(self, *args, **kwargs): meeting = super().save(commit=False, *args, **kwargs) if has_transition_perm(meeting.reserve, self.protege): meeting.reserve(reserved_by=self.protege) meeting = meeting.save() return meeting
def user_has_transition_perm(user, obj_type_name, obj_id, perm_func_name): if (obj_type_name == 'manuscript'): obj = Manuscript.objects.get(id=int(obj_id)) elif (obj_type_name == 'submission'): obj = Submission.objects.get(id=int(obj_id)) perm_func = getattr(obj, perm_func_name) return has_transition_perm(perm_func, user)
def post(self, *args, **kwargs): meeting = self.get_object() if not has_transition_perm(meeting.confirm, self.request.user): raise PermissionDenied meeting.confirm(confirmed_by=self.request.user) meeting.save() return HttpResponseRedirect(self.get_success_url())
def test_blacklisted_return(self): order = Order.objects.create(customer="Abusive Returner", address="1 main street", item="blue lightsaber", price=100) order.ship() order.save() self.assertFalse( has_transition_perm(order.receive_return, order.customer))
def get_context_data(self, **kwargs): context = super(TaskDetailView, self).get_context_data(**kwargs) task = self.object if self.request.user.has_perm('indigo_api.change_task'): context['change_task_permission'] = True if has_transition_perm(task.submit, self): context['submit_task_permission'] = True if has_transition_perm(task.reopen, self): context['reopen_task_permission'] = True if has_transition_perm(task.unsubmit, self): context['unsubmit_task_permission'] = True if has_transition_perm(task.close, self): context['close_task_permission'] = True return context
def transition(request, uuid): doc = get_object_or_404(Document, uuid=uuid) is_document_editor(request, doc) try: transition = getattr(doc, request.data['transition']) if not has_transition_perm(transition, request.user): raise PermissionDenied transition() doc.save() return Response({"message": "Success", "document": DocumentInfoSerializer(doc, context={'user': request.user}).data}) except RuntimeError as e: return Response({"message": e.message, "args": e.args}, status=400)
def inner_func(self, request, pk=None): object = self.get_object() transition_method = getattr(object, transition_name) if not has_transition_perm(transition_method, request.user): raise PermissionDenied if not object.can_transition(request.user, transition_method): raise PermissionDenied transition_method(by=request.user) if self.save_after_transition: object.save() serializer = self.get_serializer(object) return Response(serializer.data)
def fn(self, request, **kwargs): args = self.get_serializer(data=request.data) args.is_valid(raise_exception=True) obj = self.get_object() transition = getattr(obj, name) if can_proceed(transition) and\ has_transition_perm(transition, request.user): try: transition(**args.validated_data) except TransitionNotAllowed as err: raise ValidationError(str(err)) obj.save() return Response(status=204) else: raise ValidationError( "You cant perform '{}' transition".format(name))
def post(self, request, *args, **kwargs): task = self.get_object() user = self.request.user task.updated_by_user = user task_content_type = ContentType.objects.get_for_model(task) comment_text = request.POST.get('comment', None) if task.customised: # redirect to custom close url, if necessary if self.change == 'close' and task.customised.close_url(): return redirect(task.customised.close_url()) for change, verb in Task.VERBS.items(): if self.change == change: state_change = getattr(task, change) if not has_transition_perm(state_change, self): raise PermissionDenied if comment_text: comment = Comment(user=user, object_pk=task.id, user_name=user.get_full_name() or user.username, user_email=user.email, comment=comment_text, content_type=task_content_type, site_id=get_current_site(request).id) state_change(user, comment=comment.comment) # save the comment here so that it appears after the action comment.submit_date = now() comment.save() else: state_change(user) if change == 'submit': verb = 'submitted for review' if change == 'unsubmit': verb = 'returned with changes requested' messages.success(request, "Task '%s' has been %s" % (task.title, verb)) task.save() return redirect(self.get_redirect_url())
def task_view(request, task_status_id=None): task_status = get_object_or_404(TaskStatus, pk=task_status_id) if request.method == 'POST': form = SendTaskBackForm(request.POST) if form.is_valid(): task_status.comment = form.cleaned_data['comment'] task_status.response = form.cleaned_data['response'] task_status.save() return redirect('send_task_back', task_status_id=task_status_id) task = task_status.task can_be_sent = (can_proceed(task_status.send) and has_transition_perm(task_status.send, request.user)) review_mode = (task_status.state == 'RVW' and request.user.is_superuser) context = { 'task': task, 'task_status': task_status, 'can_be_sent': can_be_sent, 'review_mode': review_mode, 'user': request.user } if review_mode: form = SendTaskBackForm() context['form'] = form return render(request, "task.html", context)
def test_permission_instance_method(self): self.assertFalse(has_transition_perm(self.model.restore, self.unpriviledged)) self.assertTrue(has_transition_perm(self.model.restore, self.staff))
def test_object_only_other_access_prohibited(self): self.assertFalse(has_transition_perm(self.model.publish, self.unprivileged))
def set_transition_permissions(self, user): self.can_accept = has_transition_perm(self.accept, user) self.can_reject = has_transition_perm(self.reject, user) self.can_suspend = has_transition_perm(self.suspend, user) self.can_restore = has_transition_perm(self.restore, user) self.can_terminate = has_transition_perm(self.terminate, user)
def change_state(self, state, user): state_method = getattr(self, state) if can_proceed(state_method) and has_transition_perm( state_method, user): state_method() self.save()
def post(self, request, *args, **kwargs): task = self.get_object() user = self.request.user task.updated_by_user = user potential_changes = { 'submit': 'submitted', 'cancel': 'cancelled', 'reopen': 'reopened', 'unsubmit': 'unsubmitted', 'close': 'closed', } for change, verb in potential_changes.items(): if self.change == change: state_change = getattr(task, change) if not has_transition_perm(state_change, self): raise PermissionDenied state_change(user) if verb == 'submitted': task.last_assigned_to = task.assigned_to task.assigned_to = None action.send(user, verb=verb, action_object=task, place_code=task.place.place_code) messages.success( request, u"Task '%s' has been submitted for review" % task.title) elif verb == 'unsubmitted' and task.last_assigned_to: assignee = task.last_assigned_to task.assigned_to = assignee if user.id == assignee.id: action.send(user, verb='unsubmitted and picked up', action_object=task, place_code=task.place.place_code) messages.success( request, u"You have unsubmitted and picked up the task '%s'" % task.title) else: action.send(user, verb='unsubmitted and reassigned', action_object=task, target=assignee, place_code=task.place.place_code) messages.success( request, u"Task '%s' has been unsubmitted and reassigned" % task.title) else: if verb == 'closed' or verb == 'cancelled': task.assigned_to = None action.send(user, verb=verb, action_object=task, place_code=task.place.place_code) messages.success( request, u"Task '%s' has been %s" % (task.title, verb)) task.save() return redirect('task_detail', place=self.kwargs['place'], pk=self.kwargs['pk'])
def check_transition_permission(self, transition, user): try: if not can_proceed(transition) or not has_transition_perm(transition, user): raise PermissionDenied except CoreValidationError as exc: raise ValidationError(dict([error for error in exc]))
def test_object_only_access_success(self): self.assertTrue(has_transition_perm(self.model.publish, self.privileged)) self.model.publish()