removing old accounts app

This commit is contained in:
Élie Bouttier 2017-08-12 13:54:48 +02:00
parent 39b765bb51
commit 623b94fccd
26 changed files with 0 additions and 889 deletions

View File

@ -1 +0,0 @@
default_app_config = 'accounts.apps.AccountsConfig'

View File

@ -1,9 +0,0 @@
from django.contrib import admin
from accounts.models import Participation, Profile, Transport, Connector
admin.site.register(Profile) # FIXME extend user admin
admin.site.register(Participation)
admin.site.register(Transport)
admin.site.register(Connector)

View File

@ -1,10 +0,0 @@
from django.apps import AppConfig
from django.db.models.signals import post_migrate
class AccountsConfig(AppConfig):
name = 'accounts'
def ready(self):
import accounts.signals # noqa
post_migrate.connect(accounts.signals.create_default_options, sender=self)

View File

@ -1,28 +0,0 @@
from functools import wraps
from django.core.exceptions import PermissionDenied
from django.contrib.auth.decorators import login_required
from accounts.utils import is_orga, is_staff
def orga_required(view_func):
def _is_orga(request, *args, **kwargs):
if not request.user.is_authenticated():
return login_required(view_func)(request, *args, **kwargs)
elif is_orga(request, request.user):
return view_func(request, *args, **kwargs)
else:
raise PermissionDenied
return wraps(view_func)(_is_orga)
def staff_required(view_func):
def _is_staff(request, *args, **kwargs):
if not request.user.is_authenticated():
return login_required(view_func)(request, *args, **kwargs)
elif is_staff(request, request.user):
return view_func(request, *args, **kwargs)
else:
raise PermissionDenied
return wraps(view_func)(_is_staff)

View File

@ -1,48 +0,0 @@
from django import forms
from django.contrib.auth.models import User
from django.forms.models import modelform_factory
from django.utils.translation import ugettext_lazy as _
from django_select2.forms import Select2Widget
from .models import Participation, Profile
UserForm = modelform_factory(User, fields=['first_name', 'last_name', 'email', 'username'])
ProfileForm = modelform_factory(Profile, fields=['phone_number', 'biography', 'twitter', 'website', 'linkedin', 'facebook', 'mastodon'])
ParticipationForm = modelform_factory(Participation,
fields=['need_transport', 'transport', 'transport_city_outward', 'transport_city_return',
'accommodation',
'connector', 'sound', 'videotaped',
'video_licence', 'constraints'],
widgets={'transport': forms.CheckboxSelectMultiple(),
'connector': forms.CheckboxSelectMultiple()},
help_texts = {
'constraints': _('For example, you need to be back on saturday evening, you cannot eat meat.'),
})
ProfileOrgaForm = modelform_factory(Profile, fields=['biography'])
ParticipationOrgaForm = modelform_factory(Participation,
fields=['need_transport', 'transport', 'transport_city_outward', 'transport_city_return', 'transport_booked',
'accommodation', 'accommodation_booked',
'connector', 'sound', 'videotaped',
'video_licence',
'constraints', 'notes', 'orga'],
widgets={'transport': forms.CheckboxSelectMultiple(),
'connector': forms.CheckboxSelectMultiple()})
class ParticipationField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return obj.profile.__str__()
class NewParticipationForm(forms.Form):
def __init__(self, *args, **kwargs):
site = kwargs.pop('site')
super().__init__(*args, **kwargs)
queryset = User.objects.exclude(participation__site=site).all()
self.fields['participant'] = ParticipationField(queryset, widget=Select2Widget(),
label='Add participant from existing account')

View File

