示例#1
0
def login():
    try:
        json_schema_manager.validate(request.json, "login.json")

        email = request.json.get("email", None)
        password = request.json.get("password", None)

        user = User.query.filter_by(email=email).first()

        if not user:
            return json_api(AccessDenied, ErrorSchema), 403
        if not user.confirmed:
            return json_api(UserNotConfirmed, ErrorSchema), 403
        if not user.check_password(password):
            return json_api(AccessDenied, ErrorSchema), 403

        access_token = create_access_token(identity=user.uuid)
        refresh_token = create_refresh_token(identity=user.uuid)
        ret = {
            "access_token": access_token,
            "token_type": "Bearer",
            "expires-in": 3600,
            "refresh_token": refresh_token,
        }

        return jsonify(ret), 200
    except ValidationError:
        return json_api(BadRequest, ErrorSchema), 401
示例#2
0
def tunnel_admin() -> Tuple[Response, int]:
    """
    Stop any currently running tunnel if you are an admin
    """
    current_user = User.query.filter_by(uuid=get_jwt_identity()).first_or_404()
    if current_user.tier != "admin":
        return json_api(NotFoundError, ErrorSchema), 404

    try:
        json_schema_manager.validate(request.json, "admin_tunnel.json")

        subdomain_name = dig(request.json, "data/attributes/subdomainName")
        reason = dig(request.json, "data/attributes/reason")
    except ValidationError as e:
        return json_api(BadRequest(source=e.message), ErrorSchema), 400

    subdomain = Subdomain.query.filter_by(name=subdomain_name).first_or_404()
    tunnel = Tunnel.query.filter_by(subdomain_id=subdomain.id).first_or_404()
    try:
        TunnelDeletionService(current_user, tunnel).delete()
        logger.info(
            "%s deleted %s.holepunch.io for reason %s",
            current_user.email,
            subdomain_name,
            reason,
        )
        return make_response(""), 204
    except TunnelError:
        return json_api(TunnelError, ErrorSchema), 500
示例#3
0
 def check_api_version():
     if "Api-Version" in request.headers:
         if not re.match(r"^\d+\.\d+\.\d+\.\d+$", request.headers["Api-Version"]):
             return json_api(MalformedAPIHeader, ErrorSchema), 403
         if check_version(request.headers["Api-Version"]):
             return
         else:
             return json_api(OldAPIVersion, ErrorSchema), 400
示例#4
0
def config_release(config_id):
    current_user = User.query.filter_by(uuid=get_jwt_identity()).first_or_404()
    config = Config.query.filter_by(user=current_user,
                                    id=config_id).first_or_404()

    try:
        ConfigDeletionService(current_user, config).release()
        return "", 204
    except AccessDenied:
        return json_api(BadRequest, ErrorSchema), 403
    except ConfigInUse:
        return json_api(ConfigInUse, ErrorSchema), 403
示例#5
0
def subdomain_release(subdomain_id):
    current_user = User.query.filter_by(uuid=get_jwt_identity()).first_or_404()
    subdomain = Subdomain.query.filter_by(
        user=current_user, id=subdomain_id
    ).first_or_404()

    try:
        SubdomainDeletionService(current_user, subdomain).release()
        return "", 204
    except AccessDenied:
        return json_api(BadRequest, ErrorSchema), 403
    except SubdomainInUse:
        return json_api(SubdomainInUse, ErrorSchema), 403
示例#6
0
 def debug_error_handler(e):
     if env == "production":
         rollbar.report_exc_info()
         return json_api(InternalServerError, ErrorSchema), 500
     else:
         return (
             json_api(
                 InternalServerError(
                     detail=str(e), backtrace=traceback.format_exc().split("\n")
                 ),
                 ErrorSchema,
             ),
             500,
         )
示例#7
0
    def stripe_webhook_wrapper(*args, **kwargs):
        payload = request.data.decode("utf-8")

        try:
            sig_header = request.headers["stripe-signature"]
            event = stripe.Webhook.construct_event(
                payload, sig_header,
                current_app.config["STRIPE_ENDPOINT_SECRET"])
        except ValueError:
            # Invalid JSON
            return json_api(BadRequest(), ErrorSchema), 400
        except (KeyError, stripe.error.SignatureVerificationError):
            return json_api(AccessDenied(), ErrorSchema), 403

        return func(event=event, *args, **kwargs)
示例#8
0
def register_user():
    """ Create a new User Record"""
    try:
        json_schema_manager.validate(request.json, "user_create.json")

        user = UserCreation(
            email=dig(request.json, "data/attributes/email"),
            password=dig(request.json, "data/attributes/password"),
        ).create()

        return json_api(user, UserSchema), 204
    except UserError as e:
        return json_api(e, ErrorSchema), 422
    except ValidationError as e:
        return json_api(BadRequest(source=e.message), ErrorSchema), 400
示例#9
0
def get_tunnel(tunnel_id) -> Tuple[Response, int]:
    """
    Retrieve Tunnel Resource
    """
    current_user = User.query.filter_by(uuid=get_jwt_identity()).first_or_404()
    tunnel = Tunnel.query.filter_by(user=current_user, id=tunnel_id).first_or_404()

    return json_api(tunnel, TunnelSchema), 200
示例#10
0
def get_box(box_id) -> Tuple[Response, int]:
    """
    Retrieve Box Resource
    """
    current_user = User.query.filter_by(uuid=get_jwt_identity()).first_or_404()
    box = Box.query.filter_by(user=current_user, id=box_id).first_or_404()

    return json_api(box, BoxSchema), 200
示例#11
0
def start_box() -> Tuple[Response, int]:
    try:
        json_schema_manager.validate(request.json, "box_create.json")

        config_id = dig(request.json, "data/relationships/config/data/id")
        ssh_key = dig(request.json, "data/attributes/sshKey")

        current_user = User.query.filter_by(uuid=get_jwt_identity()).first_or_404()
        try:
            box_info = BoxCreationService(current_user, config_id, ssh_key).create()
        except ConfigLimitReached:
            return json_api(ConfigLimitReached, ErrorSchema), 403
        except BoxLimitReached:
            return json_api(BoxLimitReached, ErrorSchema), 403
        except BoxError:
            rollbar.report_exc_info(sys.exc_info())
            return json_api(BoxError, ErrorSchema), 500

        return json_api(box_info, BoxSchema), 201

    except ValidationError as e:
        return json_api(BadRequest(detail=e.message), ErrorSchema), 400

    except AccessDenied:
        return json_api(AccessDenied, ErrorSchema), 403

    except ConfigInUse:
        return json_api(ConfigInUse, ErrorSchema), 403
示例#12
0
def start_tunnel() -> Tuple[Response, int]:
    try:
        json_schema_manager.validate(request.json, "tunnel_create.json")

        subdomain_id = dig(request.json, "data/relationships/subdomain/data/id")
        port_types = dig(request.json, "data/attributes/port")
        ssh_key = dig(request.json, "data/attributes/sshKey")

        current_user = User.query.filter_by(uuid=get_jwt_identity()).first_or_404()
        try:
            tunnel_info = TunnelCreationService(
                current_user, subdomain_id, port_types, ssh_key
            ).create()
        except SubdomainLimitReached:
            return json_api(SubdomainLimitReached, ErrorSchema), 403
        except TunnelLimitReached:
            return json_api(TunnelLimitReached, ErrorSchema), 403
        except TunnelError:
            return json_api(TunnelError, ErrorSchema), 500

        return json_api(tunnel_info, TunnelSchema), 201

    except ValidationError as e:
        return json_api(BadRequest(detail=e.message), ErrorSchema), 400

    except AccessDenied:
        return json_api(AccessDenied, ErrorSchema), 403

    except SubdomainInUse:
        return json_api(SubdomainInUse, ErrorSchema), 403
示例#13
0
def subdomain_index():
    subdomains = User.query.filter_by(uuid=get_jwt_identity()).first_or_404().subdomains

    name = dig(request.query_params, "filter/name")
    if name:
        subdomains = subdomains.filter_by(name=name)

    if subdomains:
        return json_api(subdomains, SubdomainSchema, many=True)
示例#14
0
def get_config(config_id):
    """
    Stop a currently running config
    """
    current_user = User.query.filter_by(uuid=get_jwt_identity()).first_or_404()
    config = Config.query.filter_by(user=current_user,
                                    id=config_id).first_or_404()

    return json_api(config, ConfigSchema)
示例#15
0
def delete_user():
    """ Delete an existing User Record"""

    try:
        json_schema_manager.validate(request.json, "user_delete.json")
        current_user = User.query.filter_by(uuid=get_jwt_identity()).first_or_404()

        attributes = dig(request.json, "data/attributes", None)
        service = UserDeletion(
            current_user, scopes=authentication.jwt_scopes(), **attributes
        )
        entries_deleted = service.delete()

        return json_api(entries_deleted, UserSchema), 200
    except UserError:
        return json_api(UnprocessableEntity, ErrorSchema), 422
    except AccessDenied as e:
        return json_api(e, ErrorSchema), 403
示例#16
0
def config_index():
    configs = User.query.filter_by(
        uuid=get_jwt_identity()).first_or_404().configs

    name = dig(request.query_params, "filter/name")
    if name:
        configs = configs.filter_by(name=name)

    if configs:
        return json_api(configs, ConfigSchema, many=True)
示例#17
0
def get_subdomain(subdomain_id):
    """
    Stop a currently running subdomain
    """
    current_user = User.query.filter_by(uuid=get_jwt_identity()).first_or_404()
    subdomain = Subdomain.query.filter_by(
        user=current_user, id=subdomain_id
    ).first_or_404()

    return json_api(subdomain, SubdomainSchema)
示例#18
0
def account_hook(event):
    """ This endpoint is called by Stripes webhook integrations for async events """

    job_id = None

    if event.type == "invoice.payment_suceeded":
        job_id = payment_jobs.user_async_subscribe.queue(event).id
    elif event.type == "invoice.payment_failed":
        job_id = payment_jobs.user_async_unsubscribe.queue(event).id
    return json_api(AsyncJob(id=job_id), AsyncSchema), 202
示例#19
0
def subdomain_reserve():
    try:
        json_schema_manager.validate(request.json, "subdomain_create.json")
        current_user = User.query.filter_by(uuid=get_jwt_identity()).first_or_404()
        subdomain = SubdomainCreationService(
            current_user, dig(request.json, "data/attributes/name")
        ).reserve(True)

        return json_api(subdomain, SubdomainSchema), 200
    except ValidationError:
        return (
            json_api(BadRequest(detail="Request does not match schema."), ErrorSchema),
            400,
        )
    except SubdomainLimitReached:
        return json_api(SubdomainLimitReached, ErrorSchema), 403
    except SubdomainTaken:
        return json_api(SubdomainTaken, ErrorSchema), 400
    except SubdomainError:
        return json_api(SubdomainError, ErrorSchema), 500
示例#20
0
def box_index() -> Tuple[Response, int]:
    """
    Fetch index of a users current boxes
    """
    boxes = User.query.filter_by(uuid=get_jwt_identity()).first_or_404().boxes

    name = dig(request.query_params, "filter/config/name")
    if name:
        boxes = boxes.join(Config).filter(Config.name == name)

    return json_api(boxes, BoxSchema, many=True), 200
示例#21
0
def tunnel_index() -> Tuple[Response, int]:
    """
    Fetch index of a users current tunnels
    """
    tunnels = User.query.filter_by(uuid=get_jwt_identity()).first_or_404().tunnels

    name = dig(request.query_params, "filter/subdomain/name")
    if name:
        tunnels = tunnels.join(Subdomain).filter(Subdomain.name == name)

    return json_api(tunnels, TunnelSchema, many=True), 200
示例#22
0
def session():
    uuid = get_jwt_identity()
    user = User.query.filter_by(uuid=uuid).first()
    if user is None:
        return json_api(AccessDenied, ErrorSchema), 403
    ret = {
        "access_token": create_access_token(identity=uuid),
        "token_type": "Bearer",
        "expires-in": 3600,
    }
    return jsonify(ret), 200
示例#23
0
def stop_box(box_id) -> Tuple[Response, int]:
    """
    Stop a currently running box
    """
    current_user = User.query.filter_by(uuid=get_jwt_identity()).first_or_404()
    box = Box.query.filter_by(user=current_user, id=box_id).first_or_404()

    try:
        BoxDeletionService(current_user, box).delete()
        return make_response(""), 204
    except BoxError:
        return json_api(BoxError, ErrorSchema), 500
示例#24
0
def stop_tunnel(tunnel_id) -> Tuple[Response, int]:
    """
    Stop a currently running tunnel
    """
    current_user = User.query.filter_by(uuid=get_jwt_identity()).first_or_404()
    tunnel = Tunnel.query.filter_by(user=current_user, id=tunnel_id).first_or_404()

    try:
        TunnelDeletionService(current_user, tunnel).delete()
        return make_response(""), 204
    except TunnelError:
        return json_api(TunnelError, ErrorSchema), 500
