Compare commits

...

7 Commits

9 changed files with 806 additions and 60 deletions

View File

@ -77,4 +77,25 @@ class UVCommentForm(forms.ModelForm):
class Meta:
model = UVComment
fields = ()
fields = (
"author",
"uv",
"grade_global",
"grade_utility",
"grade_interest",
"grade_teaching",
"grade_work_load",
"comment",
)
widgets = {
"comment": MarkdownInput,
"author": forms.HiddenInput,
"uv": forms.HiddenInput,
}
def __init__(self, author_id, uv_id, *args, **kwargs):
super(UVCommentForm, self).__init__(*args, **kwargs)
self.fields["author"].queryset = User.objects.filter(id=author_id).all()
self.fields["author"].initial = author_id
self.fields["uv"].queryset = UV.objects.filter(id=uv_id).all()
self.fields["uv"].initial = uv_id

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-06-15 15:00
# Generated by Django 1.11.20 on 2019-06-16 14:22
from __future__ import unicode_literals
from django.conf import settings
@ -176,7 +176,7 @@ class Migration(migrations.Migration):
"author",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="created_UVs",
related_name="uv_created",
to=settings.AUTH_USER_MODEL,
verbose_name="author",
),
@ -194,7 +194,85 @@ class Migration(migrations.Migration):
serialize=False,
verbose_name="ID",
),
)
),
("comment", models.TextField(verbose_name="comment")),
(
"grade_global",
models.IntegerField(
default=-1,
validators=[
django.core.validators.MinValueValidator(-1),
django.core.validators.MaxValueValidator(5),
],
verbose_name="global grade",
),
),
(
"grade_utility",
models.IntegerField(
default=-1,
validators=[
django.core.validators.MinValueValidator(-1),
django.core.validators.MaxValueValidator(5),
],
verbose_name="utility grade",
),
),
(
"grade_interest",
models.IntegerField(
default=-1,
validators=[
django.core.validators.MinValueValidator(-1),
django.core.validators.MaxValueValidator(5),
],
verbose_name="interest grade",
),
),
(
"grade_teaching",
models.IntegerField(
default=-1,
validators=[
django.core.validators.MinValueValidator(-1),
django.core.validators.MaxValueValidator(5),
],
verbose_name="teaching grade",
),
),
(
"grade_work_load",
models.IntegerField(
default=-1,
validators=[
django.core.validators.MinValueValidator(-1),
django.core.validators.MaxValueValidator(5),
],
verbose_name="work load grade",
),
),
(
"publish_date",
models.DateField(auto_now=True, verbose_name="publish date"),
),
(
"author",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="uv_comments",
to=settings.AUTH_USER_MODEL,
verbose_name="author",
),
),
(
"uv",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="comments",
to="pedagogy.UV",
verbose_name="uv",
),
),
],
),
migrations.CreateModel(
@ -211,4 +289,64 @@ class Migration(migrations.Migration):
)
],
),
migrations.CreateModel(
name="UVResult",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"grade",
models.CharField(
choices=[
("A", "A"),
("B", "B"),
("C", "C"),
("D", "D"),
("E", "E"),
("FX", "FX"),
("F", "F"),
("ABS", "Abs"),
],
default="A",
max_length=10,
verbose_name="grade",
),
),
(
"semester",
models.CharField(
max_length=5,
validators=[
django.core.validators.RegexValidator("[AP][0-9]{3}")
],
verbose_name="semester",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="uv_results",
to=settings.AUTH_USER_MODEL,
verbose_name="user",
),
),
(
"uv",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="results",
to="pedagogy.UV",
verbose_name="uv",
),
),
],
),
]

View File

