You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

69 lines
2.0 KiB

  1. from django.conf import settings
  2. from django.contrib.auth.models import User
  3. from django.core.exceptions import ValidationError
  4. from django.db import models
  5. from django.db.models import Manager
  6. from api.models import Project
  7. from roles.models import Role
  8. class MemberManager(Manager):
  9. def can_update(self, project: int, member_id: int, new_role: str) -> bool:
  10. """The project needs at least 1 admin.
  11. Args:
  12. project: The project id.
  13. member_id: The member id.
  14. new_role: The new role name.
  15. Returns:
  16. Whether the mapping can be updated or not.
  17. """
  18. queryset = self.filter(
  19. project=project, role__name=settings.ROLE_PROJECT_ADMIN
  20. )
  21. if queryset.count() > 1:
  22. return True
  23. else:
  24. admin = queryset.first()
  25. # we can change the role except for the only admin.
  26. return admin.id != member_id or new_role == settings.ROLE_PROJECT_ADMIN
  27. def has_role(self, project_id: int, user: User, role_name: str):
  28. return self.filter(project=project_id, user=user, role__name=role_name).exists()
  29. class Member(models.Model):
  30. user = models.ForeignKey(
  31. to=User,
  32. on_delete=models.CASCADE,
  33. related_name='role_mappings'
  34. )
  35. project = models.ForeignKey(
  36. to=Project,
  37. on_delete=models.CASCADE,
  38. related_name='role_mappings'
  39. )
  40. role = models.ForeignKey(
  41. to=Role,
  42. on_delete=models.CASCADE
  43. )
  44. created_at = models.DateTimeField(auto_now_add=True)
  45. updated_at = models.DateTimeField(auto_now=True)
  46. objects = MemberManager()
  47. def clean(self):
  48. members = self.objects.exclude(id=self.id)
  49. if members.filter(user=self.user, project=self.project).exists():
  50. message = 'This user is already assigned to a role in this project.'
  51. raise ValidationError(message)
  52. @property
  53. def username(self):
  54. return self.user.username
  55. class Meta:
  56. unique_together = ('user', 'project')