示例#25
0
def update_user():
    """ Update an existing User Record"""

    try:
        json_schema_manager.validate(request.json, "user_update.json")

        current_user = User.query.filter_by(uuid=get_jwt_identity()).first_or_404()

        new_attrs = dig(request.json, "data/attributes", None)
        service = UserUpdate(
            current_user, scopes=authentication.jwt_scopes(), **new_attrs
        )
        updated_user = service.update()

        return json_api(updated_user, UserSchema), 200
    except UserError as e:
        return json_api(e, ErrorSchema), 422
    except AccessDenied as e:
        return json_api(e, ErrorSchema), 403
    except ValidationError as e:
        return json_api(BadRequest(source=e.message), ErrorSchema), 400
示例#26
0
def config_create():
    try:
        json_schema_manager.validate(request.json, "config_create.json")
        current_user = User.query.filter_by(
            uuid=get_jwt_identity()).first_or_404()
        config = ConfigCreationService(
            current_user, dig(request.json,
                              "data/attributes/name")).create(True)

        return json_api(config, ConfigSchema), 200
    except ValidationError:
        return (
            json_api(BadRequest(detail="Request does not match schema."),
                     ErrorSchema),
            400,
        )
    except ConfigLimitReached:
        return json_api(ConfigLimitReached, ErrorSchema), 403
    except ConfigTaken:
        return json_api(ConfigTaken, ErrorSchema), 400
    except ConfigError:
        return json_api(ConfigError, ErrorSchema), 500
示例#27
0
def confirm(token):
    for salt in token_types:
        uuid = authentication.decode_token(token, salt=salt)
        if salt == "password-reset-salt" and uuid:
            task_token = UserToken(uuid).issue_task_token("update:user:new_password")
            return (
                jsonify(
                    {
                        "access_token": task_token,
                        "token_type": "Bearer",
                        "expires-in": 3600,
                    }
                ),
                200,
            )
        elif salt == "email-confirm-salt" and uuid:
            uuid = authentication.decode_token(token, salt=salt)
            if not UserToken(uuid).confirm():
                return json_api(AccessDenied, ErrorSchema), 403
            return "", 204

    return json_api(AccessDenied, ErrorSchema), 403
示例#28
0
def start_box() -> Tuple[Response, int]:
    try:
        json_schema_manager.validate(request.json, "box_create.json")

        config_id = dig(request.json, "data/relationships/config/data/id")
        ssh_key = dig(request.json, "data/attributes/sshKey")
        image = dig(request.json, "data/attributes/image", "ubuntu")

        #right now there is only one valid choice
        #in the future there will be multiple choices and customer snapshots
        #we will want to throw an error in the future for an invalid choice
        if image == "ubuntu":
            image = "cypherpunkarmory/ubuntu:0.0.1"
        elif image == "debian":
            image = "cypherpunkarmory/debian:0.0.1"
        elif image == "kali":
            image = "cypherpunkarmory/kali:0.0.1"
        elif image == "alpine":
            image = "cypherpunkarmory/alpine:0.0.1"
        elif image == "arch":
            image = "cypherpunkarmory/arch:0.0.1"
        else:
            image = "cypherpunkarmory/ubuntu:0.0.1"

        current_user = User.query.filter_by(
            uuid=get_jwt_identity()).first_or_404()
        try:
            box_info = BoxCreationService(current_user, config_id, ssh_key,
                                          image).create()
        except ConfigLimitReached:
            return json_api(ConfigLimitReached, ErrorSchema), 403
        except BoxLimitReached:
            return json_api(BoxLimitReached, ErrorSchema), 403
        except BoxError:
            rollbar.report_exc_info(sys.exc_info())
            return json_api(BoxError, ErrorSchema), 500

        return json_api(box_info, BoxSchema), 201

    except ValidationError as e:
        return json_api(BadRequest(detail=e.message), ErrorSchema), 400

    except AccessDenied:
        return json_api(AccessDenied, ErrorSchema), 403

    except ConfigInUse:
        return json_api(ConfigInUse, ErrorSchema), 403
示例#29
0
def create_token():
    try:
        json_schema_manager.validate(request.json, "token.json")
        email = dig(request.json, "data/attributes/email", None)
        token_type = dig(request.json, "data/type", None)
        user = User.query.filter_by(email=email).first_or_404()
        uns = UserNotification(user)

        if token_type == "email_confirm":
            uns.activation_emails()
        elif token_type == "password_reset":
            uns.password_reset_email()

    except ValidationError as e:
        return json_api(BadRequest(source=e.message), ErrorSchema), 400
    except NotFound:
        return "", 200

    return "", 200
示例#30
0
 def page_not_found(e):
     return json_api(NotFoundError(detail=e.description), ErrorSchema), 404