From c1692771f37cac3a78b1880048b5be1b6fc06ae8 Mon Sep 17 00:00:00 2001 From: Eibriel Date: Wed, 20 May 2015 12:13:39 -0300 Subject: [PATCH] Code clean up, added computed_permissions to user data --- attract/application/pre_hooks.py | 208 +++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 attract/application/pre_hooks.py diff --git a/attract/application/pre_hooks.py b/attract/application/pre_hooks.py new file mode 100644 index 00000000..9d1f2718 --- /dev/null +++ b/attract/application/pre_hooks.py @@ -0,0 +1,208 @@ +import json +from flask import g +from flask import abort +from flask import request + +from bson import ObjectId + +# from application import app + + +def permissions_lookup(action, lookup): + type_world_permissions = g.get('type_world_permissions') + type_owner_permissions = g.get('type_owner_permissions') + node_types = [] + # Get all node_types allowed by world: + for per in type_world_permissions: + if action in type_world_permissions[per]: + node_types.append(str(per)) + # Get all nodes with node_type allowed by owner if user == owner + owner_lookup = [] + for per in type_owner_permissions: + if action in type_owner_permissions[per]: + if action not in type_world_permissions[per]: + # If one of the following is true + # If node_type==node_type and user==user + owner_lookup.append( + {'$and': [{'node_type': str(per)}, + {'user': str(g.get('token_data')['user'])}]}) + lookup['$or'] = [{'node_type': {'$in': node_types}}] + if len(owner_lookup) > 0: + lookup['$or'].append({'$or': owner_lookup}) + return lookup + + +def pre_GET(request, lookup, data_driver): + action = 'GET' + if 'token_type' not in lookup and '_id' not in request.view_args: + # Is quering for all nodes (mixed types) + lookup = permissions_lookup(action, lookup) + else: + # Is quering for one specific node + if action not in g.get('world_permissions') and \ + action not in g.get('groups_permissions'): + lookup['user'] = g.get('token_data')['user'] + # token_data = validate_token() + # validate(token_data['token']) + + # lookup["userr"] = "user" + # print ("Lookup") + # print (lookup) + + +def pre_PUT(request, lookup, data_driver): + action = 'UPDATE' + if 'token_type' not in lookup and '_id' not in request.view_args: + # Is updating all nodes (mixed types) + lookup = permissions_lookup(action, lookup) + else: + # Is updating one specific node + if action not in g.get('world_permissions') and \ + action not in g.get('groups_permissions'): + lookup['user'] = g.get('token_data')['user'] + + # print ("Lookup") + # print (lookup) + + +def pre_PATCH(request, lookup, data_driver): + print ("Patch") + + +def pre_POST(request, data_driver): + # Only Post allowed documents + action = 'POST' + print (g.get('type_groups_permissions')) + # Is quering for one specific node + if action not in g.get('world_permissions') and \ + action not in g.get('groups_permissions'): + abort(403) + + +def pre_DELETE(request, lookup, data_driver): + type_world_permissions = g.get('type_world_permissions') + type_owner_permissions = g.get('type_owner_permissions') + type_groups_permissions = g.get('type_groups_permissions') + action = 'DELETE' + + if '_id' in lookup: + nodes = data_driver.db['nodes'] + dbnode = nodes.find_one({'_id': ObjectId(lookup['_id'])}) + # print (dbnode.count()) + node_type = str(dbnode['node_type']) + if g.get('token_data')['user'] == dbnode['user']: + owner = True + else: + owner = False + if action not in type_world_permissions[node_type] and \ + action not in type_groups_permissions[node_type]: + if action not in type_owner_permissions[node_type]: + print ("Abort1") + abort(403) + else: + if not owner: + print ("Abort2") + abort(403) + else: + print ("Abort3") + abort(403) + + +def compute_permissions(user, data_driver): + node_type = None + dbnode = None + owner_permissions = [] + world_permissions = [] + groups_permissions = [] + groups = data_driver.db['groups'] + users = data_driver.db['users'] + owner_group = groups.find_one({'name': 'owner'}) + world_group = groups.find_one({'name': 'world'}) + user_data = users.find_one({'_id': ObjectId(user)}) + # If is requesting a specific node + try: + uuid = request.path.split("/")[2] + nodes = data_driver.db['nodes'] + lookup = {'_id': ObjectId(uuid)} + dbnode = nodes.find_one(lookup) + except IndexError: + pass + if dbnode: + node_type = str(dbnode['node_type']) + + json_data = None + try: + json_data = json.loads(request.data) + except ValueError: + pass + if not node_type and json_data: + if 'node_type' in json_data: + node_type = json_data['node_type'] + + # Extract query lookup + # which node_type is asking for? + for arg in request.args: + if arg == 'where': + try: + where = json.loads(request.args[arg]) + except ValueError: + raise + if where.get('node_type'): + node_type = where.get('node_type') + break + + # Get and store permissions for that node_type + type_owner_permissions = {} + type_world_permissions = {} + type_groups_permissions = {} + + for per in owner_group['permissions']: + type_owner_permissions[str(per['node_type'])] = per['permissions'] + if str(per['node_type']) == node_type: + owner_permissions = per['permissions'] + + for per in world_group['permissions']: + type_world_permissions[str(per['node_type'])] = per['permissions'] + if str(per['node_type']) == node_type: + world_permissions = per['permissions'] + + # Adding empty permissions + if str(per['node_type']) not in type_groups_permissions: + type_groups_permissions[str(per['node_type'])] = [] + + groups_data = user_data.get('groups') + if groups_data: + for group in groups_data: + group_data = groups.find_one({'_id': ObjectId(group)}) + for per in group_data['permissions']: + type_groups_permissions[str(per['node_type'])] += \ + per['permissions'] + if str(per['node_type']) == node_type: + groups_permissions = per['permissions'] + + return { + 'owner_permissions': owner_permissions, + 'world_permissions': world_permissions, + 'groups_permissions': groups_permissions, + 'type_owner_permissions': type_owner_permissions, + 'type_world_permissions': type_world_permissions, + 'type_groups_permissions': type_groups_permissions + } + + +def check_permissions(user, data_driver): + # Entry point should be nodes + entry_point = request.path.split("/")[1] + if entry_point != 'nodes': + return + + permissions = compute_permissions(user, data_driver) + + # Store permission properties on global + setattr(g, 'owner_permissions', permissions['owner_permissions']) + setattr(g, 'world_permissions', permissions['world_permissions']) + setattr(g, 'groups_permissions', permissions['groups_permissions']) + setattr(g, 'type_owner_permissions', permissions['type_owner_permissions']) + setattr(g, 'type_world_permissions', permissions['type_world_permissions']) + setattr(g, 'type_groups_permissions', + permissions['type_groups_permissions'])