Commit 7e908c53 authored by Sébastiaan Versteeg's avatar Sébastiaan Versteeg

Merge branch 'user-as-foreign-keys' into 'master'

Use the User model for foreign keys.

See merge request !606
parents 3aef177a 6aab5288
from django.contrib import admin
from django.forms import ModelForm
from activemembers.forms import CommitteeMembershipForm
from members.models import Member
from utils.translation import TranslatedModelAdmin
from . import models
class CommitteeMembershipInlineForm(ModelForm):
"""
Form for the Committee Membership inline
Doesn't do anything fancy, but we need it for speed.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Get the related fields in advance
self.fields['member'].queryset = Member.objects.select_related('user')
class CommitteeMembershipInline(admin.StackedInline):
model = models.CommitteeMembership
form = CommitteeMembershipInlineForm
can_delete = False
ordering = ('since',)
extra = 0
......@@ -67,8 +51,8 @@ class CommitteeMembershipAdmin(TranslatedModelAdmin):
form = CommitteeMembershipForm
list_display = ('member', 'committee', 'since', 'until', 'chair', 'role')
list_filter = ('committee',)
search_fields = ('member__user__first_name', 'member__user__last_name',
'member__user__email')
search_fields = ('member__first_name', 'member__last_name',
'member__email')
@admin.register(models.Mentorship)
......
......@@ -22,14 +22,17 @@ class CommitteeBackend(object):
def _get_permissions(self, user, obj):
if not user.is_active or user.is_anonymous or obj is not None:
return set()
perm_cache_name = '_committee_perm_cache'
try:
committees = user.member.committee_set.filter(
Q(committeemembership__until=None) |
Q(committeemembership__until__gte=timezone.now())
)
member = Member.objects.get(pk=user.pk)
except Member.DoesNotExist:
return set()
committees = member.committee_set.filter(
Q(committeemembership__until=None) |
Q(committeemembership__until__gte=timezone.now())
)
perm_cache_name = '_committee_perm_cache'
if not hasattr(user, perm_cache_name):
perms = (Permission.objects
.filter(committee__in=committees)
......
......@@ -6,8 +6,8 @@ from members.models import Member
class CommitteeMembershipForm(forms.ModelForm):
member = forms.ModelChoiceField(
queryset=Member.objects.order_by('user__first_name',
'user__last_name'))
queryset=Member.objects.order_by('first_name',
'last_name'))
class Meta:
model = CommitteeMembership
......
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2017-10-11 18:50
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('activemembers', '0021_auto_20170705_1902'),
]
operations = [
migrations.AlterUniqueTogether(
name='mentorship',
unique_together=set(),
),
migrations.AddField(
model_name='committee',
name='members_old',
field=models.ManyToManyField(through='activemembers.CommitteeMembership', to='members.Member', null=True, related_name='members_old'),
),
migrations.AddField(
model_name='committeemembership',
name='member_old',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='members.Member', verbose_name='Member', null=True),
),
migrations.AddField(
model_name='mentorship',
name='member_old',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='members.Member', verbose_name='Member', null=True),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2017-10-11 18:50
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
def forward_func(apps, schema_editor):
CommitteeMembership = apps.get_model('activemembers', 'CommitteeMembership')
Mentorship = apps.get_model('activemembers', 'Mentorship')
for membership in CommitteeMembership.objects.all():
membership.member_old = membership.member
membership.save(update_fields=('member_old',))
for mentorship in Mentorship.objects.all():
mentorship.member_old = mentorship.member
mentorship.save(update_fields=('member_old',))
class Migration(migrations.Migration):
dependencies = [
('activemembers', '0022_0_user_foreign_keys'),
]
operations = [
migrations.RunPython(
code=forward_func,
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2017-10-11 18:50
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('activemembers', '0022_1_user_foreign_keys'),
]
operations = [
migrations.RemoveField(
model_name='committee',
name='members',
),
migrations.RemoveField(
model_name='committeemembership',
name='member',
),
migrations.RemoveField(
model_name='mentorship',
name='member',
),
migrations.AddField(
model_name='committee',
name='members',
field=models.ManyToManyField(through='activemembers.CommitteeMembership', to=settings.AUTH_USER_MODEL, null=True),
),
migrations.AddField(
model_name='committeemembership',
name='member',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Member', null=True),
),
migrations.AddField(
model_name='mentorship',
name='member',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Member', null=True),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2017-10-11 18:50
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
def forward_func(apps, schema_editor):
CommitteeMembership = apps.get_model('activemembers', 'CommitteeMembership')
Mentorship = apps.get_model('activemembers', 'Mentorship')
for membership in CommitteeMembership.objects.all():
membership.member = membership.member_old.user
membership.save(update_fields=('member',))
for mentorship in Mentorship.objects.all():
mentorship.member = mentorship.member_old.user
mentorship.save(update_fields=('member',))
class Migration(migrations.Migration):
dependencies = [
('activemembers', '0022_2_user_foreign_keys'),
]
operations = [
migrations.RunPython(
code=forward_func,
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2017-10-11 18:50
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('activemembers', '0022_3_user_foreign_keys'),
]
operations = [
migrations.RemoveField(
model_name='committee',
name='members_old',
),
migrations.RemoveField(
model_name='committeemembership',
name='member_old',
),
migrations.RemoveField(
model_name='mentorship',
name='member_old',
),
migrations.AlterUniqueTogether(
name='mentorship',
unique_together=set([('member', 'year')]),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-10-13 12:16
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('members', '0018_create_proxy_member'),
('activemembers', '0022_4_user_foreign_keys'),
]
operations = [
migrations.AlterField(
model_name='committee',
name='members',
field=models.ManyToManyField(through='activemembers.CommitteeMembership', to='members.Member'),
),
migrations.AlterField(
model_name='committeemembership',
name='member',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='members.Member', verbose_name='Member'),
),
migrations.AlterField(
model_name='mentorship',
name='member',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='members.Member', verbose_name='Member'),
),
]
......@@ -329,11 +329,11 @@ class CommitteeMembership(models.Model, metaclass=ModelTranslateMeta):
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
self.member.user.is_staff = (self.member
.committeemembership_set
.exclude(until__lte=timezone.now().date())
.count()) >= 1
self.member.user.save()
self.member.is_staff = (self.member
.committeemembership_set
.exclude(until__lte=timezone.now().date())
.count()) >= 1
self.member.save()
def __str__(self):
return "{} membership of {} since {}, until {}".format(self.member,
......
......@@ -37,10 +37,10 @@
<a href="{{ member.get_absolute_url }}">
<div class="post-inner">
<div class="inner-img">
{% if not member.photo %}
<img alt="{{ member.display_name }}" src="{% static 'members/images/default-avatar.jpg' %}" height="220" width="220" />
{% if not member.profile.photo %}
<img alt="{{ member.profile.display_name }}" src="{% static 'members/images/default-avatar.jpg' %}" height="220" width="220" />
{% else %}
<img alt="{{ member.display_name }}" src="{% thumbnail member.photo '220x220' %}" width="220" height="220" />
<img alt="{{ member.profile.display_name }}" src="{% thumbnail member.profile.photo '220x220' %}" width="220" height="220" />
{% endif %}
</div>
{% if member.chair %}
......@@ -52,12 +52,12 @@
{% endif %}
<div class="post-overlay">
<div class="post-overlay-meta">
<h2>{{ member.display_name }}</h2>
<h2>{{ member.profile.display_name }}</h2>
<p>{{ member.role }}</p>
</div>
</div>
<div class="post-body avatar-subtitle">
{{ member.display_name }}
{{ member.profile.display_name }}
</div>
</div>
</a>
......
......@@ -33,10 +33,10 @@
<a href="{{ member.get_absolute_url }}">
<div class="post-inner">
<div class="inner-img">
{% if not member.photo %}
<img alt="{{ member.display_name }}" src="{% static 'members/images/default-avatar.jpg' %}" height="220" width="220" />
{% if not member.profile.photo %}
<img alt="{{ member.profile.display_name }}" src="{% static 'members/images/default-avatar.jpg' %}" height="220" width="220" />
{% else %}
<img alt="{{ member.display_name }}" src="{% thumbnail member.photo '220x220' %}" width="220" height="220" />
<img alt="{{ member.profile.display_name }}" src="{% thumbnail member.profile.photo '220x220' %}" width="220" height="220" />
{% endif %}
</div>
{% if member.chair %}
......@@ -48,7 +48,7 @@
{% endif %}
<div class="post-overlay">
<div class="post-overlay-meta">
<h2>{{ member.display_name }}</h2>
<h2>{{ member.profile.display_name }}</h2>
<p>
{% if member.committee_since.year == 1970 %}
{% blocktrans %}Committee member since: ?{% endblocktrans %}
......@@ -59,7 +59,7 @@
</div>
</div>
<div class="post-body avatar-subtitle">
{{ member.display_name }}
{{ member.profile.display_name }}
</div>
</div>
</a>
......
from django.contrib.auth import get_user_model
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.db.utils import IntegrityError
from django.test import TestCase
......@@ -135,7 +135,7 @@ class PermissionsBackendTest(TestCase):
@classmethod
def setUpTestData(cls):
cls.u1 = Member.objects.get(pk=1)
cls.u1.user.is_superuser = False
cls.u1.is_superuser = False
cls.u1.save()
cls.u2 = Member.objects.get(pk=2)
cls.u3 = Member.objects.get(pk=3)
......@@ -147,12 +147,12 @@ class PermissionsBackendTest(TestCase):
member=cls.u2)
def test_permissions(self):
self.assertEqual(3, len(self.u1.user.get_all_permissions()))
self.assertEqual(set(), self.u2.user.get_all_permissions())
self.assertEqual(set(), self.u3.user.get_all_permissions())
self.assertEqual(3, len(self.u1.get_all_permissions()))
self.assertEqual(set(), self.u2.get_all_permissions())
self.assertEqual(set(), self.u3.get_all_permissions())
def test_nonmember_user(self):
u = get_user_model().objects.create(username='foo')
u = User.objects.create(username='foo')
self.assertEqual(set(), u.get_all_permissions())
......
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-10-13 13:35
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('members', '0018_create_proxy_member'),
('education', '0005_auto_20170906_2109'),
]
operations = [
migrations.AlterField(
model_name='exam',
name='uploader',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='members.Member', verbose_name='uploader'),
),
migrations.AlterField(
model_name='summary',
name='uploader',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='members.Member', verbose_name='uploader'),
),
]
from django.conf import settings
from django.db import models
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from members.models import Member
from utils.snippets import datetime_to_lectureyear
from utils.translation import ModelTranslateMeta, MultilingualField
......@@ -103,7 +103,7 @@ class Exam(models.Model, metaclass=ModelTranslateMeta):
)
uploader = models.ForeignKey(
settings.AUTH_USER_MODEL,
Member,
verbose_name=_('uploader'),
on_delete=models.CASCADE,
)
......@@ -159,7 +159,7 @@ class Summary(models.Model, metaclass=ModelTranslateMeta):
)
uploader = models.ForeignKey(
settings.AUTH_USER_MODEL,
Member,
verbose_name=_('uploader'),
on_delete=models.CASCADE,
)
......
......@@ -76,7 +76,7 @@ def submit_exam(request, id=None):
if form.is_valid():
saved = True
obj = form.save(commit=False)
obj.uploader = request.user
obj.uploader = request.member
obj.uploader_date = datetime.now()
obj.save()
......@@ -101,18 +101,18 @@ def submit_summary(request, id=None):
if form.is_valid():
saved = True
obj = form.save(commit=False)
obj.uploader = request.user
obj.uploader = request.member
obj.uploader_date = datetime.now()
obj.save()
obj = Summary()
obj.author = request.user.get_full_name()
obj.author = request.member.get_full_name()
form = AddSummaryForm(instance=obj)
else:
obj = Summary()
if id is not None:
obj.course = Course.objects.get(id=id)
obj.author = request.user.get_full_name()
obj.author = request.member.get_full_name()
form = AddSummaryForm(instance=obj)
return render(request, 'education/add_summary.html',
......
......@@ -72,12 +72,9 @@ class EventAdmin(DoNextModelAdmin):
title=obj.title)
def has_change_permission(self, request, event=None):
try:
if (event is not None and
not services.is_organiser(request.user, event)):
return False
except Member.DoesNotExist:
pass
if (event is not None and
not services.is_organiser(request.member, event)):
return False
return super().has_change_permission(request, event)
def event_date(self, obj):
......@@ -113,13 +110,10 @@ class EventAdmin(DoNextModelAdmin):
@staticmethod
def _change_published(request, queryset, published):
try:
if not request.user.is_superuser:
queryset = queryset.filter(
organiser__in=request.user.member.get_committees())
queryset.update(published=published)
except Member.DoesNotExist:
pass
if not request.user.is_superuser:
queryset = queryset.filter(
organiser__in=request.member.get_committees())
queryset.update(published=published)
def save_formset(self, request, form, formset, change):
"""Save formsets with their order"""
......@@ -146,13 +140,9 @@ class EventAdmin(DoNextModelAdmin):
if db_field.name == 'organiser':
# Use custom queryset for organiser field
# Only get the current active committees the user is a member of
try:
if not (request.user.is_superuser or
request.user.has_perm('events.override_organiser')):
kwargs['queryset'] = request.user.member.get_committees()
except Member.DoesNotExist:
pass
if not (request.user.is_superuser or
request.user.has_perm('events.override_organiser')):
kwargs['queryset'] = request.member.get_committees()
return super().formfield_for_foreignkey(db_field, request, **kwargs)
def get_actions(self, request):
......
......@@ -95,10 +95,10 @@ def export(request, event_id):
_('Date'): timezone.localtime(
registration.date).strftime("%Y-%m-%d %H:%m"),
_('Present'): _('Yes') if registration.present else '',
_('Phone number'): (registration.member.phone_number
_('Phone number'): (registration.member.profile.phone_number
if registration.member
else ''),
_('Email'): (registration.member.user.email
_('Email'): (registration.member.email
if registration.member
else ''),
_('Status'): status,
......@@ -142,9 +142,9 @@ def export(request, event_id):
def export_email(request, event_id):
event = get_object_or_404(Event, pk=event_id)
registrations = event.registration_set.filter(
date_cancelled=None).prefetch_related('member__user')
date_cancelled=None)
registrations = registrations[:event.max_participants]
addresses = [r.member.user.email for r in registrations if r.member]
addresses = [r.member.email for r in registrations if r.member]
no_addresses = [r.name for r in registrations if not r.member]
return render(request, 'events/admin/email_export.html',
{'event': event, 'addresses': addresses,
......
......@@ -77,7 +77,8 @@ class EventCalenderJSSerializer(CalenderJSSerializer):
def _registered(self, instance):
try:
return services.is_user_registered(instance, self.context['user'])
return services.is_user_registered(instance,
self.context['member'])
except AttributeError:
return None
......@@ -155,15 +156,14 @@ class EventRetrieveSerializer(serializers.ModelSerializer):
def _user_registration(self, instance):
try:
reg = instance.registration_set.get(
member=self.context['request'].user.member)
member=self.context['request'].member)
return RegistrationListSerializer(reg, context=self.context).data
except Registration.DoesNotExist:
return None
def _registration_allowed(self, instance):
member = self.context['request'].user.member
return (member is not None and
member.current_membership is not None and
member = self.context['request'].member
return (member.has_active_membership</