예제 #1
0
def create_user(email, username, password):
    fb_db = firebaseDB()
    try:
        user = auth.create_user(email=email,
                                display_name=username,
                                password=password)

        ref = fb_db.reference(f"v2/users/{user.uid}/")
        ref.update({
            "username":
            username,
            "taskContributionCount":
            0,
            "groupContributionCount":
            0,
            "projectContributionCount":
            0,
            "created":
            datetime.datetime.utcnow().isoformat()[0:-3] +
            "Z",  # Store current datetime in milliseconds
        })
        logger.info(f"created new user: {user.uid}")
        return user
    except Exception as e:
        logger.info(f"could not create new user {email}.")
        raise CustomError(e)
def send_progress_notification(project_id: str):
    """Send progress notification to project managers in Slack."""
    fb_db = auth.firebaseDB()
    progress = fb_db.reference(f"v2/projects/{project_id}/progress").get()

    if not progress:
        logger.info(
            f"could not get progress from firebase for project {project_id}")
    elif progress >= 90:
        project_name = fb_db.reference(f"v2/projects/{project_id}/name").get()
        notification_90_sent = fb_db.reference(
            f"v2/projects/{project_id}/notification_90_sent").get()
        notification_100_sent = fb_db.reference(
            f"v2/projects/{project_id}/notification_100_sent").get()
        logger.info(
            f"{project_id} - progress: {progress},"
            f"notifications: {notification_90_sent} {notification_100_sent}")

        if progress >= 90 and not notification_90_sent:
            # send notification and set value in firebase
            send_slack_message(MessageType.NOTIFICATION_90, project_name,
                               project_id)
            fb_db.reference(
                f"v2/projects/{project_id}/notification_90_sent").set(True)

        if progress >= 100 and not notification_100_sent:
            # send notification and set value in firebase
            send_slack_message(MessageType.NOTIFICATION_100, project_name,
                               project_id)
            fb_db.reference(
                f"v2/projects/{project_id}/notification_100_sent").set(True)
예제 #3
0
def renew_team_token(team_id):
    """Create new team in Firebase."""
    fb_db = firebaseDB()  # noqa E841
    try:
        # check if team exist in firebase
        if not fb_db.reference(f"v2/teams/{team_id}").get():
            raise CustomError(f"can't find team in firebase: {team_id}")

        # get team name from firebase
        team_name = fb_db.reference(f"v2/teams/{team_id}/teamName").get()

        # check if reference path is valid
        ref = fb_db.reference(f"v2/teams/{team_id}")
        if not re.match(r"/v2/\w+/[-a-zA-Z0-9]+", ref.path):
            raise CustomError(
                f"""Given argument resulted in invalid Firebase Realtime Database reference.
                        {ref.path}""")

        # generate new uuid4 token
        new_team_token = str(uuid.uuid4())

        # set team token in firebase
        ref.update({"teamToken": new_team_token})
        logger.info(
            f"renewed team token: {team_id} - '{team_name}' - {new_team_token}"
        )
        return new_team_token

    except Exception as e:
        logger.info(f"could not delete team: {team_id}")
        raise CustomError(e)
예제 #4
0
    def save_tutorial(self):
        """Save the tutorial in Firebase."""

        tutorial = vars(self)
        groups = self.groups
        tasks = self.tasks

        tutorial.pop("groups", None)
        tutorial.pop("tasks", None)
        tutorial.pop("raw_tasks", None)
        tutorial.pop("examplesFile", None)
        tutorial.pop("tutorial_tasks", None)

        fb_db = auth.firebaseDB()
        ref = fb_db.reference("")

        if not self.projectId or self.projectId == "":
            raise CustomError(
                f"""Given argument resulted in invalid Firebase Realtime Database reference.
                    Project Id is invalid: {self.projectId}""")

        ref.update({
            f"v2/projects/{self.projectId}": tutorial,
            f"v2/groups/{self.projectId}": groups,
            f"v2/tasks/{self.projectId}": tasks,
        })

        logger.info(f"uploaded tutorial data to firebase for {self.projectId}")

        ref = fb_db.reference(f"v2/tutorialDrafts/{self.tutorialDraftId}")
        ref.set({})
