def patch_node(node_id): # Parse the request node_id = str2id(node_id) patch = request.get_json() # Find the node type. node = mongo.find_one_or_404('nodes', node_id, projection={'node_type': 1}) try: node_type = node['node_type'] except KeyError: msg = 'Node %s has no node_type property' % node_id log.warning(msg) raise wz_exceptions.InternalServerError(msg) log.debug('User %s wants to PATCH %s node %s', authentication.current_user_id(), node_type, node_id) # Find the PATCH handler for the node type. try: patch_handler = custom.patch_handlers[node_type] except KeyError: log.info('No patch handler for node type %r', node_type) raise wz_exceptions.MethodNotAllowed( 'PATCH on node type %r not allowed' % node_type) # Let the PATCH handler do its thing. return patch_handler(node_id, patch)
def urler(project_id): """Returns the URL of any project.""" project_id = str2id(project_id) project = mongo.find_one_or_404('projects', project_id, projection={'url': 1}) return jsonify({'_id': project_id, 'url': project['url']})
def generate_token(manager_id: str): manager_oid = str2id(manager_id) manager = mongo.find_one_or_404('flamenco_managers', manager_oid) # There are three ways in which a user can get here. One is authenticated via # Authorization header (either Bearer token or Basic token:subtoken), and the # other is via an already-existing browser session. # In the latter case it's a redirect from a Flamenco Manager and we need to # check the timeout and HMAC. if not request.headers.get('Authorization'): hasher = current_flamenco.manager_manager.hasher(manager_oid) if hasher is None: raise wz_exceptions.InternalServerError( 'Flamenco Manager not linked to this server') expires = request.args.get('expires', '') string_to_hash = f'{expires}-{manager_id}' hasher.update(string_to_hash.encode('utf8')) actual_hmac = hasher.hexdigest() query_hmac = request.args.get('hmac', '') if not hmac.compare_digest(query_hmac, actual_hmac): raise wz_exceptions.Unauthorized('Bad HMAC') # Only parse the timestamp after we learned we can trust it. expire_timestamp = dateutil.parser.parse(expires) validity_seconds_left = (expire_timestamp - utcnow()).total_seconds() if validity_seconds_left < 0: raise wz_exceptions.Unauthorized('Link expired') if validity_seconds_left > 900: # Flamenco Manager generates links that are valid for less than a minute, so # if it's more than 15 minutes in the future, it's bad. raise wz_exceptions.Unauthorized('Link too far in the future') user = authentication.current_user() if not current_flamenco.manager_manager.user_may_use(mngr_doc=manager): log.warning( 'Account %s called %s for manager %s without access to that manager', user.user_id, request.url, manager_oid) raise wz_exceptions.Unauthorized() jwt = current_flamenco.jwt if not jwt.usable: raise wz_exceptions.NotImplemented( 'JWT keystore is not usable at the moment') log.info('Generating JWT key for user_id=%s manager_id=%s remote_addr=%s', user.user_id, manager_id, request.remote_addr) key_for_manager = jwt.generate_key_for_manager(manager_oid, user.user_id) return Response(key_for_manager, content_type='text/plain')
def generate_token(manager_id: str): manager_oid = str2id(manager_id) manager = mongo.find_one_or_404('flamenco_managers', manager_oid) # There are three ways in which a user can get here. One is authenticated via # Authorization header (either Bearer token or Basic token:subtoken), and the # other is via an already-existing browser session. # In the latter case it's a redirect from a Flamenco Manager and we need to # check the timeout and HMAC. if not request.headers.get('Authorization'): hasher = current_flamenco.manager_manager.hasher(manager_oid) if hasher is None: raise wz_exceptions.InternalServerError('Flamenco Manager not linked to this server') expires = request.args.get('expires', '') string_to_hash = f'{expires}-{manager_id}' hasher.update(string_to_hash.encode('utf8')) actual_hmac = hasher.hexdigest() query_hmac = request.args.get('hmac', '') if not hmac.compare_digest(query_hmac, actual_hmac): raise wz_exceptions.Unauthorized('Bad HMAC') # Only parse the timestamp after we learned we can trust it. expire_timestamp = dateutil.parser.parse(expires) validity_seconds_left = (expire_timestamp - utcnow()).total_seconds() if validity_seconds_left < 0: raise wz_exceptions.Unauthorized('Link expired') if validity_seconds_left > 900: # Flamenco Manager generates links that are valid for less than a minute, so # if it's more than 15 minutes in the future, it's bad. raise wz_exceptions.Unauthorized('Link too far in the future') user = authentication.current_user() if not current_flamenco.manager_manager.user_may_use(mngr_doc=manager): log.warning( 'Account %s called %s for manager %s without access to that manager', user.user_id, request.url, manager_oid) raise wz_exceptions.Unauthorized() jwt = current_flamenco.jwt if not jwt.usable: raise wz_exceptions.NotImplemented('JWT keystore is not usable at the moment') log.info('Generating JWT key for user_id=%s manager_id=%s remote_addr=%s', user.user_id, manager_id, request.remote_addr) key_for_manager = jwt.generate_key_for_manager(manager_oid, user.user_id) return Response(key_for_manager, content_type='text/plain')
def wrapper(manager_id, *args, **kwargs): from flamenco import current_flamenco from pillar.api.utils import str2id, mongo manager_id = str2id(manager_id) manager = mongo.find_one_or_404('flamenco_managers', manager_id) if not current_flamenco.manager_manager.user_manages(mngr_doc=manager): user_id = authentication.current_user_id() log.warning( 'Service account %s sent startup notification for manager %s of another ' 'service account', user_id, manager_id) raise wz_exceptions.Unauthorized() return wrapped(manager_id, request.json, *args, **kwargs)
def project_quotas(project_id): """Returns information about the project's limits.""" # Check that the user has GET permissions on the project itself. project = mongo.find_one_or_404('projects', project_id) check_permissions('projects', project, 'GET') file_size_used = utils.project_total_file_size(project_id) info = { 'file_size_quota': None, # TODO: implement this later. 'file_size_used': file_size_used, } return jsonify(info)
def get_allowed_methods(project_id=None, node_type=None): """Returns allowed methods to create a node of a certain type. Either project_id or parent_node_id must be given. If the latter is given, the former is deducted from it. """ project = mongo.find_one_or_404('projects', str2id(project_id)) proj_methods = authorization.compute_allowed_methods('projects', project, node_type) resp = make_response() resp.headers['Allowed'] = ', '.join(sorted(proj_methods)) resp.status_code = 204 return resp
def wrapper(manager_id, *args, **kwargs): from pillar.api.utils import mongo manager_id = str2id(manager_id) manager = mongo.find_one_or_404('flamenco_managers', manager_id) if not current_flamenco.manager_manager.user_manages(mngr_doc=manager): user_id = authentication.current_user_id() log.warning( 'Service account %s called manager API endpoint for manager %s of another ' 'service account', user_id, manager_id) raise wz_exceptions.Unauthorized() return wrapped(manager if pass_manager_doc else manager_id, request.json, *args, **kwargs)