@ -67,7 +67,7 @@ class UV(models.Model):
)
author = models.ForeignKey(
User,
related_name="created_UVs",
related_name="uv_created",
verbose_name=_("author"),
null=False,
blank=False,
@ -152,7 +152,86 @@ class UVComment(models.Model):
A comment about an UV
"""
pass
def is_owned_by(self, user):
"""
Is owned by a pedagogy admin, a superuser or the author himself
"""
return self.author == user or user.is_owner(self.uv)
def __str__(self):
return "%s - %s" % (self.uv, self.author)
author = models.ForeignKey(
User,
related_name="uv_comments",
verbose_name=_("author"),
null=False,
blank=False,
)
uv = models.ForeignKey(UV, related_name="comments", verbose_name=_("uv"))
comment = models.TextField(_("comment"))
grade_global = models.IntegerField(
_("global grade"),
validators=[validators.MinValueValidator(-1), validators.MaxValueValidator(5)],
blank=False,
null=False,
default=-1,
)
grade_utility = models.IntegerField(
_("utility grade"),
validators=[validators.MinValueValidator(-1), validators.MaxValueValidator(5)],
blank=False,
null=False,
default=-1,
)
grade_interest = models.IntegerField(
_("interest grade"),
validators=[validators.MinValueValidator(-1), validators.MaxValueValidator(5)],
blank=False,
null=False,
default=-1,
)
grade_teaching = models.IntegerField(
_("teaching grade"),
validators=[validators.MinValueValidator(-1), validators.MaxValueValidator(5)],
blank=False,
null=False,
default=-1,
)
grade_work_load = models.IntegerField(
_("work load grade"),
validators=[validators.MinValueValidator(-1), validators.MaxValueValidator(5)],
blank=False,
null=False,
default=-1,
)
publish_date = models.DateField(_("publish date"), auto_now=True)
class UVResult(models.Model):
"""
Results got to an UV
Views will be implemented after the first release
Will list every UV done by an user
Linked to user
uv
Contains a grade settings.SITH_PEDAGOGY_UV_RESULT_GRADE
a semester (P/A)20xx
"""
uv = models.ForeignKey(UV, related_name="results", verbose_name=_("uv"))
user = models.ForeignKey(User, related_name="uv_results", verbose_name=("user"))
grade = models.CharField(
_("grade"),
max_length=10,
choices=settings.SITH_PEDAGOGY_UV_RESULT_GRADE,
default=settings.SITH_PEDAGOGY_UV_RESULT_GRADE[0][0],
)
semester = models.CharField(
_("semester"),
max_length=5,
validators=[validators.RegexValidator("[AP][0-9]{3}")],
)
class UVCommentReport(models.Model):

View File

@ -13,7 +13,7 @@
{% endif %}
{% for uv in object_list %}
<p>
{{ uv.code }}
<a href="{{ url('pedagogy:uv_detail', uv_id=uv.id) }}">{{ uv.code }}</a>
{% if user.is_owner(uv) -%}
<a href="{{ url('pedagogy:uv_update', uv_id=uv.id) }}">{% trans %}Edit{% endtrans %}</a>
<a href="{{ url('pedagogy:uv_delete', uv_id=uv.id) }}">{% trans %}Delete{% endtrans %}</a>

View File

@ -5,9 +5,35 @@
{% endblock %}
{% block content %}
<p><a href="{{ url('pedagogy:guide') }}">{% trans %}Back{% endtrans %}</a></p>
<h1>{{ object.code }} - {{ object.title }}</h1>
<p>{{ object.objectives|markdown }}</p>
<p>{{ object.program|markdown }}</p>
<p>{{ object.skills|markdown }}</p>
<p>{{ object.key_concepts|markdown }}</p>
{% if object.comments.exists() %}
<h2>{% trans %}Comments{% endtrans %}</h2>
{% for comment in object.comments.all() %}
<p>{{ comment.grade_global }}</p>
<p>{{ comment.grade_utility }}</p>
<p>{{ comment.grade_interest }}</p>
<p>{{ comment.grade_teaching }}</p>
<p>{{ comment.grade_work_load }}</p>
<p>{{ comment.comment }}</p>
<p>{% trans %}Published: {% endtrans %}{{ comment.publish_date }}</p>
<p>{% trans %}Author: {% endtrans %}{{ comment.author }}</p>
{% if user.is_owner(comment) %}
<p><a href="{{ url('pedagogy:comment_update', comment_id=comment.id) }}">{% trans %}Edit{% endtrans %}</a></p>
<p><a href="{{ url('pedagogy:comment_delete', comment_id=comment.id) }}">{% trans %}Delete{% endtrans %}</a></p>
{% endif %}
{% endfor %}
{% endif %}
<h2>{% trans %}Leave comment{% endtrans %}</h2>
<form action="{{ url('pedagogy:uv_detail', uv_id=object.id) }}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p() }}
<p><input type="submit" value="{% trans %}Comment{% endtrans %}" /></p>
</form>
{% endblock %}

View File

@ -28,7 +28,51 @@ from django.core.management import call_command
from core.models import User
from pedagogy.models import UV
from pedagogy.models import UV, UVComment
def create_uv_template(user_id, code="IFC1", exclude_list=[]):
"""
Factory to help UV creation/update in post requests
"""
uv = {
"code": code,
"author": user_id,
"credit_type": "TM",
"semester": "SPRING",
"language": "FR",
"credits": 3,
"hours_CM": 10,
"hours_TD": 28,
"hours_TP": 0,
"hours_THE": 37,
"hours_TE": 0,
"manager": "Gilles BERTRAND",
"title": "Algorithmique et programmation : niveau I, initiés - partie I",
"objectives": """* Introduction à l'algorithmique et à la programmation pour initiés.
* Pratiques et développement en langage C.""",
"program": """* Découverte des outils élémentaires utilisés pour écrire, compiler et exécuter un programme écrit en langage C
* Règles de programmation : normes en cours, règles de présentation du code, commentaires
* Initiation à l'algorithmique et découverte des bases du langage C :
* les conditions
* les boucles
* les types de données
* les tableaux à une dimension
* manipulations des chaînes de caractères
* les fonctions et procédures""",
"skills": "* D'écrire un algorithme et de l'implémenter en C",
"key_concepts": """* Algorithme
* Variables scalaires et vectorielles
* Structures alternatives, répétitives
* Fonctions, procédures
* Chaînes de caractères""",
}
for excluded in exclude_list:
uv.pop(excluded)
return uv
# UV class tests
class UVCreation(TestCase):
@ -43,48 +87,10 @@ class UVCreation(TestCase):
self.sli = User.objects.filter(username="sli").first()
self.guy = User.objects.filter(username="guy").first()
@staticmethod
def create_uv_template(user_id, code="IFC1", exclude_list=[]):
uv = {
"code": code,
"author": user_id,
"credit_type": "TM",
"semester": "SPRING",
"language": "FR",
"credits": 3,
"hours_CM": 10,
"hours_TD": 28,
"hours_TP": 0,
"hours_THE": 37,
"hours_TE": 0,
"manager": "Gilles BERTRAND",
"title": "Algorithmique et programmation : niveau I, initiés - partie I",
"objectives": """* Introduction à l'algorithmique et à la programmation pour initiés.
* Pratiques et développement en langage C.""",
"program": """* Découverte des outils élémentaires utilisés pour écrire, compiler et exécuter un programme écrit en langage C
* Règles de programmation : normes en cours, règles de présentation du code, commentaires
* Initiation à l'algorithmique et découverte des bases du langage C :
* les conditions
* les boucles
* les types de données
* les tableaux à une dimension
* manipulations des chaînes de caractères
* les fonctions et procédures""",
"skills": "* D'écrire un algorithme et de l'implémenter en C",
"key_concepts": """* Algorithme
* Variables scalaires et vectorielles
* Structures alternatives, répétitives
* Fonctions, procédures
* Chaînes de caractères""",
}
for excluded in exclude_list:
uv.pop(excluded)
return uv
def test_create_uv_admin_success(self):
self.client.login(username="root", password="plop")
response = self.client.post(
reverse("pedagogy:uv_create"), self.create_uv_template(self.bibou.id)
reverse("pedagogy:uv_create"), create_uv_template(self.bibou.id)
)
self.assertEquals(response.status_code, 302)
self.assertTrue(UV.objects.filter(code="IFC1").exists())
@ -92,7 +98,7 @@ class UVCreation(TestCase):
def test_create_uv_pedagogy_admin_success(self):
self.client.login(username="tutu", password="plop")
response = self.client.post(
reverse("pedagogy:uv_create"), self.create_uv_template(self.tutu.id)
reverse("pedagogy:uv_create"), create_uv_template(self.tutu.id)
)
self.assertEquals(response.status_code, 302)
self.assertTrue(UV.objects.filter(code="IFC1").exists())
@ -100,21 +106,21 @@ class UVCreation(TestCase):
def test_create_uv_unauthorized_fail(self):
# Test with anonymous user
response = self.client.post(
reverse("pedagogy:uv_create"), self.create_uv_template(0)
reverse("pedagogy:uv_create"), create_uv_template(0)
)
self.assertEquals(response.status_code, 403)
# Test with subscribed user
self.client.login(username="sli", password="plop")
response = self.client.post(
reverse("pedagogy:uv_create"), self.create_uv_template(self.sli.id)
reverse("pedagogy:uv_create"), create_uv_template(self.sli.id)
)
self.assertEquals(response.status_code, 403)
# Test with non subscribed user
self.client.login(username="guy", password="plop")
response = self.client.post(
reverse("pedagogy:uv_create"), self.create_uv_template(self.guy.id)
reverse("pedagogy:uv_create"), create_uv_template(self.guy.id)
)
self.assertEquals(response.status_code, 403)
@ -126,7 +132,7 @@ class UVCreation(TestCase):
# Test with wrong user id (if someone cheats on the hidden input)
response = self.client.post(
reverse("pedagogy:uv_create"), self.create_uv_template(self.bibou.id)
reverse("pedagogy:uv_create"), create_uv_template(self.bibou.id)
)
self.assertNotEquals(response.status_code, 302)
self.assertEquals(response.status_code, 200)
@ -134,10 +140,428 @@ class UVCreation(TestCase):
# Remove a required field
response = self.client.post(
reverse("pedagogy:uv_create"),
self.create_uv_template(self.tutu.id, exclude_list=["title"]),
create_uv_template(self.tutu.id, exclude_list=["title"]),
)
self.assertNotEquals(response.status_code, 302)
self.assertEquals(response.status_code, 200)
# Check that the UV hase never been created
self.assertFalse(UV.objects.filter(code="IFC1").exists())
class UVListTest(TestCase):
"""
Test guide display rights
"""
def setUp(self):
call_command("populate")
def test_uv_list_display_success(self):
# Display for root
self.client.login(username="root", password="plop")
response = self.client.get(reverse("pedagogy:guide"))
self.assertContains(response, text="PA00")
# Display for pedagogy admin
self.client.login(username="tutu", password="plop")
response = self.client.get(reverse("pedagogy:guide"))
self.assertContains(response, text="PA00")
# Display for simple subscriber
self.client.login(username="sli", password="plop")
response = self.client.get(reverse("pedagogy:guide"))
self.assertContains(response, text="PA00")
def test_uv_list_display_fail(self):
# Don't display for anonymous user
response = self.client.get(reverse("pedagogy:guide"))
self.assertEquals(response.status_code, 403)
# Don't display for none subscribed users
self.client.login(username="guy", password="plop")
response = self.client.get(reverse("pedagogy:guide"))
self.assertEquals(response.status_code, 403)
class UVDeleteTest(TestCase):
"""
Test UV deletion rights
"""
def setUp(self):
call_command("populate")
def test_uv_delete_root_success(self):
self.client.login(username="root", password="plop")
self.client.post(
reverse(
"pedagogy:uv_delete", kwargs={"uv_id": UV.objects.get(code="PA00").id}
)
)
self.assertFalse(UV.objects.filter(code="PA00").exists())
def test_uv_delete_pedagogy_admin_success(self):
self.client.login(username="tutu", password="plop")
self.client.post(
reverse(
"pedagogy:uv_delete", kwargs={"uv_id": UV.objects.get(code="PA00").id}
)
)
self.assertFalse(UV.objects.filter(code="PA00").exists())
def test_uv_delete_pedagogy_unauthorized_fail(self):
# Anonymous user
response = self.client.post(
reverse(
"pedagogy:uv_delete", kwargs={"uv_id": UV.objects.get(code="PA00").id}
)
)
self.assertEquals(response.status_code, 403)
# Not subscribed user
self.client.login(username="guy", password="plop")
response = self.client.post(
reverse(
"pedagogy:uv_delete", kwargs={"uv_id": UV.objects.get(code="PA00").id}
)
)
self.assertEquals(response.status_code, 403)
# Simply subscribed user
self.client.login(username="sli", password="plop")
response = self.client.post(
reverse(
"pedagogy:uv_delete", kwargs={"uv_id": UV.objects.get(code="PA00").id}
)
)
self.assertEquals(response.status_code, 403)
# Check that the UV still exists
self.assertTrue(UV.objects.filter(code="PA00").exists())
class UVUpdateTest(TestCase):
"""
Test UV update rights
"""
def setUp(self):
call_command("populate")
self.bibou = User.objects.filter(username="root").first()
self.tutu = User.objects.filter(username="tutu").first()
self.sli = User.objects.filter(username="sli").first()
self.guy = User.objects.filter(username="guy").first()
def test_uv_update_root_success(self):
self.client.login(username="root", password="plop")
self.client.post(
reverse(
"pedagogy:uv_update", kwargs={"uv_id": UV.objects.get(code="PA00").id}
),
create_uv_template(self.bibou.id, code="PA00"),
)
self.assertEquals(UV.objects.get(code="PA00").credit_type, "TM")
def test_uv_update_pedagogy_admin_success(self):
self.client.login(username="tutu", password="plop")
self.client.post(
reverse(
"pedagogy:uv_update", kwargs={"uv_id": UV.objects.get(code="PA00").id}
),
create_uv_template(self.tutu.id, code="PA00"),
)
self.assertEquals(UV.objects.get(code="PA00").credit_type, "TM")
def test_uv_update_pedagogy_unauthorized_fail(self):
# Anonymous user
response = self.client.post(
reverse(
"pedagogy:uv_update", kwargs={"uv_id": UV.objects.get(code="PA00").id}
),
create_uv_template(0, code="PA00"),
)
self.assertEquals(response.status_code, 403)
# Not subscribed user
self.client.login(username="guy", password="plop")
response = self.client.post(
reverse(
"pedagogy:uv_update", kwargs={"uv_id": UV.objects.get(code="PA00").id}
),
create_uv_template(self.guy.id, code="PA00"),
)
self.assertEquals(response.status_code, 403)
# Simply subscribed user
self.client.login(username="sli", password="plop")
response = self.client.post(
reverse(
"pedagogy:uv_update", kwargs={"uv_id": UV.objects.get(code="PA00").id}
),
create_uv_template(self.sli.id, code="PA00"),
)
self.assertEquals(response.status_code, 403)
# Check that the UV has not changed
self.assertEquals(UV.objects.get(code="PA00").credit_type, "OM")
# UVComment class tests
def create_uv_comment_template(user_id, uv_code="PA00", exclude_list=[]):
"""
Factory to help UVComment creation/update in post requests
"""
comment = {
"author": user_id,
"uv": UV.objects.get(code=uv_code).id,
"grade_global": 5,
"grade_utility": 5,
"grade_interest": 5,
"grade_teaching": -1,
"grade_work_load": 3,
"comment": "Superbe UV qui fait vivre la vie associative de l'école",
}
for excluded in exclude_list:
comment.pop(excluded)
return comment
class UVCommentCreationAndDisplay(TestCase):
"""
Test UVComment creation and it's display
Display and creation are the same view
"""
def setUp(self):
call_command("populate")
self.bibou = User.objects.filter(username="root").first()
self.tutu = User.objects.filter(username="tutu").first()
self.sli = User.objects.filter(username="sli").first()
self.guy = User.objects.filter(username="guy").first()
self.uv = UV.objects.get(code="PA00")
def test_create_uv_comment_admin_success(self):
self.client.login(username="root", password="plop")
response = self.client.post(
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id}),
create_uv_comment_template(self.bibou.id),
)
self.assertEquals(response.status_code, 302)
response = self.client.get(
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id})
)
self.assertContains(response, text="Superbe UV")
def test_create_uv_comment_pedagogy_admin_success(self):
self.client.login(username="tutu", password="plop")
response = self.client.post(
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id}),
create_uv_comment_template(self.tutu.id),
)
self.assertEquals(response.status_code, 302)
response = self.client.get(
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id})
)
self.assertContains(response, text="Superbe UV")
def test_create_uv_comment_subscriber_success(self):
self.client.login(username="sli", password="plop")
response = self.client.post(
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id}),
create_uv_comment_template(self.sli.id),
)
self.assertEquals(response.status_code, 302)
response = self.client.get(
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id})
)
self.assertContains(response, text="Superbe UV")
def test_create_uv_comment_unauthorized_fail(self):
# Test with anonymous user
response = self.client.post(
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id}),
create_uv_comment_template(0),
)
self.assertEquals(response.status_code, 403)
# Test with non subscribed user
self.client.login(username="guy", password="plop")
response = self.client.post(
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id}),
create_uv_comment_template(self.guy.id),
)
self.assertEquals(response.status_code, 403)
# Check that the comment has never been created
self.client.login(username="root", password="plop")
response = self.client.get(
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id})
)
self.assertNotContains(response, text="Superbe UV")
def test_create_uv_comment_bad_form_fail(self):
self.client.login(username="root", password="plop")
response = self.client.post(
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id}),
create_uv_comment_template(self.bibou.id, exclude_list=["grade_global"]),
)
self.assertEquals(response.status_code, 200)
response = self.client.get(
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id})
)
self.assertNotContains(response, text="Superbe UV")
class UVCommentDeleteTest(TestCase):
"""
Test UVComment deletion rights
"""
def setUp(self):
call_command("populate")
comment_kwargs = create_uv_comment_template(
User.objects.get(username="krophil").id
)
comment_kwargs["author"] = User.objects.get(id=comment_kwargs["author"])
comment_kwargs["uv"] = UV.objects.get(id=comment_kwargs["uv"])
self.comment = UVComment(**comment_kwargs)
self.comment.save()
def test_uv_comment_delete_root_success(self):
self.client.login(username="root", password="plop")
self.client.post(
reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
)
self.assertFalse(UVComment.objects.filter(id=self.comment.id).exists())
def test_uv_comment_delete_pedagogy_admin_success(self):
self.client.login(username="tutu", password="plop")
self.client.post(
reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
)
self.assertFalse(UVComment.objects.filter(id=self.comment.id).exists())
def test_uv_comment_delete_author_success(self):
self.client.login(username="krophil", password="plop")
self.client.post(
reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
)
self.assertFalse(UVComment.objects.filter(id=self.comment.id).exists())
def test_uv_comment_delete_unauthorized_fail(self):
# Anonymous user
response = self.client.post(
reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
)
self.assertEquals(response.status_code, 403)
# Unsbscribed user
self.client.login(username="guy", password="plop")
response = self.client.post(
reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
)
self.assertEquals(response.status_code, 403)
# Subscribed user (not author of the comment)
self.client.login(username="sli", password="plop")
response = self.client.post(
reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
)
self.assertEquals(response.status_code, 403)
# Check that the comment still exists
self.assertTrue(UVComment.objects.filter(id=self.comment.id).exists())
class UVCommentUpdateTest(TestCase):
"""
Test UVComment update rights
"""
def setUp(self):
call_command("populate")
self.krophil = User.objects.get(username="krophil")
# Prepare a comment
comment_kwargs = create_uv_comment_template(self.krophil.id)
comment_kwargs["author"] = self.krophil
comment_kwargs["uv"] = UV.objects.get(id=comment_kwargs["uv"])
self.comment = UVComment(**comment_kwargs)
self.comment.save()
# Prepare edit of this comment for post requests
self.comment_edit = create_uv_comment_template(self.krophil.id)
self.comment_edit["comment"] = "Edited"
def test_uv_comment_update_root_success(self):
self.client.login(username="root", password="plop")
response = self.client.post(
reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id}),
self.comment_edit,
)
self.assertEquals(response.status_code, 302)
self.comment.refresh_from_db()
self.assertEquals(self.comment.comment, self.comment_edit["comment"])
def test_uv_comment_update_pedagogy_admin_success(self):
self.client.login(username="tutu", password="plop")
response = self.client.post(
reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id}),
self.comment_edit,
)
self.assertEquals(response.status_code, 302)
self.comment.refresh_from_db()
self.assertEquals(self.comment.comment, self.comment_edit["comment"])
def test_uv_comment_update_author_success(self):
self.client.login(username="krophil", password="plop")
response = self.client.post(
reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id}),
self.comment_edit,
)
self.assertEquals(response.status_code, 302)
self.comment.refresh_from_db()
self.assertEquals(self.comment.comment, self.comment_edit["comment"])
def test_uv_comment_update_unauthorized_fail(self):
# Anonymous user
response = self.client.post(
reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id}),
self.comment_edit,
)
self.assertEquals(response.status_code, 403)
# Unsbscribed user
response = self.client.post(
reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id}),
self.comment_edit,
)
self.assertEquals(response.status_code, 403)
# Subscribed user (not author of the comment)
response = self.client.post(
reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id}),
self.comment_edit,
)
self.assertEquals(response.status_code, 403)
# Check that the comment hasn't change
self.comment.refresh_from_db()
self.assertNotEquals(self.comment.comment, self.comment_edit["comment"])
def test_uv_comment_update_original_author_does_not_change(self):
self.client.login(username="root", password="plop")
self.comment_edit["author"] = User.objects.get(username="root").id
response = self.client.post(
reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id}),
self.comment_edit,
)
self.assertEquals(response.status_code, 200)
self.assertEquals(self.comment.author, self.krophil)

View File

@ -31,9 +31,14 @@ urlpatterns = [
url(r"^$", UVListView.as_view(), name="guide"),
url(r"^uv/(?P<uv_id>[0-9]+)$", UVDetailFormView.as_view(), name="uv_detail"),
url(
r"^comment/(?P<comment_id>[0-9]+)$",
UVCommentDetailView.as_view(),
name="comment_detail",
r"^comment/(?P<comment_id>[0-9]+)/edit$",
UVCommentUpdateView.as_view(),
name="comment_update",
),
url(
r"^comment/(?P<comment_id>[0-9]+)/delete$",
UVCommentDeleteView.as_view(),
name="comment_delete",
),
url(
r"^comment/(?P<comment_id>[0-9]+)/report$",

View File

@ -42,7 +42,7 @@ from core.views import (
)
from pedagogy.forms import UVForm, UVCommentForm
from pedagogy.models import UV
from pedagogy.models import UV, UVComment
# Some mixins
@ -82,13 +82,55 @@ class UVDetailFormView(CanViewMixin, CanCreateUVFunctionMixin, DetailFormView):
template_name = "pedagogy/uv_detail.jinja"
form_class = UVCommentForm
def get_form_kwargs(self):
kwargs = super(UVDetailFormView, self).get_form_kwargs()
kwargs["author_id"] = self.request.user.id
kwargs["uv_id"] = self.get_object().id
return kwargs
class UVCommentDetailView(DetailView):
def form_valid(self, form):
form.save()
return super(UVDetailFormView, self).form_valid(form)
def get_success_url(self):
return reverse_lazy(
"pedagogy:uv_detail", kwargs={"uv_id": self.get_object().id}
)
class UVCommentUpdateView(CanEditPropMixin, UpdateView):
"""
Display a specified UVComment (for easy sharing of the comment)
Allow edit of a given comment
"""
pass
model = UVComment
form_class = UVCommentForm
pk_url_kwarg = "comment_id"
template_name = "core/edit.jinja"
def get_form_kwargs(self):
kwargs = super(UVCommentUpdateView, self).get_form_kwargs()
obj = self.get_object()
kwargs["author_id"] = obj.author.id
kwargs["uv_id"] = obj.uv.id
return kwargs
def get_success_url(self):
return reverse_lazy("pedagogy:uv_detail", kwargs={"uv_id": self.object.uv.id})
class UVCommentDeleteView(CanEditPropMixin, DeleteView):
"""
Allow delete of a given comment
"""
model = UVComment
pk_url_kwarg = "comment_id"
template_name = "core/delete_confirm.jinja"
def get_success_url(self):
return reverse_lazy("pedagogy:uv_detail", kwargs={"uv_id": self.object.uv.id})
class UVListView(CanViewMixin, CanCreateUVFunctionMixin, ListView):

View File

@ -431,6 +431,17 @@ SITH_PEDAGOGY_UV_LANGUAGE = [
("SP", _("Spanich")),
]
SITH_PEDAGOGY_UV_RESULT_GRADE = [
("A", _("A")),
("B", _("B")),
("C", _("C")),
("D", _("D")),
("E", _("E")),
("FX", _("FX")),
("F", _("F")),
("ABS", _("Abs")),
]
SITH_ECOCUP_CONS = 1152
SITH_ECOCUP_DECO = 1151