@ -1,107 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.3 on 2017-01-13 10:49
from __future__ import unicode_literals
import accounts.utils
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('sites', '0002_alter_domain_unique'),
]
operations = [
migrations.CreateModel(
name='AvailabilityTimeslot',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('start', models.DateTimeField(blank=True)),
('end', models.DateTimeField(blank=True)),
],
),
migrations.CreateModel(
name='Connector',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=64, unique=True)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Participation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('need_transport', models.NullBooleanField(default=None, verbose_name='Defray transportation?')),
('arrival', models.DateTimeField(blank=True, null=True)),
('departure', models.DateTimeField(blank=True, null=True)),
('transport_city_outward', models.CharField(blank=True, default='', max_length=256, verbose_name='Departure city')),
('transport_city_return', models.CharField(blank=True, default='', help_text='If different from departure city', max_length=256, verbose_name='Return city')),
('transport_booked', models.BooleanField(default=False)),
('accommodation', models.IntegerField(blank=True, choices=[(0, 'No'), (1, 'Hotel'), (2, 'Homestay')], null=True, verbose_name='Need accommodation?')),
('accommodation_booked', models.BooleanField(default=False)),
('constraints', models.TextField(blank=True, verbose_name='Constraints')),
('sound', models.BooleanField(default=False, verbose_name='I need sound')),
('videotaped', models.BooleanField(default=True, verbose_name="I'm ok to be recorded on video")),
('video_licence', models.IntegerField(choices=[(1, 'CC-Zero'), (2, 'CC-BY'), (3, 'CC-BY-SA'), (4, 'CC-BY-ND'), (5, 'CC-BY-NC'), (6, 'CC-BY-NC-SA'), (7, 'CC-BY-NC-ND')], default=2, verbose_name='Video licence')),
('notes', models.TextField(blank=True, default='', help_text='This field is only visible by organizers.', verbose_name='Notes')),
('orga', models.BooleanField(default=False)),
('connector', models.ManyToManyField(blank=True, to='accounts.Connector', verbose_name='I can output')),
('site', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sites.Site')),
],
),
migrations.CreateModel(
name='Profile',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('phone_number', models.CharField(blank=True, default='', max_length=16, verbose_name='Phone number')),
('biography', models.TextField(blank=True, verbose_name='Biography')),
('email_token', models.CharField(default=accounts.utils.generate_user_uid, max_length=12, unique=True)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Transport',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=64, unique=True)),
],
options={
'abstract': False,
},
),
migrations.AddField(
model_name='participation',
name='transport',
field=models.ManyToManyField(blank=True, to='accounts.Transport', verbose_name='I want to travel by'),
),
migrations.AddField(
model_name='participation',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='availabilitytimeslot',
name='participation',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='availabilities', to='accounts.Participation'),
),
migrations.AlterUniqueTogether(
name='participation',
unique_together=set([('site', 'user')]),
),
]

View File

@ -1,40 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2017-04-29 21:34
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='profile',
name='facebook',
field=models.CharField(blank=True, default='', max_length=100, verbose_name='Facebook'),
),
migrations.AddField(
model_name='profile',
name='linkedin',
field=models.CharField(blank=True, default='', max_length=100, verbose_name='LinkedIn'),
),
migrations.AddField(
model_name='profile',
name='mastodon',
field=models.CharField(blank=True, default='', max_length=100, verbose_name='Mastodon'),
),
migrations.AddField(
model_name='profile',
name='twitter',
field=models.CharField(blank=True, default='', max_length=100, verbose_name='Twitter'),
),
migrations.AddField(
model_name='profile',
name='website',
field=models.CharField(blank=True, default='', max_length=100, verbose_name='Website'),
),
]

View File

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2017-04-30 11:29
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0002_auto_20170429_2134'),
]
operations = [
migrations.AddField(
model_name='profile',
name='github',
field=models.CharField(blank=True, default='', max_length=100, verbose_name='Github'),
),
]

View File

@ -1,8 +0,0 @@
from django.contrib.auth.mixins import UserPassesTestMixin
from .utils import is_staff
class StaffRequiredMixin(UserPassesTestMixin):
def test_func(self):
return is_staff(self.request, self.request.user)

View File

@ -1,31 +0,0 @@
from enum import IntEnum
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext
from ponyconf.utils import PonyConfModel, enum_to_choices
#from .utils import generate_user_uid
class Profile(PonyConfModel):
user = models.OneToOneField(User)
phone_number = models.CharField(max_length=16, blank=True, default='', verbose_name=_('Phone number'))
twitter = models.CharField(max_length=100, blank=True, default='', verbose_name=_('Twitter'))
linkedin = models.CharField(max_length=100, blank=True, default='', verbose_name=_('LinkedIn'))
github = models.CharField(max_length=100, blank=True, default='', verbose_name=_('Github'))
website = models.CharField(max_length=100, blank=True, default='', verbose_name=_('Website'))
facebook = models.CharField(max_length=100, blank=True, default='', verbose_name=_('Facebook'))
mastodon = models.CharField(max_length=100, blank=True, default='', verbose_name=_('Mastodon'))
def __str__(self):
return self.user.get_full_name() or self.user.username
#def get_absolute_url(self):
# return reverse('profile')

