Example #1
0
def user_edit():

    error_list = []

    with sessionMaker.session_scope() as session:

        data = request.get_json(
            force=True)  # Force = true if not set as application/json'
        user = data.get('user', None)
        if user is None:
            out = jsonify(success=None, error_list=["No user"])
            return out, 400, {'ContentType': 'application/json'}

        # May want to update users other than the requesting user...
        #db_user = session.query(User).filter_by(email=user['email']).first()

        # Permissions model here assumes that we know who the user is
        # So therefore can only update for self

        db_user = session.query(User).filter(User.id == getUserID()).one()

        # Update info
        # TODO lots of checks and things to consider here...

        db_user.first_name = user.get('first_name', None)
        db_user.last_name = user.get('last_name', None)

        session.add(db_user)

        out = jsonify(success=True, errors=[], user=db_user.serialize())
        return out, 200, {'ContentType': 'application/json'}
Example #2
0
def user_upload_profile_image():

    file = request.files.get('file')
    if not file:
        return "No file", 400

    extension = os.path.splitext(file.filename)[1].lower()
    if extension in images_allowed_file_names:

        file.filename = secure_filename(
            file.filename
        )  # http://flask.pocoo.org/docs/0.12/patterns/fileuploads/
        temp_dir = tempfile.mkdtemp()
        file_name = temp_dir + "/" + file.filename
        file.save(file_name)

        with sessionMaker.session_scope() as session:

            with open(file_name, "rb") as file:
                content_type = "image/" + str(extension)
                short_file_name = os.path.split(file_name)[1]

                user = session.query(User).filter(User.id == getUserID()).one()

                image = process_profile_image(session=session,
                                              user=user,
                                              file=file,
                                              file_name=short_file_name,
                                              content_type=content_type,
                                              extension=extension)

            Event.new(kind="profile_image_update",
                      session=session,
                      member=user.member,
                      success=True)

            return jsonify(success=True, user=user.serialize()), 200, {
                'ContentType': 'application/json'
            }

    return jsonify(success=False), 400, {'ContentType': 'application/json'}
Example #3
0
    def check_permissions(Roles,
                          project_string_id,
                          session,
                          apis_project_list=None,
                          apis_user_list=None):
        """
		TODO this could use better organization
		ie project_string_id is None check could be here, but
		we seem to do it an extra time on line 123

		"""
        if project_string_id is None:
            # TODO merge None checks from other thing up top here.
            raise Forbidden("project_string_id is None")

        if 'allow_anonymous' in Roles:
            return True

        project = Project.get(session, project_string_id)
        if project is None:
            raise Forbidden(default_denied_message)

        # Careful here! Just becuase a project is public
        # Doesn't mean public is allowed acccess to all
        # routes. ie only admins can delete project

        # if a project is public we don't need to check a user's apis right?
        if 'allow_if_project_is_public' in Roles:
            if project:
                if project.is_public is True:
                    return True

        # TODO merge LoggedIn() with getUserID() similar internal logic
        if LoggedIn() != True:
            raise Forbidden(default_denied_message)

        if 'allow_any_logged_in_user' in Roles:  # TODO not happy with this name, want more clarity on how this effects other permissions like apis / project etc.
            return True

        user = session.query(User).filter(User.id == getUserID()).one()

        if user.is_super_admin == True:
            return True

        if apis_project_list:
            check_all_apis(project=project,
                           apis_required_list=apis_project_list)

        if apis_user_list:
            User_Permissions.general(user=user, apis_user_list=apis_user_list)

        # This could be slow if a user has a lot of projects?
        for project, Permissions in user.permissions_projects.items():

            if Permissions is None:
                continue

            if project_string_id == project:
                check_role_result = check_roles(Roles, Permissions)
                if check_role_result is True:
                    return True

        # Default
        # Good to have this here so we can call
        # this function as one line and don't ahve to worry
        # About returning False (must have returned True eariler)
        raise Forbidden(default_denied_message)
