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)
def to_dict(self, **kwargs): return ObjectDict( id=self.id, label=self.label, description=self.description, typeId=self.type_id, **kwargs, )
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
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")
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)
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"))
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, ))
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}), }, ), )
def to_dict(self, *_, **__): return ObjectDict(id=self.id, link=self.link)
def to_dict(self, **_): return ObjectDict(id=self.id, email=self.email)
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():