예제 #5
0
def delete_team(team_id):
    """Delete team in Firebase."""
    # TODO: What is the consequence of this on projects and users
    #   do we expect that the teamId is removed there as well?
    #   teamId is removed for users, but not for projects at the moment
    fb_db = firebaseDB()  # noqa E841
    try:
        # check if team exist in firebase
        if not fb_db.reference(f"v2/teams/{team_id}").get():
            raise CustomError(f"can't find team in firebase: {team_id}")

        # remove all team members
        remove_all_team_members(team_id)

        # get team name from firebase
        team_name = fb_db.reference(f"v2/teams/{team_id}/teamName").get()

        # check if reference path is valid, e.g. if team_id is None
        ref = fb_db.reference(f"v2/teams/{team_id}")
        if not re.match(r"/v2/\w+/[-a-zA-Z0-9]+", ref.path):
            raise CustomError(
                f"""Given argument resulted in invalid Firebase Realtime Database reference.
                        {ref.path}""")

        # delete team in firebase
        ref.delete()
        logger.info(f"deleted team: {team_id} - '{team_name}'")

    except Exception as e:
        logger.info(f"could not delete team: {team_id}")
        raise CustomError(e)
예제 #6
0
def move_project_data_to_v2(project_id):
    """
    Copy project information from old path to v2/projects in Firebase.
    Add status=archived attribute.
    Use Firebase transaction function for this.
    """

    # Firebase transaction function
    def transfer(current_data):
        # we need to add these attributes
        # since they are expected for version 2
        current_data["status"] = "archived"
        current_data["projectType"] = 1
        current_data["projectId"] = str(project_id)
        current_data["progress"] = current_data.get("progress", 0)
        current_data["name"] = current_data.get("name", "unknown")
        fb_db.reference("v2/projects/{0}".format(project_id)).set(current_data)
        return dict()

    fb_db = auth.firebaseDB()
    projects_ref = fb_db.reference(f"projects/{project_id}")
    try:
        projects_ref.transaction(transfer)
        logger.info(
            f"{project_id}: Transfered project to v2 and delete in old path")
        return True
    except fb_db.TransactionAbortedError:
        logger.exception(f"{project_id}: Firebase transaction"
                         f"for transferring project failed to commit")
        return False
    def test_deletion(self):
        """Test if tasks, groups, project and results are deleted."""
        delete_project.delete_project([self.project_id])
        time.sleep(1)

        fb_db = auth.firebaseDB()
        ref = fb_db.reference("v2/results/{0}".format(self.project_id))
        self.assertIsNone(ref.get())
        ref = fb_db.reference("v2/tasks/{0}".format(self.project_id))
        self.assertIsNone(ref.get())
        ref = fb_db.reference("v2/groups/{0}".format(self.project_id))
        self.assertIsNone(ref.get())
        ref = fb_db.reference("v2/projects/{0}".format(self.project_id))
        self.assertIsNone(ref.get())

        pg_db = auth.postgresDB()
        sql_query = "SELECT * FROM tasks WHERE project_id = '{}'".format(
            self.project_id)
        result = pg_db.retr_query(sql_query)
        self.assertEqual(result, [])
        sql_query = "SELECT * FROM groups WHERE project_id = '{}'".format(
            self.project_id)
        result = pg_db.retr_query(sql_query)
        self.assertEqual(result, [])
        sql_query = "SELECT * FROM projects WHERE project_id = '{}'".format(
            self.project_id)
        result = pg_db.retr_query(sql_query)
        self.assertEqual(result, [])
        sql_query = "SELECT * FROM results WHERE project_id = '{}'".format(
            self.project_id)
        result = pg_db.retr_query(sql_query)
        self.assertEqual(result, [])
