def delete_store(store_name, user=None): # noqa: E501 """Delete file store # noqa: E501 :param store_name: Name of the store :type store_name: str :rtype: None """ session = Database.get_session() try: # Check the store q = Database.get_session().query(RosbagStore).filter( RosbagStore.name == store_name) # type: Query if q.count() == 1: session.delete(q.first()) session.commit() return "", 204 else: return Error(code=404, message="Store not found"), 404 except Exception as e: logging.exception("User account deletion failed") session.rollback() return Error(code=500, message="Exception occurred"), 500
def delete_bag_comment(store_name, bag_name, comment_id, user=None): # noqa: E501 """Post a comment # noqa: E501 :param store_name: Name of the store :type store_name: str :param bag_name: Name of the bag :type bag_name: str :param comment_id: Comment identifier :type comment_id: int :rtype: None """ try: session = Database.get_session() bag, e = find_bag_in_database(session, store_name, bag_name) if e: return e, e.code q = session.query(RosbagComment).filter( RosbagComment.uid == comment_id) # type: Query if q.count() != 1 or q.first().bag_id != bag.uid: return Error(code=404, message="Comment not found"), 404 session.delete(q.first()) session.commit() return "", 204 except Exception as e: return handle_exception(e)
def put_current_user(user, logged_in_user=None): """ Change current user information :rtype: User """ if connexion.request.is_json: user = SwaggerUser.from_dict(connexion.request.get_json()) if logged_in_user.alias != user.alias: return Error(code=400, message="Alias cannot be changed"), 400 session = Database.get_session() try: logged_in_user.from_swagger_model(user, user=logged_in_user) # Users are not allowed to change their own permissions... # if user.permissions is not None: # update_user_permissions(logged_in_user, user.permissions) session.commit() q = session.query(User).filter(User.uid == logged_in_user.uid) swagger_user = q.first().to_swagger_model(user=logged_in_user) swagger_user.permissions = list_user_permissions(q.first()) return swagger_user, 200 except Exception as e: logging.exception("Current user put failed") session.rollback() return Error(code=500, message="Exception occurred"), 500
def get_file_meta(store_name, uid, file_name, user=None): """ Get file meta data :param store_name: Name of the store :type store_name: str :param uid: Unique identifier of the file :type uid: int :param file_name: Name of the file :type file_name: str :rtype: FileDetailed """ try: q = Database.get_session().query(File).filter( and_(FileStore.name == store_name, File.uid == uid)) # type: Query if q.count(): file = q[0] if file.name == file_name: return file.to_swagger_model_detailed(user=user) return Error(code=404, message="Store or file not found"), 404 except Exception as e: if current_app.config['TESTING']: return Error(code=500, message="Exception: " + str(e)), 500 else: return Error(code=500, message="Exception occurred"), 500
def get_user_account(alias, logged_in_user=None): # noqa: E501 """Get user information # noqa: E501 :param alias: Alias of the user :type alias: str :rtype: User """ session = Database.get_session() try: # Check the store q = session.query(User).filter(User.alias == alias) # type: Query if q.count() == 1: swagger_user = q.first().to_swagger_model(user=logged_in_user) swagger_user.permissions = list_user_permissions(q.first()) return swagger_user, 200 else: return Error(code=404, message="User not found"), 404 except Exception as e: logging.exception("User account put failed") session.rollback() return Error(code=500, message="Exception occurred"), 500
def new_bag_comment(store_name, bag_name, comment, user=None): # noqa: E501 """Delete a comment # noqa: E501 :param store_name: Name of the store :type store_name: str :param bag_name: Name of the bag :type bag_name: str :param comment: Comment :type comment: dict | bytes :rtype: Comment """ if connexion.request.is_json: comment = Comment.from_dict(connexion.request.get_json()) # noqa: E501 try: session = Database.get_session() bag, e = find_bag_in_database(session, store_name, bag_name) if e: return e, e.code comment_model = RosbagComment() comment_model.from_swagger_model(comment) comment_model.user_id = user.uid comment_model.bag_id = bag.uid session.add(comment_model) session.commit() return comment_model.to_swagger_model() except Exception as e: return handle_exception(e)
def delete_user_account(alias, user=None): # noqa: E501 """Delete user account # noqa: E501 :param alias: Alias of the user :type alias: str :rtype: None """ session = Database.get_session() try: # Check the store q = session.query(User).filter(User.alias == alias) # type: Query if q.count() == 1: session.delete(q.first()) session.commit() return "", 204 else: return Error(code=404, message="User not found"), 404 except Exception as e: logging.exception("User account deletion failed") session.rollback() return Error(code=500, message="Exception occurred"), 500
def list_extraction_configurations(user=None): """List available configurations :rtype: List[BagExtractionConfiguration] """ try: q = Database.get_session().query(RosbagExtractionConfiguration) return [p.to_swagger_model(user=user) for p in q] except Exception as e: return handle_exception(e)
def get_current_session(): session_info = get_current_session_id_and_token() if not session_info: return None q = Database.get_session().query(Session).filter(Session.uid == session_info['id']) if q.count(): session = q.first() if session.token == session_info['token']: return session return None
def put_user_account(alias, user, block_on_existing=None, logged_in_user=None): # noqa: E501 """Change user information # noqa: E501 :param alias: Alias of the user :type alias: str :param user: The user information :type user: dict | bytes :rtype: User """ if connexion.request.is_json: user = SwaggerUser.from_dict(connexion.request.get_json()) if alias != user.alias: return Error(code=400, message="URL and body aliases don't match"), 400 if len(user.alias) < 4: return Error(code=400, message="Minimum alias length is 4 characters"), 400 session = Database.get_session() try: # Check the store q = session.query(User).filter(User.alias == alias) # type: Query # Create new store or use existing user_model = None if q.count() == 1: # Existing user if block_on_existing: return Error(code=1000, message="Already exists."), 400 user_model = q.first() else: user_model = User() session.add(user_model) user_model.from_swagger_model(user, user=logged_in_user) if user.permissions is not None: update_user_permissions(user_model, user.permissions, session) session.commit() q = session.query(User).filter(User.uid == user_model.uid) swagger_user = q.first().to_swagger_model(user=logged_in_user) swagger_user.permissions = list_user_permissions(q.first()) return swagger_user, 200 except Exception as e: logging.exception("User account put failed") session.rollback() return Error(code=500, message="Exception occurred"), 500
def bag_store_authorize_step_get(store_name, step, user=None): """ Authorization step forwarded to storage plugin :param store_name: Name of the store :type store_name: str :param step: Step of the authorization procedure :type step: str :rtype: None """ session = Database.get_session() try: q = session.query(RosbagStore).filter( RosbagStore.name == store_name) # type: Query if q.count(): store = q[0] storage_plugin = Storage.factory(store_name, store.store_type, store.store_data) link = url_for( "/api/v0.rbb_server_controllers_store_controller_bag_store_authorize_step_get", store_name=store_name, step="", _external=True) response = storage_plugin.authorize_get_step( step, flask_request, link) if storage_plugin.needs_saving(): store.store_data = storage_plugin.get_data() flag_modified(store, 'store_data') Database.get_session().commit() return response return Error(code=404, message="Store not found"), 404 except Exception as e: logging.exception(e) return Error(code=500, message="Exception occurred"), 500
def setup_database_for_test(): Database.init(debug=True) engine = Database.get_engine() connection = engine.connect() connection.execute("DROP SCHEMA IF EXISTS unittest CASCADE") connection.execute("CREATE SCHEMA unittest") connection.execute("SET search_path TO unittest, public") tx = connection.begin() try: # Create fresh schema with open( os.path.dirname(__file__) + "/../../src/rbb_server/schema.sql", 'r') as sql_file: sql = sql_file.read() connection.execute(sql) # Insert all our testing data with open(os.path.dirname(__file__) + "/test-data.sql", 'r') as sql_file: sql = sql_file.read() statements = sql.split(";") for statement in statements: sql = statement.strip() if sql: connection.execute(sql) tx.commit() except Exception as e: tx.rollback() logging.error(e) print("ERROR: Cannot load unittest data into database!") raise e connection.close() # Make current session use the testing schema Database.get_session().execute("SET search_path TO unittest")
def test_get_bag_product_files(self): bag = Database.get_session().query(Rosbag).get(1) # type: Rosbag self.assertEqual(len(bag.products), 3) rviz_product = None for product in bag.products: #type: RosbagProduct if product.plugin == "RvizRecorder": rviz_product = product self.assertIsNotNone(rviz_product) self.assertEqual(len(rviz_product.files), 1) self.assertEqual(rviz_product.files[0].key, "video") self.assertEqual(rviz_product.files[0].file.name, "test.mp4") self.assertEqual(rviz_product.files[0].file.store.store_type, "google-cloud")
def put_file_store(store_name, store, block_on_existing=None, user=None): # noqa: E501 """Create/update store # noqa: E501 :param store_name: Name of the store :type store_name: str :param store: Store information :type store: dict | bytes :rtype: FileStore """ if connexion.request.is_json: store = SwaggerFileStore.from_dict( connexion.request.get_json()) # noqa: E501 if store_name != store.name: return Error(code=400, message="URL and body names don't match"), 400 session = Database.get_session() try: # Check the store q = session.query(FileStore).filter( FileStore.name == store_name) # type: Query # Create new store or use existing model = None if q.first(): # Existing store if block_on_existing: return Error(code=1000, message="Already exists."), 400 model = q.first() else: model = FileStore() session.add(model) model.from_swagger_model(store, user=user) session.commit() q = session.query(FileStore).filter(FileStore.uid == model.uid) return q.first().to_swagger_model(user=user), 200 except Exception as e: logging.exception("File store put failed") session.rollback() return Error(code=500, message="Exception occurred"), 500
def patch_bag_meta(store_name, bag_name, bag, trigger=None, user=None): # noqa: E501 """Partial update of bag information (this only supports a few fields) # noqa: E501 :param store_name: Name of the store :type store_name: str :param bag_name: Name of the bag :type bag_name: str :param bag: Bag to register :type bag: dict | bytes :param trigger: Hooks to trigger :type trigger: str :rtype: BagDetailed """ if connexion.request.is_json: bag = connexion.request.get_json() try: session = Database.get_session() bag_model, e = find_bag_in_database(session, store_name, bag_name) if e: return e, e.code changed = False if 'comment' in bag and isinstance(bag['comment'], str): bag_model.comment = bag['comment'] changed = True if 'extraction_failure' in bag: bag_model.extraction_failure = bag['extraction_failure'] changed = True if 'in_trash' in bag: bag_model.in_trash = bag['in_trash'] changed = True if changed: session.commit() return bag_model.to_swagger_model_detailed(user=user) except Exception as e: return handle_exception(e)
def list_stores(user=None): """ List available stores :rtype: List[BagStoreDetailed] """ try: q = Database.get_session().query(RosbagStore) return [p.to_swagger_model_detailed(user=user) for p in q] except Exception as e: if current_app.config['TESTING']: return Error(code=500, message="Exception: " + str(e)), 500 else: return Error(code=500, message="Exception occurred"), 500
def list_tags(user=None): """List all tags # noqa: E501 :rtype: List[Tag] """ try: session = Database.get_session() q = session.query(Tag) #type: Query return [p.to_swagger_model(user=user) for p in q] except Exception as e: return handle_exception(e)
def check_auth(username, password): """This function is called to check if a username / password combination is valid. """ try: q = Database.get_session().query(User).filter(User.alias == username) if q.count(): user = q.first() if user.check_password(password): return user except Exception as e: logging.exception(e) return False
def test_insert_store(self): test_store = RosbagStore( name="some-test-store", description="test", store_type="dropbox", store_data="{}" ) Database.get_session().add(test_store) Database.get_session().flush() self.assertIsNotNone(test_store.uid, "UID assigned after flush/commit") Database.get_session().commit()
def get_store_extraction_configs(store_name, user=None): """Get list of auto extraction configs :param store_name: Name of the store :type store_name: str :rtype: List[BagExtractionConfiguration] """ try: q = Database.get_session().query(RosbagStore).filter(RosbagStore.name == store_name) #type: Query if q.count(): return [x.to_swagger_model(user=user) for x in q.first().auto_extraction_configs] else: return Error(code=404, message="Store not found"), 404 except Exception as e: return handle_exception(e)
def get_extraction_config(config_name, user=None): """Get configuration details :param config_name: Name of the configuration :type config_name: str :rtype: BagExtractionConfiguration """ try: q = Database.get_session().query(RosbagExtractionConfiguration).\ filter(RosbagExtractionConfiguration.name == config_name) #type: Query if q.count(): return q[0].to_swagger_model(user=user) else: return Error(code=404, message="Configuration not found"), 404 except Exception as e: return handle_exception(e)
def read_bags_into_map(store, plugin): bags = {} bags_full_path = {} q = Database.get_session().query(Rosbag).filter( Rosbag.store_id == store.uid) for bag in q: file_info = plugin.list_file(bag.store_data) bag_basename = file_info.get_name() bag_fullname = file_info.get_path() if bag_basename in bags: logging.warning("Duplicate bag '{}' in store '{}'".format( bag_basename, store.name)) bags[bag_basename] = bag bags_full_path[bag_fullname] = bag return bags, bags_full_path
def put_bag_tags(store_name, bag_name, tags, auto_create=None, user=None): """Change bag tags # noqa: E501 :param store_name: Name of the store :type store_name: str :param bag_name: Name of the bag :type bag_name: str :param tags: List of tags :type tags: List[] :param auto_create: Create non existing tags :type auto_create: bool :rtype: List[Tag] """ try: session = Database.get_session() bag, e = find_bag_in_database(session, store_name, bag_name) if e: return e, e.code tag_models = [] tags_unique = list(set([x.strip().lower() for x in tags])) for tag in tags_unique: q = session.query(Tag).filter(Tag.tag == tag) # type: Query if q.count() == 1: tag_models.append(q.first()) else: if auto_create: tag_models.append(Tag(tag=tag, color="")) else: return Error(code=400, message="Tag '" + tag + "' does not exist"), 400 bag.tags = tag_models session.commit() return get_bag_tags(store_name, bag_name) except Exception as e: return handle_exception(e)
def list_user_accounts(user=None): # noqa: E501 """List user acounts # noqa: E501 :rtype: List[User] """ session = Database.get_session() try: # Check the store q = session.query(User) # type: Query return [x.to_swagger_model(user=user) for x in q], 200 except Exception as e: logging.exception("List user accounts") session.rollback() return Error(code=500, message="Exception occurred"), 500
def put_tag(tag, tag_obj, user=None): """Create/update tag # noqa: E501 :param tag: Name of the tag :type tag: str :param tag_obj: Tag information :type tag_obj: dict | bytes :rtype: Tag """ tag = tag.strip().lower() if connexion.request.is_json: tag_obj = SwaggerTag.from_dict(connexion.request.get_json()) # We do allow renaming tags # if tag_obj.tag != tag: # return Error(code=400, message="Path and body tag are not the same"), 400 try: session = Database.get_session() q = session.query(Tag).filter(Tag.tag == tag) # type: Query model = Tag() if q.count() == 1: model = q.first() else: if tag_obj.tag != tag: return Error( code=400, message="Path and body tag have to be equal for a new tag" ), 400 session.add(model) model.from_swagger_model(tag_obj) session.commit() return model.to_swagger_model(user=user) except Exception as e: return handle_exception(e)
def test_insert_bag(self): bag = Rosbag( store=Database.get_session().query(RosbagStore).get(1), store_data={'test':'est'}, name="Testbag", is_extracted=False, meta_available=False, size=100, start_time=datetime.datetime.now(), end_time=datetime.datetime.now(), duration=10.4, messages=10000, comment="Lalalalala" ) Database.get_session().add(bag) Database.get_session().flush() self.assertIsNotNone(bag.uid, "UID assigned after flush/commit") Database.get_session().commit() bag = Database.get_session().query(Rosbag).get(bag.uid) self.assertEqual(bag.store_data['test'], 'est')
def put_extraction_configuration(config_name, configuration_obj, block_on_existing=None, user=None): """Create/update configuration :param config_name: Name of the configuration :type config_name: str :param configuration: Configuration information :type configuration: dict | bytes :rtype: BagExtractionConfiguration """ if connexion.request.is_json: configuration_obj = BagExtractionConfiguration.from_dict(connexion.request.get_json()) if config_name != configuration_obj.name: return Error(code=400, message="URL and body names don't match"), 400 session = Database.get_session() try: # Check the store q = session.query(RosbagExtractionConfiguration).filter(RosbagExtractionConfiguration.name == config_name) # type: Query # Create new store or use existing model = None if q.count() == 1: # Existing configuration if block_on_existing: return Error(code=1000, message="Already exists."), 400 model = q.first() else: model = RosbagExtractionConfiguration() session.add(model) model.from_swagger_model(configuration_obj, user=user) session.commit() q = session.query(RosbagExtractionConfiguration).filter(RosbagExtractionConfiguration.uid == model.uid) return q.first().to_swagger_model(user=user), 200 except Exception as e: session.rollback() return handle_exception(e)
def get_tag(tag, user=None): """Get tag info # noqa: E501 :param tag: Name of the tag :type tag: str :rtype: Tag """ try: session = Database.get_session() q = session.query(Tag).filter(Tag.tag == tag) # type: Query if q.count() == 0: return Error(code=404, message="Tag not found"), 404 return q[0].to_swagger_model(user=user) except Exception as e: return handle_exception(e)
def list_sessions(user=None): """ List current session :rtype: List[Session] """ try: q = Database.get_session().query(Session).filter( Session.user_uid == user.uid) models = [] for session in q: model = session.to_swagger_model() model.token = "" models.append(model) return models except Exception as e: return error_helper.handle_exception(e)
def get_bag_meta(store_name, bag_name, user=None): """ List products from bag :param store_name: Name of the store :type store_name: str :param bag_name: Name of the bag :type bag_name: str :rtype: BagDetailed """ try: session = Database.get_session() bag_model, e = find_bag_in_database(session, store_name, bag_name) if e: return e, e.code return bag_model.to_swagger_model_detailed(user=user) except Exception as e: return handle_exception(e)