Gitlab CSE Unil

Commit 7d2e167d authored by Julien Furrer's avatar Julien Furrer
Browse files

Updated RestFramework permission, adapted AnobjMgr properties for TTP

DRF:
	Updated permission check for Annotation (compatibility with v3.*) using PermissionClass
	Added a TTPAuthentication class (adim_ttp.authentication.TTPAuthentication) so api call can be done without user token

AnObj Manager:
	Updated the properties panel for TTP shared object: the link for editing the object in the distant service is more visible
parent 6ed8a210
...@@ -13,8 +13,77 @@ from adim.permissions import has_anobj_access ...@@ -13,8 +13,77 @@ from adim.permissions import has_anobj_access
from rest_framework import viewsets from rest_framework import viewsets
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.decorators import detail_route from rest_framework.decorators import detail_route
from rest_framework.permissions import BasePermission, SAFE_METHODS
# ================================
# RestFramework Permission Classes
# ================================
class AccessibleAnObj(BasePermission):
"""
RestFramework Object-level permission to allow acces to objects related to an accessible AnObj
Assumes the model instance has an `annotable` attribute.
"""
def has_object_permission(self, request, view, obj):
try:
return has_anobj_access(request, obj.annotable)
except AnObj.DoesNotExist:
return False
except AttributeError:
return False
class IsOwnerOrReadOnly(BasePermission):
"""
RestFramework Object-level permission to only allow owners of an object to edit it.
Assumes the model instance has an `owner` or an `owners` attribute.
"""
def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in SAFE_METHODS:
return True
# Instance must have an attribute named `owner` or `owners`
if hasattr(obj, 'owner'):
return obj.owner == request.user
elif hasattr(obj, 'owners'):
return obj.owners.filter(id=request.user.id).exists()
else:
return False
class WritableAnObjOrReadonly(BasePermission):
"""
RestFramework Object-level permission to only allow modification on objects
related to an unlocked AnObj
Assumes the model instance has an `annotable` attribute.
"""
def has_permission(self, request, view):
# For CREATE action, there is no annotation yet, so we have to fetch AnObj first to check for locked state
if view.action == 'create':
try:
annotable = AnObj.objects.get(pk=request.data.get('annotable', -1))
return not annotable.locked
except AnObj.DoesNotExist:
return False
return True
def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in SAFE_METHODS:
return True
return not obj.annotable.locked
# ======================
# RestFramework ViewSets
# ======================
class AnObjViewSet(viewsets.ModelViewSet): class AnObjViewSet(viewsets.ModelViewSet):
""" """
Viewset for owned AnObj, requested by user who is the owner. Viewset for owned AnObj, requested by user who is the owner.
...@@ -211,6 +280,7 @@ class AnnotationViewSet(viewsets.ModelViewSet): ...@@ -211,6 +280,7 @@ class AnnotationViewSet(viewsets.ModelViewSet):
""" """
model = Annotation model = Annotation
serializer_class = AnnotationSerializer serializer_class = AnnotationSerializer
permission_classes = (AccessibleAnObj, IsOwnerOrReadOnly, WritableAnObjOrReadonly)
def get_queryset(self): def get_queryset(self):
if self.request.user.has_perm('adim.can_review_exercise'): if self.request.user.has_perm('adim.can_review_exercise'):
...@@ -219,38 +289,51 @@ class AnnotationViewSet(viewsets.ModelViewSet): ...@@ -219,38 +289,51 @@ class AnnotationViewSet(viewsets.ModelViewSet):
queryset = Annotation.objects.filter(owner=self.request.user) queryset = Annotation.objects.filter(owner=self.request.user)
return queryset return queryset
# def list(self, request): def create(self, request, *args, **kwargs):
# return Response([])
def pre_save(self, obj):
""" """
For new annotation, check annotable access permission Override create to set annotation's owner to request.owner
and set the owner of the annotation :param request:
:param obj: :param args:
:param kwargs:
:return: :return:
""" """
# if not obj.annotable.locked: request.data['owner'] = request.user.id
# raise Exception("Annotable locked") request.data['owner_id'] = request.user.id
return super(AnnotationViewSet, self).create(request, *args, **kwargs)
if obj.id:
if obj.owner != self.request.user:
raise Exception("Annotable access forbidden")
else:
# user = self.request.user
# anobj_q = Q(pk=obj.annotable_id) & (Q(owner=user) | Q(members=user))
try:
anobj = AnObj.objects.get(pk=obj.annotable_id)
if not has_anobj_access(self.request, anobj):
raise Exception("Annotable access forbidden")
except AnObj.DoesNotExist:
raise Exception("Annotable access forbidden")
# if not AnObj.objects.filter(anobj_q).exists():
obj.owner = self.request.user # def list(self, request):
# return Response([])
super(AnnotationViewSet, self).pre_save(obj) #
# def pre_save(self, obj):
# """
# For new annotation, check annotable access permission
# and set the owner of the annotation
# :param obj:
# :return:
# """
# if obj.annotable.locked:
# raise Exception("Annotable locked")
#
# # ok
# if obj.id:
# if obj.owner != self.request.user:
# raise Exception("Annotable access forbidden")
#
# else:
# # user = self.request.user
# # anobj_q = Q(pk=obj.annotable_id) & (Q(owner=user) | Q(members=user))
# try:
# anobj = AnObj.objects.get(pk=obj.annotable_id)
# if not has_anobj_access(self.request, anobj):
# raise Exception("Annotable access forbidden")
#
# except AnObj.DoesNotExist:
# raise Exception("Annotable access forbidden")
# # if not AnObj.objects.filter(anobj_q).exists():
#
# obj.owner = self.request.user
#
# super(AnnotationViewSet, self).pre_save(obj)
class SharedAnnotationViewSet(viewsets.ReadOnlyModelViewSet): class SharedAnnotationViewSet(viewsets.ReadOnlyModelViewSet):
......
...@@ -99,7 +99,6 @@ function($, _, Signal, paper, config, view, io, tools, attributes, Users, export ...@@ -99,7 +99,6 @@ function($, _, Signal, paper, config, view, io, tools, attributes, Users, export
_canvasCtnrTop = _canvasCtnr.offset().top + _canvasToolBar.outerHeight(); _canvasCtnrTop = _canvasCtnr.offset().top + _canvasToolBar.outerHeight();
window.DBG = tools;
//$("#annotation-property-panel").remove(); //$("#annotation-property-panel").remove();
//$("body").addClass("mode-"+config.mode); //$("body").addClass("mode-"+config.mode);
...@@ -404,7 +403,12 @@ function($, _, Signal, paper, config, view, io, tools, attributes, Users, export ...@@ -404,7 +403,12 @@ function($, _, Signal, paper, config, view, io, tools, attributes, Users, export
// //
// AnObj name edit // AnObj name edit
// --------------- // ---------------
if (! config.user.guest) { if (config.user.guest || config.annotable.locked || config.annotable.ttpShared) {
$("a.adim-image-name")
.on('click', function(e){
e.preventDefault();
});
} else {
this._anObjNameModal = $("#adim-name-modal") this._anObjNameModal = $("#adim-name-modal")
.modal({'show': false}); .modal({'show': false});
this._anObjNameModal.find("button.btn-primary").on("click", function (evt) { this._anObjNameModal.find("button.btn-primary").on("click", function (evt) {
......
...@@ -51,7 +51,9 @@ define([ ...@@ -51,7 +51,9 @@ define([
this.sharingPropEl.find(".aom-prop-locked-info").popover({ this.sharingPropEl.find(".aom-prop-locked-info").popover({
placement: 'bottom', placement: 'bottom',
trigger: 'focus', trigger: 'hover',
delay: { "show": 500, "hide": 100 },
//animation: false,
html: true, html: true,
viewport: {selector: '.aom-info-share', padding: 15} viewport: {selector: '.aom-info-share', padding: 15}
}); });
...@@ -138,18 +140,24 @@ define([ ...@@ -138,18 +140,24 @@ define([
.toggleClass("aom-prop-unlocked", !locked); .toggleClass("aom-prop-unlocked", !locked);
if (ttpShared) { if (ttpShared) {
this.$(".aom-shm-frontdrop").css("visibility", "hidden"); // Inhibbit the locking overlay for ttp sharing (not applied even for locked ttp images)
this.$(".aom-prop-lock-but").attr("disabled", "disabled"); this.$(".aom-prop-lock-but").attr("disabled", "disabled");
} else { } else {
this.$(".aom-shm-frontdrop").css("visibility", "visible"); // Restore the locking overlay capability (it is active only for locked images)
this.$(".aom-prop-lock-but").removeAttr("disabled"); this.$(".aom-prop-lock-but").removeAttr("disabled");
} }
var sharingModeSelect = this.sharingPropEl.find("[name=aom-prop-shared]"); var sharingModeSelect = this.sharingPropEl.find("[name=aom-prop-shared]");
if (ttpShared || _.isUndefined(sharingMode) || sharingMode === "" ) { if (ttpShared || _.isUndefined(sharingMode) || sharingMode === "" ) {
sharingModeSelect.attr("disabled", "disabled"); sharingModeSelect.attr("disabled", "disabled");
this.publicPublishEl.attr("disabled", "disabled"); this.publicPublishEl
.attr("disabled", "disabled")
.closest(".checkbox").addClass("disabled text-muted");
} else { } else {
sharingModeSelect.removeAttr("disabled"); sharingModeSelect.removeAttr("disabled");
this.publicPublishEl.removeAttr("disabled"); this.publicPublishEl
.removeAttr("disabled")
.closest(".checkbox").removeClass("disabled text-muted");
} }
sharingModeSelect.val([sharingMode]); sharingModeSelect.val([sharingMode]);
this.publicPublishEl.val([publicPublish]); this.publicPublishEl.val([publicPublish]);
...@@ -213,7 +221,15 @@ define([ ...@@ -213,7 +221,15 @@ define([
'attp_label': function($el, model, opts) { 'attp_label': function($el, model, opts) {
if (opts.url && opts.label) { if (opts.url && opts.label) {
$el.attr("href", opts.url).text(opts.label); $el.text(opts.label);
} else {
$el.closest('.aom-prop-shm').addClass('hidden');
}
},
'attp_url': function($el, model, opts) {
if (opts.url && opts.label) {
$el.attr("href", opts.url);
} else { } else {
$el.closest('.aom-prop-shm').addClass('hidden'); $el.closest('.aom-prop-shm').addClass('hidden');
} }
...@@ -338,7 +354,7 @@ define([ ...@@ -338,7 +354,7 @@ define([
}, },
// Registration Kes handling // Registration Key handling
// ------------------------- // -------------------------
showRegkeyValue: (function(){ showRegkeyValue: (function(){
var $but, $el; var $but, $el;
......
{
"metadata": {
"name": "Adim glyphs 1",
"lastOpened": 1432031460989,
"created": 1432031411734
},
"iconSets": [
{
"selection": [
{
"order": 5,
"id": 1,
"prevSize": 32,
"code": 58883,
"name": "moodle",
"tempChar": ""
}
],
"id": 3,
"metadata": {
"name": "TTP_icons",
"importSize": {
"width": 32,
"height": 32
}
},
"height": 1024,
"prevSize": 32,
"icons": [
{
"id": 1,
"paths": [
"M1024 528c0-19.2-3.2-38.4-6.4-54.4-16-64-57.6-102.4-115.2-124.8-48-19.2-99.2-22.4-150.4-19.2s-99.2 12.8-134.4 54.4c-3.2-3.2-6.4-6.4-9.6-9.6-9.6-6.4-16-9.6-25.6-16-19.2 38.4-44.8 67.2-76.8 92.8-3.2 3.2-6.4 6.4-9.6 9.6 3.2 3.2 9.6 3.2 12.8 6.4 19.2 16 28.8 41.6 28.8 67.2 0 105.6 0 211.2 0 320 0 6.4 0 9.6 0 16 54.4 0 108.8 0 163.2 0 0-6.4 0-12.8 0-16 0-105.6 0-211.2 0-313.6 0-19.2 6.4-38.4 16-51.2 19.2-32 64-41.6 99.2-25.6 16 6.4 32 19.2 38.4 35.2s9.6 35.2 9.6 54.4c0 102.4 0 204.8 0 304 0 6.4 0 9.6 0 16 54.4 0 108.8 0 163.2 0 0-3.2 0-9.6 0-12.8-3.2-112-3.2-220.8-3.2-332.8z",
"M572.8 336c-22.4-16-41.6-38.4-73.6-44.8 60.8-44.8 115.2-83.2 172.8-124.8 0 0 0-3.2-3.2-3.2-48 6.4-92.8 9.6-140.8 16-38.4 6.4-76.8 12.8-115.2 22.4s-80 16-118.4 28.8c-64 19.2-124.8 44.8-182.4 76.8-28.8 16-57.6 32-86.4 51.2 0 0-3.2 0-3.2 0s0 0 0 3.2c-3.2 3.2-9.6 3.2-12.8 6.4-3.2 0-6.4 3.2-9.6 3.2 0 0 0 3.2 0 3.2 6.4 0 16 0 22.4 0 0 22.4 0 44.8 0 67.2 0 38.4 3.2 76.8-9.6 112 0 3.2 0 6.4 0 9.6-3.2 44.8 9.6 89.6 25.6 131.2 3.2 6.4 6.4 12.8 9.6 22.4 3.2-57.6 6.4-112-6.4-166.4s-12.8-108.8-9.6-163.2c0-6.4 0-12.8 9.6-12.8 32 0 64 0 96-3.2 3.2 0 6.4 3.2 9.6 3.2 16 0 32 3.2 48 3.2 0 16 0 28.8 0 44.8 0 19.2 3.2 38.4 6.4 57.6 9.6 3.2 19.2 3.2 28.8 6.4 41.6 9.6 83.2 12.8 128 6.4 3.2 0 6.4 0 6.4 0 22.4-6.4 44.8-12.8 67.2-22.4 16-6.4 32-16 51.2-25.6 3.2-3.2 6.4-6.4 9.6-9.6 35.2-32 60.8-64 80-99.2z",
"M377.6 512c-3.2 0-6.4 0-6.4 0-41.6 6.4-86.4 3.2-128-6.4-9.6-3.2-19.2-3.2-28.8-6.4 0 6.4-3.2 12.8-3.2 22.4 0 112 0 227.2 0 339.2 0 3.2 0 6.4 0 12.8 51.2 0 99.2 0 147.2 0 12.8 0 16-3.2 12.8-16 0-92.8 0-182.4 0-275.2 3.2-25.6 6.4-48 6.4-70.4z"
],
"attrs": [
{},
{},
{}
],
"isMulticolor": false,
"grid": 0,
"tags": [
"moodle"
]
}
],
"invisible": false
},
{
"selection": [
{
"order": 6,
"id": 0,
"prevSize": 32,
"code": 61493,
"name": "clippy",
"tempChar": ""
}
],
"id": 1,
"metadata": {
"name": "Untitled Set 2",
"importSize": 1024
},
"height": 1024,
"prevSize": 32,
"icons": [
{
"id": 0,
"paths": [
"M704 896h-640v-576h640v192h64v-320c0-35-29-64-64-64h-192c0-71-57-128-128-128s-128 57-128 128h-192c-35 0-64 29-64 64v704c0 35 29 64 64 64h640c35 0 64-29 64-64v-128h-64v128zM192 192c29 0 29 0 64 0s64-29 64-64 29-64 64-64 64 29 64 64 32 64 64 64 33 0 64 0 64 29 64 64h-512c0-39 28-64 64-64zM128 704h128v-64h-128v64zM576 576v-128l-256 192 256 192v-128h320v-128h-320zM128 832h192v-64h-192v64zM448 384h-320v64h320v-64zM256 512h-128v64h128v-64z"
],
"attrs": [
{}
],
"width": 896,
"tags": [
"clippy"
],
"defaultCode": 61493,
"grid": 0
}
],
"invisible": false
},
{
"selection": [
{
"order": 1,
"id": 8,
"prevSize": 32,
"code": 58882,
"name": "color",
"tempChar": "",
"ligatures": ""
},
{
"order": 2,
"id": 7,
"prevSize": 32,
"code": 58881,
"name": "opacity",
"tempChar": "",
"ligatures": ""
},
{
"order": 3,
"id": 5,
"prevSize": 32,
"code": 58880,
"name": "line-width",
"tempChar": "",
"ligatures": ""
}
],
"id": 0,
"metadata": {
"name": "Drawing Tools"
},
"height": 1024,
"prevSize": 32,
"icons": [
{
"id": 8,
"paths": [
"M1024 512c0 282.77-229.23 512-512 512s-512-229.23-512-512c0-282.77 229.23-512 512-512s512 229.23 512 512z"
],
"attrs": [
{}
],
"grid": 32,
"tags": [
"color"
]
},
{
"id": 7,
"paths": [
"M528 336h32v32h-32v-32z",
"M592 336h32v32h-32v-32z",
"M656 336h32v32h-32v-32z",
"M720 336h32v32h-32v-32z",
"M496 368h32v32h-32v-32z",
"M560 368h32v32h-32v-32z",
"M624 368h32v32h-32v-32z",
"M688 368h32v32h-32v-32z",
"M464 400h32v32h-32v-32z",
"M528 400h32v32h-32v-32z",
"M592 400h32v32h-32v-32z",
"M656 400h32v32h-32v-32z",
"M720 400h32v32h-32v-32z",
"M752 368h32v32h-32v-32z",
"M432 432h32v32h-32v-32z",
"M496 432h32v32h-32v-32z",
"M560 432h32v32h-32v-32z",
"M624 432h32v32h-32v-32z",
"M688 432h32v32h-32v-32z",
"M400 464h32v32h-32v-32z",
"M464 464h32v32h-32v-32z",
"M528 464h32v32h-32v-32z",
"M592 464h32v32h-32v-32z",
"M656 464h32v32h-32v-32z",
"M720 464h32v32h-32v-32z",
"M752 432h32v32h-32v-32z",
"M368 496h32v32h-32v-32z",
"M432 496h32v32h-32v-32z",
"M496 496h32v32h-32v-32z",
"M560 496h32v32h-32v-32z",
"M624 496h32v32h-32v-32z",
"M688 496h32v32h-32v-32z",
"M336 528h32v32h-32v-32z",
"M400 528h32v32h-32v-32z",
"M464 528h32v32h-32v-32z",
"M528 528h32v32h-32v-32z",
"M592 528h32v32h-32v-32z",
"M656 528h32v32h-32v-32z",
"M720 528h32v32h-32v-32z",
"M752 496h32v32h-32v-32z",
"M368 560h32v32h-32v-32z",
"M432 560h32v32h-32v-32z",
"M496 560h32v32h-32v-32z",
"M560 560h32v32h-32v-32z",
"M624 560h32v32h-32v-32z",
"M688 560h32v32h-32v-32z",
"M336 592h32v32h-32v-32z",
"M400 592h32v32h-32v-32z",
"M464 592h32v32h-32v-32z",
"M528 592h32v32h-32v-32z",
"M592 592h32v32h-32v-32z",
"M656 592h32v32h-32v-32z",
"M720 592h32v32h-32v-32z",
"M368 624h32v32h-32v-32z",
"M432 624h32v32h-32v-32z",
"M496 624h32v32h-32v-32z",
"M560 624h32v32h-32v-32z",
"M624 624h32v32h-32v-32z",
"M688 624h32v32h-32v-32z",
"M336 656h32v32h-32v-32z",
"M400 656h32v32h-32v-32z",
"M464 656h32v32h-32v-32z",
"M528 656h32v32h-32v-32z",
"M592 656h32v32h-32v-32z",
"M656 656h32v32h-32v-32z",
"M368 688h32v32h-32v-32z",
"M432 688h32v32h-32v-32z",
"M496 688h32v32h-32v-32z",
"M560 688h32v32h-32v-32z",
"M624 688h32v32h-32v-32z",
"M336 720h32v32h-32v-32z",
"M400 720h32v32h-32v-32z",
"M464 720h32v32h-32v-32z",
"M528 720h32v32h-32v-32z",
"M592 720h32v32h-32v-32z",
"M368 752h32v32h-32v-32z",
"M432 752h32v32h-32v-32z",
"M496 752h32v32h-32v-32z",
"M432 368h32v32h-32v-32z",
"M400 400h32v32h-32v-32z",
"M368 432h32v32h-32v-32z",
"M640 976c-150.752 0-283.968-101.376-323.968-246.496l30.848-8.512c36.192 131.328 156.736 223.008 293.12 223.008 167.616 0 304-136.384 304-304 0-142.304-100.8-267.296-239.744-297.184l6.752-31.296c153.568 33.056 264.992 171.2 264.992 328.48 0 185.28-150.72 336-336 336z",
"M316 729.472c-7.968-29.088-12-59.2-12-89.472 0-185.28 150.72-336 336-336 23.936 0 47.808 2.528 71.008 7.52l-6.752 31.296c-20.96-4.512-42.592-6.816-64.256-6.816-167.616 0-304 136.384-304 304 0 27.392 3.648 54.688 10.88 81.024l-30.88 8.448z",
"M320 640c0-176.736 143.264-320 320-320 38.176 0 74.688 7.040 108.672 19.328-44.544-123.168-162.208-211.328-300.704-211.328-176.704 0-319.968 143.264-319.968 320 0 138.528 88.192 256.16 211.328 300.672-12.288-33.984-19.328-70.496-19.328-108.672z"
],
"attrs": [
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},