Commit 6af54308 authored by Gergely Ujvari's avatar Gergely Ujvari Committed by ujvari

Ditch Annotator.permissions plugin

parent 40b5dbed
......@@ -34,9 +34,10 @@ class Auth
# Set the user from the token.
plugins.Auth.withToken (token) =>
_checkingToken = false
annotator.addPlugin 'Permissions',
user: token.userId
userAuthorize: @permits
# Annotator needs to access the user property without the permissions
# plugin and since auth service depends on annotator, the annotator
# service cannot use the auth service
annotator.user = token.userId
@user = token.userId
$rootScope.$apply()
......@@ -48,10 +49,7 @@ class Auth
plugins.Auth?.destroy()
delete plugins.Auth
plugins.Permissions?.setUser(null)
plugins.Permissions?.destroy()
delete plugins.Permissions
annotator.user = null
@user = null
_checkingToken = false
......@@ -62,43 +60,10 @@ class Auth
onready = =>
if @user is undefined and not _checkingToken
@user = null
annotator.user = null
identity.watch {onlogin, onlogout, onready}
###*
# @ngdoc method
# @name auth#permits
#
# @param {String} action action to authorize (read|update|delete|admin)
# @param {Object} annotation to permit action on it or not
# @param {String} user the userId
#
# User authorization function used by (not solely) the Permissions plugin
###
permits: (action, annotation, user) ->
if annotation.permissions
tokens = annotation.permissions[action] || []
if tokens.length == 0
# Empty or missing tokens array: only admin can perform action.
return false
for token in tokens
if user == token
return true
if token == 'group:__world__'
return true
# No tokens matched: action should not be performed.
return false
# Coarse-grained authorization
else if annotation.user
return user and user == annotation.user
# No authorization info on annotation: free-for-all!
true
angular.module('h')
.service('auth', Auth)
......@@ -2,13 +2,13 @@ class AppController
this.$inject = [
'$location', '$route', '$scope', '$timeout',
'annotator', 'auth', 'documentHelpers', 'drafts', 'flash', 'identity',
'streamer', 'streamfilter'
'permissions', 'streamer', 'streamfilter'
]
constructor: (
$location, $route, $scope, $timeout,
annotator, auth, documentHelpers, drafts, flash, identity,
streamer, streamfilter,
permissions, streamer, streamfilter,
) ->
{plugins, host, providers} = annotator
......@@ -77,7 +77,7 @@ class AppController
cull = (acc, annotation) ->
if view is 'single-player' and annotation.user != user
acc.drop.push annotation
else if auth.permits 'read', annotation, user
else if permissions.permits('read', annotation, user)
acc.keep.push annotation
else
acc.drop.push annotation
......
......@@ -94,7 +94,7 @@ AnnotationController = [
###
this.authorize = (action) ->
return false unless model?
annotator.plugins.Permissions?.authorize action, model
permissions.permits action, model, auth.user
###*
# @ngdoc method
......@@ -275,7 +275,7 @@ AnnotationController = [
# Save highlights once logged in.
if highlight and this.isHighlight()
if model.user
if auth.user
model.permissions = permissions.private()
annotator.publish 'annotationCreated', model
highlight = false # skip this on future updates
......
......@@ -40,7 +40,7 @@ privacy = ['$window', 'permissions', ($window, permissions) ->
controller.$formatters.push (selectedPermissions) ->
return unless selectedPermissions?
if permissions.isPublic {permissions: selectedPermissions}
if permissions.isPublic({permissions: selectedPermissions})
getLevel(VISIBILITY_PUBLIC)
else
getLevel(VISIBILITY_PRIVATE)
......@@ -61,7 +61,7 @@ privacy = ['$window', 'permissions', ($window, permissions) ->
controller.$modelValue
controller.$render = ->
unless controller.$modelValue.read.length
unless controller.$modelValue.read?.length
name = storage.getItem VISIBILITY_KEY
name ?= VISIBILITY_PUBLIC
level = getLevel(name)
......
......@@ -51,5 +51,40 @@ class Permissions
isPublic: (annotation) ->
'group:__world__' in (annotation.permissions?.read or [])
###*
# @ngdoc method
# @name permissions#permits
#
# @param {String} action action to authorize (read|update|delete|admin)
# @param {Object} annotation to permit action on it or not
# @param {String} user the userId
#
# User authorization function used by (not solely) the Permissions plugin
###
permits: (action, annotation, user) ->
if annotation.permissions
tokens = annotation.permissions[action] || []
if tokens.length == 0
# Empty or missing tokens array: only admin can perform action.
return false
for token in tokens
if user == token
return true
if token == 'group:__world__'
return true
# No tokens matched: action should not be performed.
return false
# Coarse-grained authorization
else if annotation.user
return user and user == annotation.user
# No authorization info on annotation: free-for-all!
true
angular.module('h')
.service('permissions', Permissions)
\ No newline at end of file
.service('permissions', Permissions)
......@@ -28,7 +28,7 @@ renderFactory = ['$$rAF', ($$rAF) ->
class Hypothesis extends Annotator
events:
'beforeAnnotationCreated': 'digest'
'beforeAnnotationCreated': 'beforeAnnotationCreated'
'annotationCreated': 'digest'
'annotationDeleted': 'annotationDeleted'
'annotationUpdated': 'digest'
......@@ -47,13 +47,6 @@ class Hypothesis extends Annotator
tool: 'comment'
visibleHighlights: false
# Here as a noop just to make the Permissions plugin happy
# XXX: Change me when Annotator stops assuming things about viewers
editor:
addField: angular.noop
viewer:
addField: angular.noop
this.$inject = ['$document', '$window']
constructor: ( $document, $window ) ->
super ($document.find 'body')
......@@ -260,6 +253,11 @@ class Hypothesis extends Annotator
digest: ->
@element.scope().$evalAsync angular.noop
beforeAnnotationCreated: (annotation) ->
annotation.user = @user
annotation.permissions = {}
@digest()
annotationDeleted: (annotation) ->
scope = @element.scope()
if scope.selectedAnnotations?[annotation.id]
......@@ -323,8 +321,8 @@ class Hypothesis extends Annotator
# Sweet, nothing to do, just clean up previous filters
delete query.user
when "single-player"
if @plugins.Permissions?.user
query.user = @plugins.Permissions.user
if @user?
query.user = @user
else
delete query.user
......
// Generated by CoffeeScript 1.6.3
/*
** Annotator 1.2.6-dev-242f0df
** https://github.com/okfn/annotator/
**
** Copyright 2012 Aron Carroll, Rufus Pollock, and Nick Stenning.
** Dual licensed under the MIT and GPLv3 licenses.
** https://github.com/okfn/annotator/blob/master/LICENSE
**
** Built at: 2014-11-18 14:32:32Z
*/
/*
//
*/
// Generated by CoffeeScript 1.6.3
(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
Annotator.Plugin.Permissions = (function(_super) {
__extends(Permissions, _super);
Permissions.prototype.events = {
'beforeAnnotationCreated': 'addFieldsToAnnotation'
};
Permissions.prototype.options = {
showViewPermissionsCheckbox: true,
showEditPermissionsCheckbox: true,
userId: function(user) {
return user;
},
userString: function(user) {
return user;
},
userAuthorize: function(action, annotation, user) {
var token, tokens, _i, _len;
if (annotation.permissions) {
tokens = annotation.permissions[action] || [];
if (tokens.length === 0) {
return true;
}
for (_i = 0, _len = tokens.length; _i < _len; _i++) {
token = tokens[_i];
if (this.userId(user) === token) {
return true;
}
}
return false;
} else if (annotation.user) {
if (user) {
return this.userId(user) === this.userId(annotation.user);
} else {
return false;
}
}
return true;
},
user: '',
permissions: {
'read': [],
'update': [],
'delete': [],
'admin': []
}
};
function Permissions(element, options) {
this._setAuthFromToken = __bind(this._setAuthFromToken, this);
this.updateViewer = __bind(this.updateViewer, this);
this.updateAnnotationPermissions = __bind(this.updateAnnotationPermissions, this);
this.updatePermissionsField = __bind(this.updatePermissionsField, this);
this.addFieldsToAnnotation = __bind(this.addFieldsToAnnotation, this);
Permissions.__super__.constructor.apply(this, arguments);
if (this.options.user) {
this.setUser(this.options.user);
delete this.options.user;
}
}
Permissions.prototype.pluginInit = function() {
var createCallback, self,
_this = this;
if (!Annotator.supported()) {
return;
}
self = this;
createCallback = function(method, type) {
return function(field, annotation) {
return self[method].call(self, type, field, annotation);
};
};
if (!this.user && this.annotator.plugins.Auth) {
this.annotator.plugins.Auth.withToken(this._setAuthFromToken);
}
if (this.options.showViewPermissionsCheckbox === true) {
this.annotator.editor.addField({
type: 'checkbox',
label: Annotator._t('Allow anyone to <strong>view</strong> this annotation'),
load: createCallback('updatePermissionsField', 'read'),
submit: createCallback('updateAnnotationPermissions', 'read')
});
}
if (this.options.showEditPermissionsCheckbox === true) {
this.annotator.editor.addField({
type: 'checkbox',
label: Annotator._t('Allow anyone to <strong>edit</strong> this annotation'),
load: createCallback('updatePermissionsField', 'update'),
submit: createCallback('updateAnnotationPermissions', 'update')
});
}
this.annotator.viewer.addField({
load: this.updateViewer
});
if (this.annotator.plugins.Filter) {
return this.annotator.plugins.Filter.addFilter({
label: Annotator._t('User'),
property: 'user',
isFiltered: function(input, user) {
var keyword, _i, _len, _ref;
user = _this.options.userString(user);
if (!(input && user)) {
return false;
}
_ref = input.split(/\s*/);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
keyword = _ref[_i];
if (user.indexOf(keyword) === -1) {
return false;
}
}
return true;
}
});
}
};
Permissions.prototype.setUser = function(user) {
return this.user = user;
};
Permissions.prototype.addFieldsToAnnotation = function(annotation) {
if (annotation) {
if (!annotation.permissions) {
annotation.permissions = $.extend(true, {}, this.options.permissions);
}
if (this.user) {
return annotation.user = this.user;
}
}
};
Permissions.prototype.authorize = function(action, annotation, user) {
if (user === void 0) {
user = this.user;
}
if (this.options.userAuthorize) {
return this.options.userAuthorize.call(this.options, action, annotation, user);
} else {
return true;
}
};
Permissions.prototype.updatePermissionsField = function(action, field, annotation) {
var input;
field = $(field).show();
input = field.find('input').removeAttr('disabled');
if (!this.authorize('admin', annotation)) {
field.hide();
}
if (this.authorize(action, annotation || {}, null)) {
return input.attr('checked', 'checked');
} else {
return input.removeAttr('checked');
}
};
Permissions.prototype.updateAnnotationPermissions = function(type, field, annotation) {
var dataKey;
if (!annotation.permissions) {
annotation.permissions = $.extend(true, {}, this.options.permissions);
}
dataKey = type + '-permissions';
if ($(field).find('input').is(':checked')) {
return annotation.permissions[type] = [];
} else {
return annotation.permissions[type] = [this.user];
}
};
Permissions.prototype.updateViewer = function(field, annotation, controls) {
var user, username;
field = $(field);
username = this.options.userString(annotation.user);
if (annotation.user && username && typeof username === 'string') {
user = Annotator.Util.escape(this.options.userString(annotation.user));
field.html(user).addClass('annotator-user');
} else {
field.remove();
}
if (controls) {
if (!this.authorize('update', annotation)) {
controls.hideEdit();
}
if (!this.authorize('delete', annotation)) {
return controls.hideDelete();
}
}
};
Permissions.prototype._setAuthFromToken = function(token) {
return this.setUser(token.userId);
};
return Permissions;
})(Annotator.Plugin);
}).call(this);
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