Skip to content
Snippets Groups Projects
Commit ef77b158 authored by Ingo Leindecker's avatar Ingo Leindecker
Browse files

Restricted read/write permissions to common users

See #23

- Let them only edit their own user profile and only certain fields
- Let them only edit shows they own and only certain fields
- Let them only edit own notes and only assign them to shows and timeslots they own

Removed some unused code and added some help texts to form fields.
parent b7e10ced
No related branches found
No related tags found
No related merge requests found
......@@ -10,19 +10,29 @@ class ProfileInline(admin.StackedInline):
verbose_name_plural = 'Profile'
fk_name = 'user'
class ProfileUserAdmin(UserAdmin):
inlines = (ProfileInline, )
def get_queryset(self, request):
# Users can only edit their own profile
'''Let common users only edit their own profile'''
if not request.user.is_superuser:
return super(UserAdmin, self).get_queryset(request).filter(pk=request.user.id)
return super(UserAdmin, self).get_queryset(request)
def get_readonly_fields(self, request, obj=None):
'''Limit field access for common users'''
if not request.user.is_superuser:
return ('username', 'is_staff', 'is_superuser', 'is_active', 'date_joined', 'last_login', 'groups', 'user_permissions')
return list()
def get_inline_instances(self, request, obj=None):
'''Append profile fields to UserAdmin'''
if not obj:
return list()
return super(ProfileUserAdmin, self).get_inline_instances(request, obj)
admin.site.unregister(User)
......
......@@ -12,21 +12,21 @@ from tinymce import models as tinymce_models
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
biography = tinymce_models.HTMLField(_("Biography"), blank=True, null=True)
website = models.URLField(_("Website"), blank=True)
googleplus_url = models.URLField(_("Google+ URL"), blank=True)
facebook_url = models.URLField(_("Facebook URL"), blank=True)
twitter_url = models.URLField(_("Twitter URL"), blank=True)
linkedin_url = models.URLField(_("LinkedIn URL"), blank=True)
youtube_url = models.URLField(_("Youtube URL"), blank=True)
dorftv_url = models.URLField(_("DorfTV URL"), blank=True)
cba_url = models.URLField(_("CBA URL"), blank=True)
cba_username = models.CharField(_("CBA Username"), blank=True, max_length=60)
cba_user_token = models.CharField(_("CBA Token"), blank=True, max_length=255)
biography = tinymce_models.HTMLField(_("Biography"), blank=True, null=True, help_text=_("Describe yourself and your fields of interest in a few sentences."))
website = models.URLField(_("Website"), blank=True, help_text=_("URL to your personal website."))
googleplus_url = models.URLField(_("Google+ URL"), blank=True, help_text=_("URL to your Google+ profile."))
facebook_url = models.URLField(_("Facebook URL"), blank=True, help_text=_("URL to your Facebook profile."))
twitter_url = models.URLField(_("Twitter URL"), blank=True, help_text=_("URL to your Twitter profile."))
linkedin_url = models.URLField(_("LinkedIn URL"), blank=True, help_text=_("URL to your LinkedIn profile."))
youtube_url = models.URLField(_("Youtube URL"), blank=True, help_text=_("URL to your Youtube channel."))
dorftv_url = models.URLField(_("DorfTV URL"), blank=True, help_text=_("URL to your dorfTV channel."))
cba_url = models.URLField(_("CBA URL"), blank=True, help_text=_("URL to your CBA profile."))
cba_username = models.CharField(_("CBA Username"), blank=True, max_length=60, help_text=_("Your username in CBA. This is necessary for uploading files to your account."))
cba_user_token = models.CharField(_("CBA Token"), blank=True, max_length=255, help_text=_("The CBA upload token for your account. This is NOT your password which you use to log into CBA!"))
ppoi = PPOIField('Image PPOI')
height = models.PositiveIntegerField('Image Height', blank=True, null=True, editable=False)
width = models.PositiveIntegerField('Image Width', blank=True, null=True,editable=False)
image = VersatileImageField(_("Profile picture"), blank=True, null=True, upload_to='user_images', width_field='width', height_field='height', ppoi_field='ppoi')
image = VersatileImageField(_("Profile picture"), blank=True, null=True, upload_to='user_images', width_field='width', height_field='height', ppoi_field='ppoi', help_text=_("Upload a picture of yourself. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save."))
def __str__(self):
return self.user.username
......
......@@ -5,7 +5,7 @@ from django.shortcuts import render
from django.conf import settings
from .models import Language, Type, MusicFocus, Category, Topic, RTRCategory, Host, Note, RRule, Schedule, Show, TimeSlot
from .forms import MusicFocusForm, CollisionForm
from .forms import MusicFocusForm
from datetime import date, datetime, time, timedelta
......@@ -202,6 +202,14 @@ class ShowAdmin(admin.ModelAdmin):
'musicfocus', 'fallback_pool', 'cba_series_id',
)
class Media:
js = [ settings.MEDIA_URL + 'js/calendar/lib/moment.min.js',
settings.MEDIA_URL + 'js/show_change.js', ]
css = { 'all': ('/program/styles.css',) }
def get_queryset(self, request):
if request.user.is_superuser:
# Superusers see all shows
......@@ -212,11 +220,12 @@ class ShowAdmin(admin.ModelAdmin):
return super(ShowAdmin, self).get_queryset(request).filter(pk__in=shows)
class Media:
js = [ settings.MEDIA_URL + 'js/calendar/lib/moment.min.js',
settings.MEDIA_URL + 'js/show_change.js', ]
css = { 'all': ('/program/styles.css',) }
def get_readonly_fields(self, request, obj=None):
'''Limit field access for common users'''
if not request.user.is_superuser:
return ('predecessor', 'type', 'hosts', 'owners', 'language', 'category', 'topic', 'musicfocus', 'rtrcategory')
return list()
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
......@@ -490,13 +499,16 @@ class ShowAdmin(admin.ModelAdmin):
Displays the collision form for the current schedule otherwise
"""
# Never check for collisions if not superuser
# Common users can't edit the formset, so save_formset() will never be called thus end_reached wasn't set yet
if not request.user.is_superuser:
self.end_reached = True
if self.end_reached:
return super(ShowAdmin, self).response_change(request, obj)
timeslots_to_collisions = list(zip(self.timeslots, self.collisions))
# myform = CollisionForm(self.timeslots, self.collisions)
return render(request, 'collisions.html', {'self' : self, 'obj': obj, 'request': request,
'timeslots': self.timeslots,
'collisions': self.collisions,
......
......@@ -5,16 +5,6 @@ from django.core.files.images import get_image_dimensions
from program.models import MusicFocus, Category, Topic
# Couldn't manage call/validation for collision usecase.
class CollisionForm(forms.Form):
def __init__(self, timeslots, collisions, *args, **kwargs):
super(CollisionForm, self).__init__(*args, **kwargs)
for i in range(min(len(timeslots), len(timeslots))):
self.fields['resolved_' + str(i)] = forms.ChoiceField(widget=forms.RadioSelect,choices=((timeslots[i], timeslots[i]),(collisions[i], collisions[i])))
class FormWithButton(ModelForm):
def clean_button(self):
button = self.cleaned_data.get('button')
......
......@@ -268,18 +268,18 @@ class Show(models.Model):
rtrcategory = models.ForeignKey(RTRCategory, related_name='shows', verbose_name=_("RTR Category"))
topic = models.ManyToManyField(Topic, blank=True, related_name='shows', verbose_name=_("Topic"))
musicfocus = models.ManyToManyField(MusicFocus, blank=True, related_name='shows', verbose_name=_("Music focus"))
name = models.CharField(_("Name"), max_length=255)
slug = models.CharField(_("Slug"), max_length=255, unique=True)
name = models.CharField(_("Name"), max_length=255, help_text=_("The show's name. Avoid a subtitle."))
slug = models.CharField(_("Slug"), max_length=255, unique=True, help_text=_("A simple to read URL for your show"))
ppoi = PPOIField('Image PPOI')
height = models.PositiveIntegerField('Image Height', blank=True, null=True, editable=False)
width = models.PositiveIntegerField('Image Width', blank=True, null=True,editable=False)
image = VersatileImageField(_("Image"), blank=True, null=True, upload_to='show_images', width_field='width', height_field='height', ppoi_field='ppoi')
image = VersatileImageField(_("Image"), blank=True, null=True, upload_to='show_images', width_field='width', height_field='height', ppoi_field='ppoi', help_text=_("Upload an image to your show. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save."))
logo = models.ImageField(_("Logo"), blank=True, null=True, upload_to='show_images')
short_description = models.CharField(_("Short description"), max_length=64)
description = tinymce_models.HTMLField(_("Description"), blank=True, null=True)
email = models.EmailField(_("E-Mail"), blank=True, null=True)
website = models.URLField(_("Website"), blank=True, null=True)
cba_series_id = models.IntegerField(_("CBA Series ID"), blank=True, null=True)
short_description = models.TextField(_("Short description"), help_text=_("Describe your show in some sentences. Avoid technical data like airing times and contact information. They will be added automatically."))
description = tinymce_models.HTMLField(_("Description"), blank=True, null=True, help_text=_("Describe your show in detail."))
email = models.EmailField(_("E-Mail"), blank=True, null=True, help_text=_("The main contact email address for your show."))
website = models.URLField(_("Website"), blank=True, null=True, help_text=_("Is there a website to your show? Type in its URL."))
cba_series_id = models.IntegerField(_("CBA Series ID"), blank=True, null=True, help_text=_("Link your show to a CBA series by giving its ID. This will enable CBA upload and will automatically link your show to your CBA archive. Find out your ID under https://cba.fro.at/series"))
fallback_pool = models.CharField(_("Fallback Pool"), max_length=255, blank=True)
created = models.DateTimeField(auto_now_add=True, editable=False)
last_updated = models.DateTimeField(auto_now=True, editable=False)
......@@ -602,18 +602,18 @@ class Note(models.Model):
(2, _("Repetition")),
)
timeslot = models.OneToOneField(TimeSlot, verbose_name=_("Time slot"), unique=True)
title = models.CharField(_("Title"), max_length=128)
slug = models.SlugField(_("Slug"), max_length=32, unique=True)
summary = tinymce_models.HTMLField(_("Summary"), blank=True)
content = tinymce_models.HTMLField(_("Content"))
title = models.CharField(_("Title"), max_length=128, help_text=_("Give your note a good headline. What will your upcoming show be about? Try to arouse interest to listen to it!<br>Avoid technical data like the show's name, its airing times or its episode number. These data are added automatically."))
slug = models.SlugField(_("Slug"), max_length=32, unique=True, help_text=_("A simple to read URL for your show."))
summary = tinymce_models.HTMLField(_("Summary"), blank=True, help_text=_("Describe your upcoming show in some sentences. Avoid technical data like airing times and contact information. They will be added automatically."))
content = tinymce_models.HTMLField(_("Content"), help_text=_("Describe your upcoming show in detail."))
ppoi = PPOIField('Image PPOI')
height = models.PositiveIntegerField('Image Height', blank=True, null=True, editable=False)
width = models.PositiveIntegerField('Image Width', blank=True, null=True,editable=False)
image = VersatileImageField(_("Featured image"), blank=True, null=True, upload_to='note_images', width_field='width', height_field='height', ppoi_field='ppoi')
image = VersatileImageField(_("Featured image"), blank=True, null=True, upload_to='note_images', width_field='width', height_field='height', ppoi_field='ppoi', help_text=_("Upload an image to your show. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save."))
status = models.IntegerField(_("Status"), choices=STATUS_CHOICES, default=1)
start = models.DateTimeField(editable=False)
show = models.ForeignKey(Show, related_name='notes', editable=True) # User chooses the show. Timeslots are loaded via ajax.
cba_id = models.IntegerField(_("CBA ID"), blank=True, null=True)
show = models.ForeignKey(Show, related_name='notes', editable=True)
cba_id = models.IntegerField(_("CBA ID"), blank=True, null=True, help_text=_("Link the note to a certain CBA post by giving its ID. (E.g. if your post's CBA URL is https://cba.fro.at/1234, then your CBA ID is 1234)"))
created = models.DateTimeField(auto_now_add=True, editable=False)
last_updated = models.DateTimeField(auto_now=True, editable=False)
user = models.ForeignKey(User, editable=False, related_name='users', default=1)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment