Exemplo n.º 1
0
 def users_get_id(id: int) -> Any:
     params = RequestParameters(user=Auth.get_current_user())
     u = service.get_user(id, params)
     if u:
         return jsonify(u.to_dict())
     else:
         return "", 404
    def copy_study(uuid: str) -> Any:
        """
        Copy study
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
        - in: path
          name: uuid
          required: true
          description: study uuid stored in server
          schema:
            type: string
        - in: query
          name: dest
          required: true
          description: new study name
          schema:
            type: string
        - in: query
          name: groups
          required: false
          description: list of group id assignment separated by comma
          schema:
            type: string
        tags:
          - Manage Studies

        """

        source_uuid = uuid
        destination_study_name = request.args.get("dest")
        groups_arg = request.args.get("groups")
        group_ids = groups_arg.split(",") if groups_arg is not None else []

        if destination_study_name is None:
            content = "Copy operation need a dest query parameter."
            code = HTTPStatus.BAD_REQUEST.value
            return content, code

        source_uuid_sanitized = sanitize_uuid(source_uuid)
        destination_name_sanitized = sanitize_study_name(
            destination_study_name)

        params = RequestParameters(user=Auth.get_current_user())

        destination_uuid = storage_service.copy_study(
            src_uuid=source_uuid_sanitized,
            dest_study_name=destination_name_sanitized,
            group_ids=group_ids,
            params=params,
        )
        code = HTTPStatus.CREATED.value

        return destination_uuid, code
Exemplo n.º 3
0
    def get_file(path: str) -> Any:
        """
        Get file
        ---
        responses:
            '200':
              content:
                application/octet-stream: {}
              description: Successful operation
            '404':
              description: File not found
        parameters:
          - in: path
            name: path
            required: true
            schema:
                type: string
        tags:
          - Manage Matrix

        """

        try:
            params = RequestParameters(user=Auth.get_current_user())
            return storage_service.get_matrix(path, params)
        except FileNotFoundError:
            return f"{path} not found", HTTPStatus.NOT_FOUND.value
Exemplo n.º 4
0
 def groups_get_id(id: str) -> Any:
     params = RequestParameters(user=Auth.get_current_user())
     group = service.get_group(id, params)
     if group:
         return jsonify(group.to_dict())
     else:
         return f"Group {id} not found", 404
Exemplo n.º 5
0
    def post_file(path: str) -> Any:
        """
        Post file
        ---
        parameters:
          - in: path
            name: path
            required: true
            schema:
              type: string
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        tags:
          - Manage Matrix
        """

        data = request.files["matrix"].read()
        params = RequestParameters(user=Auth.get_current_user())
        storage_service.upload_matrix(path, data, params)
        output = b""
        code = HTTPStatus.NO_CONTENT.value

        return output, code
    def delete_study(uuid: str) -> Any:
        """
        Delete study
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: uuid
            required: true
            description: study uuid used by server
            schema:
              type: string
        tags:
          - Manage Studies
        """
        uuid_sanitized = sanitize_uuid(uuid)

        params = RequestParameters(user=Auth.get_current_user())
        storage_service.delete_study(uuid_sanitized, params)
        content = ""
        code = HTTPStatus.NO_CONTENT.value

        return content, code
Exemplo n.º 7
0
    def get_all_bots() -> Any:
        params = RequestParameters(user=Auth.get_current_user())

        owner = request.args.get("owner", default=None, type=int)
        bots = (service.get_all_bots_by_owner(owner, params)
                if owner else service.get_all_bots(params))
        return jsonify([b.to_dict() for b in bots]), 200
    def change_owner(uuid: str, user_id: int) -> Any:
        """
        Change study owner
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: uuid
            required: true
            description: study uuid used by server
            schema:
              type: string
          - in: path
            name: user_id
            required: true
            description: id of the new owner
            schema:
              type: number
        tags:
          - Manage Permissions
        """
        uuid_sanitized = sanitize_uuid(uuid)
        params = RequestParameters(user=Auth.get_current_user())
        storage_service.change_owner(uuid_sanitized, user_id, params)

        return "", HTTPStatus.OK
    def edit_study(path: str) -> Any:
        """
        Update data
        ---
        responses:
          '200':
            description: Successful operation
            content:
              application/json: {}
          '404':
            description: File not found
        parameters:
          - in: path
            name: uuid
            required: true
            schema:
              type: string
          - in: path
            name: path
            schema:
              type: string
            required: true
        tags:
          - Manage Data inside Study
        """
        new = json.loads(request.data)
        if not new:
            raise BadRequest("empty body not authorized")

        params = RequestParameters(user=Auth.get_current_user())
        storage_service.edit_study(path, new, params)
        content = ""
        code = HTTPStatus.NO_CONTENT.value

        return content, code
    def remove_group(uuid: str, group_id: str) -> Any:
        """
        Remove a group association
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: uuid
            required: true
            description: study uuid used by server
            schema:
              type: string
          - in: path
            name: group_id
            required: true
            description: id of the group to remove
            schema:
              type: string
        tags:
          - Manage Permissions
        """
        uuid_sanitized = sanitize_uuid(uuid)

        params = RequestParameters(user=Auth.get_current_user())
        storage_service.remove_group(uuid_sanitized, group_id, params)

        return "", HTTPStatus.OK
    def set_public_mode(uuid: str, mode: str) -> Any:
        """
        Set study public mode
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: uuid
            required: true
            description: study uuid used by server
            schema:
              type: string
          - in: path
            name: mode
            required: true
            description: public mode
            schema:
              type: string
              enum: [NONE,READ,EXECUTE,EDIT,FULL]
        tags:
          - Manage Permissions
        """
        uuid_sanitized = sanitize_uuid(uuid)
        params = RequestParameters(user=Auth.get_current_user())
        public_mode = PublicMode(mode)
        storage_service.set_public_mode(uuid_sanitized, public_mode, params)

        return "", HTTPStatus.OK
