Implemented merging of permissions.
Permissions are now merged between project, node type and node, instead of having the lower-level permissions override the higher-level permissions.
This commit is contained in:
@@ -28,7 +28,6 @@ EXAMPLE_FILE = {u'_id': ObjectId('5672e2c1c379cf0007b31995'),
|
||||
u'link': 'http://localhost:8002/file',
|
||||
u'link_expires': datetime.datetime(2016, 3, 22, 9, 28, 22, tzinfo=tz_util.utc)}
|
||||
|
||||
|
||||
EXAMPLE_PROJECT = {
|
||||
u'_created': datetime.datetime(2015, 12, 17, 13, 22, 56, tzinfo=tz_util.utc),
|
||||
u'_etag': u'cc4643e98d3606f87bbfaaa200bfbae941b642f3',
|
||||
@@ -116,7 +115,7 @@ EXAMPLE_PROJECT = {
|
||||
u'permissions': {u'groups': [{u'group': ObjectId('5596e975ea893b269af85c0e'),
|
||||
u'methods': [u'GET', u'PUT', u'POST']},
|
||||
{u'group': ObjectId('5596e975ea893b269af85c0f'),
|
||||
u'methods': [u'GET']},
|
||||
u'methods': [u'DELETE', u'GET']},
|
||||
{u'group': ObjectId('564733b56dcaf85da2faee8a'),
|
||||
u'methods': [u'GET']}],
|
||||
u'users': [],
|
||||
@@ -240,9 +239,9 @@ EXAMPLE_PROJECT = {
|
||||
u'order': {u'type': u'integer'},
|
||||
u'resolution': {u'type': u'string'},
|
||||
u'stat_ensure_file_existsus': {u'allowed': [u'published',
|
||||
u'pending',
|
||||
u'processing'],
|
||||
u'type': u'string'},
|
||||
u'pending',
|
||||
u'processing'],
|
||||
u'type': u'string'},
|
||||
u'tags': {u'schema': {u'type': u'string'}, u'type': u'list'}},
|
||||
u'form_schema': {u'aspect_ratio': {},
|
||||
u'categories': {},
|
||||
@@ -270,7 +269,7 @@ EXAMPLE_PROJECT = {
|
||||
u'organization': ObjectId('55a99fb43004867fb9934f01'),
|
||||
u'owners': {u'groups': [], u'users': []},
|
||||
u'permissions': {u'groups': [{u'group': ObjectId('5596e975ea893b269af85c0e'),
|
||||
u'methods': [u'GET', u'PUT', u'POST']}],
|
||||
u'methods': [u'GET', u'POST', u'PUT']}],
|
||||
u'users': [],
|
||||
u'world': [u'GET']},
|
||||
u'picture_header': ObjectId('5673f260c379cf0007b31bc4'),
|
||||
@@ -279,3 +278,21 @@ EXAMPLE_PROJECT = {
|
||||
u'summary': u'Texture collection from all Blender Institute open projects.',
|
||||
u'url': u'textures',
|
||||
u'user': ObjectId('552b066b41acdf5dec4436f2')}
|
||||
|
||||
EXAMPLE_NODE = {
|
||||
u'_id': ObjectId('572761099837730efe8e120d'),
|
||||
u'picture': ObjectId('572761f39837730efe8e1210'),
|
||||
u'description': u'',
|
||||
u'node_type': u'asset',
|
||||
u'user': ObjectId('57164ca1983773118cbaf779'),
|
||||
u'properties': {
|
||||
u'status': u'published',
|
||||
u'content_type': u'image',
|
||||
u'file': ObjectId('572761129837730efe8e120e')
|
||||
},
|
||||
u'_updated': datetime.datetime(2016, 5, 2, 14, 19, 58, 0, tzinfo=tz_util.utc),
|
||||
u'name': u'Image test',
|
||||
u'project': EXAMPLE_PROJECT_ID,
|
||||
u'_created': datetime.datetime(2016, 5, 2, 14, 19, 37, 0, tzinfo=tz_util.utc),
|
||||
u'_etag': u'6b8589b42c880e3626f43f3e82a5c5b946742687'
|
||||
}
|
||||
|
@@ -1,11 +1,15 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
import copy
|
||||
import datetime
|
||||
import responses
|
||||
import json
|
||||
|
||||
from bson import tz_util, ObjectId
|
||||
from werkzeug.exceptions import Forbidden
|
||||
|
||||
from common_test_class import AbstractPillarTest, TEST_EMAIL_USER, TEST_EMAIL_ADDRESS
|
||||
from common_test_data import EXAMPLE_PROJECT, EXAMPLE_NODE
|
||||
|
||||
PUBLIC_USER_FIELDS = {'full_name', 'email'}
|
||||
|
||||
@@ -352,3 +356,117 @@ class UserListTests(AbstractPillarTest):
|
||||
resp = self.client.delete('/users/323456789abc123456789abc',
|
||||
headers={'Authorization': self.make_header('admin-token')})
|
||||
self.assertEqual(405, resp.status_code, resp.data)
|
||||
|
||||
|
||||
class PermissionComputationTest(AbstractPillarTest):
|
||||
maxDiff = None
|
||||
|
||||
def test_merge_permissions(self):
|
||||
from application.utils.authorization import merge_permissions
|
||||
|
||||
with self.app.test_request_context():
|
||||
self.assertEqual({}, merge_permissions())
|
||||
self.assertEqual({}, merge_permissions({}))
|
||||
self.assertEqual({}, merge_permissions({}, {}, {}))
|
||||
|
||||
# Merge one level deep
|
||||
self.assertEqual(
|
||||
{},
|
||||
merge_permissions({'users': []}, {'groups': []}, {'world': []}))
|
||||
self.assertEqual(
|
||||
{'users': [{'user': 'micak', 'methods': ['GET', 'POST', 'PUT']}],
|
||||
'groups': [{'group': 'manatees', 'methods': ['DELETE', 'GET']}],
|
||||
'world': ['GET']},
|
||||
merge_permissions(
|
||||
{'users': [{'user': 'micak', 'methods': ['GET', 'POST', 'PUT']}]},
|
||||
{'groups': [{'group': 'manatees', 'methods': ['DELETE', 'GET']}]},
|
||||
{'world': ['GET']}))
|
||||
|
||||
# Merge two levels deep.
|
||||
self.assertEqual(
|
||||
{'users': [{'user': 'micak', 'methods': ['GET', 'POST', 'PUT']}],
|
||||
'groups': [{'group': 'lions', 'methods': ['GET']},
|
||||
{'group': 'manatees', 'methods': ['GET', 'POST', 'PUT']}],
|
||||
'world': ['GET']},
|
||||
merge_permissions(
|
||||
{'users': [{'user': 'micak', 'methods': ['GET', 'PUT', 'POST']}],
|
||||
'groups': [{'group': 'lions', 'methods': ['GET']}]},
|
||||
{'groups': [{'group': 'manatees', 'methods': ['GET', 'PUT', 'POST']}]},
|
||||
{'world': ['GET']}))
|
||||
|
||||
# Merge three levels deep
|
||||
self.assertEqual(
|
||||
{'users': [{'user': 'micak', 'methods': ['DELETE', 'GET', 'POST', 'PUT']}],
|
||||
'groups': [{'group': 'lions', 'methods': ['GET', 'PUT', 'SCRATCH']},
|
||||
{'group': 'manatees', 'methods': ['GET', 'POST', 'PUT']}],
|
||||
'world': ['GET']},
|
||||
merge_permissions(
|
||||
{'users': [{'user': 'micak', 'methods': ['GET', 'PUT', 'POST']}],
|
||||
'groups': [{'group': 'lions', 'methods': ['GET']},
|
||||
{'group': 'manatees', 'methods': ['GET', 'PUT', 'POST']}],
|
||||
'world': ['GET']},
|
||||
{'users': [{'user': 'micak', 'methods': ['DELETE']}],
|
||||
'groups': [{'group': 'lions', 'methods': ['GET', 'PUT', 'SCRATCH']}],
|
||||
}
|
||||
))
|
||||
|
||||
def sort(self, permissions):
|
||||
"""Returns a sorted copy of the permissions."""
|
||||
|
||||
from application.utils.authorization import merge_permissions
|
||||
return merge_permissions(permissions, {})
|
||||
|
||||
def test_effective_permissions(self):
|
||||
from application.utils.authorization import compute_aggr_permissions
|
||||
|
||||
with self.app.test_request_context():
|
||||
# Test project permissions.
|
||||
self.assertEqual(
|
||||
{
|
||||
u'groups': [{u'group': ObjectId('5596e975ea893b269af85c0e'),
|
||||
u'methods': [u'GET', u'POST', u'PUT']}],
|
||||
u'world': [u'GET']
|
||||
},
|
||||
self.sort(compute_aggr_permissions('projects', EXAMPLE_PROJECT, None)))
|
||||
|
||||
# Test node type permissions.
|
||||
self.assertEqual(
|
||||
{
|
||||
u'groups': [{u'group': ObjectId('5596e975ea893b269af85c0e'),
|
||||
u'methods': [u'GET', u'POST', u'PUT']},
|
||||
{u'group': ObjectId('5596e975ea893b269af85c0f'),
|
||||
u'methods': [u'GET']},
|
||||
{u'group': ObjectId('564733b56dcaf85da2faee8a'),
|
||||
u'methods': [u'GET']}],
|
||||
u'world': [u'GET']
|
||||
},
|
||||
self.sort(compute_aggr_permissions('projects', EXAMPLE_PROJECT, 'texture')))
|
||||
|
||||
# Test node permissions with non-existing project.
|
||||
node = copy.deepcopy(EXAMPLE_NODE)
|
||||
self.assertRaises(Forbidden, compute_aggr_permissions, 'nodes', node, None)
|
||||
|
||||
# Test node permissions without embedded project.
|
||||
self.ensure_project_exists()
|
||||
self.assertEqual(
|
||||
{u'groups': [{u'group': ObjectId('5596e975ea893b269af85c0e'),
|
||||
u'methods': [u'GET', u'POST', u'PUT']},
|
||||
{u'group': ObjectId('5596e975ea893b269af85c0f'),
|
||||
u'methods': [u'DELETE', u'GET']},
|
||||
{u'group': ObjectId('564733b56dcaf85da2faee8a'),
|
||||
u'methods': [u'GET']}],
|
||||
u'world': [u'GET']},
|
||||
self.sort(compute_aggr_permissions('nodes', node, None)))
|
||||
|
||||
# Test node permissions with embedded project.
|
||||
node = copy.deepcopy(EXAMPLE_NODE)
|
||||
node['project'] = EXAMPLE_PROJECT
|
||||
self.assertEqual(
|
||||
{u'groups': [{u'group': ObjectId('5596e975ea893b269af85c0e'),
|
||||
u'methods': [u'GET', u'POST', u'PUT']},
|
||||
{u'group': ObjectId('5596e975ea893b269af85c0f'),
|
||||
u'methods': [u'DELETE', u'GET']},
|
||||
{u'group': ObjectId('564733b56dcaf85da2faee8a'),
|
||||
u'methods': [u'GET']}],
|
||||
u'world': [u'GET']},
|
||||
self.sort(compute_aggr_permissions('nodes', node, None)))
|
||||
|
Reference in New Issue
Block a user