예제 #8
0
    def test_project_id_equals_none(self):
        """Test for project id which does not exists."""
        delete_project.delete_project([None])

        time.sleep(5)  # Wait for Firebase Functions to complete

        fb_db = auth.firebaseDB()
        ref = fb_db.reference("v2/results")
        self.assertIsNotNone(ref.get(shallow=True))
        ref = fb_db.reference("v2/tasks")
        self.assertIsNotNone(ref.get(shallow=True))
        ref = fb_db.reference("v2/groups")
        self.assertIsNotNone(ref.get(shallow=True))
        ref = fb_db.reference("v2/groupsUsers")
        self.assertIsNotNone(ref.get(shallow=True))
        ref = fb_db.reference("v2/projects")
        self.assertIsNotNone(ref.get(shallow=True))

        pg_db = auth.postgresDB()
        sql_query = f"SELECT * FROM tasks WHERE project_id = '{self.project_id}'"
        result = pg_db.retr_query(sql_query)
        self.assertNotEqual(result, [])
        sql_query = f"SELECT * FROM groups WHERE project_id = '{self.project_id}'"
        result = pg_db.retr_query(sql_query)
        self.assertNotEqual(result, [])
        sql_query = f"SELECT * FROM projects WHERE project_id = '{self.project_id}'"
        result = pg_db.retr_query(sql_query)
        self.assertNotEqual(result, [])
        sql_query = f"SELECT * FROM results WHERE project_id = '{self.project_id}'"
        result = pg_db.retr_query(sql_query)
        self.assertNotEqual(result, [])
    def test_project_id_equals_none(self):
        """Test for project id which does not exists."""
        delete_project.delete_project([None])

        fb_db = auth.firebaseDB()
        ref = fb_db.reference("v2/results")
        self.assertIsNotNone(ref.get(shallow=True))
        ref = fb_db.reference("v2/tasks")
        self.assertIsNotNone(ref.get(shallow=True))
        ref = fb_db.reference("v2/groups")
        self.assertIsNotNone(ref.get(shallow=True))
        ref = fb_db.reference("v2/projects")
        self.assertIsNotNone(ref.get(shallow=True))

        pg_db = auth.postgresDB()
        sql_query = "SELECT * FROM tasks WHERE project_id = '{}'".format(
            self.project_id)
        result = pg_db.retr_query(sql_query)
        self.assertNotEqual(result, [])
        sql_query = "SELECT * FROM groups WHERE project_id = '{}'".format(
            self.project_id)
        result = pg_db.retr_query(sql_query)
        self.assertNotEqual(result, [])
        sql_query = "SELECT * FROM projects WHERE project_id = '{}'".format(
            self.project_id)
        result = pg_db.retr_query(sql_query)
        self.assertNotEqual(result, [])
        sql_query = "SELECT * FROM results WHERE project_id = '{}'".format(
            self.project_id)
        result = pg_db.retr_query(sql_query)
        self.assertNotEqual(result, [])
예제 #10
0
def run_create_tutorials() -> None:
    """Create a tutorial project from provided JSON file."""

    fb_db = auth.firebaseDB()
    ref = fb_db.reference("v2/tutorialDrafts/")
    tutorial_drafts = ref.get()

    if tutorial_drafts is None:
        logger.info("There are no tutorial drafts in firebase.")
        return None

    for tutorial_draft_id, tutorial_draft in tutorial_drafts.items():
        tutorial_draft["tutorialDraftId"] = tutorial_draft_id
        project_type = tutorial_draft["projectType"]
        project_name = tutorial_draft["name"]

        try:
            tutorial = ProjectType(project_type).tutorial(tutorial_draft)
            tutorial.create_tutorial_groups()
            tutorial.create_tutorial_tasks()
            tutorial.save_tutorial()
            send_slack_message(MessageType.SUCCESS, project_name,
                               tutorial.projectId)
            logger.info(f"Success: Tutorial Creation ({project_name})")
        except CustomError:
            ref = fb_db.reference(f"v2/tutorialDrafts/{tutorial_draft_id}")
            ref.set({})
            send_slack_message(MessageType.FAIL, project_name,
                               tutorial.projectId)
            logger.exception(
                "Failed: Project Creation ({0}))".format(project_name))
            sentry.capture_exception()
        continue
예제 #11
0
def get_all_projects_of_type(project_type: int):
    """Get the project ids for active and inactive projects in Firebase DB."""

    project_id_list = []
    fb_db = firebaseDB()

    # we neglect private projects here
    # since there are no projects set up in production yet
    status_list = ["active", "inactive"]

    for status in status_list:
        logger.info(f"query {status} projects")
        projects = (
            fb_db.reference(f"v2/projects/")
            .order_by_child("status")
            .equal_to(status)
            .get()
        )
        for project_id, data in projects.items():
            if (data.get("projectType", 1) == project_type) & (
                data.get("tutorialId", None) is None
            ):
                project_id_list.append(project_id)

    logger.info(f"got {len(project_id_list)} project from firebase.")
    return project_id_list
def add_tutorial_id_to_projects(project_id_list, tutorial_id):
    fb_db = firebaseDB()
    for project_id in project_id_list:
        fb_db.reference(f"v2/projects/{project_id}/tutorialId").set(
            tutorial_id)
        logger.info(
            f"added tutorial id '{tutorial_id}' to project '{project_id}'")
