def inner_wrapper(*args, **kwargs): try: with Yosai.context(self._yosai): # Context Manager functions try: try: identity = self.authenticate(request_proxy) if not identity.username: raise UnauthenticatedError('Authentication Required') except: raise UnauthenticatedError('Authentication Required') ApiRequestContextProxy.set_identity(identity) if self._check_account(identity.user_account, identity.user_account_type, with_names, with_types): return f(*args, **kwargs) finally: # Teardown the request context ApiRequestContextProxy.set_identity(None) except UnauthorizedAccountError as ex: return make_response_error(str(ex), in_httpcode=403), 403 except UnauthenticatedError as ex: return Response(response='Unauthorized', status=401, headers=[('WWW-Authenticate', 'basic realm="Authentication required"')]) except Exception as ex: logger.exception('Unexpected exception: {}'.format(ex)) return make_response_error('Internal error', in_httpcode=500), 500
def get_analysis_archive_rule(rule_id): """ GET /archives/rules/{rule_id} :param rule_id: :return: """ try: with session_scope() as session: rule = ( session.query(ArchiveTransitionRule) .filter_by(account=ApiRequestContextProxy.namespace(), rule_id=rule_id) .one_or_none() ) if rule is None: # Allow users to get the system global rules rule = ( session.query(ArchiveTransitionRule) .filter_by(rule_id=rule_id, system_global=True) .one_or_none() ) if rule is None: return make_response_error("Rule not found", in_httpcode=404), 404 return transition_rule_db_to_json(rule), 200 except Exception as ex: return make_response_error(ex, in_httpcode=500), 500
def archive_image_analysis(imageReferences): """ POST /archives/images body = [digest1, digest2, ... ] """ try: if not imageReferences or len(imageReferences) > 100: return make_response_error('Bad Request. Must include a list of digests between 1 and 100 entries long', in_httpcode=400), 400 results = [] for digest in imageReferences: try: # Do synchronous part to start the state transition task = ArchiveImageTask(account=ApiRequestContextProxy.namespace(), image_digest=digest) result_status, result_detail = task.run() results.append({'digest': task.image_digest, 'status': result_status, 'detail': result_detail}) except Exception as ex: logger.exception('Unexpected an uncaught exception from the archive task execution') results.append({'digest': digest, 'status': 'error', 'detail': str(ex)}) return results, 200 except Exception as err: logger.exception('Error processing image add') return make_response_error(err, in_httpcode=500), 500
def delete_archived_analysis(imageDigest, force=False): """ DELETE /archives/images/{digest} :param imageDigest: image digest to delete the archive for :return: """ # # Read the archive manifest, and delete or restore the artifacts try: if force: start_statuses = ['archiving', 'archived', 'deleting', 'deleted'] else: start_statuses = ['archived', 'deleting'] with session_scope() as session: resp = db_archived_images.update_image_status(session, ApiRequestContextProxy.namespace(), imageDigest, start_statuses, 'deleting') if resp is None: return make_response_error('Not found in archive', in_httpcode=404), 404 except Exception as ex: logger.exception("Error deleting archive for image {}/{}".format(ApiRequestContextProxy.namespace(), imageDigest)) return make_response_error('Invalid object state: {}'.format(ex), in_httpcode=400), 400 try: task = DeleteArchivedImageTask(account=ApiRequestContextProxy.namespace(), image_digest=imageDigest) task.run() resp = None return resp, 200 except Exception as ex: logger.exception('Failed deleting archived image') return make_response_error('Error deleting image archive: {}'.format(ex), in_httpcode=500), 500
def sync_feeds(sync=True, force_flush=False): """ POST /feeds?sync=True&force_flush=True :param sync: Boolean. If true, do a sync. If false, don't sync. :param force_flush: Boolean. If true, remove all previous data and replace with data from upstream source :return: """ result = [] if sync: try: result = FeedsUpdateTask.run_feeds_update(force_flush=force_flush) except (LeaseAcquisitionFailedError, LeaseUnavailableError) as e: log.exception( 'Could not acquire lock on feed sync, likely another sync already in progress' ) return make_response_error( 'Feed sync lock already held', in_httpcode=409, details={ 'error_codes': [AnchoreError.FEED_SYNC_ALREADY_IN_PROGRESS.name], 'message': AnchoreError.FEED_SYNC_ALREADY_IN_PROGRESS.value }), 409 except Exception as e: log.exception('Error executing feed update task') return jsonify(make_response_error(e, in_httpcode=500)), 500 return jsonify(result), 200
def list_users(accountname): """ GET /accounts/{accountname}/users :param account: :return: """ try: with session_scope() as session: mgr = manager_factory.for_session(session) verify_account(accountname, mgr) users = mgr.list_users(accountname) if users is None: return make_response_error("No such account", in_httpcode=404), 404 response = list(map(user_db_to_msg, users)) return response, 200 except AccountNotFoundError as ex: return make_response_error("Account not found", in_httpcode=404), 404 except Exception as e: logger.exception("API Error") return make_response_error("Error listing account users", in_httpcode=500), 500
def create_user(accountname, user): """ POST /accounts/{accountname}/users :param accountname: :param user: :return: """ try: with session_scope() as session: mgr = manager_factory.for_session(session) verify_account(accountname, mgr) usr = mgr.create_user( account_name=accountname, username=user['username'], creator_name=ApiRequestContextProxy.identity().username, password=user['password']) return user_db_to_msg(usr), 200 except UserAlreadyExistsError as ex: return make_response_error('User already exists', in_httpcode=400), 400 except AccountNotFoundError as ex: return make_response_error('Account not found', in_httpcode=404), 404 except Exception as e: logger.exception('API Error') return make_response_error( 'Internal error deleting account {}'.format(accountname)), 500
def delete_user(accountname, username): """ DELETE /accounts/{accountname}/users/{username} :param accountname: :param username: the user to delete :return: """ try: with session_scope() as session: mgr = manager_factory.for_session(session) verify_user(username, accountname, mgr) if ApiRequestContextProxy.identity().username == username: return make_response_error( 'Cannot delete credential used for authentication of the request', in_httpcode=400), 400 if mgr.delete_user(username): return None, 204 else: return make_response_error( 'Failed to delete user: {}'.format(username), in_httpcode=500), 500 except (UserNotFoundError, AccountNotFoundError): return make_response_error('User not found', in_httpcode=404), 404 except Exception as e: logger.exception('API Error') return make_response_error( 'Internal error deleting user {}'.format(username), in_httpcode=500), 500
def delete_group(feed, group): session = db.get_session() try: f = db.lookup_feed_group(db_session=session, feed_name=feed, group_name=group) if not f: raise ResourceNotFound(group, detail={}) elif f.enabled: raise ConflictingRequest(message='Cannot delete an enabled feed group. Disable the feed group first', detail={}) except AnchoreApiError: raise except Exception as e: return jsonify(make_response_error(e, in_httpcode=500)), 500 finally: session.rollback() try: g = sync.DataFeeds.delete_feed_group(feed_name=feed, group_name=group) log.info('Flushed group records {}'.format(g)) if g: return jsonify(_marshall_group_response(g)), 200 else: raise ResourceNotFound(group, detail={}) except KeyError as e: raise ResourceNotFound(resource=str(e), detail={'feed': feed, 'group': group}) except AnchoreApiError: raise except Exception as e: log.error('Could not flush feed group {}/{}'.format(feed, group)) return jsonify(make_response_error(e, in_httpcode=500)), 500
def activate_account(accountname): """ POST /accounts/{accountname}/activate idempotently activate an account :param accountname: str account name to activate :return: account json object """ try: with session_scope() as session: mgr = manager_factory.for_session(session) verify_account(accountname, mgr) result = mgr.activate_account(accountname) if result: return account_db_to_status_msg(result), 200 else: return make_response_error('Error updating account state'), 500 except AccountNotFoundError as ex: return make_response_error('Account not found', in_httpcode=404), 404 except Exception as e: logger.exception('API Error') return make_response_error('Error activating account', in_httpcode=500), 500
def create_account(account): """ POST /accounts :param account: :return: """ try: if account.get('type') != AccountTypes.user.value: return make_response_error( 'Invalid account type: {}. Only valid value is "user"'.format( account.get('type')), in_httpcode=400), 400 with session_scope() as session: mgr = manager_factory.for_session(session) resp = mgr.create_account( account_name=account['name'], account_type=account.get('type', AccountTypes.user.value), email=account.get('email'), creator=ApiRequestContextProxy.identity().username) return account_db_to_msg(resp), 200 except AccountAlreadyExistsError as ex: return make_response_error(errmsg='Account already exists', in_httpcode=400), 400 except Exception as ex: logger.exception('Unexpected Error creating account') return make_response_error('Error creating account', in_httpcode=500), 500
def add_credential(credential): """ POST /user/credentials The same logic as /users/{userId}/credentials, but gets the userId from the auth context rather than path. This is for use by regular (non-admin) users to update their own credentials. :param credential: :return: credential json object """ try: if credential['type'] != UserAccessCredentialTypes.password.value: return make_response_error('Invalid credential type', in_httpcode=400), 400 else: cred_type = UserAccessCredentialTypes(credential['type']) with session_scope() as session: mgr = identities.manager_factory.for_session(session) user = ApiRequestContextProxy.identity().username result = mgr.add_user_credential(username=user, credential_type=cred_type, value=credential['value']) return credential_db_to_msg(result), 200 except Exception as ex: logger.exception('API Error') return make_response_error(errmsg=str(ex), in_httpcode=500), 500
def content_upload(operation_id, content_type, request): """ Generic handler for multiple types of content uploads. Still operates at the API layer :param operation_id: :param content_type: :param request: :return: """ try: client = internal_client_for( CatalogClient, userId=ApiRequestContextProxy.namespace() ) return ( client.upload_image_import_content( operation_id, content_type, request.data ), 200, ) except api_exceptions.AnchoreApiError as ex: return ( make_response_error(ex, in_httpcode=ex.__response_code__), ex.__response_code__, ) except Exception as ex: logger.exception("Unexpected error in api processing") return make_response_error(ex, in_httpcode=500), 500
def delete_user(accountname, username): """ DELETE /accounts/{accountname}/users/{username} :param accountname: :param username: the user to delete :return: """ try: with session_scope() as session: mgr = manager_factory.for_session(session) usr = verify_user(username, accountname, mgr) if not can_delete_user(usr): return make_response_error('User not allowed to be deleted due to system constraints', in_httpcode=400), 400 elif ApiRequestContextProxy.identity().username == username: return make_response_error('Cannot delete credential used for authentication of the request', in_httpcode=400), 400 else: if mgr.delete_user(username): # Flush from authz system if necessary, will rollback if this fails, but rely on the db state checks first to gate this authorizer.notify(NotificationTypes.principal_deleted, username) return None, 204 else: return make_response_error('Failed to delete user: {}'.format(username), in_httpcode=500), 500 except (UserNotFoundError, AccountNotFoundError): return make_response_error('User not found', in_httpcode=404), 404 except Exception as e: logger.exception('API Error') return make_response_error('Internal error deleting user {}'.format(username), in_httpcode=500), 500
def delete_feed(feed): session = db.get_session() try: f = db.lookup_feed(db_session=session, feed_name=feed) if not f: raise ResourceNotFound(resource=feed, detail={}) elif f.enabled: raise ConflictingRequest( message="Cannot delete an enabled feed. Disable the feed first", detail={}, ) except AnchoreApiError: raise except Exception as e: return jsonify(make_response_error(e, in_httpcode=500)), 500 finally: session.rollback() try: f = sync.DataFeeds.delete_feed(feed) if f: return jsonify(_marshall_feed_response(f).to_json()), 200 else: raise ResourceNotFound(feed, detail={}) except KeyError as e: raise ResourceNotFound(resource=str(e), detail={"feed": feed}) except AnchoreApiError: raise except Exception as e: return jsonify(make_response_error(e, in_httpcode=500)), 500
def update_account_state(accountname, desired_state): """ POST /accounts/{accountname}/state Body: {"state": "enabled"|"disabled"} :param accountname: str account name to update :param desired_state: json object for desired state to set :return: account json object """ try: with session_scope() as session: mgr = manager_factory.for_session(session) verify_account(accountname, mgr) result = mgr.update_account_state( accountname, AccountStates(desired_state.get("state"))) if result: return account_db_to_status_msg(result), 200 else: return make_response_error("Error updating account state"), 500 except (InvalidStateError, DisableAdminAccountError) as ex: return make_response_error(str(ex), in_httpcode=400), 400 except AccountNotFoundError as ex: return make_response_error("Account not found", in_httpcode=404), 404 except Exception as e: logger.exception("API Error") return make_response_error("Error updating account state", in_httpcode=500), 500
def list_user_credentials(accountname, username): """ GET /accounts/{accountname}/users/{username}/credentials :param username: :return: """ try: with session_scope() as session: mgr = manager_factory.for_session(session) usr = verify_user(username, accountname, mgr) cred = usr["credentials"].get(UserAccessCredentialTypes.password) if cred is None: return [], 200 else: cred = credential_db_to_msg(cred) return [cred], 200 except UserNotFoundError as ex: return make_response_error("User not found", in_httpcode=404), 404 except AccountNotFoundError as ex: return make_response_error("Account not found", in_httpcode=404), 404 except Exception as ex: logger.exception("Api Error") return make_response_error(errmsg=str(ex), in_httpcode=500), 500
def create_user(accountname, user): """ POST /accounts/{accountname}/users :param accountname: :param user: :return: """ try: with session_scope() as session: mgr = manager_factory.for_session(session) verify_account(accountname, mgr) try: usr = mgr.create_user(account_name=accountname, username=user['username'], password=user['password']) except ValueError as ex: return make_response_error('Validation failed: {}'.format(ex), in_httpcode=400), 400 # Flush from authz system if necessary, will rollback if this fails, but rely on the db state checks first to gate this authorizer.notify(NotificationTypes.principal_created, usr['username']) return user_db_to_msg(usr), 200 except UserAlreadyExistsError as ex: return make_response_error('User already exists', in_httpcode=400), 400 except AccountNotFoundError as ex: return make_response_error('Account not found', in_httpcode=404), 404 except Exception as e: logger.exception('API Error') return make_response_error('Internal error adding user'), 500
def list_accounts(state=None): """ GET /accounts :param active: :return: """ try: with session_scope() as session: mgr = manager_factory.for_session(session) if state is not None: try: state = AccountStates(state) except: return ( make_response_error( "Bad Request: state {} not a valid value", in_httpcode=400), 400, ) response = mgr.list_accounts(with_state=state) return list(map(account_db_to_msg, response)), 200 except Exception as ex: logger.exception("API Error") return make_response_error("Error listing accounts", in_httpcode=500), 500
def delete_user(accountname, username): """ DELETE /accounts/{accountname}/users/{username} :param accountname: :param username: the user to delete :return: """ try: with session_scope() as session: mgr = manager_factory.for_session(session) if request.authorization.accountname == accountname: return make_response_error('Cannot delete credential used for authentication of the request'), 400 user = mgr.get_user(username) if user['account_name'] != accountname: return make_response_error('username {} not valid for account {}'.format(username, accountname)), 404 if mgr.delete_user(username): return '', 200 else: return make_response_error('Failed to delete credential: {}'.format(accountname)), 500 except Exception as ex: logger.exception('API Error') return make_response_error(errmsg=str(ex)), 500
def create_user_credential(accountname, username, credential): """ POST /accounts/{accountname}/users/{username}/credentials :param accountname: str account id for account account record :param username: str username :param credential: json object of the credential type :return: credential json object """ try: with session_scope() as session: mgr = manager_factory.for_session(session) usr = mgr.get_user(username) if not usr or usr['account_name'] != accountname: return make_response_error('Username not found in account'), 404 # For now, only support passwords via the api if credential['type'] != 'password': return make_response_error('Invalid credential type'), 400 if not credential.get('value'): return make_response_error('Invalid credential value, must be non-null and non-empty'), 400 try: cred_type = UserAccessCredentialTypes(credential['type']) except: return make_response_error(errmsg='Invalid credential type'), 400 cred = mgr.add_user_credential(session, creator_name=ApiRequestContextProxy.user(), username=username, credential_type=cred_type, value=credential['value']) return credential_db_to_msg(cred), 200 except Exception as ex: logger.exception('API Error') return make_response_error(errmsg=str(ex)), 500
def sync_feeds(sync=True, force_flush=False): """ POST /feeds?sync=True&force_flush=True :param sync: Boolean. If true, do a sync. If false, don't sync. :param force_flush: Boolean. If true, remove all previous data and replace with data from upstream source :return: """ result = [] if sync: try: result = FeedsUpdateTask.run_feeds_update(force_flush=force_flush) except LeaseAcquisitionFailedError as e: log.exception( 'Could not acquire lock on feed sync, likely another sync already in progress' ) return make_response_error( 'Failed to execute feed sync', in_httpcode=409, detail= 'Could not acquire lock on feed sync, likely another sync already in progress' ), 409 except Exception as e: log.exception('Error executing feed update task') return make_response_error( 'Failed to execute feed sync due to an internal error', in_httpcode=500), 500 return jsonify(['{}/{}'.format(x[0], x[1]) for x in result]), 200
def inner_wrapper(*args, **kwargs): try: with Yosai.context(self._yosai): # Context Manager functions try: try: identity = self.authenticate(request_proxy) if not identity.username: raise UnauthenticatedError('Authentication Required') except: raise UnauthenticatedError('Authentication Required') ApiRequestContextProxy.set_identity(identity) permissions_final = [] # Bind all the permissions as needed for perm in permission_s: domain = perm.domain if perm.domain else '*' action = perm.action if perm.action else '*' target = perm.target if perm.target else '*' if hasattr(domain, 'bind'): domain.bind(operation=f, kwargs=kwargs) domain = domain.value if hasattr(action, 'bind'): action.bind(operation=f, kwargs=kwargs) action = action.value if hasattr(target, 'bind'): target.bind(operation=f, kwargs=kwargs) target = target.value #permissions_final.append(':'.join([domain, action, target])) permissions_final.append(Permission(domain, action, target)) # Do the authz on the bound permissions try: self.authorize(ApiRequestContextProxy().identity(), permissions_final) except UnauthorizedError as ex: raise ex except Exception as e: logger.exception('Error doing authz: {}'.format(e)) raise UnauthorizedError(permissions_final) return f(*args, **kwargs) finally: # Teardown the request context ApiRequestContextProxy.set_identity(None) except UnauthorizedError as ex: return make_response_error(str(ex), in_httpcode=403), 403 except UnauthenticatedError as ex: return Response(response='Unauthorized', status=401, headers=[('WWW-Authenticate', 'basic realm="Authentication required"')]) except AnchoreApiError: raise except Exception as ex: logger.exception('Unexpected exception: {}'.format(ex)) return make_response_error('Internal error', in_httpcode=500), 500
def inline_authz(self, permission_s: list, authc_token: AuthenticationToken=None): """ Non-decorator impl of the @requires() decorator for isolated and inline invocation. Returns authenticated user identity on success or raises an exception :param permission_s: list of Permission objects :param authc_token: optional authc token to use for the authc portion, if omitted or None, the flask request context is used :return: IdentityContext object """ try: with Yosai.context(self._yosai): # Context Manager functions try: try: if not authc_token: identity = self.authenticate(request_proxy) else: identity = self.authenticate_token(authc_token) if not identity.username: raise UnauthenticatedError('Authentication Required') except: raise UnauthenticatedError('Authentication Required') ApiRequestContextProxy.set_identity(identity) permissions_final = [] # Bind all the permissions as needed for perm in permission_s: domain = perm.domain if perm.domain else '*' action = perm.action if perm.action else '*' target = perm.target if perm.target else '*' permissions_final.append(Permission(domain, action, target)) # Do the authz on the bound permissions try: self.authorize(ApiRequestContextProxy.identity(), permissions_final) except UnauthorizedError as ex: raise ex except Exception as e: logger.exception('Error doing authz: {}'.format(e)) raise UnauthorizedError(permissions_final) return ApiRequestContextProxy.identity() finally: # Teardown the request context ApiRequestContextProxy.set_identity(None) except UnauthorizedError as ex: return make_response_error(str(ex), in_httpcode=403), 403 except UnauthenticatedError as ex: return Response(response='Unauthorized', status=401, headers=[('WWW-Authenticate', 'basic realm="Authentication required"')]) except AnchoreApiError: raise except Exception as ex: logger.exception('Unexpected exception: {}'.format(ex)) return make_response_error('Internal error', in_httpcode=500), 500
def handle_proxy_response(resp): if issubclass(Exception, resp.__class__): if hasattr(resp, 'httpcode'): return make_response_error( resp, in_httpcode=resp.httpcode), resp.httpcode else: return make_response_error(resp, in_httpcode=500), 500 else: return resp, 200
def inline_authz(self, permission_s: list): """ Non-decorator impl of the @requires() decorator for isolated and inline invocation. Returns None on success or raises an exception :param permission_s: :return: """ try: with Yosai.context(self._yosai): # Context Manager functions try: try: identity = self.authenticate(request_proxy) if not identity.username: raise UnauthenticatedError( 'Authentication Required') except: raise UnauthenticatedError('Authentication Required') ApiRequestContextProxy.set_identity(identity) permissions_final = [] # Bind all the permissions as needed for perm in permission_s: domain = perm.domain if perm.domain else '*' action = perm.action if perm.action else '*' target = perm.target if perm.target else '*' permissions_final.append(':'.join( [domain, action, target])) # Do the authz on the bound permissions try: self.authorize(identity, permissions_final) except UnauthorizedError as ex: raise ex except Exception as e: logger.exception('Error doing authz: {}'.format(e)) raise UnauthorizedError(permissions_final) return None finally: # Teardown the request context ApiRequestContextProxy.set_identity(None) except UnauthorizedError as ex: return make_response_error(str(ex), in_httpcode=403), 403 except UnauthenticatedError as ex: return Response(response='Unauthorized', status=401, headers=[('WWW-Authenticate', 'basic realm="Authentication required"') ]) except Exception as ex: logger.exception('Unexpected exception: {}'.format(ex)) return make_response_error('Internal error', in_httpcode=500), 500
def content_upload(operation_id, content_type, request): """ Generic handler for multiple types of content uploads. Still operates at the API layer :param operation_id: :param content_type: :param request: :return: """ try: with session_scope() as db_session: record = (db_session.query(ImageImportOperation).filter_by( account=ApiRequestContextProxy.namespace(), uuid=operation_id).one_or_none()) if not record: raise api_exceptions.ResourceNotFound(resource=operation_id, detail={}) if not record.status.is_active(): raise api_exceptions.ConflictingRequest( message="import operation status does not allow uploads", detail={"status": record.status}, ) if not request.content_length: raise api_exceptions.BadRequest( message="Request must contain content-length header", detail={}) elif request.content_length > MAX_UPLOAD_SIZE: raise api_exceptions.BadRequest( message= "too large. Max size of 100MB supported for content", detail={"content-length": request.content_length}, ) digest, created_at = save_import_content(db_session, operation_id, request.data, content_type) resp = { "digest": digest, "created_at": datetime_to_rfc3339(created_at) } return resp, 200 except api_exceptions.AnchoreApiError as ex: return ( make_response_error(ex, in_httpcode=ex.__response_code__), ex.__response_code__, ) except Exception as ex: logger.exception("Unexpected error in api processing") return make_response_error(ex, in_httpcode=500), 500
def create_account(account): """ POST /accounts :param account: :return: """ try: try: can_create_account(account) except ValueError as ex: return make_response_error('Invalid account request: {}'.format( ex.args[0]), in_httpcode=400), 400 except Exception as ex: logger.exception('Unexpected exception in account validation') return make_response_error('Invalid account request', in_httpcode=400), 400 with session_scope() as session: mgr = manager_factory.for_session(session) try: resp = mgr.create_account(account_name=account['name'], account_type=account.get( 'type', AccountTypes.user.value), email=account.get('email')) except ValueError as ex: return make_response_error('Validation failed: {}'.format(ex), in_httpcode=400), 400 authorizer.notify(NotificationTypes.domain_created, account['name']) # Initialize account stuff try: _init_policy(account['name'], config=get_config()) except Exception: logger.exception( 'Could not initialize policy bundle for new account: {}'. format(account['name'])) raise return account_db_to_msg(resp), 200 except AccountAlreadyExistsError as ex: return make_response_error(errmsg='Account already exists', in_httpcode=400), 400 except Exception as ex: logger.exception('Unexpected Error creating account') return make_response_error('Error creating account', in_httpcode=500), 500
def list_artifacts(user_id, image_id, artifact_type): db = get_session() try: log.info("Getting retrieved files from image {}/{}".format(user_id, image_id)) img = db.query(Image).get((image_id, user_id)) if img: handlers = artifact_handlers.get(artifact_type) if not handlers: # Bad request return ( make_response_error( "Invalid artifact type {}".format(artifact_type), in_httpcode=400, ), 400, ) if not handlers.get("filter") or not handlers.get("mapper"): raise Exception( "incomplete artifact handler definition for {}".format( artifact_type ) ) filter_fn = handlers["filter"] artifact_items = filter_fn(img).all() map_fn = handlers["mapper"] artifact_listing = [map_fn(x) for x in artifact_items] return artifact_listing, 200 else: return None, 404 except HTTPException: raise except Exception as e: log.exception( "Error processing GET request for artifacts on image {}/{}".format( user_id, image_id ) ) return ( make_response_error( "Error getting artifacts from image {}/{}: {}".format( user_id, image_id, e ), in_httpcode=500, ), 500, ) finally: db.rollback()
def delete_account(accountname): """ DELETE /account/{accountname} :param accountname: :return: """ try: with session_scope() as session: mgr = manager_factory.for_session(session) account = verify_account(accountname, mgr) if not can_delete_account(account): return ( make_response_error("Account cannot be deleted", in_httpcode=400), 400, ) else: account = mgr.update_account_state(accountname, AccountStates.deleting) # Flush from authz system if necessary authorizer.notify(NotificationTypes.domain_deleted, accountname) users = mgr.list_users(accountname) for user in users: # Flush users logger.debug( "Deleting account user {} on authz system if using plugin" .format(user["username"])) authorizer.notify(NotificationTypes.principal_deleted, user["username"]) logger.debug("Deleting account user: {}".format( user["username"])) mgr.delete_user(user["username"]) return account_db_to_status_msg(account), 200 except InvalidStateError as ex: return make_response_error(str(ex), in_httpcode=400), 400 except AccountNotFoundError as ex: return make_response_error("Account not found", in_httpcode=404), 404 except Exception as e: logger.exception("API Error") return make_response_error("Error deleting account", in_httpcode=500), 500