Ejemplo n.º 1
0
    def post(self, datapoint_id: str, model_id: str) -> ResponseType:
        form = ResultForm(request.get_json() or {})
        if not form.validate():
            return {"message": "invalid data", "errors": form.errors}, 400
        with settings.session() as session:
            obj = DatapointModelResult(**form.valid_data)
            obj.datapoint = request.datapoint
            obj.model = request.model

            session.expunge(obj)

            existing_obj = obj.get_existing(session)
            # if a matching result already exists we do not create a new one
            if existing_obj:

                # we update the existing object instead
                update_form = ResultForm(request.get_json() or {},
                                         is_update=True)
                if not update_form.validate():
                    return {
                        "message": "invalid data",
                        "errors": form.errors
                    }, 400

                for k, v in update_form.valid_data.items():
                    setattr(existing_obj, k, v)

                session.commit()

                return existing_obj.export(), 201

            session.add(obj)
            session.commit()
            return obj.export(), 201
Ejemplo n.º 2
0
 def get(self, datapoint_id: str, model_id: str) -> ResponseType:
     """
     Return all objects that match the given criteria and that the user is
     allowed to see.
     """
     with settings.session() as session:
         filters = [
             DatapointModelResult.deleted_at == None,
             DatapointModelResult.datapoint == request.datapoint,
             DatapointModelResult.model == request.model,
         ]
         objs = session.query(DatapointModelResult).filter(*filters).all()
         return {"data": [obj.export() for obj in objs]}, 200
Ejemplo n.º 3
0
def _clean_db(settings, plugin):
    with settings.session() as session:
        if plugin is None:
            plugins = list(settings.get("plugins", {}).keys()) + ["core"]
        else:
            plugins = [plugin]
        for plugin in plugins:
            if plugin == "core":
                clean_db(session)
                continue
            config = settings.load_plugin_config(plugin)
            if "clean_db" in config:
                config["clean_db"](session)
Ejemplo n.º 4
0
        def get(self, object_id: Optional[str] = None) -> ResponseType:
            """
            Return all objects that match the given criteria and that the user is
            allowed to see.
            """
            with settings.session() as session:
                if DependentTypes:
                    dependent_type = DependentTypes[0]().type
                    dependent_obj = getattr(request, dependent_type)
                    filters = [Type.deleted_at == None]
                    joins = []
                    if JoinBy:
                        joins.append(JoinBy)
                        filters.extend(
                            [getattr(JoinBy, dependent_type) == dependent_obj])
                    else:
                        filters.append(
                            getattr(Type, dependent_type) == dependent_obj)
                    query = session.query(Type).filter(*filters).join(*joins)
                else:
                    visible_objs = ObjectRole.select_for(
                        session, request.user,
                        Type().type)
                    # we add objects visible via the users organizations
                    org_ids = admin_orgs_id_query(session, request.user)
                    query = session.query(Type).filter(
                        or_(Type.id.in_(visible_objs),
                            Type.organization_id.in_(org_ids)),
                        Type.deleted_at == None,
                    )

                # If requested, we join dependent objects for faster response times...
                if Joins:
                    for j in Joins:
                        joinedloads = None
                        for Join in j:
                            if joinedloads is None:
                                joinedloads = joinedload(Join, innerjoin=True)
                            else:
                                joinedloads = joinedloads.joinedload(
                                    Join, innerjoin=True)
                        query = query.options(joinedloads)
                objs = query.all()

                return {"data": [obj.export() for obj in objs]}, 200
Ejemplo n.º 5
0
    def post(self, algorithm_id: str, dataset_id: str) -> ResponseType:
        form = ModelForm(request.get_json() or {})
        if not form.validate():
            return {"message": "invalid data", "errors": form.errors}, 400
        with settings.session() as session:
            obj = Model(**form.valid_data)

            existing_obj = (session.query(Model).filter(
                Model.algorithm_id == request.algorithm.id,
                Model.dataset_id == request.dataset.id,
                Model.hash == obj.hash,
                Model.deleted_at == None,
            ).one_or_none())
            if existing_obj:
                return existing_obj.export(), 201

            obj.algorithm = request.algorithm
            obj.dataset = request.dataset
            session.add(obj)

            session.commit()
            return obj.export(), 201
