Enhancement: Create the wiki page if not exist when new links are created

remotes/origin/issue/4795/notification_even_they_are_disabled
David Barragán Merino 2016-06-17 17:10:05 +02:00 committed by Alejandro Alonso
parent e4f96e6053
commit d59e90885c
5 changed files with 173 additions and 20 deletions

View File

@ -6,6 +6,7 @@
- Include created, modified and finished dates for tasks in CSV reports. - Include created, modified and finished dates for tasks in CSV reports.
- Add gravatar url to Users API endpoint. - Add gravatar url to Users API endpoint.
- ProjectTemplates now are sorted by the attribute 'order'. - ProjectTemplates now are sorted by the attribute 'order'.
- Create enpty wiki pages (if not exist) when a new link is created.
- Comments: - Comments:
- Now comment owners and project admins can edit existing comments with the history Entry endpoint. - Now comment owners and project admins can edit existing comments with the history Entry endpoint.
- Add a new permissions to allow add comments instead of use the existent modify permission for this purpose. - Add a new permissions to allow add comments instead of use the existent modify permission for this purpose.

View File

@ -223,6 +223,7 @@ def send_notifications(obj, *, history):
if settings.CHANGE_NOTIFICATIONS_MIN_INTERVAL == 0: if settings.CHANGE_NOTIFICATIONS_MIN_INTERVAL == 0:
send_sync_notifications(notification.id) send_sync_notifications(notification.id)
@transaction.atomic @transaction.atomic
def send_sync_notifications(notification_id): def send_sync_notifications(notification_id):
""" """
@ -261,19 +262,21 @@ def send_sync_notifications(notification_id):
msg_id = 'taiga-system' msg_id = 'taiga-system'
now = datetime.datetime.now() now = datetime.datetime.now()
format_args = {"project_slug": notification.project.slug, format_args = {
"project_slug": notification.project.slug,
"project_name": notification.project.name, "project_name": notification.project.name,
"msg_id": msg_id, "msg_id": msg_id,
"time": int(now.timestamp()), "time": int(now.timestamp()),
"domain": domain} "domain": domain
}
headers = {"Message-ID": "<{project_slug}/{msg_id}/{time}@{domain}>".format(**format_args), headers = {
"Message-ID": "<{project_slug}/{msg_id}/{time}@{domain}>".format(**format_args),
"In-Reply-To": "<{project_slug}/{msg_id}@{domain}>".format(**format_args), "In-Reply-To": "<{project_slug}/{msg_id}@{domain}>".format(**format_args),
"References": "<{project_slug}/{msg_id}@{domain}>".format(**format_args), "References": "<{project_slug}/{msg_id}@{domain}>".format(**format_args),
"List-ID": 'Taiga/{project_name} <taiga.{project_slug}@{domain}>'.format(**format_args), "List-ID": 'Taiga/{project_name} <taiga.{project_slug}@{domain}>'.format(**format_args),
"Thread-Index": make_ms_thread_index("<{project_slug}/{msg_id}@{domain}>".format(**format_args), now)
"Thread-Index": make_ms_thread_index("<{project_slug}/{msg_id}@{domain}>".format(**format_args), now)} }
for user in notification.notify_users.distinct(): for user in notification.notify_users.distinct():
context["user"] = user context["user"] = user
@ -370,9 +373,11 @@ def get_projects_watched(user_or_id):
user = get_user_model().objects.get(id=user_or_id) user = get_user_model().objects.get(id=user_or_id)
project_class = apps.get_model("projects", "Project") project_class = apps.get_model("projects", "Project")
project_ids = user.notify_policies.exclude(notify_level=NotifyLevel.none).values_list("project__id", flat=True) project_ids = (user.notify_policies.exclude(notify_level=NotifyLevel.none)
.values_list("project__id", flat=True))
return project_class.objects.filter(id__in=project_ids) return project_class.objects.filter(id__in=project_ids)
def add_watcher(obj, user): def add_watcher(obj, user):
"""Add a watcher to an object. """Add a watcher to an object.

View File

@ -18,23 +18,27 @@
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from taiga.base.api.permissions import IsAuthenticated
from taiga.base import filters
from taiga.base import exceptions as exc from taiga.base import exceptions as exc
from taiga.base import filters
from taiga.base import response from taiga.base import response
from taiga.base.api import ModelCrudViewSet, ModelListViewSet from taiga.base.api import ModelCrudViewSet
from taiga.base.api import ModelListViewSet
from taiga.base.api.mixins import BlockedByProjectMixin from taiga.base.api.mixins import BlockedByProjectMixin
from taiga.base.api.permissions import IsAuthenticated
from taiga.base.api.utils import get_object_or_404 from taiga.base.api.utils import get_object_or_404
from taiga.base.decorators import list_route from taiga.base.decorators import list_route
from taiga.projects.models import Project
from taiga.mdrender.service import render as mdrender from taiga.mdrender.service import render as mdrender
from taiga.projects.notifications.mixins import WatchedResourceMixin, WatchersViewSetMixin
from taiga.projects.history.mixins import HistoryResourceMixin from taiga.projects.history.mixins import HistoryResourceMixin
from taiga.projects.history.services import take_snapshot
from taiga.projects.models import Project
from taiga.projects.notifications.mixins import WatchedResourceMixin
from taiga.projects.notifications.mixins import WatchersViewSetMixin
from taiga.projects.notifications.services import analize_object_for_watchers
from taiga.projects.notifications.services import send_notifications
from taiga.projects.occ import OCCResourceMixin from taiga.projects.occ import OCCResourceMixin
from . import models from . import models
from . import permissions from . import permissions
from . import serializers from . import serializers
@ -99,3 +103,27 @@ class WikiLinkViewSet(BlockedByProjectMixin, ModelCrudViewSet):
permission_classes = (permissions.WikiLinkPermission,) permission_classes = (permissions.WikiLinkPermission,)
filter_backends = (filters.CanViewWikiPagesFilterBackend,) filter_backends = (filters.CanViewWikiPagesFilterBackend,)
filter_fields = ["project"] filter_fields = ["project"]
def post_save(self, obj, created=False):
if created:
self._create_wiki_page_when_create_wiki_link_if_not_exist(obj)
super().pre_save(obj)
def _create_wiki_page_when_create_wiki_link_if_not_exist(self, wiki_link):
try:
self.check_permissions(request, "create_wiki_page", wiki_link)
except exc.PermissionDenied:
pass
else:
# Create the wiki link and the wiki page if not exist.
wiki_page, created = models.WikiPage.objects.get_or_create(
slug=wiki_link.href,
project=wiki_link.project,
defaults={"owner": self.request.user,"last_modifier": self.request.user})
if created:
# Creaste the new history entre, sSet watcher for the new wiki page
# and send notifications about the new page created
history = take_snapshot(wiki_page, user=self.request.user)
analize_object_for_watchers(wiki_page, history.comment, history.owner)
send_notifications(wiki_page, history=history)

View File

@ -54,3 +54,4 @@ class WikiLinkPermission(TaigaResourcePermission):
partial_update_perms = HasProjectPerm('modify_wiki_link') partial_update_perms = HasProjectPerm('modify_wiki_link')
destroy_perms = HasProjectPerm('delete_wiki_link') destroy_perms = HasProjectPerm('delete_wiki_link')
list_perms = AllowAny() list_perms = AllowAny()
create_wiki_page_perms = HasProjectPerm('add_wiki_page')

View File

@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2014-2016 Andrey Antukh <niwi@niwi.nz>
# Copyright (C) 2014-2016 Jesús Espino <jespinog@gmail.com>
# Copyright (C) 2014-2016 David Barragán <bameda@dbarragan.com>
# Copyright (C) 2014-2016 Alejandro Alonso <alejandro.alonso@kaleidos.net>
# Copyright (C) 2014-2016 Anler Hernández <hello@anler.me>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.core.urlresolvers import reverse
from django.core import mail
from taiga.base.utils import json
from taiga.projects.notifications.choices import NotifyLevel
from .. import factories as f
import pytest
pytestmark = pytest.mark.django_db
def test_create_wiki_link_of_existent_wiki_page_with_permissions(client):
project = f.ProjectFactory.create()
role = f.RoleFactory.create(project=project, permissions=['view_wiki_pages', 'view_wiki_link',
'add_wiki_page', 'add_wiki_link'])
f.MembershipFactory.create(project=project, user=project.owner, role=role)
project.owner.notify_policies.filter(project=project).update(notify_level=NotifyLevel.all)
user = f.UserFactory.create()
f.MembershipFactory.create(project=project, user=user, role=role)
wiki_page = f.WikiPageFactory.create(project=project, owner=user, slug="test", content="test content")
mail.outbox = []
url = reverse("wiki-links-list")
data = {
"title": "test",
"href": "test",
"project": project.pk,
}
assert project.wiki_pages.all().count() == 1
client.login(user)
response = client.json.post(url, json.dumps(data))
assert response.status_code == 201
assert len(mail.outbox) == 0
assert project.wiki_pages.all().count() == 1
def test_create_wiki_link_of_inexistent_wiki_page_with_permissions(client):
project = f.ProjectFactory.create()
role = f.RoleFactory.create(project=project, permissions=['view_wiki_pages', 'view_wiki_link',
'add_wiki_page', 'add_wiki_link'])
f.MembershipFactory.create(project=project, user=project.owner, role=role)
project.owner.notify_policies.filter(project=project).update(notify_level=NotifyLevel.all)
user = f.UserFactory.create()
f.MembershipFactory.create(project=project, user=user, role=role)
mail.outbox = []
url = reverse("wiki-links-list")
data = {
"title": "test",
"href": "test",
"project": project.pk,
}
assert project.wiki_pages.all().count() == 0
client.login(user)
response = client.json.post(url, json.dumps(data))
assert response.status_code == 201
assert len(mail.outbox) == 1
assert project.wiki_pages.all().count() == 1
def test_create_wiki_link_of_inexistent_wiki_page_without_permissions(client):
project = f.ProjectFactory.create()
role = f.RoleFactory.create(project=project, permissions=['view_wiki_pages', 'view_wiki_link',
'add_wiki_link'])
f.MembershipFactory.create(project=project, user=project.owner, role=role)
project.owner.notify_policies.filter(project=project).update(notify_level=NotifyLevel.all)
user = f.UserFactory.create()
f.MembershipFactory.create(project=project, user=user, role=role)
mail.outbox = []
url = reverse("wiki-links-list")
data = {
"title": "test",
"href": "test",
"project": project.pk,
}
assert project.wiki_pages.all().count() == 0
client.login(user)
response = client.json.post(url, json.dumps(data))
assert response.status_code == 201
assert len(mail.outbox) == 0
assert project.wiki_pages.all().count() == 0