Example #4
0
def label_edit(project_string_id):
    with sessionMaker.session_scope() as session:

        data = request.get_json(
            force=True)  # Force = true if not set as application/json'
        label_file = data.get('label_file', None)

        if label_file is None:
            return json.dumps("file is None"), 400, {
                'ContentType': 'application/json'
            }

        label_proposed = label_file.get('label', None)
        if label_proposed is None:
            return json.dumps("label is None"), 400, {
                'ContentType': 'application/json'
            }

        name_proposed = label_proposed.get('name', None)
        if name_proposed is None or len(name_proposed) < 1:
            return json.dumps("label less than 1 character"), 400, {
                'ContentType': 'application/json'
            }

        label_file_id = label_file.get('id', None)
        if label_file_id is None:
            return json.dumps("no label id"), 400, {
                'ContentType': 'application/json'
            }

        # WIP...
        user_id = getUserID()

        existing_file = File.get_by_id_untrusted(session, user_id,
                                                 project_string_id,
                                                 label_file_id)

        if existing_file is None:
            return jsonify("No file"), 400

        if existing_file.committed is True:
            return jsonify("File committed"), 400

            # TODO # WIP WIP
            new_file = File.copy_file_from_existing(session, working_dir,
                                                    existing_file)

            label_file = File.new_label_file(
                session=session,
                name=name_proposed,
                default_sequences_to_single_frame=None,
                working_dir_id=project.directory_default_id,
                project=project,
                colour=colour_proposed,
                log=log,
                existing_file=new_file)
        # WIP

        if existing_file.committed is not True:

            project = Project.get(session, project_string_id)

            user = session.query(User).filter(User.id == user_id).one()
            working_dir = project.directory_default

            colour_proposed = label_file.get("colour", None)

            # Caution note, 'label_proposed' not file
            default_sequences_to_single_frame_proposed = label_proposed.get(
                "default_sequences_to_single_frame")

            if default_sequences_to_single_frame_proposed is None:
                default_sequences_to_single_frame_proposed = False

            # Caution
            # We need this because we are trying to
            # maintain unique labels...
            # It's the Label() class we are getting not the File()
            # (Which we already have).
            label = Label.new(session,
                              name=name_proposed,
                              default_sequences_to_single_frame=
                              default_sequences_to_single_frame_proposed)

            existing_file.label_id = label.id
            existing_file.colour = colour_proposed

            session.add(existing_file)

            working_dir.label_file_colour_map[
                existing_file.id] = colour_proposed
            # Caution: https://stackoverflow.com/questions/42559434/updates-to-json-field-dont-persist-to-db
            flag_modified(working_dir, "label_file_colour_map")
            # This seems to be needed to reliably detect changes
            # Maybe didn't need it prior as was editing sub "lists" vs editing ID directly
            # This still feels better than passing whole item to python memory and editing it
            # (Which still also doesn't always work as expected.)

            session.add(working_dir)
        # return existing_file
        """

        Option 1
        Create new files for a label change
        ie get all file attached to the label
        Create a new file for every one, and attach it to that new label
        Then any future changes to label don't have to create new files
        Till it's comitted
        Then would whave to create new ones again

        ie Instance.label_id == 

        """

        out = 'success'
        return json.dumps(out), 200, {'ContentType': 'application/json'}
Example #5
0
    def get(session):

        return session.query(User).filter_by(id=getUserID()).first()
Example #6
0
    def get_current_user(session):

        return session.query(User).filter_by(id=getUserID()).first()
Example #7
0
            def inner(*args, **kwds):

                job_id = kwds.get('job_id', None)
                if job_id is None or job_id == "null" or job_id == "undefined":
                    raise Forbidden("job_id is invalid")

                with sessionMaker.session_scope() as session:

                    # Permissions cascading from project
                    project_string_id = get_project_string_from_job_id(
                        session, job_id)

                    # API
                    if request.authorization is not None:

                        result = API_Permissions.by_project(
                            session=session,
                            project_string_id=project_string_id,
                            Roles=project_role_list)
                        if result is True:
                            return func(*args, **kwds)
                        else:
                            raise Forbidden("API access invalid")

                    # TODO do we need to validate user has applicable mode?
                    # ie they pass mode builder but are trainer?
                    # Basics should fail on project level check anyway here...

                    # User
                    # TODO move login stuff into the general User_Permissions
                    if LoggedIn() != True:
                        raise Forbidden("Login again.")

                    user = session.query(User).filter(
                        User.id == getUserID()).first()

                    if user is None:
                        raise Forbidden("Login again.")

                    # Want to use the builder API permissions instead of
                    # flags since a user may be testing this as a builder
                    # TODO deprecate 'mode' flag or have it as something else
                    # like "builder_only" or something

                    # Jan 3, 2020
                    # One downside of doing it this way is it means
                    # that we need to be careful with
                    # project_role_list list...

                    if user.api_enabled_builder is True:
                        result = Project_permissions.check_permissions(
                            session=session,
                            project_string_id=project_string_id,
                            Roles=project_role_list,
                            apis_project_list=apis_project_list,
                            apis_user_list=apis_user_list)

                        if result is True:
                            return func(*args, **kwds)
                        else:
                            raise Forbidden("Project access invalid")

                    if user.api_enabled_trainer is True:

                        # TODO refactor into function

                        # TODO handle "info" case of a trainer not yet
                        # on a job seeing basic stuff on active jobs...

                        # We allow trainers to see
                        # Basic info before they apply
                        # as long as job is active...

                        #if job.status != "active":
                        #	raise Forbidden("No access.")

                        User_Permissions.general(user=user,
                                                 apis_user_list=apis_user_list)

                        user_to_job = User_To_Job.get_single_by_ids(
                            session=session, user_id=user.id, job_id=job_id)

                        # TODO other status checking on this...

                        if user_to_job is None:
                            raise Forbidden(
                                "No access to this job. Please apply first.")

                        # Success case for trainer
                        return func(*args, **kwds)

                raise Forbidden("No access.")