View File

@ -1,45 +0,0 @@
from django.contrib import messages
from django.contrib.auth.models import User
from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.contrib.sites.shortcuts import get_current_site
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext_noop
from ponyconf.decorators import disable_for_loaddata
from .models import Connector, Participation, Profile, Transport
def create_default_options(sender, **kwargs):
Transport.objects.get_or_create(name=ugettext_noop('Train'))
Transport.objects.get_or_create(name=ugettext_noop('Plane'))
Transport.objects.get_or_create(name=ugettext_noop('Carpooling'))
Connector.objects.get_or_create(name=ugettext_noop('VGA'))
Connector.objects.get_or_create(name=ugettext_noop('HDMI'))
Connector.objects.get_or_create(name=ugettext_noop('miniDP'))
Connector.objects.get_or_create(name=ugettext_noop('I need a computer'))
@receiver(user_logged_in)
def on_user_logged_in(sender, request, user, **kwargs):
participation, created = Participation.objects.get_or_create(user=user, site=get_current_site(request))
if user.is_superuser:
participation.orga = True
participation.save()
if created:
messages.info(request, "Please check your profile!\n", fail_silently=True) # FIXME
messages.success(request, _('Welcome!'), fail_silently=True) # FIXME
@receiver(user_logged_out)
def on_user_logged_out(sender, request, **kwargs):
messages.success(request, _('Goodbye!'), fail_silently=True) # FIXME
@receiver(post_save, sender=User, weak=False, dispatch_uid='create_profile')
@disable_for_loaddata
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)

View File

@ -1,76 +0,0 @@
{% extends 'staff.html' %}
{% load accounts_tags i18n avatar_tags %}
{% block participantstab %} class="active"{% endblock %}
{% block content %}
<h1>{{ profile }}</h1>
{% if request|staff %}
<a href="{% url 'user-conversation' profile.user.username %}" class="btn btn-primary ">{% trans "Contact" %}</a>
{% endif %}
{% if request|edit_profile:profile %}
<a href="{% url 'edit-participant' profile.user.username %}" class="btn btn-success">{% trans "Edit" %}</a>
{% endif %}
<img class="pull-right" src="{% avatar_url profile.user 160 %}" />
<h2>{% trans "Biography" %}</h2>
<p>{{ profile.biography }}</p>
{% if request|staff %}
<p><a href="mailto:{{ profile.user.email }}?subject=[Capitole du Libre]">{{ profile.user.email }}</a></p>
{% endif %}
<h2>{% trans "Talks" %}</h2>
{% include "proposals/_talk_list.html" %}
{% if request|edit_profile:profile %}
<h2>{% trans "Information" %}</h2>
<h3>{% trans "Travels and hosting" %}</h3>
<ul>
<li>
<b>{% trans "Need transport:" %}</b> {{ participation.need_transport|yesno:"Yes,No,Not specified" }}
{% if participation.need_transport %}
<ul>
{% comment %}
<li><b>{% trans "Arrival:" %}</b> {{ participation.arrival }}</li>
<li><b>{% trans "Departure:" %}</b> {{ participation.departure }}</li>
{% endcomment %}
<li><b>{% trans "Accepted transport means:" %}</b> {% for transport in participation.transport.all %}{% if not forloop.first %}, {% endif %}{{ transport }}{% endfor %}</li>
<li><b>{% trans "Departure city:" %}</b> {{ participation.transport_city_outward|default:'Not specified' }}</li>
{% if participation.transport_city_return %}
<li><b>{% trans "Return city:" %}</b> {{ participation.transport_city_return }}</li>
{% endif %}
<li><b>{% trans "Transport booked:" %}</b> {{ participation.transport_booked|yesno }}</li>
</ul>
{% endif %}
</li>
<li><b>{% trans "Need accommodation:" %}</b> {% if participation.accommodation is None %}Not specified{% else %}{{ participation.get_accommodation_display }}{% endif %}</li>
<li><b>{% trans "Accommodation booked:" %}</b> {{ participation.accommodation_booked|yesno }}</li>
</ul>
<h3>{% trans "Talk needs" %}</h3>
<ul>
<li><b>{% trans "Video output:" %}</b> {% for conn in participation.connector.all %}{% if not forloop.first %}, {% endif %}{{ conn }}{% endfor %}</li>
<li><b>{% trans "Need sound:" %}</b> {{ participation.sound|yesno }}</li>
<li><b>{% trans "Ok to be recorded on video:" %}</b> {{ participation.videotaped|yesno }}</li>
<li><b>{% trans "Video licence:" %}</b> {{ participation.get_video_licence_display }}</li>
</ul>
<h3>{% trans "Constraints" %}</h3>
<p>{{ participation.constraints|linebreaksbr }}</p>
<h3>{% trans "Notes" %}</h3>
<p>{{ participation.notes|linebreaksbr }}</p>
{% endif %}
{% endblock %}

View File

@ -1,18 +0,0 @@
{% extends 'staff.html' %}
{% load i18n %}
{% block participantstab %} class="active"{% endblock %}
{% block content %}
<div class="panel panel-default">
<div class="panel-heading">
<h3>{% blocktrans %}{{ profile }}'s profile{% endblocktrans %}</h3>
</div>
<div class="panel-body">
{% include "_form.html" %}
</div>
</div>
{% endblock %}

View File

@ -1,62 +0,0 @@
{% extends 'staff.html' %}
{% load bootstrap3 accounts_tags i18n %}
{% block participantstab %} class="active"{% endblock %}
{% block content %}
<h1>{% trans "Participants" %}</h1>
<table class="table table-striped">
<tr>
<th>Username</th>
<th>Full name</th>
<th>Orga</th>
<th>Reviews</th>
<th>Conversations</th>
</tr>
{% for participation in participation_list %}
<tr>
<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.topic_set.all %}{{ topic.get_link }}{% if not forloop.last %},
{% endif %}{% endfor %}</td>
<td>
<a href="{% url 'user-conversation' participation.user.username %}" data-toggle="tooltip" data-placement="bottom"
title="{% trans "View conversation" %}"><span class="glyphicon glyphicon-envelope"></span></a>
{% if request.user in participation.conversation.subscribers.all %}
<a href="{% url 'unsubscribe-conversation' participation.user.username %}?next={% url 'list-participants' %}"
data-toggle="tooltip" data-placement="bottom" title="{% trans "Unsubscribe from the conversation" %}">
<span class="glyphicon glyphicon-star"></span></a>
{% else %}
<a href="{% url 'subscribe-conversation' participation.user.username %}?next={% url 'list-participants' %}"
data-toggle="tooltip" data-placement="bottom" title="{% trans "Subscribe to the conversation" %}">
<span class="glyphicon glyphicon-star-empty"></span></a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
{% if request|orga %}
{% include "_form.html" %}
{% endif %}
{% endblock %}
{% block css %}
{{ block.css }}
{{ form.media.css }}
{% endblock %}
{% block js_end %}
{{ block.super }}
{{ form.media.js }}
<script type="text/javascript">
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})
</script>
{% endblock %}

View File

@ -1,65 +0,0 @@
{% extends 'base.html' %}
{% load bootstrap3 i18n avatar_tags %}
{% block profiletab %} class="active"{% endblock %}
{% block content %}
<div class="panel panel-default">
<div class="panel-heading">
<h3>{% trans "Profile" %}</h3>
</div>
<div class="panel-body">
<form action="" method="post" class="form-horizontal">
{% csrf_token %}
<div class="form-group">
<label class="col-md-3 control-label" for="id_first_name">Avatar</label>
{% avatar request.user %}
<a href="{% url 'avatar_change' %}" class="btn btn-default">{% trans "Change avatar" %}</a>
</div>
{% bootstrap_form user_form layout="horizontal" %}
{% bootstrap_form profile_form layout="horizontal" %}
{% bootstrap_field participation_form.need_transport layout="horizontal" %}
<div id="transport_fields">
{% bootstrap_field participation_form.transport layout="horizontal" %}
{% bootstrap_field participation_form.transport_city_outward layout="horizontal" %}
{% bootstrap_field participation_form.transport_city_return layout="horizontal" %}
</div>
{% bootstrap_form participation_form exclude="need_transport,transport,transport_city_outward,transport_city_return" layout="horizontal" %}
{% buttons layout="horizontal" %}
<button type="submit" class="btn btn-primary">{% trans "Submit" %}</button>
{% for url, class, text in buttons %}
<a href="{% url url %}" class="btn btn-{{ class }}">{{ text }}</a>
{% endfor %}
<a href="{% if request.META.HTTP_REFERER %}{{ request.META.HTTP_REFERER }}{% else %}{% url 'home' %}{% endif %}" class="btn btn-default">{% trans "Cancel" %}</a>
{% endbuttons %}
</form>
</div>
</div>
{% endblock %}
{% block css %}
{{ block.super }}
{{ form.media.css }}
{% endblock %}
{% block js_end %}
{{ block.super }}
{{ form.media.js }}
<script type="text/javascript">
var update_transport = function() {
if ($('#id_need_transport').val() == 2) { // 2 == 'Yes'
$("#transport_fields").show();
} else {
$("#transport_fields").hide();
}
}
$(function(){
update_transport();
$('#id_need_transport').change(update_transport);
})
</script>
{% endblock %}

