Commit 25d04332 authored by alexandre's avatar alexandre

Switched from django guardian to plain permissions

parent 01ba42fc
......@@ -28,6 +28,8 @@ INSTALLED_APPS = [
'django.contrib.flatpages',
'guardian',
'adminsortable2',
'taggit',
......
......@@ -39,7 +39,7 @@ class Score(models.Model):
is_public = models.BooleanField(default=False)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, blank=True, null=True, related_name="creator")
shared_with = models.ManyToManyField(settings.AUTH_USER_MODEL)
shared_with = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True)
def __str__(self):
return self.title
......
......@@ -8,6 +8,8 @@ from taggit_serializer.serializers import (TagListSerializerField,
from django.contrib.auth.models import User
from django.contrib.flatpages.models import FlatPage
from django.contrib.auth.validators import UnicodeUsernameValidator
class FlatPageSerializer(serializers.HyperlinkedModelSerializer):
......@@ -24,6 +26,13 @@ class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ['username', 'id']
# Dealing with "A user with that username already exists." Thanks!
# https://medium.com/django-rest-framework/dealing-with-unique-constraints-in-nested-serializers-dade33b831d9
extra_kwargs = {
'username': {
'validators': [UnicodeUsernameValidator()],
}
}
class AttachmentSerializer(serializers.HyperlinkedModelSerializer):
......@@ -39,37 +48,36 @@ class ScoreSerializer(TaggitSerializer, serializers.HyperlinkedModelSerializer):
id = serializers.ReadOnlyField()
tags = TagListSerializerField(required=False)
is_editable = serializers.SerializerMethodField()
created_by = UserSerializer()
shared_with = UserSerializer(many=True)
created_by = UserSerializer(required=False)
shared_with = UserSerializer(many=True, required=False)
class Meta:
model = Score
fields = '__all__'
# def create(self, validated_data):
# validated_data.pop('permissions', None)
# instance = Score.objects.create(**validated_data)
# assign_perm("view_score", self.context['request'].user, instance)
# return instance
def create(self, validated_data):
validated_data["created_by"] = self.context['request'].user
instance = Score.objects.create(**validated_data)
return instance
def get_is_editable(self, obj):
current_user = self.context['request'].user
return obj.created_by == current_user
# return self.context['request'].user.has_perm('change_score', obj)
return obj.created_by == current_user or current_user in obj.shared_with.all()
def update(self, instance, validated_data):
# Dealing with "A user with that username already exists." Thanks!
# https://medium.com/django-rest-framework/dealing-with-unique-constraints-in-nested-serializers-dade33b831d9
created_by_data = validated_data.pop('created_by')
shared_with = validated_data.pop('shared_with')
self.instance.shared_with.clear()
for i in shared_with:
user = User.objects.get(username=i["username"])
if user:
print("adding {}".format(user.username))
self.instance.shared_with.add(user)
instance = super(ScoreSerializer, self).update(instance, validated_data)
### for user, perms in get_users_with_perms(instance, attach_perms=True).items():
# for perm in perms:
### remove_perm(perm, user, instance)
# for i in instance.permissions:
# user = User.objects.get(username=i.get('username'))
# perms = i.get('permissions')
# for perm in perms:
### assign_perm(perm, user, instance)
return instance
......
......@@ -1840,3 +1840,12 @@ ol::before {
margin-top: var(--line-height);
margin-bottom: var(--line-height);
}
.autocomplete-suggestions { background: #FFF; overflow: auto; }
.autocomplete-suggestion { padding: 2px 5px; white-space: nowrap; overflow: hidden; color: var(--background-color); cursor: default; }
.autocomplete-selected { background: #F0F0F0; }
.autocomplete-suggestions strong { font-weight: bold; }
/* .autocomplete-group { padding: 2px 5px; } */
/* .autocomplete-group strong { display: block; border-bottom: 1px solid #000; } */
......@@ -55,7 +55,7 @@ window.W = window.W || {};
W.ChoiceModel = Backbone.Model.extend({});
W.UserModel = Backbone.Model.extend({
W.UserModel = Backbone.RelationalModel.extend({
urlRoot: '/api/users/',
label: function () {
......@@ -129,7 +129,8 @@ window.W = window.W || {};
presentation: "",
effectif: "",
language: "",
permissions: {}
permissions: {},
shared_with: []
},
urlRoot: '/api/scores/',
......@@ -161,6 +162,17 @@ window.W = window.W || {};
includeInJSON: false,
type: Backbone.HasOne
}
},
{
type: Backbone.HasMany,
key: 'shared_with',
relatedModel: 'UserModel',
collectionType: 'UserCollection',
reverseRelation: {
key: 'score',
includeInJSON: false,
type: Backbone.HasOne
}
}
],
......
This diff is collapsed.
......@@ -159,6 +159,10 @@
{% include "playground/underscore/search.mtpl" %}
</script>
<script id="share-with-template" type="text/template">
{% include "playground/underscore/share-with.mtpl" %}
</script>
<script id="slider-template" type="text/template">
{% include "playground/underscore/slider.mtpl" %}
</script>
......@@ -190,6 +194,7 @@
<script src="{% static 'playground/vendors/moment-with-locales.min.js' %}"></script>
<script src="{% static 'playground/vendors/jquery-ui.min.js' %}"></script>
<script src="{% static 'playground/vendors/jquery.mjs.nestedSortable.js' %}"></script>
<script src="{% static 'playground/vendors/jquery.autocomplete.min.js' %}"></script>
<script src="{% static 'playground/js/i18n/fr.js' %}"></script>
<script src="{% static 'playground/js/i18n/en.js' %}"></script>
......
......@@ -13,10 +13,9 @@
</ul>
</nav>
<div id="create"></div>
<div id="create" class="main-header__create create"></div>
<nav class="main-header__user">
<%- isLoggedIn %> -----
<% if (isLoggedIn) { %>
<%- t('Bienvenue') %> <a href="/compte"><%- username %></a> <a href="#" class="js-logout">(←)</a>
<% } %>
......
......@@ -60,5 +60,13 @@
<input type="text" name="language" value="<%- (language) ? language : W.utils.getUserLanguage() %>">
</label>
<!-- Permissions -->
<label>
<span class="label-text"><%- t('Est public?') %>: </span>
<input type="checkbox" name="is_public" <% if (is_public) { %>checked<% } %>>
</label>
<div id="share_with"></div>
<button data-name="close"><%- t('Annuler') %></button>
<button data-name="submit">OK</button>
......@@ -106,6 +106,23 @@
<dd class="score-meta__def"><%- formatTimestamp(updated_at) %></dd>
</dl>
{% comment %}
<dl class="score-meta">
<dt class="score-meta__term score-meta__term--inline"><%- t('Créé par') %></dt>
<dd class="score-meta__def"><%- created_by.username %></dd>
<dt class="score-meta__term score-meta__term--inline"><%- t('Partagé avec') %></dt>
<dd class="score-meta__def">
<ul>
<% for (var i=0; i < shared_with.length; i++) { %>
<li><%- shared_with[i].username %></li>
<% } %>
</ul>
</dd>
<dt class="score-meta__term score-meta__term--inline"><%- t('Est public?') %></dt>
<dd class="score-meta__def"><%- is_public %></dd>
</dl>
{% endcomment %}
<div id="permissions"></div>
<form></form>
......
<input type="text" name="country" id="autocomplete"/>
<div id="user-list"></div>
<h2>Partitions partagées avec vous</h2>
<div id="list"></div>
......@@ -99,19 +99,6 @@ class ScoreFilterBackend(BaseFilterBackend):
"""
Filter that only allows users to see their own objects.
"""
# def filter_queryset(self, request, queryset, view):
# import ipdb; ipdb.set_trace()
# qs1 = queryset.filter(is_public=True)
# # returns Public scores only for Anonymous users
# if request.user.is_anonymous():
# return qs1
# qs2 = queryset.filter(created_by=request.user)
# qs3 = queryset.filter(shared_with=request.user)
# # returns public scores together with owned or shared-with scores
# return qs1.union(qs2, qs3)
def filter_queryset(self, request, queryset, view):
# returns Public scores only for Anonymous users
if request.user.is_anonymous():
......@@ -119,7 +106,7 @@ class ScoreFilterBackend(BaseFilterBackend):
else:
return queryset.filter(Q(is_public=True)
| Q(created_by=request.user)
| Q(shared_with=request.user))
| Q(shared_with=request.user)).distinct()
class ScoreViewSet(viewsets.ModelViewSet):
......@@ -129,7 +116,6 @@ class ScoreViewSet(viewsets.ModelViewSet):
_ignore_model_permissions = True # Seems essential to django guardian
queryset = Score.objects.all()
pagination_class = ScoreViewSetPagination
# filter_backends = (DjangoFilterBackend, OrderingFilter, SearchFilter, ScoreFilterBackend)
filter_backends = (DjangoFilterBackend, OrderingFilter, SearchFilter, ScoreFilterBackend)
authentication_classes = (SessionAuthentication,)
permission_classes = (ScorePermission,)
......@@ -164,25 +150,35 @@ class ScoreViewSet(viewsets.ModelViewSet):
data = [{'value': i['language'], 'label': i['language'], 'n': i['n']} for i in data if i['language']]
return Response(data)
# def get_queryset(self):
# """
# Filter featured scores
# """
# queryset = super(ScoreViewSet, self).get_queryset()
# shared_with = self.request.query_params.get('shared_with', None)
# if shared_with is not None:
# # Do not return scores for AnonymousUser
# if (self.request.user.is_anonymous()):
# return queryset.none()
# ### return get_objects_for_user(self.request.user, 'playground.view_score')
# is_featured= self.request.query_params.get('is_featured', None)
# if is_featured is not None:
# ids = FeaturedScore.objects.all().order_by('-order').values_list("score__id", flat=True)
# return queryset.filter(id__in=ids)
# return queryset
def get_queryset(self):
"""
Filter featured scores
"""
queryset = super(ScoreViewSet, self).get_queryset()
can_edit = self.request.query_params.get('can_edit', None)
if can_edit is not None:
if (self.request.user.is_anonymous()):
# Do not return scores for AnonymousUser
queryset = queryset.none()
else:
queryset = queryset.filter(Q(created_by=self.request.user)
| Q(shared_with=self.request.user)).distinct()
shared_with = self.request.query_params.get('shared_with', None)
if shared_with is not None:
if (self.request.user.is_anonymous()):
# Do not return scores for AnonymousUser
queryset = queryset.none()
else:
queryset = queryset.filter(shared_with=self.request.user)
is_featured= self.request.query_params.get('is_featured', None)
if is_featured is not None:
ids = FeaturedScore.objects.all().order_by('-order').values_list("score__id", flat=True)
queryset = queryset.filter(id__in=ids)
return queryset
def get_serializer_class(self, *args, **kwargs):
"""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment