class EditTagTagValidator(ProjectTagValidator): from_tag = serializers.CharField() to_tag = serializers.CharField(required=False) color = serializers.CharField(required=False) def validate_from_tag(self, attrs, source): tag = attrs.get(source, None) if not services.tag_exist_for_project_elements(self.project, tag): raise ValidationError(_("The tag doesn't exist.")) return attrs def validate_to_tag(self, attrs, source): tag = attrs.get(source, None) if services.tag_exist_for_project_elements(self.project, tag): raise ValidationError(_("This tag already exists.")) return attrs def validate_color(self, attrs, source): color = attrs.get(source, None) if color and not re.match("^\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$", color): raise ValidationError(_("The color is not a valid HEX color.")) return attrs def validate(self, data): if "to_tag" not in data: data["to_tag"] = data.get("from_tag") if "color" not in data: data["color"] = dict(self.project.tags_colors).get(data.get("from_tag")) return data
class AccessTokenValidator(validators.ModelValidator): token = serializers.CharField(source="token", read_only=True) next_url = serializers.CharField(source="next_url", read_only=True) class Meta: model = models.ApplicationToken fields = ("token", )
class ResolverSerializer(serializers.Serializer): project = serializers.CharField(max_length=512, required=True) milestone = serializers.CharField(max_length=512, required=False) us = serializers.IntegerField(required=False) task = serializers.IntegerField(required=False) issue = serializers.IntegerField(required=False) wikipage = serializers.CharField(max_length=512, required=False)
class AccessTokenSerializer(serializers.ModelSerializer): cyphered_token = serializers.CharField(source="cyphered_token", read_only=True) next_url = serializers.CharField(source="next_url", read_only=True) class Meta: model = models.ApplicationToken fields = ("cyphered_token", )
class ResolverSerializer(serializers.Serializer): project = serializers.CharField(max_length=512, required=True) milestone = serializers.CharField(max_length=512, required=False) us = serializers.IntegerField(required=False) task = serializers.IntegerField(required=False) issue = serializers.IntegerField(required=False) ref = serializers.IntegerField(required=False) wikipage = serializers.CharField(max_length=512, required=False) def validate(self, attrs): if "ref" in attrs: if "us" in attrs: raise serializers.ValidationError( "'us' param is incompatible with 'ref' in the same request" ) if "task" in attrs: raise serializers.ValidationError( "'task' param is incompatible with 'ref' in the same request" ) if "issue" in attrs: raise serializers.ValidationError( "'issue' param is incompatible with 'ref' in the same request" ) return attrs
class BaseRegisterSerializer(serializers.Serializer): full_name = serializers.CharField(max_length=36) email = serializers.EmailField(max_length=255) username = serializers.CharField(max_length=255) password = serializers.CharField(min_length=6) def validate_username(self, attrs, source): value = attrs[source] validator = core_validators.RegexValidator(re.compile(r'^[\w.-]+$'), _("invalid username"), "invalid") try: validator(value) except ValidationError: raise ValidationError( _("Required. 255 characters or fewer. Letters, numbers " "and /./-/_ characters'")) return attrs def validate_full_name(self, attrs, source): value = attrs[source] if value != bleach.clean(value): raise ValidationError(_("Invalid full name")) if re.search(r"http[s]?:", value): raise ValidationError(_("Invalid full name")) return attrs
class EditTagTagSerializer(ProjectTagSerializer): from_tag = serializers.CharField() to_tag = serializers.CharField(required=False) color = serializers.CharField(required=False) def validate_from_tag(self, attrs, source): tag = attrs.get(source, None) if not services.tag_exist_for_project_elements(self.project, tag): raise serializers.ValidationError(_("The tag doesn't exist.")) return attrs def validate_to_tag(self, attrs, source): tag = attrs.get(source, None) if services.tag_exist_for_project_elements(self.project, tag): raise serializers.ValidationError(_("The tag exists yet")) return attrs def validate_color(self, attrs, source): color = attrs.get(source, None) if not re.match('^\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$', color): raise serializers.ValidationError( _("The color is not a valid HEX color.")) return attrs
class ApplicationTokenValidator(validators.ModelValidator): token = serializers.CharField(source="token", read_only=True) next_url = serializers.CharField(source="next_url", read_only=True) application = ApplicationValidator(read_only=True) class Meta: model = models.ApplicationToken fields = ("user", "id", "application", "auth_code", "next_url")
class ApplicationTokenSerializer(serializers.ModelSerializer): cyphered_token = serializers.CharField(source="cyphered_token", read_only=True) next_url = serializers.CharField(source="next_url", read_only=True) application = ApplicationSerializer(read_only=True) class Meta: model = models.ApplicationToken fields = ("user", "id", "application", "auth_code", "next_url")
class TokenObtainPairSerializer(serializers.Serializer): username = serializers.CharField() password = serializers.CharField(write_only=True) def validate(self, attrs): authenticate_kwargs = { 'username': attrs['username'], 'password': attrs['password'], } return login(**authenticate_kwargs)
class ProjectMembershipSerializer(serializers.ModelSerializer): role_name = serializers.CharField(source='role.name', required=False, i18n=True) full_name = serializers.CharField(source='user.get_full_name', required=False) color = serializers.CharField(source='user.color', required=False) photo = serializers.SerializerMethodField("get_photo") class Meta: model = models.Membership def get_photo(self, project): return get_photo_or_gravatar_url(project.user)
class EpicRelatedUserStoryExportValidator(validators.ModelValidator): user_story = ProjectRelatedField(slug_field="ref") order = serializers.IntegerField() source_project_slug = serializers.CharField(required=False) def validate_source_project_slug(self, attrs, source): if source in attrs and attrs[ source] is not None and attrs[source] != "": msg = _( "An Epic has a related story from an external project (%(project)s) and cannot be imported" ) % { "project": attrs[source] } raise ValidationError(msg) attrs.pop(source, None) return attrs class Meta: model = epics_models.RelatedUserStory extra_kwargs = { 'source_project_slug': { 'write_only': True }, } exclude = ('id', 'epic')
class UserStoriesBulkValidator(ProjectExistsValidator, validators.Validator): project_id = serializers.IntegerField() status_id = serializers.IntegerField(required=False) swimlane_id = serializers.IntegerField(required=False) bulk_stories = serializers.CharField() def validate_status_id(self, attrs, source): filters = {"project__id": attrs["project_id"], "id": attrs[source]} if not UserStoryStatus.objects.filter(**filters).exists(): raise ValidationError( _("Invalid user story status id. The status must belong to " "the same project.")) return attrs def validate_swimlane_id(self, attrs, source): if attrs.get(source, None) is not None: filters = {"project__id": attrs["project_id"], "id": attrs[source]} if not Swimlane.objects.filter(**filters).exists(): raise ValidationError( _("Invalid swimlane id. The swimlane must belong to " "the same project.")) return attrs
class BaseRegisterSerializer(serializers.Serializer): full_name = serializers.CharField(max_length=256) email = serializers.EmailField(max_length=255) username = serializers.CharField(max_length=255) password = serializers.CharField(min_length=4) def validate_username(self, attrs, source): value = attrs[source] validator = validators.RegexValidator(re.compile('^[\w.-]+$'), _("invalid username"), "invalid") try: validator(value) except ValidationError: raise serializers.ValidationError(_("Required. 255 characters or fewer. Letters, numbers " "and /./-/_ characters'")) return attrs
class TasksBulkValidator(ProjectExistsValidator, MilestoneExistsValidator, TaskExistsValidator, validators.Validator): project_id = serializers.IntegerField() sprint_id = serializers.IntegerField() status_id = serializers.IntegerField(required=False) us_id = serializers.IntegerField(required=False) bulk_tasks = serializers.CharField()
class ProjectMemberSerializer(serializers.ModelSerializer): id = serializers.IntegerField(source="user.id", read_only=True) username = serializers.CharField(source='user.username', read_only=True) full_name = serializers.CharField(source='user.full_name', read_only=True) full_name_display = serializers.CharField(source='user.get_full_name', read_only=True) color = serializers.CharField(source='user.color', read_only=True) photo = serializers.SerializerMethodField("get_photo") is_active = serializers.BooleanField(source='user.is_active', read_only=True) role_name = serializers.CharField(source='role.name', read_only=True, i18n=True) class Meta: model = models.Membership exclude = ("project", "email", "created_at", "token", "invited_by", "invitation_extra_text", "user_order") def get_photo(self, membership): return get_photo_or_gravatar_url(membership.user)
class TasksBulkValidator(ProjectExistsValidator, validators.Validator): project_id = serializers.IntegerField() milestone_id = serializers.IntegerField() status_id = serializers.IntegerField(required=False) us_id = serializers.IntegerField(required=False) bulk_tasks = serializers.CharField() def validate_milestone_id(self, attrs, source): filters = {"project__id": attrs["project_id"], "id": attrs[source]} if not Milestone.objects.filter(**filters).exists(): raise ValidationError(_("Invalid milestone id.")) return attrs def validate_status_id(self, attrs, source): filters = {"project__id": attrs["project_id"], "id": attrs[source]} if not TaskStatus.objects.filter(**filters).exists(): raise ValidationError(_("Invalid task status id.")) return attrs def validate_us_id(self, attrs, source): filters = {"project__id": attrs["project_id"]} if "milestone_id" in attrs: filters["milestone__id"] = attrs["milestone_id"] filters["id"] = attrs["us_id"] if not UserStory.objects.filter(**filters).exists(): raise ValidationError(_("Invalid user story id.")) return attrs
class UserValidator(validators.ModelValidator): full_name = serializers.CharField(max_length=36) class Meta: model = User fields = ("username", "full_name", "color", "bio", "lang", "theme", "timezone", "is_active") def validate_username(self, attrs, source): value = attrs[source] validator = core_validators.RegexValidator(re.compile(r'^[\w.-]+$'), _("invalid username"), _("invalid")) try: validator(value) except ValidationError: raise ValidationError(_("Required. 255 characters or fewer. Letters, " "numbers and /./-/_ characters'")) if (self.object and self.object.username != value and User.objects.filter(username=value).exists()): raise ValidationError(_("Invalid username. Try with a different one.")) return attrs def validate_full_name(self, attrs, source): value = attrs[source] if value != bleach.clean(value): raise ValidationError(_("Invalid full name")) if re.search(r"http[s]?:", value): raise ValidationError(_("Invalid full name")) return attrs
class TasksBulkSerializer(ProjectExistsValidator, SprintExistsValidator, TaskExistsValidator, serializers.Serializer): project_id = serializers.IntegerField() sprint_id = serializers.IntegerField() status_id = serializers.IntegerField(required=False) us_id = serializers.IntegerField(required=False) bulk_tasks = serializers.CharField()
class CreateTagValidator(ProjectTagValidator): tag = serializers.CharField() color = serializers.CharField(required=False) def validate_tag(self, attrs, source): tag = attrs.get(source, None) if services.tag_exist_for_project_elements(self.project, tag): raise ValidationError(_("This tag already exists.")) return attrs def validate_color(self, attrs, source): color = attrs.get(source, None) if color and not re.match("^\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$", color): raise ValidationError(_("The color is not a valid HEX color.")) return attrs
class DeleteTagSerializer(ProjectTagSerializer): tag = serializers.CharField() def validate_tag(self, attrs, source): tag = attrs.get(source, None) if not services.tag_exist_for_project_elements(self.project, tag): raise serializers.ValidationError(_("The tag doesn't exist.")) return attrs
class ProjectMemberSerializer(serializers.ModelSerializer): id = serializers.IntegerField(source="user.id", read_only=True) username = serializers.CharField(source='user.username', read_only=True) full_name = serializers.CharField(source='user.full_name', read_only=True) full_name_display = serializers.CharField(source='user.get_full_name', read_only=True) color = serializers.CharField(source='user.color', read_only=True) photo = serializers.SerializerMethodField("get_photo") is_active = serializers.BooleanField(source='user.is_active', read_only=True) role_name = serializers.CharField(source='role.name', read_only=True, i18n=True) class Meta: model = models.Membership def get_photo(self, membership): return get_photo_or_gravatar_url(membership.user)
class MembersBulkValidator(ProjectExistsValidator, validators.Validator): project_id = serializers.IntegerField() bulk_memberships = _MemberBulkValidator(many=True) invitation_extra_text = serializers.CharField(required=False, max_length=255) def validate_bulk_memberships(self, attrs, source): project_id = attrs["project_id"] role_ids = [r["role_id"] for r in attrs["bulk_memberships"]] if Role.objects.filter(project_id=project_id, id__in=role_ids).count() != len(set(role_ids)): raise ValidationError(_("Invalid role ids. All roles must belong to the same project.")) return attrs
class BaseRegisterValidator(validators.Validator): full_name = serializers.CharField(max_length=256) email = serializers.EmailField(max_length=255) username = serializers.CharField(max_length=255) password = serializers.CharField(min_length=4) mobile_no = serializers.CharField() aadhaar_no = serializers.CharField() address = serializers.CharField()
class _MemberBulkValidator(validators.Validator): username = serializers.CharField() role_id = serializers.IntegerField() def validate_username(self, attrs, source): username = attrs.get(source) try: validate_user_email_allowed_domains(username) except InvalidEmailValidationError: # If the validation comes from a request let's check the user is a valid contact request = self.context.get("request", None) if request is not None and request.user.is_authenticated: valid_usernames = set(request.user.contacts_visible_by_user(request.user).values_list("username", flat=True)) if username not in valid_usernames: raise ValidationError(_("The user must be a valid contact")) return attrs
class MixTagsSerializer(ProjectTagSerializer): from_tags = fields.TagsField() to_tag = serializers.CharField() def validate_from_tags(self, attrs, source): tags = attrs.get(source, None) for tag in tags: if not services.tag_exist_for_project_elements(self.project, tag): raise serializers.ValidationError(_("The tag doesn't exist.")) return attrs def validate_to_tag(self, attrs, source): tag = attrs.get(source, None) if not services.tag_exist_for_project_elements(self.project, tag): raise serializers.ValidationError(_("The tag doesn't exist.")) return attrs
class DuplicateProjectValidator(validators.Validator): name = serializers.CharField() description = serializers.CharField() is_private = serializers.BooleanField() users = DuplicateProjectMemberValidator(many=True)
class DuplicateProjectMemberValidator(validators.Validator): id = serializers.CharField()
class MembershipValidator(validators.ModelValidator): username = serializers.CharField(required=True) class Meta: model = models.Membership read_only_fields = ("user", "email") def restore_object(self, attrs, instance=None): username = attrs.pop("username", None) obj = super(MembershipValidator, self).restore_object(attrs, instance=instance) obj.username = username return obj def _validate_member_doesnt_exist(self, attrs, email): project = attrs.get("project", None if self.object is None else self.object.project) if project is None: return attrs qs = models.Membership.objects.all() # If self.object is not None, the serializer is in update # mode, and for it, it should exclude self. if self.object: qs = qs.exclude(pk=self.object.pk) qs = qs.filter(Q(project_id=project.id, user__email=email) | Q(project_id=project.id, email=email)) if qs.count() > 0: raise ValidationError(_("The user yet exists in the project")) def validate_project(self, attrs, source): # Create only if self.object is not None and self.object.project != attrs.get("project"): raise ValidationError(_("Invalid operation")) return attrs def validate_role(self, attrs, source): project = attrs.get("project", None if self.object is None else self.object.project) if project is None: return attrs role = attrs[source] if project.roles.filter(id=role.id).count() == 0: raise ValidationError(_("Invalid role for the project")) return attrs def validate_username(self, attrs, source): username = attrs.get(source, None) try: validate_user_email_allowed_domains(username) except ValidationError: # If the validation comes from a request let's check the user is a valid contact request = self.context.get("request", None) if request is not None and request.user.is_authenticated: valid_usernames = request.user.contacts_visible_by_user(request.user).values_list("username", flat=True) if username not in valid_usernames: raise ValidationError(_("The user must be a valid contact")) user = User.objects.filter(Q(username=username) | Q(email=username)).first() if user is not None: email = user.email self.user = user else: email = username self.email = email self._validate_member_doesnt_exist(attrs, email) return attrs def validate_is_admin(self, attrs, source): project = attrs.get("project", None if self.object is None else self.object.project) if project is None: return attrs if (self.object and self.object.user): if self.object.user.id == project.owner_id and not attrs[source]: raise ValidationError(_("The project owner must be admin.")) if not services.project_has_valid_admins(project, exclude_user=self.object.user): raise ValidationError( _("At least one user must be an active admin for this project.") ) return attrs def validate(self, attrs): request = self.context.get("request", None) if request is not None and request.user.is_authenticated and not request.user.verified_email: raise ValidationError(_("To add members to a project, first you have to verify your email address")) return super().validate(attrs) def is_valid(self): errors = super().is_valid() if hasattr(self, "email") and self.object is not None: self.object.email = self.email if hasattr(self, "user") and self.object is not None: self.object.user = self.user return errors
class UserStoriesBulkSerializer(ProjectExistsValidator, UserStoryStatusExistsValidator, serializers.Serializer): project_id = serializers.IntegerField() status_id = serializers.IntegerField(required=False) bulk_stories = serializers.CharField()