View File

@ -1,14 +0,0 @@
{% extends "avatar/base.html" %}
{% load i18n avatar_tags %}
{% block avatarcontent %}
<p>{% trans "Your current avatar: " %}</p>
{% avatar user %}
{% if not avatars %}
<p>{% trans "You haven't uploaded an avatar yet. Please upload one now." %}</p>
{% endif %}
<form enctype="multipart/form-data" method="POST" action="{% url 'avatar_add' %}">
{{ upload_avatar_form.as_p }}
<p>{% csrf_token %}<input type="submit" value="{% trans "Upload New Image" %}" /></p>
</form>
{% endblock %}

View File

@ -1 +0,0 @@
<img src="{{ url }}" alt="{{ alt }}" width="{{ size }}" height="{{ size }}" />

View File

@ -1,20 +0,0 @@
{% extends 'base.html' %}
{% load i18n %}
{% block profiletab %} class="active"{% endblock %}
{% block content %}
<div class="panel panel-default">
<div class="panel-heading">
<h3>{% trans "Avatar" %}
<a href="{% url 'profile' %}" class="btn btn-primary pull-right"><span class="glyphicon glyphicon-arrow-left"> {% trans "Back to profile" %}</a>
</h3>
</div>
<div class="panel-body">
{% block avatarcontent %}{% endblock %}
</div>
</div>
{% endblock %}

View File

@ -1,21 +0,0 @@
{% extends "avatar/base.html" %}
{% load i18n avatar_tags %}
{% block avatarcontent %}
<p>{% trans "Your current avatar: " %}</p>
{% avatar user %}
{% if not avatars %}
<p>{% trans "You haven't uploaded an avatar yet. Please upload one now." %}</p>
{% else %}
<form method="POST" action="{% url 'avatar_change' %}">
<ul>
{{ primary_avatar_form.as_ul }}
</ul>
<p>{% csrf_token %}<input type="submit" value="{% trans "Choose new Default" %}" /></p>
</form>
{% endif %}
<form enctype="multipart/form-data" method="POST" action="{% url 'avatar_add' %}">
{{ upload_avatar_form.as_p }}
<p>{% csrf_token %}<input type="submit" value="{% trans "Upload New Image" %}" /></p>
</form>
{% endblock %}

View File

@ -1,17 +0,0 @@
{% extends "avatar/base.html" %}
{% load i18n %}
{% block avatarcontent %}
<p>{% trans "Please select the avatars that you would like to delete." %}</p>
{% if not avatars %}
{% url 'avatar_change' as avatar_change_url %}
<p>{% blocktrans %}You have no avatars to delete. Please <a href="{{ avatar_change_url }}">upload one</a> now.{% endblocktrans %}</p>
{% else %}
<form method="POST" action="{% url 'avatar_delete' %}">
<ul>
{{ delete_avatar_form.as_ul }}
</ul>
<p>{% csrf_token %}<input type="submit" value="{% trans "Delete These" %}" /></p>
</form>
{% endif %}
{% endblock %}

View File

@ -1,20 +0,0 @@
from django import template
from accounts.utils import can_edit_profile, is_orga, is_staff
register = template.Library()
@register.filter
def orga(request):
return is_orga(request, request.user)
@register.filter
def staff(request):
return is_staff(request, request.user)
@register.filter
def edit_profile(request, profile):
return can_edit_profile(request, profile)

View File