예제 #13
0
def remove_all_team_members(team_id):
    """Remove teamId attribute for all users of the team."""
    fb_db = firebaseDB()  # noqa E841
    try:
        # check if team exist in firebase
        if not fb_db.reference(f"v2/teams/{team_id}").get():
            raise CustomError(f"can't find team in firebase: {team_id}")

        # get team name from firebase
        team_name = fb_db.reference(f"v2/teams/{team_id}/teamName").get()

        # generate random uuid4 token
        team_members = (fb_db.reference("v2/users/").order_by_child(
            "teamId").equal_to(team_id).get())

        # remove teamId attribute for each members
        if not team_members:
            logger.info(
                f"there are no members of the team {team_id} - '{team_name}'")
        else:
            for user_id in team_members.keys():
                # update data in firebase
                ref = fb_db.reference(f"v2/users/{user_id}/")
                ref.update({"teamId": None})
                logger.info(
                    f"removed teamId {team_id} - '{team_name}' for user {user_id}"
                )
            logger.info(
                f"removed all team members from team: {team_id} - '{team_name}'"
            )
    except Exception as e:
        logger.info(f"could not create team: {team_name}")
        raise CustomError(e)
def update_user_data(user_ids: list = []) -> None:
    """Copies new users from Firebase to Postgres."""
    # TODO: On Conflict
    fb_db = auth.firebaseDB()
    pg_db = auth.postgresDB()

    ref = fb_db.reference("v2/users")
    last_updated = get_last_updated_timestamp()

    if user_ids:
        logger.info("Add custom user ids to user list, which will be updated.")
        users = {}
        for user_id in user_ids:
            users[user_id] = ref.child(user_id).get()
    elif last_updated:
        # Get only new users from Firebase.
        query = ref.order_by_child("created").start_at(last_updated)
        users = query.get()
        if len(users) == 0:
            logger.info("there are no new users in Firebase.")
        else:
            # Delete first user in ordered dict (FIFO).
            # This user is already in the database (user.created = last_updated).
            users.popitem(last=False)
    else:
        # Get all users from Firebase.
        users = ref.get()

    for user_id, user in users.items():
        # Convert timestamp (ISO 8601) from string to a datetime object.
        try:
            created = dt.datetime.strptime(
                user["created"].replace("Z", ""), "%Y-%m-%dT%H:%M:%S.%f"
            )
        except KeyError:
            # If user has no "created" attribute set it to current time.
            created = dt.datetime.utcnow().isoformat()[0:-3] + "Z"
            logger.info(
                "user {0} didn't have a 'created' attribute. ".format(user_id)
                + "Set it to '{0}' now.".format(created)
            )
        username = user.get("username", None)
        query_update_user = """
            INSERT INTO users (user_id, username, created)
            VALUES(%s, %s, %s)
            ON CONFLICT (user_id) DO UPDATE
            SET username=%s,
            created=%s;
        """
        data_update_user = [
            user_id,
            username,
            created,
            username,
            created,
        ]
        pg_db.query(query_update_user, data_update_user)
    logger.info("Updated user data in Potgres.")
def transfer_results(project_id_list=None):
    """
    Download results from firebase,
    saves them to postgres and then deletes the results in firebase.
    This is implemented as a transactional operation as described in
    the Firebase docs to avoid missing new generated results in
    Firebase during execution of this function.
    """

    # Firebase transaction function
    def transfer(current_results):
        if current_results is None:
            logger.info(f"{project_id}: No results in Firebase")
            return dict()
        else:
            results_user_id_list = get_user_ids_from_results(current_results)
            update_data.update_user_data(results_user_id_list)
            results_file = results_to_file(current_results, project_id)
            save_results_to_postgres(results_file)
            return dict()

    fb_db = auth.firebaseDB()

    if not project_id_list:
        # get project_ids from existing results if no project ids specified
        project_id_list = fb_db.reference("v2/results/").get(shallow=True)
        if not project_id_list:
            project_id_list = []
            logger.info(f"There are no results to transfer.")

    # get all project ids from postgres,
    # we will only transfer results for projects we have there
    postgres_project_ids = get_projects_from_postgres()

    for project_id in project_id_list:
        if project_id not in postgres_project_ids:
            logger.info(f"{project_id}: This project is not in postgres. "
                        f"We will not transfer results")
            continue
        elif "tutorial" in project_id:
            logger.info(f"{project_id}: these are results for a tutorial. "
                        f"We will not transfer these")
            continue

        logger.info(f"{project_id}: Start transfering results")

        results_ref = fb_db.reference(f"v2/results/{project_id}")
        truncate_temp_results()

        try:
            results_ref.transaction(transfer)
            logger.info(f"{project_id}: Transfered results to postgres")
        except fb_db.TransactionAbortedError:
            logger.exception(f"{project_id}: Firebase transaction for "
                             f"transfering results failed to commit")

    del fb_db
    return project_id_list