Ejemplo n.º 6
0
        def decorated_function(*args, **kwargs) -> ResponseType:

            if Type is None:
                # if not type is given, we return the original result without change
                return f(*args, **kwargs)

            object_id = kwargs.get(id_field)
            if not object_id:
                return {"message": "invalid ID"}, 400

            def authorize(
                    session: sqlalchemy.orm.session.Session) -> ResponseType:

                # required to make mypy happy
                assert Type is not None

                # we retrieve the requested object from the database
                query = session.query(Type).filter(Type.ext_id == object_id,
                                                   Type.deleted_at == None)

                if Joins:
                    for j in Joins:
                        joinedloads = None
                        for Join in j:
                            if joinedloads is None:
                                joinedloads = joinedload(Join, innerjoin=True)
                            else:
                                joinedloads = joinedloads.joinedload(
                                    Join, innerjoin=True)
                        query = query.options(joinedloads)

                obj = query.one_or_none()

                if not obj:
                    return not_found

                if Type is ObjectRole:
                    # this is an object role, we check if the user has admin
                    # privileges for the organization.
                    if not "admin" in request.user.roles.roles:
                        return not_found
                else:
                    if DependentTypes:
                        # this object depends on a chain of dependent objects from which it
                        # inherits roles. We therefore need to retrieve these dependent objects
                        # from the database.
                        DependentType = DependentTypes[0]
                        dependent_id = kwargs.get(dependent_id_field)
                        if dependent_id:
                            # if a dependent ID is given in the URL, we retrieve
                            # the dependent object through this
                            query = session.query(DependentType).filter(
                                DependentType.ext_id == dependent_id,
                                DependentType.deleted_at == None,
                            )
                        else:
                            # otherwise, we retrieve the object by its relation
                            # to the main object.
                            if JoinBy is not None:
                                # if there is a M2M table that we should join by, we
                                # include it in the query to ensure there is an actual entry between
                                # the requested object and the dependent objects
                                query = (session.query(DependentType).filter(
                                    DependentType.deleted_at == None).join(
                                        JoinBy).filter(
                                            getattr(JoinBy, obj.type) == obj,
                                            getattr(
                                                JoinBy, "{}_id".format(
                                                    DependentType().type)) ==
                                            DependentType.id,
                                            DependentType.deleted_at == None,
                                        ))
                            else:
                                query = session.query(DependentType).filter(
                                    DependentType.id == getattr(
                                        obj,
                                        "{}_id".format(DependentType().type)),
                                    DependentType.deleted_at == None,
                                )
                        if len(DependentTypes) > 1:
                            # if there are more than one dependent types, we add joinedload
                            # conditions for all of them to make sure they get loaded efficiently
                            # from the database.
                            joinedloads = None
                            for NextType in DependentTypes[1:]:
                                nt = NextType().type
                                query = query.filter(
                                    NextType.deleted_at == None)
                                if joinedloads is None:
                                    joinedloads = joinedload(getattr(
                                        DependentType, nt),
                                                             innerjoin=True)
                                else:
                                    joinedloads = joinedloads.joinedload(
                                        getattr(DependentType, nt),
                                        innerjoin=True)
                                DependentType = NextType
                                # if the dependent type has an organization
                                # we also load it...
                                if hasattr(DependentType, "organization"):
                                    joinedloads = joinedloads.joinedload(
                                        DependentType.organization,
                                        innerjoin=True)
                            query = query.options(joinedloads)

                        dependent_obj = query.one_or_none()

                        if not dependent_obj:
                            return not_found

                        # we extract the dependent types from the object and store them
                        # on the request object
                        setattr(request, dependent_obj.type, dependent_obj)
                        for DependentType in DependentTypes[1:]:
                            next_type = DependentType().type
                            next_obj = getattr(dependent_obj, next_type)
                            if next_obj is None:
                                return not_found
                            setattr(request, next_type, next_obj)
                            dependent_obj = next_obj
                        # we set the role object to the last object in the dependency chain
                        role_obj = dependent_obj
                    else:
                        role_obj = obj

                    role_found = False
                    # this object is owned by an organization, so we check the roles of
                    # the currently logged in user in the organization and see if the
                    # the user is an admin or superuser, in which case he/she has access
                    # to the object regardless of explicitly set object roles.
                    if (hasattr(role_obj, "organization")
                            and not role_obj.organization.deleted_at):
                        for org_roles in request.user.roles:
                            if (org_roles.organization.id
                                    == role_obj.organization.source_id
                                    and org_roles.organization.source
                                    == role_obj.organization.source):
                                for role in ["admin", "superuser"]:
                                    if role in org_roles.roles:
                                        role_found = True
                                        break
                                else:
                                    continue
                                break
                    # we retrieve the roles for the role object and the currently logged in user
                    obj_roles = ObjectRole.roles_for(session, request.user,
                                                     role_obj)
                    obj_roles_set = set(
                        [role.object_role for role in obj_roles])
                    # we check the roles against the required ones to see if the user has one of the
                    # requested roles on the object, otherwise we return "not found"
                    if roles is None:
                        if obj_roles:
                            role_found = True
                    else:
                        for role in roles:
                            if role in obj_roles_set:
                                role_found = True
                                break
                    if not role_found:
                        return not_found
                    # we add the roles to the object as a context information
                    obj._roles = obj_roles
                setattr(request, obj.type, obj)
                return f(*args, **kwargs)

            if hasattr(request, "session"):
                return authorize(request.session)
            with settings.session() as session:
                request.session = session
                return authorize(session)