@ -1,108 +0,0 @@
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 Participation, Profile
ROOT_URL = 'accounts'
class AccountTests(TestCase):
def setUp(self):
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())
Participation.objects.create(user=b, site=Site.objects.first())
Participation.objects.create(user=c, site=Site.objects.first(), orga=True)
def test_models(self):
self.assertEqual(Profile.objects.count(), 3)
self.client.login(username='c', password='c')
for model in [Profile, Participation]:
item = model.objects.first()
self.assertEqual(self.client.get(item.full_link()).status_code, 200)
self.assertTrue(str(item))
def test_views(self):
# User b wants to update its username, email and biography
user = User.objects.get(username='b')
self.assertEqual(user.email, 'b@example.org')
self.assertEqual(user.profile.biography, '')
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.assertEqual(User.objects.filter(username='z').count(), 0)
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')
self.assertEqual(user.profile.biography, 'tester')
self.client.logout()
def test_participant_views(self):
self.assertEqual(self.client.get(reverse('registration_register')).status_code, 200)
self.client.login(username='b', password='b')
self.assertEqual(self.client.get(reverse('list-participants')).status_code, 403)
self.assertEqual(self.client.post(reverse('edit-participant', kwargs={'username': 'a'}),
{'biography': 'foo'}).status_code, 403)
b = User.objects.get(username='b')
b.is_superuser = True
b.save()
p = Participation.objects.get(user=b)
self.assertFalse(p.orga)
self.assertEqual(self.client.get(reverse('list-participants')).status_code, 403)
# login signal should set orga to True due to superuser status
self.client.login(username='b', password='b')
p = Participation.objects.get(user=b)
self.assertTrue(p.orga)
self.assertEqual(self.client.get(reverse('list-participants')).status_code, 200)
self.assertEqual(self.client.post(reverse('edit-participant', kwargs={'username': 'a'}),
{'biography': 'foo', 'nootes': 'bar'}).status_code, 200)
self.assertEqual(User.objects.get(username='a').profile.biography, '')
self.assertEqual(self.client.post(reverse('edit-participant', kwargs={'username': 'a'}),
{'biography': 'foo', 'notes': 'bar', 'first_name': 'Jules', 'username': 'a',
'last_name': 'César', 'email': 'a@example.org', 'transport': 1,
'connector': 1, 'video_licence': 2, 'constraints': 'nope', 'orga': 0,
}).status_code, 200)
self.assertEqual(User.objects.get(username='a').profile.biography, 'foo')
self.assertEqual(Participation.objects.get(user=User.objects.get(username='a')).video_licence, 2)
from datetime import datetime
from .models import AvailabilityTimeslot
class DisponibilitiesTests(TestCase):
def setUp(self):
self.user = User.objects.create_user('a', email='a@example.org', password='a')
self.participation = Participation.objects.create(user=self.user, site=Site.objects.first())
def test_is_available(self):
from django.utils.timezone import is_naive, get_default_timezone
tz = get_default_timezone()
d = {}
for i in range(8, 18, 1):
d[i] = datetime(2016, 10, 10, i, 0, 0, tzinfo=tz)
self.assertEquals(self.participation.is_available(d[10]), None)
AvailabilityTimeslot.objects.create(participation=self.participation, start=d[10], end=d[12])
self.assertEquals(self.participation.is_available(d[9]), False)
self.assertEquals(self.participation.is_available(d[11]), True)
self.assertEquals(self.participation.is_available(d[13]), False)
self.assertEquals(self.participation.is_available(d[8], d[9]), False)
self.assertEquals(self.participation.is_available(d[9], d[11]), False)
self.assertEquals(self.participation.is_available(d[10], d[11]), True)
self.assertEquals(self.participation.is_available(d[11], d[12]), True)
self.assertEquals(self.participation.is_available(d[10], d[12]), True)
self.assertEquals(self.participation.is_available(d[11], d[13]), False)
self.assertEquals(self.participation.is_available(d[13], d[14]), False)
AvailabilityTimeslot.objects.create(participation=self.participation, start=d[14], end=d[16])
self.assertEquals(self.participation.is_available(d[10], d[12]), True)
self.assertEquals(self.participation.is_available(d[14], d[16]), True)
self.assertEquals(self.participation.is_available(d[11], d[15]), False)
self.assertEquals(self.participation.is_available(d[11], d[17]), False)
self.assertEquals(self.participation.is_available(d[13], d[17]), False)
self.assertEquals(self.participation.is_available(d[9], d[15]), False)