Exemplo n.º 12
0
 def run(study_id: str) -> Any:
     """
     Run study
     ---
     responses:
       '200':
         content:
           application/json:
             schema:
                 $ref: '#/definitions/RunInfo'
         description: Successful operation
       '400':
         description: Invalid request
       '401':
         description: Unauthenticated User
       '403':
         description: Unauthorized
     parameters:
     - in: path
       name: study_id
       required: true
       description: study id
       schema:
         type: string
     definitions:
         - schema:
             id: RunInfo
             properties:
               job_id:
                 type: string
     tags:
       - Run Studies
     """
     params = RequestParameters(user=Auth.get_current_user())
     return jsonify({"job_id": service.run_study(study_id, params)})
    def get_study(path: str) -> Any:
        """
        Read data
        ---
        responses:
          '200':
            description: Successful operation
            content:
              application/json: {}
          '404':
            description: File not found
        parameters:
          - in: path
            name: uuid
            required: true
            schema:
              type: string
          - in: path
            name: path
            schema:
              type: string
            required: true
          - in: query
            name: depth
            schema:
              type: string
        tags:
          - Manage Data inside Study
        """
        parameters = RequestParameters(user=Auth.get_current_user())
        depth = request.args.get("depth", 3, type=int)
        output = storage_service.get(path, depth, parameters)

        return jsonify(output), 200
Exemplo n.º 14
0
    def users_update(id: int) -> Any:
        params = RequestParameters(user=Auth.get_current_user())
        u = User.from_dict(json.loads(request.data))

        if id != u.id:
            return "Id in path must be same id in body", 400

        return jsonify(service.save_user(u, params).to_dict())
