Fix stuffs.
Maybe breaks other things, don't know, can't test mails for now.
This commit is contained in:
parent
f4b7eb629d
commit
b4490c8eee
|
@ -1,6 +1,6 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from accounts.models import Profile, Participation
|
||||
from accounts.models import Participation, Profile
|
||||
|
||||
admin.site.register(Profile) # FIXME extend user admin
|
||||
admin.site.register(Participation)
|
||||
|
|
|
@ -5,4 +5,4 @@ class AccountsConfig(AppConfig):
|
|||
name = 'accounts'
|
||||
|
||||
def ready(self):
|
||||
import accounts.signals
|
||||
import accounts.signals # noqa
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.7 on 2016-06-19 20:26
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('accounts', '0003_auto_20160615_2031'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='participation',
|
||||
name='review_topics',
|
||||
),
|
||||
]
|
|
@ -6,9 +6,9 @@ from django.contrib.sites.models import Site
|
|||
from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
|
||||
from .utils import enum_to_choices, generate_user_uid
|
||||
from proposals.models import Topic
|
||||
from ponyconf.utils import enum_to_choices
|
||||
|
||||
from .utils import generate_user_uid
|
||||
|
||||
__all__ = ['Profile']
|
||||
|
||||
|
@ -41,9 +41,6 @@ class Participation(models.Model):
|
|||
connector = models.IntegerField(choices=enum_to_choices(CONNECTORS), blank=True, null=True)
|
||||
constraints = models.TextField(blank=True)
|
||||
|
||||
# Participe as reviewer for theses topics
|
||||
review_topics = models.ManyToManyField(Topic, blank=True)
|
||||
|
||||
objects = models.Manager()
|
||||
on_site = CurrentSiteManager()
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
from django.contrib.auth.signals import user_logged_in, user_logged_out
|
||||
from django.dispatch import receiver
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.signals import user_logged_in, user_logged_out
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.dispatch import receiver
|
||||
|
||||
from .models import Participation
|
||||
|
||||
|
||||
@receiver(user_logged_in)
|
||||
def on_user_logged_in(sender, request, **kwargs):
|
||||
Participation.on_site.get_or_create(user=request.user, site=get_current_site(request))
|
||||
def on_user_logged_in(sender, request, user, **kwargs):
|
||||
Participation.on_site.get_or_create(user=user, site=get_current_site(request))
|
||||
messages.success(request, 'Welcome!', fail_silently=True) # FIXME
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% load bootstrap3 %}
|
||||
|
||||
{% block admintab %}active{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Participant: {{ participant }}</h1>
|
||||
</div>
|
||||
|
||||
<dl class="dl-horizontal">
|
||||
<dt>User</dt><dd>{{ participation.user.profil }}</dd>
|
||||
<dt>Arrival</dt><dd>{{ participation.arrival }}</dd>
|
||||
</dl>
|
||||
|
||||
<!-- TODO -->
|
||||
|
||||
{% endblock %}
|
|
@ -3,7 +3,9 @@ from django.contrib.sites.models import Site
|
|||
from django.core.urlresolvers import reverse
|
||||
from django.test import TestCase
|
||||
|
||||
from .models import Profile, Participation
|
||||
from ponyconf.utils import full_link
|
||||
|
||||
from .models import Participation, Profile
|
||||
|
||||
ROOT_URL = 'accounts'
|
||||
|
||||
|
@ -19,7 +21,7 @@ class AccountTests(TestCase):
|
|||
self.client.login(username='b', password='b')
|
||||
for model in [Profile, Participation]:
|
||||
item = model.objects.first()
|
||||
self.assertEqual(self.client.get(item.get_absolute_url()).status_code, 200)
|
||||
self.assertEqual(self.client.get(full_link(item)).status_code, 200)
|
||||
self.assertTrue(str(item))
|
||||
|
||||
def test_views(self):
|
||||
|
@ -40,3 +42,12 @@ class AccountTests(TestCase):
|
|||
self.assertEqual(user.email, 'b@newdomain.com')
|
||||
self.assertEqual(user.profile.biography, 'tester')
|
||||
self.client.logout()
|
||||
|
||||
def test_participant_views(self):
|
||||
self.assertEqual(self.client.get(reverse('participants')).status_code, 302)
|
||||
self.client.login(username='b', password='b')
|
||||
self.assertEqual(self.client.get(reverse('participants')).status_code, 403)
|
||||
b = User.objects.get(username='b')
|
||||
b.is_superuser = True
|
||||
b.save()
|
||||
self.assertEqual(self.client.get(reverse('participants')).status_code, 200)
|
||||
|
|
|
@ -8,5 +8,6 @@ urlpatterns = [
|
|||
url(r'^profile$', views.profile, name='profile'),
|
||||
url(r'^logout/$', auth_views.logout, {'next_page': settings.LOGOUT_REDIRECT_URL}, name='logout'),
|
||||
url(r'^admin/participants/$', views.participants, name='participants'),
|
||||
url(r'^admin/participant/(?P<username>[\w.@+-]+)$', views.participant, name='show-participation'),
|
||||
url(r'', include('django.contrib.auth.urls')),
|
||||
]
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
from django.utils.crypto import get_random_string
|
||||
|
||||
|
||||
def enum_to_choices(enum):
|
||||
return ((item.value, item.name) for item in list(enum))
|
||||
|
||||
def generate_user_uid():
|
||||
return get_random_string(length=12, allowed_chars='abcdefghijklmnopqrstuvwxyz0123456789')
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.shortcuts import render
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.contrib.auth.models import User
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
|
||||
from .forms import ProfileForm, UserForm
|
||||
from .models import Participation
|
||||
|
@ -35,3 +33,8 @@ def participants(request):
|
|||
participation_list = Participation.on_site.all()
|
||||
|
||||
return render(request, 'admin/participants.html', {'participation_list': participation_list})
|
||||
|
||||
|
||||
def participant(request, username):
|
||||
return render(request, 'admin/participant.html',
|
||||
{'participant': get_object_or_404(Participation, user__username=username)})
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from .models import ConversationWithParticipant, ConversationAboutTalk, Message
|
||||
|
||||
from .models import ConversationAboutTalk, ConversationWithParticipant, Message
|
||||
|
||||
admin.site.register(ConversationWithParticipant)
|
||||
admin.site.register(ConversationAboutTalk)
|
||||
|
|
|
@ -5,4 +5,4 @@ class ConversationsConfig(AppConfig):
|
|||
name = 'conversations'
|
||||
|
||||
def ready(self):
|
||||
import conversations.signals
|
||||
import conversations.signals # noqa
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
from django.shortcuts import get_object_or_404
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.views.decorators.http import require_http_methods
|
||||
from django.conf import settings
|
||||
from django.http import HttpResponse
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.http import Http404
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.mail import mail_admins
|
||||
|
||||
from .utils import hexdigest_sha256
|
||||
from .models import Message
|
||||
|
||||
import email
|
||||
import re
|
||||
from sys import version_info as python_version
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.http import Http404, HttpResponse
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.views.decorators.http import require_http_methods
|
||||
|
||||
from .models import Message
|
||||
from .utils import hexdigest_sha256
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@require_http_methods(["POST"])
|
||||
|
@ -22,14 +20,14 @@ def email_recv(request):
|
|||
|
||||
if not hasattr(settings, 'REPLY_EMAIL') \
|
||||
or not hasattr(settings, 'REPLY_KEY'):
|
||||
return HttpResponse(status=501) # Not Implemented
|
||||
return HttpResponse(status=501) # Not Implemented
|
||||
|
||||
key = request.POST.get('key')
|
||||
if key != settings.REPLY_KEY:
|
||||
raise PermissionDenied
|
||||
|
||||
if 'email' not in request.FILES:
|
||||
raise HttpResponse(status=400) # Bad Request
|
||||
raise HttpResponse(status=400) # Bad Request
|
||||
|
||||
msg = request.FILES['email']
|
||||
if python_version < (3,):
|
||||
|
@ -37,10 +35,6 @@ def email_recv(request):
|
|||
else:
|
||||
msg = email.message_from_bytes(msg.read())
|
||||
|
||||
mfrom = msg.get('From')
|
||||
mto = msg.get('To')
|
||||
subject = msg.get('Subject')
|
||||
|
||||
if msg.is_multipart():
|
||||
msgs = msg.get_payload()
|
||||
for m in msgs:
|
||||
|
@ -63,11 +57,11 @@ def email_recv(request):
|
|||
regexp = '^%s\+(?P<dest>[a-z0-9]{12})(?P<token>[a-z0-9]{60})(?P<key>[a-z0-9]{12})@%s$' % (name, domain)
|
||||
p = re.compile(regexp)
|
||||
m = None
|
||||
for _mto in map(lambda x: x.strip(), mto.split(',')):
|
||||
for _mto in map(lambda x: x.strip(), msg.get('To').split(',')):
|
||||
m = p.match(_mto)
|
||||
if m:
|
||||
break
|
||||
if not m: # no one matches
|
||||
if not m: # no one matches
|
||||
raise Http404
|
||||
|
||||
author = get_object_or_404(User, profile__email_token=m.group('dest'))
|
||||
|
|
|
@ -2,9 +2,5 @@ from django.forms.models import modelform_factory
|
|||
|
||||
from .models import Message
|
||||
|
||||
|
||||
MessageForm = modelform_factory(Message,
|
||||
fields=['content'])
|
||||
|
||||
|
||||
|
||||
fields=['content'])
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
|
||||
from .utils import generate_message_token, notify_by_email
|
||||
from accounts.models import Participation
|
||||
from proposals.models import Talk
|
||||
|
||||
from .utils import generate_message_token, notify_by_email
|
||||
|
||||
|
||||
class Message(models.Model):
|
||||
|
||||
|
@ -27,6 +28,9 @@ class Message(models.Model):
|
|||
def __str__(self):
|
||||
return "Message from %s" % self.author
|
||||
|
||||
def get_absolute_url(self):
|
||||
return self.conversation.get_absolute_url()
|
||||
|
||||
|
||||
class Conversation(models.Model):
|
||||
|
||||
|
@ -36,7 +40,7 @@ class Conversation(models.Model):
|
|||
abstract = True
|
||||
|
||||
|
||||
class ConversationWithParticipant(Conversation):
|
||||
class ConversationWithParticipant(Conversation):
|
||||
|
||||
participation = models.OneToOneField(Participation, related_name='conversation')
|
||||
messages = GenericRelation(Message)
|
||||
|
@ -44,12 +48,15 @@ class ConversationWithParticipant(Conversation):
|
|||
uri = 'inbox'
|
||||
template = 'participant_message'
|
||||
|
||||
def get_site(self):
|
||||
return self.participation.site
|
||||
|
||||
def __str__(self):
|
||||
return "Conversation with %s" % self.participation.user
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('conversation', kwargs={'username': self.participation.user.username})
|
||||
|
||||
def get_site(self):
|
||||
return self.participation.site
|
||||
|
||||
def new_message(self, message):
|
||||
site = self.get_site()
|
||||
subject = '[%s] Conversation with %s' % (site.name, self.participation.user.profile)
|
||||
|
@ -84,12 +91,15 @@ class ConversationAboutTalk(Conversation):
|
|||
uri = 'inbox'
|
||||
template = 'talk_message'
|
||||
|
||||
def get_site(self):
|
||||
return self.talk.site
|
||||
|
||||
def __str__(self):
|
||||
return "Conversation about %s" % self.talk.title
|
||||
|
||||
def get_absolute_url(self):
|
||||
self.talk.get_absolute_url()
|
||||
|
||||
def get_site(self):
|
||||
return self.talk.site
|
||||
|
||||
def new_message(self, message):
|
||||
site = self.get_site()
|
||||
first = self.messages.first()
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
from django.db.models.signals import post_save, m2m_changed
|
||||
from django.dispatch import receiver
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
|
||||
from .models import ConversationWithParticipant, ConversationAboutTalk, Message
|
||||
from .utils import notify_by_email
|
||||
from proposals.models import Talk, Topic
|
||||
from proposals.signals import new_talk
|
||||
from accounts.models import Participation
|
||||
from proposals.models import Talk
|
||||
from proposals.signals import new_talk
|
||||
|
||||
from .models import ConversationAboutTalk, ConversationWithParticipant, Message
|
||||
|
||||
|
||||
@receiver(post_save, sender=Participation, dispatch_uid="Create ConversationWithParticipant")
|
||||
|
@ -31,15 +28,14 @@ def create_conversation_about_talk(sender, instance, created, **kwargs):
|
|||
@receiver(new_talk, dispatch_uid="Notify new talk")
|
||||
def notify_new_talk(sender, instance, **kwargs):
|
||||
# Subscribe reviewer for these topics to conversations
|
||||
topics = instance.topics.all()
|
||||
reviewers = User.objects.filter(participation__review_topics=topics).all()
|
||||
reviewers = User.objects.filter(participation__topic__talk=instance)
|
||||
instance.conversation.subscribers.add(*reviewers)
|
||||
for user in instance.speakers.all():
|
||||
participation = Participation.on_site.get(user=user)
|
||||
participation.conversation.subscribers.add(*reviewers)
|
||||
# Notification of this new talk
|
||||
message = Message(conversation=instance.conversation, author=instance.proposer,
|
||||
content='The talk has been proposed.')
|
||||
content='The talk has been proposed.')
|
||||
message.save()
|
||||
|
||||
|
||||
|
|
|
@ -1,27 +1,29 @@
|
|||
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 accounts.models import Participation
|
||||
|
||||
from .models import Conversation, Message
|
||||
from .utils import get_reply_addr
|
||||
from .models import ConversationWithParticipant, Message
|
||||
|
||||
|
||||
class ConversationTests(TestCase):
|
||||
def setUp(self):
|
||||
a, b = (User.objects.create_user(guy, email='%s@example.org' % guy, password=guy) for guy in 'ab')
|
||||
participation = Participation.objects.create(user=a, site=Site.objects.first())
|
||||
conversation = Conversation.objects.create(speaker=speaker)
|
||||
Message.objects.create(token='pipo', conversation=conversation, author=a, content='allo')
|
||||
a, b, c = (User.objects.create_user(guy, email='%s@example.org' % guy, password=guy) for guy in 'abc')
|
||||
pa, _ = Participation.objects.get_or_create(user=a, site=Site.objects.first())
|
||||
conversation, _ = ConversationWithParticipant.objects.get_or_create(participation=pa)
|
||||
Message.objects.create(content='allo', conversation=conversation, author=b)
|
||||
|
||||
def test_models(self):
|
||||
self.assertEqual(str(Conversation.objects.first()), 'Conversation with a')
|
||||
self.assertEqual(str(Message.objects.first()), 'Message from a')
|
||||
self.assertEqual(str(ConversationWithParticipant.objects.first()), 'Conversation with a')
|
||||
self.assertEqual(str(Message.objects.first()), 'Message from b')
|
||||
|
||||
def test_views(self):
|
||||
self.assertEqual(self.client.get(Conversation.objects.first().get_absolute_url()).status_code, 200)
|
||||
|
||||
def test_utils(self):
|
||||
ret = ['pipo+ 11183704aabfddb3d694ff4f24c0daadfa2d8d2193336e345f92a6fd3ffb6a19e7@example.org']
|
||||
self.assertEqual(get_reply_addr(1, User.objects.first()), ret)
|
||||
url = ConversationWithParticipant.objects.first().get_absolute_url()
|
||||
self.assertEqual(self.client.get(url).status_code, 302)
|
||||
self.client.login(username='c', password='c')
|
||||
self.assertEqual(self.client.get(url).status_code, 403)
|
||||
self.assertEqual(self.client.get(reverse('correspondents')).status_code, 200)
|
||||
self.assertEqual(self.client.get(reverse('inbox')).status_code, 200)
|
||||
self.client.post(reverse('inbox'), {'content': 'coucou'})
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
from django.conf.urls import url
|
||||
|
||||
from conversations import views, emails
|
||||
|
||||
from conversations import emails, views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^recv/$', emails.email_recv),
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
from django.conf import settings
|
||||
from django.utils.crypto import get_random_string
|
||||
from django.template.loader import render_to_string
|
||||
from django.core.mail import EmailMultiAlternatives
|
||||
from django.core import mail
|
||||
|
||||
import hashlib
|
||||
|
||||
from django.conf import settings
|
||||
from django.core import mail
|
||||
from django.core.mail import EmailMultiAlternatives
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.crypto import get_random_string
|
||||
|
||||
|
||||
def hexdigest_sha256(*args):
|
||||
|
||||
|
@ -47,9 +47,7 @@ def notify_by_email(template, data, subject, sender, dests, message_id, ref=None
|
|||
email=settings.DEFAULT_FROM_EMAIL)
|
||||
|
||||
# Generating headers
|
||||
headers = {
|
||||
'Message-ID': "<%s.%s>" % (message_id, settings.DEFAULT_FROM_EMAIL),
|
||||
}
|
||||
headers = {'Message-ID': "<%s.%s>" % (message_id, settings.DEFAULT_FROM_EMAIL)}
|
||||
if ref:
|
||||
# This email reference a previous one
|
||||
headers.update({
|
||||
|
@ -68,7 +66,8 @@ def notify_by_email(template, data, subject, sender, dests, message_id, ref=None
|
|||
messages = []
|
||||
for subject, message, from_email, dest_emails, reply_to, headers in mails:
|
||||
text_message, html_message = message
|
||||
msg = EmailMultiAlternatives(subject, text_message, from_email, dest_emails, reply_to=reply_to, headers=headers)
|
||||
msg = EmailMultiAlternatives(subject, text_message, from_email, dest_emails, reply_to=reply_to,
|
||||
headers=headers)
|
||||
msg.attach_alternative(html_message, 'text/html')
|
||||
messages += [msg]
|
||||
with mail.get_connection() as connection:
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
from django.shortcuts import render
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
|
||||
from accounts.models import Participation
|
||||
from .models import Message
|
||||
|
||||
from .forms import MessageForm
|
||||
|
||||
|
||||
|
@ -64,8 +62,7 @@ def subscribe(request, username):
|
|||
|
||||
# TODO check admin
|
||||
|
||||
participation = get_object_or_404(Participation, user__username=username,
|
||||
site=get_current_site(request))
|
||||
participation = get_object_or_404(Participation, user__username=username, site=get_current_site(request))
|
||||
participation.conversation.subscribers.add(request.user)
|
||||
messages.success(request, 'Subscribed.')
|
||||
|
||||
|
@ -79,8 +76,7 @@ def unsubscribe(request, username):
|
|||
|
||||
# TODO check admin
|
||||
|
||||
participation = get_object_or_404(Participation, user__username=username,
|
||||
site=get_current_site(request))
|
||||
participation = get_object_or_404(Participation, user__username=username, site=get_current_site(request))
|
||||
participation.conversation.subscribers.remove(request.user)
|
||||
messages.success(request, 'Unsubscribed.')
|
||||
|
||||
|
|
|
@ -179,4 +179,4 @@ BOOTSTRAP3 = {
|
|||
AUTHENTICATION_BACKENDS = ['yeouia.backends.YummyEmailOrUsernameInsensitiveAuth']
|
||||
LOGOUT_REDIRECT_URL = 'home'
|
||||
|
||||
ACCOUNT_ACTIVATION_DAYS = 7 # django-registration
|
||||
ACCOUNT_ACTIVATION_DAYS = 7 # django-registration
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
from django.contrib.sites.shortcuts import get_current_site
|
||||
|
||||
|
||||
def enum_to_choices(enum):
|
||||
return ((item.value, item.name) for item in list(enum))
|
||||
|
||||
|
||||
def full_link(obj, request=None):
|
||||
protocol = 'https' if request is None or request.is_secure() else 'http'
|
||||
return '%s://%s%s' % (protocol, get_current_site(request), obj.get_absolute_url())
|
|
@ -0,0 +1,21 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.7 on 2016-06-19 20:26
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('accounts', '0004_remove_participation_review_topics'),
|
||||
('proposals', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='topic',
|
||||
name='reviewers',
|
||||
field=models.ManyToManyField(blank=True, to='accounts.Participation'),
|
||||
),
|
||||
]
|
|
@ -8,8 +8,8 @@ from django.db import models
|
|||
|
||||
from autoslug import AutoSlugField
|
||||
|
||||
from accounts.utils import enum_to_choices
|
||||
|
||||
from accounts.models import Participation
|
||||
from ponyconf.utils import enum_to_choices
|
||||
|
||||
__all__ = ['Topic', 'Talk', 'Speech']
|
||||
|
||||
|
@ -19,6 +19,8 @@ class Topic(models.Model):
|
|||
name = models.CharField(max_length=128, verbose_name='Name', unique=True)
|
||||
slug = AutoSlugField(populate_from='name', unique=True)
|
||||
|
||||
reviewers = models.ManyToManyField(Participation, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
@ -54,13 +56,13 @@ class Talk(models.Model):
|
|||
return True
|
||||
if user == self.proposer:
|
||||
return True
|
||||
if user in talk.speakers.all():
|
||||
if user in self.speakers.all():
|
||||
return True
|
||||
try:
|
||||
participation = Participation.on_site.get(user=user)
|
||||
except Participation.DoesNotExists:
|
||||
return False
|
||||
return self.topics.filter(pk=participation.review_topics.pk).exists()
|
||||
return self.topics.filter(reviewers=participation).exists()
|
||||
|
||||
|
||||
class Speech(models.Model):
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from django.dispatch import Signal
|
||||
|
||||
|
||||
new_talk = Signal(providing_args=["sender", "instance"])
|
||||
|
|
|
@ -1,20 +1,25 @@
|
|||
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 .models import Talk, Topic, Speech
|
||||
from accounts.models import Participation
|
||||
|
||||
from .models import Speech, Talk, Topic
|
||||
|
||||
|
||||
class ProposalsTests(TestCase):
|
||||
def setUp(self):
|
||||
for guy in 'ab':
|
||||
User.objects.create_user(guy, email='%s@example.org' % guy, password=guy)
|
||||
Topic.objects.create(name='pipo')
|
||||
a, b, c = (User.objects.create_user(guy, email='%s@example.org' % guy, password=guy) for guy in 'abc')
|
||||
Participation.objects.create(user=a, site=Site.objects.first())
|
||||
Topic.objects.create(name='topipo')
|
||||
c.is_superuser = True
|
||||
c.save()
|
||||
|
||||
def test_everything(self):
|
||||
# talk-edit
|
||||
self.client.login(username='a', password='a')
|
||||
self.client.post(reverse('add-talk'), {'title': 'super talk', 'description': 'super', 'event': 1})
|
||||
self.client.post(reverse('add-talk'), {'title': 'super talk', 'description': 'super', 'event': 1, 'topics': 1})
|
||||
self.assertEqual(str(Talk.on_site.first()), 'super talk')
|
||||
self.client.post(reverse('edit-talk', kwargs={'talk': 'super-talk'}),
|
||||
{'title': 'mega talk', 'description': 'mega', 'event': 1})
|
||||
|
@ -41,3 +46,9 @@ class ProposalsTests(TestCase):
|
|||
self.assertEqual(self.client.get(item.get_absolute_url()).status_code, 200)
|
||||
self.assertTrue(str(item))
|
||||
self.assertEqual(Speech.objects.first().username(), 'a')
|
||||
|
||||
# Talkis_editable_by
|
||||
a, b, c = User.objects.all()
|
||||
self.assertTrue(talk.is_editable_by(c))
|
||||
Speech.objects.create(talk=talk, speaker=b, order=2)
|
||||
self.assertTrue(talk.is_editable_by(b))
|
||||
|
|
|
@ -9,6 +9,7 @@ from django.views.generic import DetailView, ListView
|
|||
|
||||
from proposals.forms import TalkForm
|
||||
from proposals.models import Speech, Talk, Topic
|
||||
|
||||
from .signals import new_talk
|
||||
|
||||
|
||||
|
@ -48,7 +49,7 @@ def talk_edit(request, talk=None):
|
|||
talk = get_object_or_404(Talk, slug=talk)
|
||||
if talk.site != get_current_site(request):
|
||||
raise PermissionDenied()
|
||||
if not talk.has_perm(request.user):
|
||||
if not talk.is_editable_by(request.user):
|
||||
raise PermissionDenied()
|
||||
form = TalkForm(request.POST or None, instance=talk)
|
||||
if request.method == 'POST' and form.is_valid():
|
||||
|
@ -72,10 +73,9 @@ def talk_edit(request, talk=None):
|
|||
|
||||
class TalkDetail(LoginRequiredMixin, DetailView):
|
||||
queryset = Talk.on_site.all()
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(TalkDetail, self).get_context_data(**kwargs)
|
||||
context['edit_perm'] = self.object.is_editable_by(self.request.user)
|
||||
return context
|
||||
return super().get_context_data(edit_perm=self.object.is_editable_by(self.request.user), **kwargs)
|
||||
|
||||
|
||||
class TopicList(LoginRequiredMixin, ListView):
|
||||
|
|
Loading…
Reference in New Issue