clean
This commit is contained in:
parent
8fa2341ff6
commit
878a139075
|
@ -1,15 +1,16 @@
|
|||
from functools import wraps
|
||||
|
||||
from django.core.exceptions import PermissionDenied
|
||||
|
||||
from accounts.utils import is_orga, is_staff
|
||||
|
||||
|
||||
def orga_required(func):
|
||||
def orga_required(view_func):
|
||||
def _is_orga(request, *args, **kwargs):
|
||||
if is_orga(request, request.user):
|
||||
return view_func(request, *args, **kwargs)
|
||||
raise PermissionDenied
|
||||
return wraps(func)(_is_orga)
|
||||
return wraps(view_func)(_is_orga)
|
||||
|
||||
|
||||
def staff_required(view_func):
|
||||
|
|
|
@ -1,26 +1,28 @@
|
|||
from django import forms
|
||||
from django.contrib.auth.models import User
|
||||
from django.forms.models import modelform_factory
|
||||
from django import forms
|
||||
|
||||
from django_select2.forms import Select2Widget, Select2MultipleWidget
|
||||
from django_select2.forms import Select2Widget
|
||||
|
||||
from .models import Participation, Profile
|
||||
|
||||
__all__ = ['UserForm', 'ProfileForm', 'ProfileOrgaForm', 'ParticipationOrgaForm']
|
||||
|
||||
|
||||
UserForm = modelform_factory(User, fields=['first_name', 'last_name', 'email', 'username'])
|
||||
|
||||
ProfileForm = modelform_factory(Profile, fields=['biography'])
|
||||
|
||||
ParticipationForm = modelform_factory(Participation, fields=['transport', 'connector', 'sound', 'videotaped', 'video_licence', 'constraints'],
|
||||
widgets={'transport': forms.CheckboxSelectMultiple(), 'connector': forms.CheckboxSelectMultiple()})
|
||||
ParticipationForm = modelform_factory(Participation, fields=['transport', 'connector', 'sound', 'videotaped',
|
||||
'video_licence', 'constraints'],
|
||||
widgets={'transport': forms.CheckboxSelectMultiple(),
|
||||
'connector': forms.CheckboxSelectMultiple()})
|
||||
|
||||
ProfileOrgaForm = modelform_factory(Profile, fields=['biography', 'notes'])
|
||||
|
||||
ParticipationOrgaForm = modelform_factory(Participation,
|
||||
fields=['transport', 'connector', 'sound', 'videotaped', 'video_licence', 'constraints', 'orga'],
|
||||
widgets={'transport': forms.CheckboxSelectMultiple(), 'connector': forms.CheckboxSelectMultiple()})
|
||||
fields=['transport', 'connector', 'sound', 'videotaped', 'video_licence',
|
||||
'constraints', 'orga'],
|
||||
widgets={'transport': forms.CheckboxSelectMultiple(),
|
||||
'connector': forms.CheckboxSelectMultiple()})
|
||||
|
||||
|
||||
class ParticipationField(forms.ModelChoiceField):
|
||||
def label_from_instance(self, obj):
|
||||
|
@ -29,4 +31,5 @@ class ParticipationField(forms.ModelChoiceField):
|
|||
|
||||
class NewParticipationForm(forms.Form):
|
||||
|
||||
participant = ParticipationField(User.objects.all(), widget=Select2Widget(), label='Add participant from existing account')
|
||||
participant = ParticipationField(User.objects.all(), widget=Select2Widget(),
|
||||
label='Add participant from existing account')
|
||||
|
|
|
@ -9,8 +9,6 @@ from ponyconf.utils import PonyConfModel, enum_to_choices
|
|||
|
||||
from .utils import generate_user_uid
|
||||
|
||||
__all__ = ['Profile']
|
||||
|
||||
|
||||
class Profile(PonyConfModel):
|
||||
|
||||
|
@ -46,8 +44,6 @@ class Connector(Option):
|
|||
|
||||
class Participation(PonyConfModel):
|
||||
|
||||
TRANSPORTS = IntEnum('Transport', 'train plane others')
|
||||
CONNECTORS = IntEnum('Connector', 'VGA HDMI miniDP')
|
||||
LICENCES = IntEnum('Video licence', 'CC-Zero CC-BY CC-BY-SA CC-BY-ND CC-BY-NC CC-BY-NC-SA CC-BY-NC-ND')
|
||||
|
||||
site = models.ForeignKey(Site, on_delete=models.CASCADE)
|
||||
|
@ -78,8 +74,3 @@ class Participation(PonyConfModel):
|
|||
|
||||
def is_staff(self):
|
||||
return self.is_orga() or self.user.topic_set.exists()
|
||||
|
||||
@property
|
||||
def reviewed_topics(self):
|
||||
from proposals.models import Topic
|
||||
return Topic.objects.filter(reviewers=self.user).all()
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.contrib.sites.shortcuts import get_current_site
|
|||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
|
||||
from .models import Participation, Profile, Transport, Connector
|
||||
from .models import Connector, Participation, Profile, Transport
|
||||
|
||||
|
||||
def create_default_options(sender, **kwargs):
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<td><a href="{{ participation.get_absolute_url }}">{{ participation.user.username }}</a></td>
|
||||
<td>{{ participation.user.get_full_name }}</td>
|
||||
<td>{{ participation.is_orga|yesno:"✔,✘" }}</td>
|
||||
<td>{% for topic in participation.reviewed_topics %}{{ topic.get_link }}{% if not forloop.last %},
|
||||
<td>{% for topic in participation.user.topic_set.all %}{{ topic.get_link }}{% if not forloop.last %},
|
||||
{% endif %}{% endfor %}</td>
|
||||
<td>
|
||||
<a href="{% url 'conversation' participation.user.username %}" data-toggle="tooltip" data-placement="bottom"
|
||||
|
|
|
@ -32,10 +32,12 @@ class AccountTests(TestCase):
|
|||
self.client.login(username='b', password='b')
|
||||
|
||||
# He tries with an invalid address
|
||||
self.client.post(reverse('profile'), {'email': 'bnewdomain.com', 'username': 'z', 'biography': 'tester', 'video_licence': 1})
|
||||
self.client.post(reverse('profile'), {'email': 'bnewdomain.com', 'username': 'z', 'biography': 'tester',
|
||||
'video_licence': 1})
|
||||
self.assertEqual(User.objects.filter(username='z').count(), 0)
|
||||
|
||||
self.client.post(reverse('profile'), {'email': 'b@newdomain.com', 'username': 'z', 'biography': 'tester', 'video_licence': 1})
|
||||
self.client.post(reverse('profile'), {'email': 'b@newdomain.com', 'username': 'z', 'biography': 'tester',
|
||||
'video_licence': 1})
|
||||
|
||||
user = User.objects.get(username='z')
|
||||
self.assertEqual(user.email, 'b@newdomain.com')
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.shortcuts import get_object_or_404, render, redirect
|
||||
from django.views.generic import ListView
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
|
||||
from registration.backends.default.views import RegistrationView
|
||||
|
||||
from .forms import ParticipationForm, ParticipationOrgaForm, ProfileForm, ProfileOrgaForm, UserForm, NewParticipationForm
|
||||
from .mixins import StaffRequiredMixin
|
||||
from .decorators import staff_required
|
||||
from .models import Participation, Profile
|
||||
from .forms import (NewParticipationForm, ParticipationForm,
|
||||
ParticipationOrgaForm, ProfileForm, ProfileOrgaForm, UserForm)
|
||||
from .models import Participation, Profile, User
|
||||
from .utils import can_edit_profile, is_orga
|
||||
from .models import User
|
||||
|
||||
RESET_PASSWORD_BUTTON = ('password_reset', 'warning', 'Reset your password')
|
||||
CHANGE_PASSWORD_BUTTON = ('password_change', 'warning', 'Change password')
|
||||
|
@ -30,7 +27,8 @@ def profile(request):
|
|||
|
||||
forms = [UserForm(request.POST or None, instance=request.user),
|
||||
ProfileForm(request.POST or None, instance=request.user.profile),
|
||||
ParticipationForm(request.POST or None, instance=Participation.objects.get(site=get_current_site(request), user=request.user))]
|
||||
ParticipationForm(request.POST or None, instance=Participation.objects.get(site=get_current_site(request),
|
||||
user=request.user))]
|
||||
|
||||
if request.method == 'POST':
|
||||
if all(form.is_valid() for form in forms):
|
||||
|
@ -72,10 +70,11 @@ def edit(request, username):
|
|||
if not can_edit_profile(request, profile):
|
||||
raise PermissionDenied()
|
||||
|
||||
participation_form_class = ParticipationOrgaForm if is_orga(request, request.user) else ParticipationForm
|
||||
participation_form = ParticipationOrgaForm if is_orga(request, request.user) else ParticipationForm
|
||||
forms = [UserForm(request.POST or None, instance=profile.user),
|
||||
ProfileOrgaForm(request.POST or None, instance=profile),
|
||||
participation_form_class(request.POST or None, instance=Participation.objects.get(site=get_current_site(request), user=profile.user))]
|
||||
participation_form(request.POST or None,
|
||||
instance=Participation.objects.get(site=get_current_site(request), user=profile.user))]
|
||||
|
||||
if request.method == 'POST':
|
||||
if all(form.is_valid() for form in forms):
|
||||
|
|
|
@ -2,5 +2,4 @@ from django.forms.models import modelform_factory
|
|||
|
||||
from .models import Message
|
||||
|
||||
MessageForm = modelform_factory(Message,
|
||||
fields=['content'])
|
||||
MessageForm = modelform_factory(Message, fields=['content'])
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# Get the value of REPLY_KEY from the django setting.
|
||||
|
||||
# Postfix users can set up an alias file with this content:
|
||||
# reply: "|/path/to/post-mail.sh mykey@https://example.org/conversations/recv/
|
||||
# don't forget to run postalias and to add the alias file to main.cf under alias_map.
|
||||
# reply: "|/path/to/post-mail.sh mykey@https://example.org/conversations/recv/
|
||||
# don't forget to run postalias and to add the alias file to main.cf under alias_map.
|
||||
|
||||
curl ${@#*\@} -F key=${@%\@*} -F "email=@-"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import requests
|
||||
|
||||
import requests
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: %s KEY@URL" % sys.argv[0])
|
||||
|
@ -11,7 +11,7 @@ if len(sys.argv) != 2:
|
|||
key, url = sys.argv[1].split('@')
|
||||
|
||||
email = sys.stdin.buffer.raw.read()
|
||||
sys.stdout.buffer.write(email) # DO NOT REMOVE
|
||||
sys.stdout.buffer.write(email) # DO NOT REMOVE
|
||||
|
||||
requests.post(
|
||||
url,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
from django.contrib.auth.models import User
|
||||
from django.db.models import Q
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
from django.db.models import Q
|
||||
|
||||
from accounts.models import Participation
|
||||
from proposals.models import Talk
|
||||
from proposals.signals import *
|
||||
from proposals.signals import talk_added, talk_edited
|
||||
|
||||
from .models import ConversationAboutTalk, ConversationWithParticipant, Message
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ from django.core.exceptions import PermissionDenied
|
|||
from django.core.urlresolvers import reverse
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
|
||||
from accounts.decorators import staff_required
|
||||
from accounts.models import Participation
|
||||
from accounts.decorators import orga_required, staff_required
|
||||
from proposals.models import Talk
|
||||
|
||||
from .forms import MessageForm
|
||||
|
@ -66,7 +66,8 @@ def talk_conversation(request, talk):
|
|||
@login_required
|
||||
def correspondents(request):
|
||||
|
||||
correspondent_list = Participation.objects.filter(site=get_current_site(request), conversation__subscribers=request.user)
|
||||
correspondent_list = Participation.objects.filter(site=get_current_site(request),
|
||||
conversation__subscribers=request.user)
|
||||
|
||||
return render(request, 'conversations/correspondents.html', {
|
||||
'correspondent_list': correspondent_list,
|
||||
|
|
|
@ -5,9 +5,6 @@ from django_select2.forms import Select2TagWidget
|
|||
|
||||
from proposals.models import Talk, Topic
|
||||
|
||||
__all__ = ['TalkForm', 'TopicCreateForm', 'TopicUpdateForm']
|
||||
|
||||
|
||||
TalkForm = modelform_factory(Talk, fields=['title', 'description', 'topics', 'event', 'speakers'],
|
||||
widgets={'topics': CheckboxSelectMultiple(), 'speakers': Select2TagWidget()})
|
||||
|
||||
|
|
|
@ -13,8 +13,6 @@ from ponyconf.utils import PonyConfModel, enum_to_choices
|
|||
|
||||
from .utils import query_sum
|
||||
|
||||
__all__ = ['Topic', 'Talk']
|
||||
|
||||
|
||||
class Topic(PonyConfModel):
|
||||
|
||||
|
@ -72,7 +70,7 @@ class Talk(PonyConfModel):
|
|||
class Vote(PonyConfModel):
|
||||
|
||||
talk = models.ForeignKey(Talk)
|
||||
user = models.ForeignKey(Participation)
|
||||
user = models.ForeignKey(User)
|
||||
vote = models.IntegerField(validators=[MinValueValidator(-2), MaxValueValidator(2)], default=0)
|
||||
|
||||
class Meta:
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
from django.dispatch import Signal, receiver
|
||||
from django.db.models.signals import m2m_changed
|
||||
from django.dispatch import Signal, receiver
|
||||
|
||||
|
||||
from .models import Talk, Topic
|
||||
from accounts.models import Participation
|
||||
|
||||
|
||||
__all__ = [ 'talk_added', 'talk_edited' ]
|
||||
|
||||
from .models import Talk, Topic
|
||||
|
||||
talk_added = Signal(providing_args=["sender", "instance", "author"])
|
||||
talk_edited = Signal(providing_args=["sender", "instance", "author"])
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.contrib.auth.models import User
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.test import TestCase
|
||||
from django.contrib.sites.models import Site
|
||||
|
||||
from accounts.models import Participation
|
||||
|
||||
|
@ -56,17 +56,17 @@ class ProposalsTests(TestCase):
|
|||
|
||||
# Talk.is_{editable,moderable}_by
|
||||
a, b, c = User.objects.all()
|
||||
self.assertTrue(talk.is_editable_by(c)) # c is superuser
|
||||
self.assertTrue(talk.is_moderable_by(c)) # c is superuser
|
||||
self.assertFalse(talk.is_editable_by(b)) # b is not speaker
|
||||
self.assertFalse(talk.is_moderable_by(b)) # b is not orga
|
||||
self.assertTrue(talk.is_editable_by(c)) # c is superuser
|
||||
self.assertTrue(talk.is_moderable_by(c)) # c is superuser
|
||||
self.assertFalse(talk.is_editable_by(b)) # b is not speaker
|
||||
self.assertFalse(talk.is_moderable_by(b)) # b is not orga
|
||||
self.client.login(username='a', password='a')
|
||||
self.client.post(reverse('edit-talk', kwargs={'talk': 'super-talk'}),
|
||||
{'title': 'mega talk', 'description': 'mega', 'event': 1, 'speakers': (a.pk, b.pk)})
|
||||
talk = Talk.objects.get(slug='super-talk')
|
||||
self.assertTrue(b in talk.speakers.all())
|
||||
self.assertTrue(talk.is_editable_by(b)) # b is speaker now
|
||||
self.assertFalse(talk.is_moderable_by(b)) # b is not orga
|
||||
self.assertTrue(talk.is_editable_by(b)) # b is speaker now
|
||||
self.assertFalse(talk.is_moderable_by(b)) # b is not orga
|
||||
|
||||
def test_topic_edition_permissions(self):
|
||||
# Only orga and superuser can edit topics
|
||||
|
@ -75,6 +75,6 @@ class ProposalsTests(TestCase):
|
|||
self.assertEqual(self.client.get(reverse('edit-topic', kwargs={'slug': 'topipo'})).status_code, 302)
|
||||
Participation.objects.filter(user__username='b').update(orga=True)
|
||||
self.assertEqual(self.client.get(reverse('edit-topic', kwargs={'slug': 'topipo'})).status_code, 200)
|
||||
self.client.login(username='c', password='c') # superuser
|
||||
self.client.login(username='c', password='c') # superuser
|
||||
self.assertEqual(self.client.get(reverse('edit-topic', kwargs={'slug': 'topipo'})).status_code, 200)
|
||||
self.assertEqual(self.client.get(reverse('list-topics')).status_code, 200)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.db.models import Q, Sum
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
|
||||
from accounts.models import Participation
|
||||
|
||||
|
@ -10,7 +10,6 @@ def query_sum(queryset, field):
|
|||
|
||||
|
||||
def allowed_talks(talks, request):
|
||||
participation = Participation.objects.get(site=get_current_site(request), user=request.user)
|
||||
if not participation.is_orga():
|
||||
talks = talks.filter(Q(topics__reviewers=participation.user) | Q(speakers=request.user) | Q(proposer=request.user))
|
||||
if not Participation.objects.get(site=get_current_site(request), user=request.user).is_orga():
|
||||
talks = talks.filter(Q(topics__reviewers=request.user) | Q(speakers=request.user) | Q(proposer=request.user))
|
||||
return talks.distinct()
|
||||
|
|
|
@ -8,17 +8,13 @@ from django.core.urlresolvers import reverse
|
|||
from django.db.models import Q
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.views.generic import CreateView, DetailView, ListView, UpdateView
|
||||
from django.http import JsonResponse
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
||||
from accounts.mixins import OrgaRequiredMixin, StaffRequiredMixin, SuperuserRequiredMixin
|
||||
from accounts.models import Participation
|
||||
from accounts.utils import is_orga
|
||||
from accounts.mixins import OrgaRequiredMixin, StaffRequiredMixin
|
||||
|
||||
from .forms import TalkForm, TopicCreateForm, TopicUpdateForm
|
||||
from .models import Talk, Topic, Vote
|
||||
from .signals import talk_added, talk_edited
|
||||
from .utils import allowed_talks
|
||||
from .signals import *
|
||||
|
||||
|
||||
def home(request):
|
||||
|
@ -27,9 +23,10 @@ def home(request):
|
|||
|
||||
@login_required
|
||||
def talk_list(request):
|
||||
talks = Talk.objects.filter(site=get_current_site(request))
|
||||
return render(request, 'proposals/talks.html', {
|
||||
'my_talks': Talk.objects.filter(site=get_current_site(request)).filter(Q(speakers=request.user) | Q(proposer=request.user)).distinct(),
|
||||
'other_talks': allowed_talks(Talk.objects.filter(site=get_current_site(request)).exclude(speakers=request.user, proposer=request.user), request)
|
||||
'my_talks': talks.filter(Q(speakers=request.user) | Q(proposer=request.user)).distinct(),
|
||||
'other_talks': allowed_talks(talks.exclude(Q(speakers=request.user) | Q(proposer=request.user)), request)
|
||||
})
|
||||
|
||||
|
||||
|
@ -74,19 +71,16 @@ class TalkDetail(LoginRequiredMixin, DetailView):
|
|||
return Talk.objects.filter(site=get_current_site(self.request)).all()
|
||||
|
||||
def get_context_data(self, **ctx):
|
||||
user = self.request.user
|
||||
if self.object.is_moderable_by(user):
|
||||
vote = Vote.objects.filter(talk=self.object, user=Participation.objects.get(site=get_current_site(self.request), user=user)).first()
|
||||
if self.object.is_moderable_by(self.request.user):
|
||||
vote = Vote.objects.filter(talk=self.object, user=self.request.user).first()
|
||||
ctx.update(edit_perm=True, moderate_perm=True, vote=vote,
|
||||
form_url=reverse('talk-conversation', kwargs={'talk': self.object.slug}))
|
||||
else:
|
||||
ctx['edit_perm'] = self.object.is_editable_by(user)
|
||||
ctx['edit_perm'] = self.object.is_editable_by(self.request.user)
|
||||
return super().get_context_data(**ctx)
|
||||
|
||||
|
||||
class TopicMixin(object):
|
||||
model = Topic
|
||||
|
||||
def get_queryset(self):
|
||||
return Topic.objects.filter(site=get_current_site(self.request)).all()
|
||||
|
||||
|
@ -96,10 +90,12 @@ class TopicList(LoginRequiredMixin, TopicMixin, ListView):
|
|||
|
||||
|
||||
class TopicCreate(OrgaRequiredMixin, TopicMixin, CreateView):
|
||||
model = Topic
|
||||
form_class = TopicCreateForm
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.site = get_current_site(self.request)
|
||||
return super(TopicCreate, self).form_valid(form)
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class TopicUpdate(OrgaRequiredMixin, TopicMixin, UpdateView):
|
||||
|
@ -111,18 +107,16 @@ class SpeakerList(StaffRequiredMixin, ListView):
|
|||
template_name = 'proposals/speaker_list.html'
|
||||
|
||||
def get_queryset(self):
|
||||
current_site = get_current_site(self.request)
|
||||
return User.objects.filter(talk__in=Talk.objects.filter(site=current_site)).all().distinct()
|
||||
site = get_current_site(self.request)
|
||||
return User.objects.filter(talk__in=Talk.objects.filter(site=site)).all().distinct()
|
||||
|
||||
|
||||
@login_required
|
||||
def vote(request, talk, score):
|
||||
current_site = get_current_site(request)
|
||||
talk = get_object_or_404(Talk, site=current_site, slug=talk)
|
||||
user = Participation.objects.get(site=current_site, user=request.user)
|
||||
talk = get_object_or_404(Talk, site=get_current_site(request), slug=talk)
|
||||
if not talk.is_moderable_by(request.user):
|
||||
raise PermissionDenied()
|
||||
vote, created = Vote.objects.get_or_create(talk=talk, user=user)
|
||||
vote, created = Vote.objects.get_or_create(talk=talk, user=request.user)
|
||||
vote.vote = int(score)
|
||||
vote.save()
|
||||
messages.success(request, "Vote successfully %s" % ('created' if created else 'updated'))
|
||||
|
|
Loading…
Reference in New Issue