Exemplo n.º 15
0
 def test_connect() -> None:
     if not config.security.disabled:
         try:
             token = request.event["args"][1]["token"]  # type: ignore
             user = Auth.get_user_from_token(token)
             if user is None:
                 # TODO check auth and subscribe to rooms
                 raise ConnectionRefusedError("unauthorized!")
         except Exception as e:
             logger.error(
                 "Failed to check token from websocket connexion",
                 exc_info=e,
             )
             raise ConnectionRefusedError("Failed to check auth")
 def get_studies() -> Any:
     """
     Get Studies
     ---
     responses:
       '200':
         content:
           application/json: {}
         description: Successful operation
       '400':
         description: Invalid request
     tags:
       - Manage Studies
     """
     params = RequestParameters(user=Auth.get_current_user())
     available_studies = storage_service.get_studies_information(params)
     return jsonify(available_studies), HTTPStatus.OK.value
    def export_study(uuid: str) -> Any:
        """
        Export Study
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
        - in: path
          name: uuid
          required: true
          description: study uuid stored in server
          schema:
            type: string
        - in: query
          name: no-output
          required: false
          example: false
          description: specify
          schema:
            type: boolean
        tags:
          - Manage Studies
        """
        uuid_sanitized = sanitize_uuid(uuid)
        outputs: bool = ("no-output" not in request.args
                         or request.args["no-output"] == "false")

        params = RequestParameters(user=Auth.get_current_user())
        content = storage_service.export_study(uuid_sanitized, params, outputs)

        return send_file(
            content,
            mimetype="application/zip",
            as_attachment=True,
            attachment_filename=f"{uuid_sanitized}.zip",
        )
    def create_study(name: str) -> Any:
        """
        Create study name
        ---
        description: Create an empty study
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: name
            required: true
            description: study name asked
            schema:
              type: string
          - in: query
            name: groups
            required: false
            description: list of group id assignment separated by comma
            schema:
              type: string
        tags:
          - Manage Studies
        """
        name_sanitized = sanitize_study_name(name)
        groups_arg = request.args.get("groups")
        group_ids = groups_arg.split(",") if groups_arg is not None else []

        params = RequestParameters(user=Auth.get_current_user())
        uuid = storage_service.create_study(name_sanitized, group_ids, params)

        content = "/studies/" + uuid
        code = HTTPStatus.CREATED.value

        return jsonify(content), code
    def import_study() -> Any:
        """
        Import Study
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
        - in: query
          name: groups
          required: false
          description: list of group id assignment separated by comma
          schema:
            type: string
        tags:
          - Manage Studies
        """

        if "study" not in request.files:
            content = "No data provided."
            code = HTTPStatus.BAD_REQUEST.value
            return content, code

        zip_binary = io.BytesIO(request.files["study"].read())

        params = RequestParameters(user=Auth.get_current_user())
        groups_arg = request.args.get("groups")
        group_ids = groups_arg.split(",") if groups_arg is not None else []

        uuid = storage_service.import_study(zip_binary, group_ids, params)
        content = "/studies/" + uuid
        code = HTTPStatus.CREATED.value

        return jsonify(content), code
    def import_output(uuid: str) -> Any:
        """
        Import Output
        ---
        responses:
          '202':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: uuid
            required: true
            description: study uuid used by server
            schema:
              type: string
        tags:
          - Manage Outputs
        """
        uuid_sanitized = sanitize_uuid(uuid)

        if "output" not in request.files:
            content = "No data provided."
            code = HTTPStatus.BAD_REQUEST.value
            return content, code

        zip_binary = io.BytesIO(request.files["output"].read())

        params = RequestParameters(user=Auth.get_current_user())
        content = str(
            storage_service.import_output(uuid_sanitized, zip_binary, params))
        code = HTTPStatus.ACCEPTED.value

        return jsonify(content), code
Exemplo n.º 21
0
 def bots_delete(id: int) -> Any:
     """
     Revoke bot
     ---
     responses:
       '200':
         content:
           application/json: {}
         description: Successful operation
       '400':
         description: Invalid request
     parameters:
       - in: path
         name: id
         required: true
         description: bot id
         schema:
           type: int
     tags:
       - Bot
     """
     params = RequestParameters(user=Auth.get_current_user())
     service.delete_bot(id, params)
     return jsonify(id), 200
Exemplo n.º 22
0
 def roles_get_all(group: str) -> Any:
     params = RequestParameters(user=Auth.get_current_user())
     return jsonify([
         r.to_dict()
         for r in service.get_all_roles_in_group(group=group, params=params)
     ])
Exemplo n.º 23
0
def create_launcher_api(service: LauncherService, config: Config) -> Blueprint:
    bp = Blueprint(
        "create_launcher_api",
        __name__,
    )

    auth = Auth(config)

    @bp.route("/launcher/run/<string:study_id>", methods=["POST"])
    @auth.protected()
    def run(study_id: str) -> Any:
        """
        Run study
        ---
        responses:
          '200':
            content:
              application/json:
                schema:
                    $ref: '#/definitions/RunInfo'
            description: Successful operation
          '400':
            description: Invalid request
          '401':
            description: Unauthenticated User
          '403':
            description: Unauthorized
        parameters:
        - in: path
          name: study_id
          required: true
          description: study id
          schema:
            type: string
        definitions:
            - schema:
                id: RunInfo
                properties:
                  job_id:
                    type: string
        tags:
          - Run Studies
        """
        params = RequestParameters(user=Auth.get_current_user())
        return jsonify({"job_id": service.run_study(study_id, params)})

    @bp.route("/launcher/jobs", methods=["GET"])
    @auth.protected()
    def get_job() -> Any:
        """
        Retrieve jobs
        ---
        responses:
          '200':
            content:
              application/json:
                schema:
                    type: array
                    items:
                        $ref: '#/definitions/LaunchJob'
            description: Successful operation
          '400':
            description: Invalid request
          '401':
            description: Unauthenticated User
          '403':
            description: Unauthorized
        parameters:
        - in: query
          name: study
          required: false
          description: study id
          schema:
            type: string
        definitions:
            - schema:
                id: LaunchJob
                properties:
                  id:
                    type: string
                  study_id:
                    type: string
                  job_status:
                    type: string
                  creation_date:
                    type: string
                  completion_date:
                    type: string
                  msg:
                    type: string
                  exit_code:
                    type: number
        tags:
          - Run Studies
        """
        study_id: Optional[str] = None
        if "study" in request.args:
            study_id = request.args["study"]

        return jsonify([job.to_dict() for job in service.get_jobs(study_id)])

    @bp.route("/launcher/jobs/<uuid:job_id>", methods=["GET"])
    @auth.protected()
    def get_result(job_id: UUID) -> Any:
        """
        Retrieve job info from job id
        ---
        responses:
          '200':
            content:
              application/json:
                schema:
                  $ref: '#/definitions/LaunchJob'
            description: Successful operation
          '400':
            description: Invalid request
          '401':
            description: Unauthenticated User
          '403':
            description: Unauthorized
        parameters:
        - in: path
          name: job_id
          required: true
          description: job id
          schema:
            type: string
        definitions:
            - schema:
                id: LaunchJob
                properties:
                  id:
                    type: string
                  study_id:
                    type: string
                  job_status:
                    type: string
                  creation_date:
                    type: string
                  completion_date:
                    type: string
                  msg:
                    type: string
                  exit_code:
                    type: number
        tags:
          - Run Studies
        """
        return jsonify(service.get_result(job_id).to_dict())

    return bp