def run_create_projects():
    """
    Create projects from submitted project drafts.

    Get project drafts from Firebase.
    Create projects with groups and tasks.
    Save created projects, groups and tasks to Firebase and Postgres.
    """

    fb_db = auth.firebaseDB()
    ref = fb_db.reference("v2/projectDrafts/")
    project_drafts = ref.get()

    if project_drafts is None:
        logger.info("There are no project drafts in firebase.")
        return None

    for project_draft_id, project_draft in project_drafts.items():
        project_draft["projectDraftId"] = project_draft_id
        project_type = project_draft["projectType"]
        project_name = project_draft["name"]
        try:
            # Create a project object using appropriate class (project type).
            project = ProjectType(project_type).constructor(project_draft)
            # TODO: here the project.geometry attribute is overwritten
            #  this is super confusing since it's not a geojson anymore
            #  but this is what we set initially,
            #  e.g. in tile_map_service_grid/project.py
            #  project.geometry is set to a list of wkt geometries now
            #  this can't be handled in postgres,
            #  postgres expects just a string not an array
            #  validated_geometries should be called during init already
            #  for the respective project types

            project.geometry = project.validate_geometries()
            project.create_groups()
            project.calc_required_results()
            # Save project and its groups and tasks to Firebase and Postgres.
            project.save_project()
            send_slack_message(MessageType.SUCCESS, project_name,
                               project.projectId)
            logger.info("Success: Project Creation ({0})".format(project_name))
        except CustomError as e:
            ref = fb_db.reference(f"v2/projectDrafts/{project_draft_id}")
            ref.set({})

            # check if project could be initialized
            try:
                project_id = project.projectId
            except UnboundLocalError:
                project_id = None

            send_slack_message(MessageType.FAIL, project_name, project_id,
                               str(e))
            logger.exception(
                "Failed: Project Creation ({0}))".format(project_name))
            sentry.capture_exception()
        continue
예제 #17
0
def delete_other_old_data():
    """
    Delete old imports, results, announcements in Firebase
    """
    fb_db = auth.firebaseDB()
    fb_db.reference("imports").set({})
    fb_db.reference("results").set({})
    fb_db.reference("announcements").set({})
    logger.info("deleted old results, imports, announcements")
    def test_remove_all_team_members(self):
        team_management.remove_all_team_members(self.team_id)

        # check if no members
        fb_db = firebaseDB()
        team_members = (
            fb_db.reference(f"v2/users/").order_by_child("teamId").equal_to(
                self.team_id).get())
        self.assertEqual(len(team_members), 0)
def set_up_team_member():
    fb_db = firebaseDB()
    team_id = "unittest-team-1234"
    user_id = "unittest-team-member-1"
    data = {"teamId": team_id}
    ref = fb_db.reference(f"v2/users/{user_id}")
    ref.set(data)

    return user_id
def set_up_team():
    fb_db = firebaseDB()
    team_id = "unittest-team-1234"
    team_name = "unittest-team"
    team_token = "12345678-1234-5678-1234-567812345678"
    data = {"teamName": team_name, "teamToken": team_token}
    ref = fb_db.reference(f"v2/teams/{team_id}")
    ref.set(data)

    return team_id, team_name, team_token
def transfer_results(project_id_list=None):
    """Transfer results for one project after the other.
    Will only trigger the transfer of results for projects
    that are defined in the postgres database.
    Will not transfer results for tutorials and
    for projects which are not set up in postgres.
    """
    if project_id_list is None:
        # get project_ids from existing results if no project ids specified
        fb_db = auth.firebaseDB()
        project_id_list = fb_db.reference("v2/results/").get(shallow=True)
        if project_id_list is None:
            project_id_list = []
            logger.info("There are no results to transfer.")

    # Get all project ids from postgres.
    # We will only transfer results for projects we in postgres.
    postgres_project_ids = get_projects_from_postgres()

    project_id_list_transfered = []
    for project_id in project_id_list:
        if project_id not in postgres_project_ids:
            logger.info(
                f"{project_id}: This project is not in postgres. "
                f"We will not transfer results"
            )
            continue
        elif "tutorial" in project_id:
            logger.info(
                f"{project_id}: these are results for a tutorial. "
                f"We will not transfer these"
            )
            continue
        else:
            logger.info(f"{project_id}: Start transfer results")
            fb_db = auth.firebaseDB()
            results_ref = fb_db.reference(f"v2/results/{project_id}")
            results = results_ref.get()
            del fb_db
            transfer_results_for_project(project_id, results)
            project_id_list_transfered.append(project_id)

    return project_id_list_transfered
