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 ...@@ -34,9 +34,10 @@ class Auth
# Set the user from the token. # Set the user from the token.
plugins.Auth.withToken (token) => plugins.Auth.withToken (token) =>
_checkingToken = false _checkingToken = false
annotator.addPlugin 'Permissions', # Annotator needs to access the user property without the permissions
user: token.userId # plugin and since auth service depends on annotator, the annotator
userAuthorize: @permits # service cannot use the auth service
annotator.user = token.userId
@user = token.userId @user = token.userId
$rootScope.$apply() $rootScope.$apply()
...@@ -48,10 +49,7 @@ class Auth ...@@ -48,10 +49,7 @@ class Auth
plugins.Auth?.destroy() plugins.Auth?.destroy()
delete plugins.Auth delete plugins.Auth
plugins.Permissions?.setUser(null) annotator.user = null
plugins.Permissions?.destroy()
delete plugins.Permissions
@user = null @user = null
_checkingToken = false _checkingToken = false
...@@ -62,43 +60,10 @@ class Auth ...@@ -62,43 +60,10 @@ class Auth
onready = => onready = =>
if @user is undefined and not _checkingToken if @user is undefined and not _checkingToken
@user = null @user = null
annotator.user = null
identity.watch {onlogin, onlogout, onready} 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') angular.module('h')
.service('auth', Auth) .service('auth', Auth)
...@@ -2,13 +2,13 @@ class AppController ...@@ -2,13 +2,13 @@ class AppController
this.$inject = [ this.$inject = [
'$location', '$route', '$scope', '$timeout', '$location', '$route', '$scope', '$timeout',
'annotator', 'auth', 'documentHelpers', 'drafts', 'flash', 'identity', 'annotator', 'auth', 'documentHelpers', 'drafts', 'flash', 'identity',
'streamer', 'streamfilter' 'permissions', 'streamer', 'streamfilter'
] ]
constructor: ( constructor: (
$location, $route, $scope, $timeout, $location, $route, $scope, $timeout,
annotator, auth, documentHelpers, drafts, flash, identity, annotator, auth, documentHelpers, drafts, flash, identity,
streamer, streamfilter, permissions, streamer, streamfilter,
) -> ) ->
{plugins, host, providers} = annotator {plugins, host, providers} = annotator
...@@ -77,7 +77,7 @@ class AppController ...@@ -77,7 +77,7 @@ class AppController
cull = (acc, annotation) -> cull = (acc, annotation) ->
if view is 'single-player' and annotation.user != user if view is 'single-player' and annotation.user != user
acc.drop.push annotation acc.drop.push annotation
else if auth.permits 'read', annotation, user else if permissions.permits('read', annotation, user)
acc.keep.push annotation acc.keep.push annotation
else else
acc.drop.push annotation acc.drop.push annotation
......
...@@ -94,7 +94,7 @@ AnnotationController = [ ...@@ -94,7 +94,7 @@ AnnotationController = [
### ###
this.authorize = (action) -> this.authorize = (action) ->
return false unless model? return false unless model?
annotator.plugins.Permissions?.authorize action, model permissions.permits action, model, auth.user
###* ###*
# @ngdoc method # @ngdoc method
...@@ -275,7 +275,7 @@ AnnotationController = [ ...@@ -275,7 +275,7 @@ AnnotationController = [
# Save highlights once logged in. # Save highlights once logged in.
if highlight and this.isHighlight() if highlight and this.isHighlight()
if model.user if auth.user
model.permissions = permissions.private() model.permissions = permissions.private()
annotator.publish 'annotationCreated', model annotator.publish 'annotationCreated', model
highlight = false # skip this on future updates highlight = false # skip this on future updates
......
...@@ -40,7 +40,7 @@ privacy = ['$window', 'permissions', ($window, permissions) -> ...@@ -40,7 +40,7 @@ privacy = ['$window', 'permissions', ($window, permissions) ->
controller.$formatters.push (selectedPermissions) -> controller.$formatters.push (selectedPermissions) ->
return unless selectedPermissions? return unless selectedPermissions?
if permissions.isPublic {permissions: selectedPermissions} if permissions.isPublic({permissions: selectedPermissions})
getLevel(VISIBILITY_PUBLIC) getLevel(VISIBILITY_PUBLIC)
else else
getLevel(VISIBILITY_PRIVATE) getLevel(VISIBILITY_PRIVATE)
...@@ -61,7 +61,7 @@ privacy = ['$window', 'permissions', ($window, permissions) -> ...@@ -61,7 +61,7 @@ privacy = ['$window', 'permissions', ($window, permissions) ->
controller.$modelValue controller.$modelValue
controller.$render = -> controller.$render = ->
unless controller.$modelValue.read.length unless controller.$modelValue.read?.length
name = storage.getItem VISIBILITY_KEY name = storage.getItem VISIBILITY_KEY
name ?= VISIBILITY_PUBLIC name ?= VISIBILITY_PUBLIC
level = getLevel(name) level = getLevel(name)
......
...@@ -51,5 +51,40 @@ class Permissions ...@@ -51,5 +51,40 @@ class Permissions
isPublic: (annotation) -> isPublic: (annotation) ->
'group:__world__' in (annotation.permissions?.read or []) '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') angular.module('h')
.service('permissions', Permissions) .service('permissions', Permissions)
\ No newline at end of file
...@@ -28,7 +28,7 @@ renderFactory = ['$$rAF', ($$rAF) -> ...@@ -28,7 +28,7 @@ renderFactory = ['$$rAF', ($$rAF) ->
class Hypothesis extends Annotator class Hypothesis extends Annotator
events: events:
'beforeAnnotationCreated': 'digest' 'beforeAnnotationCreated': 'beforeAnnotationCreated'
'annotationCreated': 'digest' 'annotationCreated': 'digest'
'annotationDeleted': 'annotationDeleted' 'annotationDeleted': 'annotationDeleted'
'annotationUpdated': 'digest' 'annotationUpdated': 'digest'
...@@ -47,13 +47,6 @@ class Hypothesis extends Annotator ...@@ -47,13 +47,6 @@ class Hypothesis extends Annotator
tool: 'comment' tool: 'comment'
visibleHighlights: false 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'] this.$inject = ['$document', '$window']
constructor: ( $document, $window ) -> constructor: ( $document, $window ) ->
super ($document.find 'body') super ($document.find 'body')
...@@ -260,6 +253,11 @@ class Hypothesis extends Annotator ...@@ -260,6 +253,11 @@ class Hypothesis extends Annotator
digest: -> digest: ->
@element.scope().$evalAsync angular.noop @element.scope().$evalAsync angular.noop
beforeAnnotationCreated: (annotation) ->
annotation.user = @user
annotation.permissions = {}
@digest()
annotationDeleted: (annotation) -> annotationDeleted: (annotation) ->
scope = @element.scope() scope = @element.scope()
if scope.selectedAnnotations?[annotation.id] if scope.selectedAnnotations?[annotation.id]
...@@ -323,8 +321,8 @@ class Hypothesis extends Annotator ...@@ -323,8 +321,8 @@ class Hypothesis extends Annotator
# Sweet, nothing to do, just clean up previous filters # Sweet, nothing to do, just clean up previous filters
delete query.user delete query.user
when "single-player" when "single-player"
if @plugins.Permissions?.user if @user?
query.user = @plugins.Permissions.user query.user = @user
else else
delete query.user 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