def post(self, request, **kwargs): context = self.get_context_data(**kwargs) response = [] if not request.data: raise BadgrApiException400('No provisionments sent', 0) for provisionment in request.data: serializer = self.v1_serializer_class(data=provisionment, context=context) try: serializer.is_valid(raise_exception=True) serializer.save(created_by=request.user) message = {'status': 'success', 'message': serializer.data} except ValidationError as e: if not isinstance( e, BadgrValidationError) and 'email' in e.detail: # Consistency with other BadgrValidationErrors e = BadgrValidationError("Enter a valid email address", 509) # check if email address was a duplicate duplicate_with_success = [ x for x in response if x['status'] == 'success' and x['email'] == provisionment['email'] ] if duplicate_with_success: e = BadgrValidationError( 'You entered this email address multiple times.', 510) message = {'status': 'failure', 'message': e.detail} message['email'] = provisionment['email'] response.append(message) return Response(response, status=status.HTTP_201_CREATED)
def award(self, recipient): """Accept the direct award and make an assertion out of it""" from issuer.models import BadgeInstance if self.eppn not in recipient.eppns: raise BadgrValidationError('Cannot award, eppn does not match', 999) institution = self.badgeclass.institution identifiers = [inst.identifier for inst in self.badgeclass.award_allowed_institutions.all()] + [ institution.identifier] schac_homes = recipient.schac_homes if self.badgeclass.formal: allowed = institution.identifier in schac_homes else: allowed = any(identifier in schac_homes for identifier in identifiers) if not allowed: raise BadgrValidationError('Cannot award, you are not a member of the institution of the badgeclass', 999) assertion = self.badgeclass.issue(recipient=recipient, created_by=self.created_by, acceptance=BadgeInstance.ACCEPTANCE_ACCEPTED, recipient_type=BadgeInstance.RECIPIENT_TYPE_EDUID, send_email=False, award_type=BadgeInstance.AWARD_TYPE_DIRECT_AWARD, direct_award_bundle=self.bundle) # delete any pending enrollments for this badgeclass and user recipient.cached_pending_enrollments().filter(badge_class=self.badgeclass).delete() recipient.remove_cached_data(['cached_pending_enrollments']) return assertion
def create(self, validated_data, **kwargs): user_permissions = validated_data['issuer'].get_permissions( validated_data['created_by']) if user_permissions['may_create']: if validated_data['formal'] and not validated_data[ 'issuer'].faculty.institution.grondslag_formeel: raise BadgrValidationError( "Cannot create a formal badgeclass for an institution without the judicial basis for formal badges", 215) if not validated_data['formal'] and not validated_data[ 'issuer'].faculty.institution.grondslag_informeel: raise BadgrValidationError( "Cannot create an informal badgeclass for an institution without the judicial basis for informal badges", 216) try: new_badgeclass = BadgeClass.objects.create(**validated_data) except IntegrityError: raise BadgrValidationFieldError( 'name', "There is already a Badgeclass with this name inside this Issuer", 911) return new_badgeclass else: raise BadgrValidationError( "You don't have the necessary permissions", 100)
def update(self, instance, validated_data): if instance.rejected: raise BadgrValidationError('You cannot edit an invitation that has been rejected.', 508) if not instance.entity.has_permissions(self.context['request'].user, ['may_administrate_users']): raise BadgrValidationError('You do not have permission to invite user for this entity.', 507) [setattr(instance, attr, validated_data.get(attr)) for attr in validated_data] instance.save() return instance
def revoke(self, revocation_reason): if self.status == DirectAward.STATUS_REVOKED: raise BadgrValidationError("DirectAward is already revoked", 999) if not revocation_reason: raise BadgrValidationError("revocation_reason is required", 999) self.status = DirectAward.STATUS_REVOKED self.revocation_reason = revocation_reason self.save()
def match_user(self, user): '''Sets given user as the matched user''' try: entity_institution = self.entity.institution except AttributeError: entity_institution = self.entity if user.institution != entity_institution: raise BadgrValidationError( 'May not invite user from other institution', 504) if user.is_teacher and not self.for_teacher: raise BadgrValidationError('This invite is for a student', 505) if not user.is_teacher and self.for_teacher: raise BadgrValidationError('This invite is for a teacher', 506) self.user = user self.save()
def _validate_staff_collision(self): """validate to see if there is a existing staff membership that conflicts for the entity of this invite""" if self.user and self.entity.get_all_staff_memberships_in_current_branch( self.user): raise BadgrValidationError( 'Cannot invite user for this entity. There is a conflicting staff membership.', 502)
def validate_errors(serializer): serializer.is_valid() errors = serializer.errors if errors: fields = {} for attr, field_errors in errors.items(): fields[attr] = [] for error in field_errors: try: fields[attr].append({ 'error_code': get_form_error_code(vars(error)['code']), 'error_message': error }) except TypeError as e: # TODO: make this recursive for endless depth sub_fields = {} for sub_attr, sub_errors in error.items(): sub_fields[sub_attr] = [] for sub_error in sub_errors: sub_fields[sub_attr].append({ 'error_code': get_form_error_code(vars(sub_error)['code']), 'error_message': sub_error }) fields[attr].append(sub_fields) raise BadgrValidationError(error_message=fields, error_code=999)
def validate(self, attrs): validated_data = super(UserProvisionmentSerializer, self).validate(attrs) entity = validated_data['content_type'].get_object_for_this_type(entity_id=validated_data['object_id']) if not entity.has_permissions(self.context['request'].user, ['may_administrate_users']): raise BadgrValidationError('You do not have permission to invite user for this entity.', 507) validated_data['object_id'] = entity.id return attrs
def _validate_unique(self, exclude=None): """Custom uniqueness validation of the provisionment, used before save""" if UserProvisionment.objects.filter( type=self.type, rejected=False, for_teacher=self.for_teacher, email=self.email).exclude(pk=self.pk).exists(): raise BadgrValidationError( 'There may be only one invite per email address.', 501) return super(UserProvisionment, self).validate_unique(exclude=exclude)
def validate_extensions(self, extensions): if extensions: for ext in extensions.values(): if "@context" in ext and not ext['@context'].startswith( settings.EXTENSIONS_ROOT_URL): raise BadgrValidationError( error_code=999, error_message= f"extensions @context invalid {ext['@context']}") return extensions
def _validate_invite_collision(self): """validate to see if the there is another invite that collides with this one (i.e. if both are created the staff memberships will collide""" all_entities_in_same_branch = self.entity.get_all_entities_in_branch() all_invites_for_same_user = UserProvisionment.objects.filter( email=self.email) for invite in all_invites_for_same_user: if invite != self and invite.entity in all_entities_in_same_branch: raise BadgrValidationError( 'Cannot invite user for this entity. There is a conflicting invite.', 503)
def create(self, validated_data): terms = Terms.objects.get(entity_id=validated_data['terms_entity_id']) if terms.institution: if not terms.institution.identifier in self.context[ 'request'].user.get_all_associated_institutions_identifiers( ): raise BadgrValidationError( 'You cannot accept terms that are not from your institution', 0) if validated_data['accepted']: return terms.accept(self.context['request'].user)
def post(self, request, **kwargs): directaward = self.get_object(request, **kwargs) if not self.has_object_permissions(request, directaward): return Response(status=status.HTTP_404_NOT_FOUND) if request.data.get('accept', False): # has accepted it if not directaward.badgeclass.terms_accepted(request.user): raise BadgrValidationError( "Cannot accept direct award, must accept badgeclass terms first", 999) assertion = directaward.award(recipient=request.user) directaward.badgeclass.remove_cached_data(['cached_direct_awards']) directaward.delete() return Response({'entity_id': assertion.entity_id}, status=status.HTTP_201_CREATED) elif not request.data.get('accept', True): # has rejected it directaward.status = DirectAward.STATUS_REJECTED # reject it directaward.save() directaward.badgeclass.remove_cached_data(['cached_direct_awards']) return Response({'rejected': True}, status=status.HTTP_200_OK) raise BadgrValidationError( 'Neither accepted or rejected the direct award', 999)
def update(self, instance, validated_data): if instance.assertions and instance.name_english and instance.name_english != validated_data[ "name_english"]: raise BadgrValidationError( "Cannot change the name, assertions have already been issued within this entity", 214) if instance.assertions and instance.name_dutch and instance.name_dutch != validated_data[ "name_dutch"]: raise BadgrValidationError( "Cannot change the name, assertions have already been issued within this entity", 214) [ setattr(instance, attr, validated_data.get(attr)) for attr in validated_data ] self.save_extensions(validated_data, instance) if not instance.badgrapp_id: instance.badgrapp = BadgrApp.objects.get_current( self.context.get('request', None)) instance.save() return instance
def create(self, validated_data): terms = Terms.objects.get(entity_id=validated_data['terms_entity_id']) institution = terms.institution if institution: identifiers = [inst.identifier for inst in institution.award_allowed_institutions.all()] + [ institution.identifier] schac_homes = self.context['request'].user.schac_homes allowed = any(identifier in schac_homes for identifier in identifiers) or institution.award_allow_all_institutions if not allowed: raise BadgrValidationError('You cannot accept terms that are not allowed by your institution', 0) if validated_data['accepted']: return terms.accept(self.context['request'].user)
def validate(self, data): badgeclass = self.context['request'].data.get('badgeclass') if badgeclass.narrative_required and not data.get('narrative'): raise BadgrValidationError(error_code=999, error_message="Narrative is required") if badgeclass.evidence_required and not data.get("evidence_items"): raise BadgrValidationError(error_code=999, error_message="Eviidence is required") if data.get('email') and not data.get('recipient_identifier'): data['recipient_identifier'] = data.get('email') hashed = data.get('hashed', None) if hashed is None: recipient_type = data.get('recipient_type') if recipient_type in (BadgeInstance.RECIPIENT_TYPE_URL, BadgeInstance.RECIPIENT_TYPE_ID): data['hashed'] = False else: data['hashed'] = True return data
def get_general_terms(cls, user): if user.is_student: return list( Terms.objects.filter( terms_type__in=(Terms.TYPE_SERVICE_AGREEMENT_STUDENT, Terms.TYPE_TERMS_OF_SERVICE))) elif user.is_teacher: return list( Terms.objects.filter( terms_type__in=(Terms.TYPE_SERVICE_AGREEMENT_EMPLOYEE, Terms.TYPE_TERMS_OF_SERVICE))) raise BadgrValidationError( 'Cannot get general terms user is neither teacher nor student', 0)
def create(self, validated_data, **kwargs): user_permissions = validated_data['faculty'].get_permissions( validated_data['created_by']) if user_permissions['may_create']: new_issuer = Issuer(**validated_data) # set badgrapp new_issuer.badgrapp = BadgrApp.objects.get_current( self.context.get('request', None)) new_issuer.save() return new_issuer else: raise BadgrValidationError( "You don't have the necessary permissions", 100)
def create(self, validated_data): """ Requires self.context to include request (with authenticated request.user) and badgeclass: issuer.models.BadgeClass. """ badgeclass = self.context['request'].data.get('badgeclass') enrollment = StudentsEnrolled.objects.get( entity_id=validated_data.get('enrollment_entity_id')) expires_at = None if badgeclass.expiration_period: expires_at = datetime.datetime.now().replace( microsecond=0, second=0, minute=0, hour=0) + badgeclass.expiration_period if enrollment.badge_instance: raise BadgrValidationError( "Can't award enrollment, it has already been awarded", 213) if self.context['request'].data.get('issue_signed', False): assertion = badgeclass.issue_signed( recipient=enrollment.user, created_by=self.context.get('request').user, allow_uppercase=validated_data.get('allow_uppercase'), recipient_type=validated_data.get( 'recipient_type', BadgeInstance.RECIPIENT_TYPE_EDUID), expires_at=expires_at, extensions=validated_data.get('extension_items', None), identifier=uuid.uuid4().urn, signer=validated_data.get('created_by'), # evidence=validated_data.get('evidence_items', None) # Dont forget this one when you re-implement signing # narrative=validated_data.get('narrative', None) # idem ) else: assertion = badgeclass.issue( recipient=enrollment.user, created_by=self.context.get('request').user, allow_uppercase=validated_data.get('allow_uppercase'), recipient_type=validated_data.get( 'recipient_type', BadgeInstance.RECIPIENT_TYPE_EDUID), expires_at=expires_at, extensions=validated_data.get('extension_items', None), evidence=validated_data.get('evidence_items', None), narrative=validated_data.get('narrative', None)) enrollment.date_awarded = timezone.now() enrollment.badge_instance = assertion enrollment.save() enrollment.user.remove_cached_data(['cached_pending_enrollments']) # delete the pending direct awards for this badgeclass and this user badgeclass.cached_pending_direct_awards().filter( eppn__in=enrollment.user.eppns).delete() return assertion
def create(self, validated_data): badgeclass = validated_data['badgeclass'] batch_mode = validated_data.pop('batch_mode') notify_recipients = validated_data.pop('notify_recipients') direct_awards = validated_data.pop('direct_awards') user_permissions = badgeclass.get_permissions( validated_data['created_by']) if user_permissions['may_award']: successfull_direct_awards = [] try: with transaction.atomic(): direct_award_bundle = DirectAwardBundle.objects.create( initial_total=direct_awards.__len__(), **validated_data) for direct_award in direct_awards: successfull_direct_awards.append( DirectAward.objects.create( bundle=direct_award_bundle, badgeclass=badgeclass, **direct_award)) except IntegrityError: raise BadgrValidationError( "A direct award already exists with this eppn for this badgeclass", 999) if notify_recipients: for da in successfull_direct_awards: da.notify_recipient() if batch_mode: direct_award_bundle.notify_awarder() direct_award_bundle.badgeclass.remove_cached_data( ['cached_direct_awards']) direct_award_bundle.badgeclass.remove_cached_data( ['cached_direct_award_bundles']) return direct_award_bundle raise BadgrValidationError("You don't have the necessary permissions", 100)
def validate_extensions(self, extensions): is_formal = False if extensions: for ext_name, ext in extensions.items(): if "@context" in ext and not ext['@context'].startswith( settings.EXTENSIONS_ROOT_URL): raise BadgrValidationError( error_code=999, error_message= f"extensions @context invalid {ext['@context']}") if ext_name.endswith('ECTSExtension') or ext_name.endswith( 'StudyLoadExtension'): is_formal = True self.formal = is_formal return extensions
def create(self, validated_data, **kwargs): user_institution = self.context['request'].user.institution user_permissions = user_institution.get_permissions( validated_data['created_by']) if user_permissions['may_create']: validated_data['institution'] = user_institution del validated_data['created_by'] new_faculty = Faculty(**validated_data) try: new_faculty.save() except IntegrityError as e: raise serializers.ValidationError( "Faculty name already exists") return new_faculty else: BadgrValidationError("You don't have the necessary permissions", 100)
def update(self, instance, validated_data): if instance.assertions: raise BadgrValidationError( error_code=999, error_message= "Cannot change any value, assertions have already been issued") self.save_extensions(validated_data, instance) for key, value in validated_data.items(): setattr(instance, key, value) try: instance.save() except IntegrityError: raise BadgrValidationFieldError( 'name', "There is already a Badgeclass with this name inside this Issuer", 909) return instance
def create(self, validated_data, **kwargs): user_permissions = validated_data['faculty'].get_permissions( validated_data['created_by']) if user_permissions['may_create']: new_issuer = Issuer(**validated_data) # set badgrapp new_issuer.badgrapp = BadgrApp.objects.get_current( self.context.get('request', None)) try: new_issuer.save() except IntegrityError: raise BadgrValidationFieldError( 'name', "There is already an Issuer with this name inside this Issuer group", 908) return new_issuer else: raise BadgrValidationError( "You don't have the necessary permissions", 100)
def update(self, instance, validated_data): if instance.assertions and instance.name != validated_data["name"]: raise BadgrValidationError( "Cannot change the name, assertions have already been issued within this entity", 214) [ setattr(instance, attr, validated_data.get(attr)) for attr in validated_data ] self.save_extensions(validated_data, instance) if not instance.badgrapp_id: instance.badgrapp = BadgrApp.objects.get_current( self.context.get('request', None)) try: instance.save() except IntegrityError: raise BadgrValidationFieldError( 'name', "There is already an Issuer with this name inside this Issuer group", 908) return instance
def update(self, instance, validated_data): if instance.assertions and len( [ass for ass in instance.assertions if not ass.revoked]) > 0: raise BadgrValidationError( error_code=999, error_message= "Cannot change any value, assertions have already been issued") self.save_extensions(validated_data, instance) for key, value in validated_data.items(): if key is not 'award_allowed_institutions': setattr(instance, key, value) instance.award_allowed_institutions.set( validated_data.get('award_allowed_institutions', [])) try: instance.save() except IntegrityError: raise BadgrValidationFieldError( 'name', "There is already a Badgeclass with this name inside this Issuer", 911) return instance
def post(self, request, **kwargs): if 'badgeclass_slug' not in request.data: raise BadgrApiException400("Missing badgeclass id", 208) badge_class = get_object_or_404( BadgeClass, entity_id=request.data['badgeclass_slug']) if not badge_class.terms_accepted(request.user): raise BadgrValidationError( "Cannot enroll, must accept terms first", 0) if request.user.may_enroll(badge_class, raise_exception=True): enrollment = StudentsEnrolled.objects.create( badge_class_id=badge_class.pk, user=request.user, date_consent_given=timezone.now()) message = EmailMessageMaker.create_student_badge_request_email( request.user, badge_class) request.user.email_user( subject='You have successfully requested an edubadge', html_message=message) return Response(data={ 'status': 'enrolled', 'entity_id': enrollment.entity_id }, status=201) raise BadgrApiException400('Cannot enroll', 209)
def is_valid(self, raise_exception=False): try: return super(BadgrBaseModelSerializer, self).is_valid(raise_exception) except ValidationError as e: raise BadgrValidationError(error_message=e.detail, error_code=999)
def delete(self, *args, **kwargs): if self._is_last_staff_membership(): raise BadgrValidationError( 'Cannot remove the last staff membership of this institution.', 500) return super(InstitutionStaff, self).delete(*args, **kwargs)