예제 #22
0
def get_old_projects():
    """
    Get all projects from Firebase which have been created
    before we switched to v2.
    """
    fb_db = auth.firebaseDB()
    ref = fb_db.reference("projects")
    projects = ref.get()
    logger.info("got old projects from firebase")
    return projects
예제 #23
0
def update_username(email, username):
    fb_db = firebaseDB()
    try:
        user = auth.get_user_by_email(email)
        auth.update_user(user.uid, display_name=username)
        ref = fb_db.reference(f"v2/users/{user.uid}/username")
        ref.set(username)
        logger.info(f"updated username for user {email}: {username}")
    except Exception as e:
        logger.info(f"could not find user {email} in firebase to update username.")
        raise CustomError(e)
예제 #24
0
def delete_user(email):
    fb_db = firebaseDB()
    try:
        user = auth.get_user_by_email(email)
        ref = fb_db.reference(f"v2/users/")
        ref.update({user.uid: None})
        auth.delete_user(user.uid)
        logger.info(f"deleted user {email}")
    except Exception as e:
        logger.info(f"could not find user {email} in firebase to delete.")
        raise CustomError(e)
예제 #25
0
def set_project_manager_rights(email):
    fb_db = firebaseDB()  # noqa E841
    try:
        user = auth.get_user_by_email(email)
        auth.set_custom_user_claims(user.uid, {"projectManager": True})
        logger.info(f"user {email} has project manager rights.")
    except Exception as e:
        logger.info(
            f"could not find user {email} in firebase to set project manager rights."
        )
        raise CustomError(e)
    def test_renew_team_token(self):
        new_team_token = team_management.renew_team_token(self.team_id)

        self.assertGreaterEqual(len(new_team_token), 32)
        self.assertNotEqual(new_team_token, self.team_token)

        # check data in Firebase
        fb_db = firebaseDB()
        ref = fb_db.reference(f"v2/teams/{self.team_id}/teamToken")
        team_token = ref.get()
        self.assertEqual(team_token, new_team_token)
def tear_down_team_member(user_id):
    fb_db = firebaseDB()
    # check if reference path is valid, e.g. if team_id is None
    ref = fb_db.reference(f"v2/users/{user_id}")
    if not re.match(r"/v2/\w+/[-a-zA-Z0-9]+", ref.path):
        raise CustomError(
            f"""Given argument resulted in invalid Firebase Realtime Database reference.
                                    {ref.path}""")

    # delete team in firebase
    ref.delete()
예제 #28
0
def remove_project_manager_rights(email):
    fb_db = firebaseDB()  # noqa E841
    try:
        user = auth.get_user_by_email(email)
        auth.update_user(user.uid, custom_claims=auth.DELETE_ATTRIBUTE)
        logger.info(f"user {email} has no project manager rights.")
    except Exception as e:

        logger.info(
            f"could not find user {email} in firebase to remove project manager rights."
        )
        raise CustomError(e)
예제 #29
0
def delete_test_user(user_ids: List) -> None:
    for user_id in user_ids:
        if not re.match(r"[-a-zA-Z0-9]+", user_id):
            raise ValueError(f"Given argument resulted in invalid "
                             f"Firebase Realtime Database reference. ")

        fb_db = auth.firebaseDB()
        ref = fb_db.reference("v2/users/{0}".format(user_id))
        ref.delete()

        pg_db = auth.postgresDB()
        sql_query = "DELETE FROM users WHERE user_id = '{0}'".format(user_id)
        pg_db.query(sql_query)
    def test_changes(self):
        """Test if results are deleted from Firebase for given project id."""
        transfer_results.transfer_results()

        fb_db = auth.firebaseDB()
        ref = fb_db.reference("v2/results/{0}".format(self.project_id))
        self.assertIsNone(ref.get())

        pg_db = auth.postgresDB()
        sql_query = "SELECT * FROM results WHERE project_id = '{0}' and user_id = '{0}'".format(
            self.project_id)
        result = pg_db.retr_query(sql_query)
        self.assertIsNotNone(result)