def clean(self): super(FlowRuleException, self).clean() if (self.kind == flow_rule_kind.grading and self.expiration is not None): raise ValidationError(_("grading rules may not expire")) from course.validation import ( ValidationError as ContentValidationError, validate_session_start_rule, validate_session_access_rule, validate_session_grading_rule, ValidationContext) from course.content import (get_course_repo, get_course_commit_sha, get_flow_desc) from relate.utils import dict_to_struct rule = dict_to_struct(self.rule) repo = get_course_repo(self.participation.course) commit_sha = get_course_commit_sha( self.participation.course, self.participation) ctx = ValidationContext( repo=repo, commit_sha=commit_sha) flow_desc = get_flow_desc(repo, self.participation.course, self.flow_id, commit_sha) tags = None if hasattr(flow_desc, "rules"): tags = getattr(flow_desc.rules, "tags", None) try: if self.kind == flow_rule_kind.start: validate_session_start_rule(ctx, unicode(self), rule, tags) elif self.kind == flow_rule_kind.access: validate_session_access_rule(ctx, unicode(self), rule, tags) elif self.kind == flow_rule_kind.grading: validate_session_grading_rule(ctx, unicode(self), rule, tags) else: # the rule refers to FlowRuleException rule raise ValidationError(_("invalid rule kind: ")+self.kind) except ContentValidationError as e: # the rule refers to FlowRuleException rule raise ValidationError(_("invalid existing_session_rules: ")+str(e))
def clean(self): if (self.kind == flow_rule_kind.grading and self.expiration is not None): raise ValidationError("grading rules may not expire") from course.validation import (ValidationError as ContentValidationError, validate_session_start_rule, validate_session_access_rule, validate_session_grading_rule, ValidationContext) from course.content import (get_course_repo, get_course_commit_sha, get_flow_desc) from relate.utils import dict_to_struct rule = dict_to_struct(self.rule) repo = get_course_repo(self.participation.course) commit_sha = get_course_commit_sha(self.participation.course, self.participation) ctx = ValidationContext(repo=repo, commit_sha=commit_sha) flow_desc = get_flow_desc(repo, self.participation.course, self.flow_id, commit_sha) tags = None if hasattr(flow_desc, "rules"): tags = getattr(flow_desc.rules, "tags", None) try: if self.kind == flow_rule_kind.start: validate_session_start_rule(ctx, unicode(self), rule, tags) elif self.kind == flow_rule_kind.access: validate_session_access_rule(ctx, unicode(self), rule, tags) elif self.kind == flow_rule_kind.grading: validate_session_grading_rule(ctx, unicode(self), rule, tags) else: raise ValidationError("invalid rule kind: " + self.kind) except ContentValidationError as e: raise ValidationError("invalid existing_session_rules: " + str(e))
def grant_exception_stage_3(pctx, participation_id, flow_id, session_id): # type: (CoursePageContext, int, Text, int) -> http.HttpResponse if not pctx.has_permission(pperm.grant_exception): raise PermissionDenied(_("may not grant exceptions")) participation = get_object_or_404(Participation, id=participation_id) from course.content import get_flow_desc try: flow_desc = get_flow_desc(pctx.repo, pctx.course, flow_id, pctx.course_commit_sha) except ObjectDoesNotExist: raise http.Http404() session = FlowSession.objects.get(id=int(session_id)) now_datetime = get_now_or_fake_time(pctx.request) from course.utils import (get_session_access_rule, get_session_grading_rule) access_rule = get_session_access_rule(session, flow_desc, now_datetime) grading_rule = get_session_grading_rule(session, flow_desc, now_datetime) request = pctx.request if request.method == "POST": form = ExceptionStage3Form({}, flow_desc, session.access_rules_tag, request.POST) from course.constants import flow_rule_kind if form.is_valid(): permissions = [ key for key, _ in FLOW_PERMISSION_CHOICES if form.cleaned_data[key] ] from course.validation import (validate_session_access_rule, validate_session_grading_rule, ValidationContext) from relate.utils import dict_to_struct vctx = ValidationContext(repo=pctx.repo, commit_sha=pctx.course_commit_sha) flow_desc = get_flow_desc(pctx.repo, pctx.course, flow_id, pctx.course_commit_sha) tags = [] # type: List[Text] if hasattr(flow_desc, "rules"): try: from typing import Text # noqa except ImportError: Text = None # noqa tags = cast(List[Text], getattr(flow_desc.rules, "tags", [])) # type: ignore # noqa # {{{ put together access rule if form.cleaned_data["create_access_exception"]: new_access_rule = {"permissions": permissions} if (form.cleaned_data.get("restrict_to_same_tag") and session.access_rules_tag is not None): new_access_rule["if_has_tag"] = session.access_rules_tag validate_session_access_rule( vctx, ugettext("newly created exception"), dict_to_struct(new_access_rule), tags) fre_access = FlowRuleException( flow_id=flow_id, participation=participation, expiration=form.cleaned_data["access_expires"], creator=pctx.request.user, comment=form.cleaned_data["comment"], kind=flow_rule_kind.access, rule=new_access_rule) fre_access.save() # }}} new_access_rules_tag = form.cleaned_data.get( "set_access_rules_tag") if new_access_rules_tag == NONE_SESSION_TAG: new_access_rules_tag = None if session.access_rules_tag != new_access_rules_tag: session.access_rules_tag = new_access_rules_tag session.save() # {{{ put together grading rule if form.cleaned_data["create_grading_exception"]: due = form.cleaned_data["due"] if form.cleaned_data["due_same_as_access_expiration"]: due = form.cleaned_data["access_expires"] descr = ugettext("Granted excecption") if form.cleaned_data["credit_percent"] is not None: descr += string_concat(" (%.1f%% ", ugettext('credit'), ")") \ % form.cleaned_data["credit_percent"] due_local_naive = due if due_local_naive is not None: from relate.utils import as_local_time due_local_naive = (as_local_time(due_local_naive).replace( tzinfo=None)) new_grading_rule = { "description": descr, } if due_local_naive is not None: new_grading_rule["due"] = due_local_naive new_grading_rule["if_completed_before"] = due_local_naive for attr_name in [ "credit_percent", "bonus_points", "max_points", "max_points_enforced_cap", "generates_grade" ]: if form.cleaned_data[attr_name] is not None: new_grading_rule[attr_name] = form.cleaned_data[ attr_name] if (form.cleaned_data.get("restrict_to_same_tag") and session.access_rules_tag is not None): new_grading_rule["if_has_tag"] = session.access_rules_tag validate_session_grading_rule( vctx, ugettext("newly created exception"), dict_to_struct(new_grading_rule), tags, grading_rule.grade_identifier) fre_grading = FlowRuleException( flow_id=flow_id, participation=participation, creator=pctx.request.user, comment=form.cleaned_data["comment"], kind=flow_rule_kind.grading, rule=new_grading_rule) fre_grading.save() # }}} messages.add_message( pctx.request, messages.SUCCESS, ugettext("Exception granted to '%(participation)s' " "for '%(flow_id)s'.") % { 'participation': participation, 'flow_id': flow_id }) return redirect("relate-grant_exception", pctx.course.identifier) else: data = { "restrict_to_same_tag": session.access_rules_tag is not None, #"due_same_as_access_expiration": True, "due": grading_rule.due, "generates_grade": grading_rule.generates_grade, "credit_percent": grading_rule.credit_percent, "bonus_points": grading_rule.bonus_points, "max_points": grading_rule.max_points, "max_points_enforced_cap": grading_rule.max_points_enforced_cap, } for perm in access_rule.permissions: data[perm] = True form = ExceptionStage3Form(data, flow_desc, session.access_rules_tag) return render_course_page( pctx, "course/generic-course-form.html", { "form": form, "form_description": ugettext("Grant Exception"), "form_text": string_concat( "<div class='well'>", ugettext("Granting exception to '%(participation)s' " "for '%(flow_id)s' (session %(session)s)."), "</div>") % { 'participation': participation, 'flow_id': flow_id, 'session': strify_session_for_exception(session) }, })
def grant_exception_stage_3(pctx, participation_id, flow_id, session_id): # type: (CoursePageContext, int, Text, int) -> http.HttpResponse if not pctx.has_permission(pperm.grant_exception): raise PermissionDenied(_("may not grant exceptions")) participation = get_object_or_404(Participation, id=participation_id) from course.content import get_flow_desc try: flow_desc = get_flow_desc(pctx.repo, pctx.course, flow_id, pctx.course_commit_sha) except ObjectDoesNotExist: raise http.Http404() session = FlowSession.objects.get(id=int(session_id)) now_datetime = get_now_or_fake_time(pctx.request) from course.utils import ( get_session_access_rule, get_session_grading_rule) access_rule = get_session_access_rule(session, flow_desc, now_datetime) grading_rule = get_session_grading_rule(session, flow_desc, now_datetime) request = pctx.request if request.method == "POST": form = ExceptionStage3Form( {}, flow_desc, session.access_rules_tag, request.POST) from course.constants import flow_rule_kind if form.is_valid(): permissions = [ key for key, _ in FLOW_PERMISSION_CHOICES if form.cleaned_data[key]] from course.validation import ( validate_session_access_rule, validate_session_grading_rule, ValidationContext) from relate.utils import dict_to_struct vctx = ValidationContext( repo=pctx.repo, commit_sha=pctx.course_commit_sha) flow_desc = get_flow_desc(pctx.repo, pctx.course, flow_id, pctx.course_commit_sha) tags = None if hasattr(flow_desc, "rules"): tags = getattr(flow_desc.rules, "tags", None) # {{{ put together access rule if form.cleaned_data["create_access_exception"]: new_access_rule = {"permissions": permissions} if (form.cleaned_data.get("restrict_to_same_tag") and session.access_rules_tag is not None): new_access_rule["if_has_tag"] = session.access_rules_tag validate_session_access_rule( vctx, ugettext("newly created exception"), dict_to_struct(new_access_rule), tags) fre_access = FlowRuleException( flow_id=flow_id, participation=participation, expiration=form.cleaned_data["access_expires"], creator=pctx.request.user, comment=form.cleaned_data["comment"], kind=flow_rule_kind.access, rule=new_access_rule) fre_access.save() # }}} new_access_rules_tag = form.cleaned_data.get("set_access_rules_tag") if new_access_rules_tag == NONE_SESSION_TAG: new_access_rules_tag = None if session.access_rules_tag != new_access_rules_tag: session.access_rules_tag = new_access_rules_tag session.save() # {{{ put together grading rule if form.cleaned_data["create_grading_exception"]: due = form.cleaned_data["due"] if form.cleaned_data["due_same_as_access_expiration"]: due = form.cleaned_data["access_expires"] descr = ugettext("Granted excecption") if form.cleaned_data["credit_percent"] is not None: descr += string_concat(" (%.1f%% ", ugettext('credit'), ")") \ % form.cleaned_data["credit_percent"] due_local_naive = due if due_local_naive is not None: from relate.utils import as_local_time due_local_naive = ( as_local_time(due_local_naive) .replace(tzinfo=None)) new_grading_rule = { "description": descr, } if due_local_naive is not None: new_grading_rule["due"] = due_local_naive new_grading_rule["if_completed_before"] = due_local_naive for attr_name in ["credit_percent", "bonus_points", "max_points", "max_points_enforced_cap"]: if form.cleaned_data[attr_name] is not None: new_grading_rule[attr_name] = form.cleaned_data[attr_name] if (form.cleaned_data.get("restrict_to_same_tag") and session.access_rules_tag is not None): new_grading_rule["if_has_tag"] = session.access_rules_tag if hasattr(grading_rule, "generates_grade"): new_grading_rule["generates_grade"] = \ grading_rule.generates_grade validate_session_grading_rule( vctx, ugettext("newly created exception"), dict_to_struct(new_grading_rule), tags, grading_rule.grade_identifier) fre_grading = FlowRuleException( flow_id=flow_id, participation=participation, creator=pctx.request.user, comment=form.cleaned_data["comment"], kind=flow_rule_kind.grading, rule=new_grading_rule) fre_grading.save() # }}} messages.add_message(pctx.request, messages.SUCCESS, ugettext( "Exception granted to '%(participation)s' " "for '%(flow_id)s'.") % { 'participation': participation, 'flow_id': flow_id}) return redirect( "relate-grant_exception", pctx.course.identifier) else: data = { "restrict_to_same_tag": session.access_rules_tag is not None, "credit_percent": grading_rule.credit_percent, #"due_same_as_access_expiration": True, "due": grading_rule.due, } for perm in access_rule.permissions: data[perm] = True form = ExceptionStage3Form(data, flow_desc, session.access_rules_tag) return render_course_page(pctx, "course/generic-course-form.html", { "form": form, "form_description": ugettext("Grant Exception"), "form_text": string_concat( "<div class='well'>", ugettext("Granting exception to '%(participation)s' " "for '%(flow_id)s' (session %(session)s)."), "</div>") % { 'participation': participation, 'flow_id': flow_id, 'session': strify_session_for_exception(session)}, })
def grant_exception_stage_3(pctx, participation_id, flow_id, session_id): if pctx.role not in [ participation_role.instructor, participation_role.teaching_assistant]: raise PermissionDenied("must be instructor or TA to grant exceptions") participation = get_object_or_404(Participation, id=participation_id) from course.content import get_flow_desc try: flow_desc = get_flow_desc(pctx.repo, pctx.course, flow_id, pctx.course_commit_sha) except ObjectDoesNotExist: raise http.Http404() session = FlowSession.objects.get(id=int(session_id)) now_datetime = get_now_or_fake_time(pctx.request) from course.utils import ( get_session_access_rule, get_session_grading_rule) access_rule = get_session_access_rule( session, pctx.role, flow_desc, now_datetime) grading_rule = get_session_grading_rule( session, pctx.role, flow_desc, now_datetime) request = pctx.request if request.method == "POST": form = ExceptionStage3Form({}, session.access_rules_tag, request.POST) from course.constants import flow_rule_kind if form.is_valid(): permissions = [ key for key, _ in FLOW_PERMISSION_CHOICES if form.cleaned_data[key]] from course.validation import ( validate_session_access_rule, validate_session_grading_rule, ValidationContext) from relate.utils import dict_to_struct vctx = ValidationContext( repo=pctx.repo, commit_sha=pctx.course_commit_sha) from course.content import get_flow_desc flow_desc = get_flow_desc(pctx.repo, pctx.course, flow_id, pctx.course_commit_sha) tags = None if hasattr(flow_desc, "rules"): tags = getattr(flow_desc.rules, "tags", None) # {{{ put together access rule new_access_rule = {"permissions": permissions} if (form.cleaned_data["restrict_to_same_tag"] and session.access_rules_tag is not None): new_access_rule["if_has_tag"] = session.access_rules_tag validate_session_access_rule(vctx, "newly created exception", dict_to_struct(new_access_rule), tags) fre_access = FlowRuleException( flow_id=flow_id, participation=participation, expiration=form.cleaned_data["access_expires"], creator=pctx.request.user, comment=form.cleaned_data["comment"], kind=flow_rule_kind.access, rule=new_access_rule) fre_access.save() # }}} # {{{ put together grading rule due = form.cleaned_data["due"] if form.cleaned_data["due_same_as_access_expiration"]: due = form.cleaned_data["access_expires"] descr = "Granted excecption" if form.cleaned_data["credit_percent"] is not None: descr += " (%.1f%% credit)" % form.cleaned_data["credit_percent"] from relate.utils import as_local_time new_grading_rule = { "credit_percent": form.cleaned_data["credit_percent"], "due": as_local_time(due).replace(tzinfo=None), "if_completed_before": as_local_time(due).replace(tzinfo=None), "description": descr, } if (form.cleaned_data["restrict_to_same_tag"] and session.access_rules_tag is not None): new_grading_rule["if_has_tag"] = session.access_rules_tag if hasattr(grading_rule, "grade_identifier"): new_grading_rule["grade_identifier"] = \ grading_rule.grade_identifier if hasattr(grading_rule, "grade_aggregation_strategy"): new_grading_rule["grade_aggregation_strategy"] = \ grading_rule.grade_aggregation_strategy validate_session_grading_rule(vctx, "newly created exception", dict_to_struct(new_grading_rule), tags) fre_grading = FlowRuleException( flow_id=flow_id, participation=participation, creator=pctx.request.user, comment=form.cleaned_data["comment"], kind=flow_rule_kind.grading, rule=new_grading_rule) fre_grading.save() # }}} messages.add_message(pctx.request, messages.SUCCESS, "Exception granted to '%s' for '%s'." % (participation, flow_id)) return redirect( "course.views.grant_exception", pctx.course.identifier) else: data = { "restrict_to_same_tag": session.access_rules_tag is not None, "credit_percent": grading_rule.credit_percent, #"due_same_as_access_expiration": True, "due": grading_rule.due, } for perm in access_rule.permissions: data[perm] = True form = ExceptionStage3Form(data, session.access_rules_tag) return render_course_page(pctx, "course/generic-course-form.html", { "form": form, "form_description": "Grant Exception", "form_text": "<div class='well'>Granting exception to '%s' for '%s'.</div>" % (participation, flow_id), })