示例#1
0
def test_http_status():
    h.Asserter.assert_true(h.httpcode.is_informational(h.httpcode.PROCESSING))
    h.Asserter.assert_true(h.httpcode.is_success(h.httpcode.CREATED))
    h.Asserter.assert_false(h.httpcode.is_success(h.httpcode.MULTIPLE_CHOICES))
    h.Asserter.assert_true(h.httpcode.is_redirection(h.httpcode.SEE_OTHER))
    h.Asserter.assert_false(h.httpcode.is_redirection(h.httpcode.BAD_REQUEST))
    h.Asserter.assert_true(h.httpcode.is_client_error(h.httpcode.UNAUTHORIZED))
    h.Asserter.assert_false(
        h.httpcode.is_client_error(h.httpcode.INTERNAL_SERVER_ERROR))
    h.Asserter.assert_true(
        h.httpcode.is_server_error(h.httpcode.NOT_IMPLEMENTED))
    h.Asserter.assert_false(h.httpcode.is_server_error(
        h.httpcode.NOT_MODIFIED))
    h.Asserter.assert_true(h.httpcode.is_ok(h.httpcode.FOUND))
    h.Asserter.assert_false(h.httpcode.is_ko(h.httpcode.SUCCESS))
    h.Asserter.assert_status_code(ObjectDict(status=201),
                                  code=(201, 202, 203),
                                  is_in=True)
    h.Asserter.assert_status_code(ObjectDict(status=201),
                                  code=(200, 299),
                                  in_range=True)
    h.Asserter.assert_status_code(ObjectDict(status=400),
                                  code=300,
                                  greater=True)
    h.Asserter.assert_status_code(ObjectDict(status=200), code=300, less=True)
示例#2
0
 def to_dict(self, **kwargs):
     return ObjectDict(
         id=self.id,
         label=self.label,
         description=self.description,
         typeId=self.type_id,
         **kwargs,
     )
示例#3
0
 def create_event(self, data, raise_exc=False):
     webhook_secret = cap.config.STRIPE_WEBHOOK_SECRET
     signature = flask.request.headers.get("stripe-signature")
     try:
         return ObjectDict(**self._stripe.Webhook.construct_event(
             payload=data, sig_header=signature, secret=webhook_secret))
     except StripeError as exc:
         cap.logger.exception(exc)
         if raise_exc:
             raise
     return None
示例#4
0
 def __init__(
     self,
     session=None,
     auth_code_handler=None,
     notifications=None,
     scheduler=None,
 ):
     self.session = session or ExtProxy("sqlalchemy.db.session")
     self.auth_code_handler = auth_code_handler or AuthCode(
         ExtProxy("redis"), ObjectDict())
     self.scheduler = scheduler or ExtProxy("scheduler")
     """ EXAMPLE
     ------------------------------------------------
         register:
           subject: Confirm your registration
           body: emails/registration.html
         forgot:
           subject: Forgot Password
           body: emails/forgot.html
     """
     self.notifications = notifications or ConfigProxy("NOTIFICATIONS")
示例#5
0
class AccountHandler:
    user_model = None

    SCHEMAS = ObjectDict(
        register="REGISTER",
        register_confirm="REGISTER_CONFIRM",
        password_reset="PASSWORD_RESET",
        password_forgot="PASSWORD_FORGOT",
        password_confirm="PASSWORD_CONFIRM",
    )
    CACHE_TEMP_KEYS = ObjectDict(
        account_forgot="account_forgot",
        account_register="account_register",
    )

    def __init__(
        self,
        session=None,
        auth_code_handler=None,
        notifications=None,
        scheduler=None,
    ):
        self.session = session or ExtProxy("sqlalchemy.db.session")
        self.auth_code_handler = auth_code_handler or AuthCode(
            ExtProxy("redis"), ObjectDict())
        self.scheduler = scheduler or ExtProxy("scheduler")
        """ EXAMPLE
        ------------------------------------------------
            register:
              subject: Confirm your registration
              body: emails/registration.html
            forgot:
              subject: Forgot Password
              body: emails/forgot.html
        """
        self.notifications = notifications or ConfigProxy("NOTIFICATIONS")

    def send_notification(self, recipients, subject, template, **kwargs):
        raise NotImplementedError

    def __check_user_model(self):
        assert self.user_model is not None, "user_model must be defined"

    @staticmethod
    def get_payload(schema):
        return PayloadValidator.validate(schema)

    def prepare_user(self, data):
        self.__check_user_model()
        return self.user_model(**data)  # pylint: disable=not-callable

    def find_by_email(self, email):
        self.__check_user_model()
        return self.user_model.query.filter_by(email=email).first_or_404()

    def register(self):
        payload = self.get_payload(self.SCHEMAS.register)
        user = self.prepare_user(payload)

        try:
            self.session.add(user)
            self.session.commit()
        except Exception as exc:  # pragma: no cover pylint: disable=broad-except
            cap.logger.exception(exc)
            self.session.rollback()
            flask.abort(httpcode.CONFLICT if isinstance(exc, IntegrityError)
                        else httpcode.INTERNAL_SERVER_ERROR)

        token = self.auth_code_handler.generate(
            self.CACHE_TEMP_KEYS.account_register, user)
        self.send_notification(
            recipients=[user.email],
            subject=self.notifications.register.subject,
            template=self.notifications.register.body,
            token=token,
            user=user.to_dict(),
        )

    def register_confirm(self):
        payload = self.get_payload(self.SCHEMAS.register_confirm)
        email = self.auth_code_handler.check(
            self.CACHE_TEMP_KEYS.account_register, payload.token)

        try:
            user = self.find_by_email(email)
            user.confirmed = True
            self.session.merge(user)
            self.session.commit()
        except SQLAlchemyError as exc:  # pragma: no cover
            cap.logger.exception(exc)
            self.session.rollback()
            flask.abort(httpcode.INTERNAL_SERVER_ERROR)

    def check_user(self, email, password):
        user = self.find_by_email(email)
        if not user.check_password(password):
            flask.abort(httpcode.BAD_REQUEST)  # pragma: no cover
        return user

    def password_reset(self):
        payload = self.get_payload(self.SCHEMAS.password_reset)
        user = self.check_user(payload.email, payload.old_password)
        try:
            user.password = payload.new_password
            self.session.merge(user)
            self.session.commit()
        except SQLAlchemyError as exc:  # pragma: no cover
            cap.logger.exception(exc)
            self.session.rollback()
            flask.abort(httpcode.INTERNAL_SERVER_ERROR)

    def password_forgot(self):
        payload = self.get_payload(self.SCHEMAS.password_forgot)
        user = self.find_by_email(payload.email)
        token = self.auth_code_handler.generate(
            self.CACHE_TEMP_KEYS.account_forgot, user)
        self.send_notification(
            recipients=[payload.email],
            subject=self.notifications.forgot.subject,
            template=self.notifications.forgot.body,
            token=token,
            user=user.to_dict(),
        )

    def password_confirm(self):
        payload = self.get_payload(self.SCHEMAS.password_confirm)
        email = self.auth_code_handler.check(
            self.CACHE_TEMP_KEYS.account_forgot, payload.token)
        user = self.find_by_email(email)
        user.password = payload.password

        try:
            self.session.merge(user)
            self.session.commit()
        except SQLAlchemyError as exc:  # pragma: no cover
            cap.logger.exception(exc)
            self.session.rollback()
            flask.abort(httpcode.INTERNAL_SERVER_ERROR)
示例#6
0
from flaskel.http import (
    batch,
    FlaskelHttp,
    FlaskelJsonRPC,
    HTTPClient,
    HTTPStatusError,
    rpc,
    useragent,
)
from flaskel.tester import helpers as h
from flaskel.tester.http import TestHttpApi, TestHttpCall, TestJsonRPC, TestRestApi
from flaskel.utils import datetime, ExtProxy, schemas
from flaskel.utils.faker import DummyLogger

HOSTS = ObjectDict(
    apitester="http://httpbin.org",
    fake="http://localhost",
)


def test_app_dev(app_dev):
    h.Asserter.assert_equals(app_dev.config.FLASK_ENV, "development")
    h.Asserter.assert_equals(app_dev.config.SECRET_KEY,
                             "fake_very_complex_string")

    client = TestHttpCall(app_dev.test_client())
    client.perform(request={"url": h.url_for("web.index")})

    client = TestHttpApi(app_dev.test_client())
    client.perform(request={"url": h.url_for("test.test_https")})
    h.Asserter.assert_equals(client.json.scheme, "https")
    h.Asserter.assert_true(client.json.url_for.startswith("https"))
示例#7
0
 def create_payment_intent(self, amount, currency=None, **kwargs):
     return ObjectDict(**self._stripe.PaymentIntent.create(
         amount=amount,
         currency=currency or cap.config.STRIPE_DEFAULT_CURRENCY,
         **kwargs,
     ))
示例#8
0
SCHEMAS = ObjectDict(
    JSONRPC=ObjectDict(
        REQUEST=Fields.oneof(
            Fields.ref("/definitions/request",
                       description="An individual request"),
            Fields.array(
                items=Fields.ref("/definitions/request"),
                description="An array of requests",
            ),
            **Fields.schema,
            description="A JSON RPC 2.0 request",
            definitions={
                "request":
                Fields.object(
                    required=["jsonrpc", "method"],
                    properties={
                        "jsonrpc":
                        Fields.enum("2.0"),
                        "method":
                        Fields.string,
                        "params":
                        Fields.type("array", "object"),
                        "id":
                        Fields.type(
                            "string",
                            "number",
                            "null",
                            note=[
                                "While allowed, null should be avoided: "
                                "http://www.jsonrpc.org/specification#id1",
                                "While allowed, a number with a fractional part should be avoided: "
                                "http://www.jsonrpc.org/specification#id2",
                            ],
                        ),
                    },
                )
            },
        ),
        RESPONSE=Fields.oneof(
            Fields.ref("/definitions/response"),
            Fields.array(items=Fields.ref("/definitions/response")),
            **Fields.schema,
            definitions={
                "response":
                Fields.type(
                    "array",
                    "object",
                    required=["jsonrpc"],
                    properties={
                        "jsonrpc":
                        Fields.enum("2.0"),
                        "id":
                        Fields.type("string", "number", "null"),
                        "result":
                        Fields.type("array", "object", "null"),
                        "error":
                        Fields.type(
                            "array",
                            "object",
                            properties={
                                "code": Fields.number,
                                "message": Fields.string,
                            },
                        ),
                    },
                )
            },
        ),
    ),
    POST_REVOKE_TOKEN=Fields.object(
        all_required=False,
        properties={
            "access_token": Fields.string,
            "refresh_token": Fields.string,
            "device_token": Fields.string,
        },
    ),
    POST_ACCESS_TOKEN=Fields.object(properties={
        "email": Fields.string,
        "password": Fields.string
    }),
    ACCESS_TOKEN=Fields.object(
        required=["access_token", "refresh_token", "expires_in", "issued_at"],
        properties={
            "access_token": Fields.string,
            "refresh_token": Fields.string,
            "expires_in": Fields.Opt.integer,
            "issued_at": Fields.integer,
            "token_type": Fields.string,
            "scope": Fields.Opt.string,
        },
    ),
    REFRESH_TOKEN=Fields.object(
        required=["access_token", "expires_in", "issued_at"],
        properties={
            "access_token": Fields.string,
            "expires_in": Fields.Opt.integer,
            "issued_at": Fields.integer,
            "token_type": Fields.string,
            "scope": Fields.Opt.string,
        },
    ),
    REGISTER_CONFIRM=Fields.object(properties={"token": Fields.string}),
    PASSWORD_RESET=Fields.object(
        properties={
            "email": Fields.string,
            "new_password": Fields.string,
            "old_password": Fields.string,
        }),
    PASSWORD_FORGOT=Fields.object(properties={"email": Fields.string}),
    PASSWORD_CONFIRM=Fields.object(properties={
        "token": Fields.string,
        "password": Fields.string
    }),
    API_PROBLEM=Fields.object(
        properties={
            "type": Fields.string,
            "title": Fields.string,
            "detail": Fields.string,
            "instance": Fields.string,
            "status": Fields.integer,
            "response": Fields.any,
        }),
    HEALTH_CHECK=Fields.object(
        **Fields.schema,
        properties={
            "status":
            Fields.string,
            "checks":
            Fields.object(
                patternProperties={
                    ".":
                    Fields.object(
                        properties={
                            "status": Fields.string,
                            "output": Fields.type("null", "string", "object"),
                        })
                }),
            "links":
            Fields.object(properties={"about": Fields.Opt.string}),
        },
    ),
)
示例#9
0
文件: repo.py 项目: cs91chris/flaskel
 def to_dict(self, *_, **__):
     return ObjectDict(id=self.id, link=self.link)
示例#10
0
 def to_dict(self, **_):
     return ObjectDict(id=self.id, email=self.email)
示例#11
0
import os

import pytest

# pylint: disable=import-error
from scripts.cli import APP_CONFIG  # type: ignore

from flaskel import ObjectDict, TestClient
from flaskel.ext.sqlalchemy.support import SQLASupport
from flaskel.tester import helpers as h
from .helpers import Views

DB_TEST = "test.sqlite"
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
SAMPLE_DATA = os.path.join(BASE_DIR, "..", "resources", "sample.sql")
CONFIG = ObjectDict()

CONFIG.MAIL_DEBUG = True
CONFIG.CACHE_TYPE = "null"
CONFIG.RATELIMIT_ENABLED = False
CONFIG.SQLALCHEMY_ECHO = True
CONFIG.SQLALCHEMY_DATABASE_URI = f"sqlite:///{DB_TEST}"

CONFIG.SENDRIA = dict(
    endpoint="http://sendria.local:61000/api/messages",
    username="******",
    password="******",
)


def load_sample_data():