Ejemplo n.º 7
0
        def post(self,
                 object_id: Optional[str] = None,
                 organization_id: Optional[str] = None) -> ResponseType:
            form = Form(request.get_json() or {})
            if not form.validate():
                return {"message": "invalid data", "errors": form.errors}, 400

            dependent_obj: Optional[Base] = None
            org: Optional[Organization] = None
            join_by: Optional[Base] = None

            if DependentTypes:
                dependent_type = DependentTypes[0]().type
                dependent_obj = getattr(request, dependent_type)

            with settings.session() as session:

                obj = Type(**form.valid_data)

                if organization_id is not None:
                    org = Organization.get_or_create(session,
                                                     request.organization)
                    obj.organization = org

                if dependent_obj:
                    if JoinBy:
                        # if this object has a M2M table, we create a row in
                        # the table for the newly created object
                        join_by = JoinBy()
                        setattr(join_by, dependent_type, dependent_obj)
                        setattr(join_by, obj.type, obj)
                    else:
                        setattr(obj, dependent_type, dependent_obj)

                # we expunge the object from the session, as it might have been added
                # when we associated the dependent properties with it...
                session.expunge(obj)

                existing_obj = obj.get_existing(session)

                if existing_obj:

                    # we update the existing object instead

                    update_form = Form(request.get_json() or {},
                                       is_update=True)
                    if not update_form.validate():
                        return {
                            "message": "invalid data",
                            "errors": form.errors
                        }, 400

                    for k, v in update_form.valid_data.items():
                        setattr(existing_obj, k, v)

                    session.commit()

                    return existing_obj.export(), 201

                if join_by:
                    session.add(join_by)

                session.add(obj)

                if not DependentTypes:
                    # we create an object role for the newly created object
                    # only if it does not depends on another object
                    assert isinstance(org, Organization)
                    for org_role in ["admin", "superuser"]:
                        ObjectRole.get_or_create(session, obj, org, "admin",
                                                 org_role)

                session.commit()

                return obj.export(), 201