View File

@ -1,18 +0,0 @@
from django.conf import settings
from django.conf.urls import include, url
from django.contrib.auth import views as auth_views
#from . import views
urlpatterns = [
#url(r'^profile/$', views.profile, name='profile'),
#url(r'^login/$', auth_views.login, {'extra_context': {'buttons': [views.RESET_PASSWORD_BUTTON]}}, name='login'),
url(r'^login/$', auth_views.login, name='login'),
url(r'^logout/$', auth_views.logout, {'next_page': settings.LOGOUT_REDIRECT_URL}, name='logout'),
#url(r'^participant/$', views.participation_list, name='list-participants'),
#url(r'^participant/(?P<username>[\w.@+-]+)$', views.participant_details, name='show-participant'),
#url(r'^participant/(?P<username>[\w.@+-]+)/edit/$', views.participant_edit, name='edit-participant'),
#url(r'^avatar/', include('avatar.urls')),
url(r'', include('django.contrib.auth.urls')),
#url(r'', include('registration.backends.default.urls')),
]

View File

@ -1,102 +0,0 @@
from django.contrib import messages
from django.contrib.auth.decorators import login_required
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 django.utils.translation import ugettext_lazy as _
from .decorators import staff_required
from .forms import (NewParticipationForm, ParticipationForm,
ParticipationOrgaForm, ProfileForm, ProfileOrgaForm, UserForm)
from .models import Participation, Profile, User
from .utils import can_edit_profile, is_orga
from proposals.models import Talk
from proposals.utils import allowed_talks
RESET_PASSWORD_BUTTON = ('password_reset', 'warning', _('Reset your password'))
CHANGE_PASSWORD_BUTTON = ('password_change', 'warning', _('Change password'))
CHANGE_AVATAR_BUTTON = ('avatar_change', 'default', _('Change avatar'))
@login_required
def profile(request):
user_form = UserForm(request.POST or None, instance=request.user)
profile_form = ProfileForm(request.POST or None, instance=request.user.profile)
participation_form = ParticipationForm(request.POST or None, instance=Participation.objects.get(site=get_current_site(request),
user=request.user))
forms = [user_form, profile_form, participation_form]
if request.method == 'POST':
if all(form.is_valid() for form in forms):
for form in forms:
form.save()
messages.success(request, _('Profile updated successfully.'))
else:
messages.error(request, _('Please correct those errors.'))
return render(request, 'accounts/profile.html', {
'user_form': user_form,
'profile_form': profile_form,
'participation_form': participation_form,
'buttons': [CHANGE_PASSWORD_BUTTON]
})
@login_required
def participant_edit(request, username):
profile = get_object_or_404(Profile, user__username=username)
if not can_edit_profile(request, profile):
raise PermissionDenied()
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(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):
for form in forms:
form.save()
messages.success(request, _('Profile updated successfully.'))
else:
messages.error(request, _('Please correct those errors.'))
return render(request, 'accounts/participant_edit.html', {'forms': forms, 'profile': profile})
@staff_required
def participation_list(request):
participation_list = Participation.objects.filter(site=get_current_site(request)).all()
form = NewParticipationForm(request.POST or None, site=get_current_site(request))
if request.method == 'POST' and form.is_valid():
if not Participation.objects.get(user=request.user, site=get_current_site(request)).is_orga():
raise PermissionDenied()
user = User.objects.get(username=form.cleaned_data['participant'])
participation, created = Participation.objects.get_or_create(user=user, site=get_current_site(request))
if created:
messages.success(request, _("%(name)s added to participants") % {'name': user.profile})
else:
messages.info(request, _("%(name)s is already a participant") % {'name': user.profile})
return redirect(reverse('list-participants'))
return render(request, 'accounts/participant_list.html', {
'participation_list': participation_list,
'form': form,
})
@login_required
def participant_details(request, username):
user = get_object_or_404(User, username=username)
participation = get_object_or_404(Participation, user=user, site=get_current_site(request))
return render(request, 'accounts/participant_details.html', {
'profile': user.profile,
'participation': participation,
'talk_list': allowed_talks(Talk.objects.filter(site=get_current_site(request), speakers=user), request),
})