Exemplo n.º 24
0
 def role_create() -> Any:
     params = RequestParameters(user=Auth.get_current_user())
     role = RoleCreationDTO.from_dict(json.loads(request.data))
     return jsonify(service.save_role(role, params).to_dict())
Exemplo n.º 25
0
 def roles_delete(user: int, group: str) -> Any:
     params = RequestParameters(user=Auth.get_current_user())
     service.delete_role(user, group, params)
     return jsonify((user, group)), 200
Exemplo n.º 26
0
    def bots_create() -> Any:
        """
        Create Bot
        ---
        responses:
          '200':
            content:
              application/json:
                schema:
                  type: string
                  description: Bot token API
            description: Successful operation
          '400':
            description: Invalid request
          '401':
            description: Unauthenticated User
          '403':
            description: Unauthorized
        consumes:
            - application/json
        parameters:
        - in: body
          name: body
          required: true
          description: Bot
          schema:
            id: User
            required:
                - name
                - group
                - role
            properties:
                name:
                    type: string
                    description: Bot name
                isAuthor:
                    type: boolean
                    description: Set Bot impersonator between itself or it owner
                group:
                    type: string
                    description: group id linked to bot
                role:
                    type: int
                    description: RoleType used by bot. Should be lower or equals ot owner role type inside same group
        tags:
          - Bot
        """
        params = RequestParameters(user=Auth.get_current_user())
        create = BotCreateDTO.from_dict(json.loads(request.data))
        bot = service.save_bot(create, params)

        if not bot:
            return UserHasNotPermissionError()

        group = service.get_group(create.group, params)
        if not group:
            return UserHasNotPermissionError()

        jwt = JWTUser(
            id=bot.id,
            impersonator=bot.get_impersonator(),
            type=bot.type,
            groups=[JWTGroup(id=group.id, name=group.name, role=create.role)],
        )
        tokens = generate_tokens(jwt, expire=timedelta(days=368 * 200))
        return tokens["access_token"]
