From 511bfe403f7ca6ed64ae294835da3328e5c6226f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Wed, 17 May 2017 17:13:01 +0200 Subject: [PATCH] Adding initial endpoint for games --- taiga/projects/admin.py | 8 +++++ taiga/projects/api.py | 8 +++++ taiga/projects/models.py | 30 ++++++++++++++++++ taiga/projects/permissions.py | 8 +++++ taiga/projects/serializers.py | 13 ++++++++ taiga/projects/validators.py | 57 +++++++++++++++++++++++++++++++++++ taiga/routers.py | 2 ++ 7 files changed, 126 insertions(+) diff --git a/taiga/projects/admin.py b/taiga/projects/admin.py index 61925837..2a8a0798 100644 --- a/taiga/projects/admin.py +++ b/taiga/projects/admin.py @@ -289,6 +289,13 @@ class IssueStatusAdmin(admin.ModelAdmin): class ProjectTemplateAdmin(admin.ModelAdmin): pass + +class GameAdmin(admin.ModelAdmin): + list_display = ["project", "name", "uuid"] + list_display_links = ["name"] + raw_id_fields = ["project"] + + admin.site.register(models.IssueStatus, IssueStatusAdmin) admin.site.register(models.TaskStatus, TaskStatusAdmin) admin.site.register(models.UserStoryStatus, UserStoryStatusAdmin) @@ -299,3 +306,4 @@ admin.site.register(models.Severity, SeverityAdmin) admin.site.register(models.Priority, PriorityAdmin) admin.site.register(models.IssueType, IssueTypeAdmin) admin.site.register(models.ProjectTemplate, ProjectTemplateAdmin) +admin.site.register(models.Game, GameAdmin) diff --git a/taiga/projects/api.py b/taiga/projects/api.py index 007e939c..40b63015 100644 --- a/taiga/projects/api.py +++ b/taiga/projects/api.py @@ -1070,3 +1070,11 @@ class InvitationViewSet(ModelListViewSet): def list(self, *args, **kwargs): raise exc.PermissionDenied(_("You don't have permisions to see that.")) + + +class GameViewSet(ModelCrudViewSet): + model = models.Game + serializer_class = serializers.GameSerializer + validator_class = validators.GameValidator + permission_classes = (permissions.GamePermission,) + filter_fields = ('project', 'uuid') diff --git a/taiga/projects/models.py b/taiga/projects/models.py index 9db260df..f7894228 100644 --- a/taiga/projects/models.py +++ b/taiga/projects/models.py @@ -16,6 +16,8 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import uuid + from django.conf import settings from django.contrib.auth import get_user_model from django.contrib.postgres.fields import ArrayField @@ -1261,3 +1263,31 @@ class ProjectTemplate(TaggedMixin, TagsColorsMixin, models.Model): project.looking_for_people_note = self.looking_for_people_note return project + + +class Game(models.Model): + uuid = models.CharField(max_length=32, editable=False, null=True, + blank=True, default=None, db_index=True) + name = models.CharField(max_length=250, null=False, blank=False, + verbose_name=_("name")) + project = models.ForeignKey(Project, null=False, blank=False) + created_at = models.DateTimeField(default=timezone.now, + verbose_name=_("create at")) + end_at = models.DateTimeField(null=True, blank=True) + userstories = JSONField() + scales = JSONField() + roles = JSONField() + + def save(self, *args, **kwargs): + if not self.uuid: + self.uuid = uuid.uuid4().hex + return super().save(*args, **kwargs) + + class Meta: + verbose_name = "Game" + verbose_name_plural = "Games" + ordering = ["project", "name", "uuid"] + unique_together = ("project", "uuid") + + def __str__(self): + return self.name diff --git a/taiga/projects/permissions.py b/taiga/projects/permissions.py index e7b15c9a..4c731475 100644 --- a/taiga/projects/permissions.py +++ b/taiga/projects/permissions.py @@ -241,3 +241,11 @@ class ProjectTemplatePermission(TaigaResourcePermission): partial_update_perms = IsSuperUser() destroy_perms = IsSuperUser() list_perms = AllowAny() + +class GamePermission(TaigaResourcePermission): + retrieve_perms = HasProjectPerm('modify_us') + create_perms = HasProjectPerm('modify_us') + update_perms = HasProjectPerm('modify_us') + partial_update_perms = HasProjectPerm('modify_us') + destroy_perms = HasProjectPerm('modify_us') + list_perms = HasProjectPerm('modify_us') diff --git a/taiga/projects/serializers.py b/taiga/projects/serializers.py index 4d138e71..2065585a 100644 --- a/taiga/projects/serializers.py +++ b/taiga/projects/serializers.py @@ -523,3 +523,16 @@ class ProjectTemplateSerializer(serializers.LightSerializer): priorities = Field() severities = Field() roles = Field() + + +class GameSerializer(serializers.LightSerializer): + uuid = Field() + name = Field() + project = Field(attr="project_id") + created_at = Field() + end_at = Field() + userstories = Field() + scales = Field() + roles = Field() + + diff --git a/taiga/projects/validators.py b/taiga/projects/validators.py index b3abe1e6..d2d512fb 100644 --- a/taiga/projects/validators.py +++ b/taiga/projects/validators.py @@ -318,3 +318,60 @@ class DuplicateProjectValidator(validators.Validator): description = serializers.CharField() is_private = serializers.BooleanField() users = DuplicateProjectMemberValidator(many=True) + + +class GameValidator(validators.ModelValidator): + class Meta: + model = models.Game + + def validate_roles(self, attrs, source): + project = attrs.get("project", None if self.object is None else self.object.project) + if project is None: + return attrs + + roles = attrs[source] + if not isinstance(roles, list): + raise ValidationError(_("Invalid roles format")) + + for role in roles: + if "id" not in role or "name" not in role: + raise ValidationError(_("Invalid role format")) + + if project.roles.filter(id=role['id']).count() == 0: + raise ValidationError(_("Invalid role for the project")) + + return attrs + + def validate_scales(self, attrs, source): + scales = attrs[source] + if not isinstance(scales, list): + raise ValidationError(_("Invalid scales format")) + + for scale in scales: + if "id" not in scale or "name" not in scale: + raise ValidationError(_("Invalid scale format")) + + return attrs + + def validate_userstories(self, attrs, source): + project = attrs.get("project", None if self.object is None else self.object.project) + if project is None: + return attrs + + userstories = attrs[source] + if not isinstance(userstories, list): + raise ValidationError(_("Invalid user stories format")) + + scales = map(lambda x: x['id'], attrs["scales"]) + + for us in userstories: + if "id" not in us or "scale_id" not in us: + raise ValidationError(_("Invalid user story format")) + + if project.user_stories.filter(id=us['id']).count() == 0: + raise ValidationError(_("Invalid user story for the project")) + + if us['scale_id'] is not None and us['scale_id'] not in scales: + raise ValidationError(_("Invalid scale id for user story")) + + return attrs diff --git a/taiga/routers.py b/taiga/routers.py index e70203c9..a4d4a674 100644 --- a/taiga/routers.py +++ b/taiga/routers.py @@ -77,6 +77,7 @@ from taiga.projects.api import IssueDueDateViewSet from taiga.projects.api import PriorityViewSet from taiga.projects.api import SeverityViewSet from taiga.projects.api import ProjectTemplateViewSet +from taiga.projects.api import GameViewSet router.register(r"projects", ProjectViewSet, base_name="projects") router.register(r"projects/(?P\d+)/fans", ProjectFansViewSet, base_name="project-fans") @@ -95,6 +96,7 @@ router.register(r"issue-types", IssueTypeViewSet, base_name="issue-types") router.register(r"issue-due-dates", IssueDueDateViewSet, base_name="issue-due-dates") router.register(r"priorities", PriorityViewSet, base_name="priorities") router.register(r"severities",SeverityViewSet , base_name="severities") +router.register(r"games", GameViewSet, base_name="games") # Custom Attributes