Exemplo n.º 27
0
def create_login_api(service: LoginService, config: Config,
                     jwt: JWTManager) -> Blueprint:
    bp = Blueprint(
        "create_login_api",
        __name__,
        template_folder=str(config.resources_path / "templates"),
    )

    auth = Auth(config)

    def generate_tokens(user: JWTUser,
                        expire: Optional[timedelta] = None) -> Any:
        access_token = create_access_token(identity=user.to_dict(),
                                           expires_delta=expire)
        refresh_token = create_refresh_token(identity=user.to_dict())
        return {
            "user": user.id,
            "access_token": access_token,
            "refresh_token": refresh_token,
        }

    @jwt.token_in_blocklist_loader  # type: ignore
    def check_if_token_is_revoked(jwt_header: Any, jwt_payload: JSON) -> bool:
        id = jwt_payload["sub"]["id"]
        type = jwt_payload["sub"]["type"]
        return type == "bots" and not service.exists_bot(id)

    @bp.route("/login", methods=["POST"])
    def login() -> Any:
        """
        Login
        ---
        responses:
          '200':
            content:
              application/json:
                schema:
                  $ref: '#/definitions/UserCredentials'
            description: Successful operation
          '400':
            description: Invalid request
          '401':
            description: Unauthenticated User
          '403':
            description: Unauthorized
        consumes:
            - application/x-www-form-urlencoded
        parameters:
        - in: body
          name: body
          required: true
          description: user credentials
          schema:
            id: User
            required:
                - username
                - password
            properties:
                username:
                    type: string
                password:
                    type: string
        definitions:
            - schema:
                id: UserCredentials
                properties:
                  user:
                    type: string
                    description: User name
                  access_token:
                    type: string
                  refresh_token:
                    type: string
        tags:
          - User
        """
        username = request.form.get("username") or request.json.get("username")
        password = request.form.get("password") or request.json.get("password")

        if not username:
            return jsonify({"msg": "Missing username parameter"}), 400
        if not password:
            return jsonify({"msg": "Missing password parameter"}), 400

        user = service.authenticate(username, password)
        if not user:
            return jsonify({"msg": "Bad username or password"}), 401

        # Identity can be any data that is json serializable
        resp = generate_tokens(user)

        return (
            jsonify(resp),
            200,
        )

    @bp.route("/refresh", methods=["POST"])
    @jwt_required(refresh=True)  # type: ignore
    def refresh() -> Any:
        """
        Refresh access token
        ---
        responses:
          '200':
            content:
              application/json:
                schema:
                  $ref: '#/definitions/UserCredentials'
            description: Successful operation
          '400':
            description: Invalid request
          '401':
            description: Unauthenticated User
          '403':
            description: Unauthorized
        consumes:
            - application/x-www-form-urlencoded
        parameters:
        - in: header
          name: Authorization
          required: true
          description: refresh token
          schema:
            type: string
            description: (Bearer {token}) Refresh token received from login or previous refreshes
        definitions:
            - schema:
                id: UserCredentials
                properties:
                  user:
                    type: string
                    description: User name
                  access_token:
                    type: string
                  refresh_token:
                    type: string
        tags:
          - User
        """
        identity = get_jwt_identity()
        user = service.get_jwt(identity["id"])
        if user:
            resp = generate_tokens(user)

            return (
                jsonify(resp),
                200,
            )
        else:
            return "Token invalid", 403

    @bp.route("/users", methods=["GET"])
    @auth.protected()
    def users_get_all() -> Any:
        params = RequestParameters(user=Auth.get_current_user())
        return jsonify([u.to_dict() for u in service.get_all_users(params)])

    @bp.route("/users/<int:id>", methods=["GET"])
    @auth.protected()
    def users_get_id(id: int) -> Any:
        params = RequestParameters(user=Auth.get_current_user())
        u = service.get_user(id, params)
        if u:
            return jsonify(u.to_dict())
        else:
            return "", 404

    @bp.route("/users", methods=["POST"])
    @auth.protected()
    def users_create() -> Any:
        params = RequestParameters(user=Auth.get_current_user())
        create_user = UserCreateDTO.from_dict(json.loads(request.data))

        return jsonify(service.create_user(create_user, params).to_dict())

    @bp.route("/users/<int:id>", methods=["PUT"])
    @auth.protected()
    def users_update(id: int) -> Any:
        params = RequestParameters(user=Auth.get_current_user())
        u = User.from_dict(json.loads(request.data))

        if id != u.id:
            return "Id in path must be same id in body", 400

        return jsonify(service.save_user(u, params).to_dict())

    @bp.route("/users/<int:id>", methods=["DELETE"])
    @auth.protected()
    def users_delete(id: int) -> Any:
        params = RequestParameters(user=Auth.get_current_user())
        service.delete_user(id, params)
        return jsonify(id), 200

    @bp.route("/groups", methods=["GET"])
    @auth.protected()
    def groups_get_all() -> Any:
        params = RequestParameters(user=Auth.get_current_user())
        return jsonify([g.to_dict() for g in service.get_all_groups(params)])

    @bp.route("/groups/<int:id>", methods=["GET"])
    @auth.protected()
    def groups_get_id(id: str) -> Any:
        params = RequestParameters(user=Auth.get_current_user())
        group = service.get_group(id, params)
        if group:
            return jsonify(group.to_dict())
        else:
            return f"Group {id} not found", 404

    @bp.route("/groups", methods=["POST"])
    @auth.protected()
    def groups_create() -> Any:
        params = RequestParameters(user=Auth.get_current_user())
        group = Group.from_dict(json.loads(request.data))
        return jsonify(service.save_group(group, params).to_dict())

    @bp.route("/groups/<int:id>", methods=["DELETE"])
    @auth.protected()
    def groups_delete(id: str) -> Any:
        params = RequestParameters(user=Auth.get_current_user())
        service.delete_group(id, params)
        return jsonify(id), 200

    @bp.route("/roles/group/<string:group>", methods=["GET"])
    @auth.protected()
    def roles_get_all(group: str) -> Any:
        params = RequestParameters(user=Auth.get_current_user())
        return jsonify([
            r.to_dict()
            for r in service.get_all_roles_in_group(group=group, params=params)
        ])

    @bp.route("/roles", methods=["POST"])
    @auth.protected()
    def role_create() -> Any:
        params = RequestParameters(user=Auth.get_current_user())
        role = RoleCreationDTO.from_dict(json.loads(request.data))
        return jsonify(service.save_role(role, params).to_dict())

    @bp.route("/roles/<string:group>/<int:user>", methods=["DELETE"])
    @auth.protected()
    def roles_delete(user: int, group: str) -> Any:
        params = RequestParameters(user=Auth.get_current_user())
        service.delete_role(user, group, params)
        return jsonify((user, group)), 200

    @bp.route("/bots", methods=["POST"])
    @auth.protected()
    def bots_create() -> Any:
        """
        Create Bot
        ---
        responses:
          '200':
            content:
              application/json:
                schema:
                  type: string
                  description: Bot token API
            description: Successful operation
          '400':
            description: Invalid request
          '401':
            description: Unauthenticated User
          '403':
            description: Unauthorized
        consumes:
            - application/json
        parameters:
        - in: body
          name: body
          required: true
          description: Bot
          schema:
            id: User
            required:
                - name
                - group
                - role
            properties:
                name:
                    type: string
                    description: Bot name
                isAuthor:
                    type: boolean
                    description: Set Bot impersonator between itself or it owner
                group:
                    type: string
                    description: group id linked to bot
                role:
                    type: int
                    description: RoleType used by bot. Should be lower or equals ot owner role type inside same group
        tags:
          - Bot
        """
        params = RequestParameters(user=Auth.get_current_user())
        create = BotCreateDTO.from_dict(json.loads(request.data))
        bot = service.save_bot(create, params)

        if not bot:
            return UserHasNotPermissionError()

        group = service.get_group(create.group, params)
        if not group:
            return UserHasNotPermissionError()

        jwt = JWTUser(
            id=bot.id,
            impersonator=bot.get_impersonator(),
            type=bot.type,
            groups=[JWTGroup(id=group.id, name=group.name, role=create.role)],
        )
        tokens = generate_tokens(jwt, expire=timedelta(days=368 * 200))
        return tokens["access_token"]

    @bp.route("/bots/<int:id>", methods=["GET"])
    @auth.protected()
    def get_bot(id: int) -> Any:
        params = RequestParameters(user=Auth.get_current_user())
        bot = service.get_bot(id, params)
        return jsonify(bot.to_dict()), 200

    @bp.route("/bots", methods=["GET"])
    @auth.protected()
    def get_all_bots() -> Any:
        params = RequestParameters(user=Auth.get_current_user())

        owner = request.args.get("owner", default=None, type=int)
        bots = (service.get_all_bots_by_owner(owner, params)
                if owner else service.get_all_bots(params))
        return jsonify([b.to_dict() for b in bots]), 200

    @bp.route("/bots/<int:id>", methods=["DELETE"])
    @auth.protected()
    def bots_delete(id: int) -> Any:
        """
        Revoke bot
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: id
            required: true
            description: bot id
            schema:
              type: int
        tags:
          - Bot
        """
        params = RequestParameters(user=Auth.get_current_user())
        service.delete_bot(id, params)
        return jsonify(id), 200

    @bp.route("/protected")
    @auth.protected()
    def protected() -> Any:
        return f"user id={get_jwt_identity()}"

    @bp.route("/auth")
    @auth.protected()
    def auth_needed() -> Any:
        return "ok"

    return bp
def create_study_routes(storage_service: StorageService,
                        config: Config) -> Blueprint:
    bp = Blueprint("create_study_route", __name__)
    auth = Auth(config)

    @bp.route("/studies", methods=["GET"])
    @auth.protected()
    def get_studies() -> Any:
        """
        Get Studies
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        tags:
          - Manage Studies
        """
        params = RequestParameters(user=Auth.get_current_user())
        available_studies = storage_service.get_studies_information(params)
        return jsonify(available_studies), HTTPStatus.OK.value

    @bp.route("/studies", methods=["POST"])
    @auth.protected()
    def import_study() -> Any:
        """
        Import Study
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
        - in: query
          name: groups
          required: false
          description: list of group id assignment separated by comma
          schema:
            type: string
        tags:
          - Manage Studies
        """

        if "study" not in request.files:
            content = "No data provided."
            code = HTTPStatus.BAD_REQUEST.value
            return content, code

        zip_binary = io.BytesIO(request.files["study"].read())

        params = RequestParameters(user=Auth.get_current_user())
        groups_arg = request.args.get("groups")
        group_ids = groups_arg.split(",") if groups_arg is not None else []

        uuid = storage_service.import_study(zip_binary, group_ids, params)
        content = "/studies/" + uuid
        code = HTTPStatus.CREATED.value

        return jsonify(content), code

    @bp.route(
        "/studies/<path:path>",
        methods=["GET"],
    )
    @auth.protected()
    def get_study(path: str) -> Any:
        """
        Read data
        ---
        responses:
          '200':
            description: Successful operation
            content:
              application/json: {}
          '404':
            description: File not found
        parameters:
          - in: path
            name: uuid
            required: true
            schema:
              type: string
          - in: path
            name: path
            schema:
              type: string
            required: true
          - in: query
            name: depth
            schema:
              type: string
        tags:
          - Manage Data inside Study
        """
        parameters = RequestParameters(user=Auth.get_current_user())
        depth = request.args.get("depth", 3, type=int)
        output = storage_service.get(path, depth, parameters)

        return jsonify(output), 200

    @bp.route(
        "/studies/<string:uuid>/copy",
        methods=["POST"],
    )
    @auth.protected()
    def copy_study(uuid: str) -> Any:
        """
        Copy study
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
        - in: path
          name: uuid
          required: true
          description: study uuid stored in server
          schema:
            type: string
        - in: query
          name: dest
          required: true
          description: new study name
          schema:
            type: string
        - in: query
          name: groups
          required: false
          description: list of group id assignment separated by comma
          schema:
            type: string
        tags:
          - Manage Studies

        """

        source_uuid = uuid
        destination_study_name = request.args.get("dest")
        groups_arg = request.args.get("groups")
        group_ids = groups_arg.split(",") if groups_arg is not None else []

        if destination_study_name is None:
            content = "Copy operation need a dest query parameter."
            code = HTTPStatus.BAD_REQUEST.value
            return content, code

        source_uuid_sanitized = sanitize_uuid(source_uuid)
        destination_name_sanitized = sanitize_study_name(
            destination_study_name)

        params = RequestParameters(user=Auth.get_current_user())

        destination_uuid = storage_service.copy_study(
            src_uuid=source_uuid_sanitized,
            dest_study_name=destination_name_sanitized,
            group_ids=group_ids,
            params=params,
        )
        code = HTTPStatus.CREATED.value

        return destination_uuid, code

    @bp.route(
        "/studies/<string:name>",
        methods=["POST"],
    )
    @auth.protected()
    def create_study(name: str) -> Any:
        """
        Create study name
        ---
        description: Create an empty study
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: name
            required: true
            description: study name asked
            schema:
              type: string
          - in: query
            name: groups
            required: false
            description: list of group id assignment separated by comma
            schema:
              type: string
        tags:
          - Manage Studies
        """
        name_sanitized = sanitize_study_name(name)
        groups_arg = request.args.get("groups")
        group_ids = groups_arg.split(",") if groups_arg is not None else []

        params = RequestParameters(user=Auth.get_current_user())
        uuid = storage_service.create_study(name_sanitized, group_ids, params)

        content = "/studies/" + uuid
        code = HTTPStatus.CREATED.value

        return jsonify(content), code

    @bp.route("/studies/<string:uuid>/export", methods=["GET"])
    @auth.protected()
    def export_study(uuid: str) -> Any:
        """
        Export Study
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
        - in: path
          name: uuid
          required: true
          description: study uuid stored in server
          schema:
            type: string
        - in: query
          name: no-output
          required: false
          example: false
          description: specify
          schema:
            type: boolean
        tags:
          - Manage Studies
        """
        uuid_sanitized = sanitize_uuid(uuid)
        outputs: bool = ("no-output" not in request.args
                         or request.args["no-output"] == "false")

        params = RequestParameters(user=Auth.get_current_user())
        content = storage_service.export_study(uuid_sanitized, params, outputs)

        return send_file(
            content,
            mimetype="application/zip",
            as_attachment=True,
            attachment_filename=f"{uuid_sanitized}.zip",
        )

    @bp.route("/studies/<string:uuid>", methods=["DELETE"])
    @auth.protected()
    def delete_study(uuid: str) -> Any:
        """
        Delete study
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: uuid
            required: true
            description: study uuid used by server
            schema:
              type: string
        tags:
          - Manage Studies
        """
        uuid_sanitized = sanitize_uuid(uuid)

        params = RequestParameters(user=Auth.get_current_user())
        storage_service.delete_study(uuid_sanitized, params)
        content = ""
        code = HTTPStatus.NO_CONTENT.value

        return content, code

    @bp.route("/studies/<path:path>", methods=["POST"])
    @auth.protected()
    def edit_study(path: str) -> Any:
        """
        Update data
        ---
        responses:
          '200':
            description: Successful operation
            content:
              application/json: {}
          '404':
            description: File not found
        parameters:
          - in: path
            name: uuid
            required: true
            schema:
              type: string
          - in: path
            name: path
            schema:
              type: string
            required: true
        tags:
          - Manage Data inside Study
        """
        new = json.loads(request.data)
        if not new:
            raise BadRequest("empty body not authorized")

        params = RequestParameters(user=Auth.get_current_user())
        storage_service.edit_study(path, new, params)
        content = ""
        code = HTTPStatus.NO_CONTENT.value

        return content, code

    @bp.route(
        "/studies/<string:uuid>/output",
        methods=["POST"],
    )
    @auth.protected()
    def import_output(uuid: str) -> Any:
        """
        Import Output
        ---
        responses:
          '202':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: uuid
            required: true
            description: study uuid used by server
            schema:
              type: string
        tags:
          - Manage Outputs
        """
        uuid_sanitized = sanitize_uuid(uuid)

        if "output" not in request.files:
            content = "No data provided."
            code = HTTPStatus.BAD_REQUEST.value
            return content, code

        zip_binary = io.BytesIO(request.files["output"].read())

        params = RequestParameters(user=Auth.get_current_user())
        content = str(
            storage_service.import_output(uuid_sanitized, zip_binary, params))
        code = HTTPStatus.ACCEPTED.value

        return jsonify(content), code

    @bp.route(
        "/studies/<string:uuid>/owner/<int:user_id>",
        methods=["PUT"],
    )
    @auth.protected()
    def change_owner(uuid: str, user_id: int) -> Any:
        """
        Change study owner
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: uuid
            required: true
            description: study uuid used by server
            schema:
              type: string
          - in: path
            name: user_id
            required: true
            description: id of the new owner
            schema:
              type: number
        tags:
          - Manage Permissions
        """
        uuid_sanitized = sanitize_uuid(uuid)
        params = RequestParameters(user=Auth.get_current_user())
        storage_service.change_owner(uuid_sanitized, user_id, params)

        return "", HTTPStatus.OK

    @bp.route(
        "/studies/<string:uuid>/groups/<string:group_id>",
        methods=["PUT"],
    )
    @auth.protected()
    def add_group(uuid: str, group_id: str) -> Any:
        """
        Add a group association
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: uuid
            required: true
            description: study uuid used by server
            schema:
              type: string
          - in: path
            name: group_id
            required: true
            description: id of the group to add
            schema:
              type: string
        tags:
          - Manage Permissions
        """
        uuid_sanitized = sanitize_uuid(uuid)
        params = RequestParameters(user=Auth.get_current_user())
        storage_service.add_group(uuid_sanitized, group_id, params)

        return "", HTTPStatus.OK

    @bp.route(
        "/studies/<string:uuid>/groups/<string:group_id>",
        methods=["DELETE"],
    )
    @auth.protected()
    def remove_group(uuid: str, group_id: str) -> Any:
        """
        Remove a group association
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: uuid
            required: true
            description: study uuid used by server
            schema:
              type: string
          - in: path
            name: group_id
            required: true
            description: id of the group to remove
            schema:
              type: string
        tags:
          - Manage Permissions
        """
        uuid_sanitized = sanitize_uuid(uuid)

        params = RequestParameters(user=Auth.get_current_user())
        storage_service.remove_group(uuid_sanitized, group_id, params)

        return "", HTTPStatus.OK

    @bp.route(
        "/studies/<string:uuid>/public_mode/<string:mode>",
        methods=["PUT"],
    )
    @auth.protected()
    def set_public_mode(uuid: str, mode: str) -> Any:
        """
        Set study public mode
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: uuid
            required: true
            description: study uuid used by server
            schema:
              type: string
          - in: path
            name: mode
            required: true
            description: public mode
            schema:
              type: string
              enum: [NONE,READ,EXECUTE,EDIT,FULL]
        tags:
          - Manage Permissions
        """
        uuid_sanitized = sanitize_uuid(uuid)
        params = RequestParameters(user=Auth.get_current_user())
        public_mode = PublicMode(mode)
        storage_service.set_public_mode(uuid_sanitized, public_mode, params)

        return "", HTTPStatus.OK

    return bp
Exemplo n.º 29
0
 def get_bot(id: int) -> Any:
     params = RequestParameters(user=Auth.get_current_user())
     bot = service.get_bot(id, params)
     return jsonify(bot.to_dict()), 200
Exemplo n.º 30
0
 def shutdown_session(exception: Any = None) -> None:
     Auth.invalidate()
     db_session.remove()