예제 #1
0
from restfulpy.authorization import authorize
from restfulpy.controllers import ModelRestController
from restfulpy.logging_ import get_logger
from restfulpy.orm import commit, DBSession
from restfulpy.validation import validate_form, prevent_form
from sqlalchemy_media import store_manager
from sqlalchemy_media.exceptions import DimensionValidationError, AspectRatioValidationError, AnalyzeError, \
    ContentTypeValidationError

from stemerald.authentication import VerificationEmailPrincipal, ResetPasswordPrincipal
from stemerald.models import Client, Admin, Member, ClientEvidence, VerificationEmail, VerificationSms, \
    ResetPasswordEmail, SecurityLog, Invitation
from stemerald.oath import Oath

logger = get_logger('CLIENT')

MemberId = Union[int, str]

phone_pattern = r'\+[1-9]{1}[0-9]{3,14}'  # TODO: Close begin and end
email_pattern = r'(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)'


# TODO: IMPORTANT: Invalidate member sessions in all services!

class SessionController(RestController):
    @json
    @authorize('admin', 'client')
    @validate_form(
        whitelist=['take', 'skip'],
        types={'take': int, 'skip': int}
예제 #2
0
import time
import traceback
from datetime import datetime

from nanohttp import settings
from sqlalchemy import Integer, Enum, Unicode, DateTime
from sqlalchemy.sql.expression import text

from restfulpy.exceptions import RestfulException
from restfulpy.logging_ import get_logger
from restfulpy.orm import TimestampMixin, DeclarativeBase, Field, DBSession, \
    create_thread_unsafe_session

logger = get_logger('taskqueue')


class TaskPopError(RestfulException):
    pass


class RestfulpyTask(TimestampMixin, DeclarativeBase):
    __tablename__ = 'restfulpy_task'

    id = Field(Integer, primary_key=True, json='id')
    priority = Field(Integer, nullable=False, default=50, json='priority')
    status = Field(Enum('new',
                        'success',
                        'in-progress',
                        'failed',
                        name='task_status_enum'),
                   default='new',
예제 #3
0
from nanohttp import settings
from restfulpy.logging_ import get_logger
from restfulpy.messaging import Email
from restfulpy.orm import Field
from restfulpy.taskqueue import Task
from sqlalchemy import Integer, ForeignKey, Unicode, JSON

from stemerald.sms import create_sms_provider

logger = get_logger('MESSAGING')


class Sms(Task):
    """
    This is the base SMS task
    """
    __tablename__ = 'sms'
    __mapper_args__ = {'polymorphic_identity': __tablename__}

    id = Field(Integer, ForeignKey('task.id'), primary_key=True, json='id')
    to = Field(Unicode(25), pattern=r'\+[1-9]{1}[0-9]{3,14}')
    body = Field(JSON, json='body')

    @property
    def message_format(self):
        raise NotImplementedError()

    @property
    def sms_text(self):
        return self.message_format % self.body
예제 #4
0
class Application(NanohttpApplication):
    builtin_configuration = None
    __logger__ = get_logger()
    __authenticator__ = None

    def __init__(self,
                 name: str,
                 root: Controller,
                 root_path='.',
                 version='0.1.0-dev.0',
                 process_name=None,
                 authenticator=None):
        super(Application, self).__init__(root=root)
        self.process_name = process_name or name
        self.version = version
        self.root_path = abspath(root_path)
        self.name = name
        self.cli_main = MainLauncher(self)
        if authenticator:
            self.__authenticator__ = authenticator
        elif self.__authenticator__ is None:
            self.__authenticator__ = Authenticator()

    def _handle_exception(self, ex):
        if not isinstance(ex, HttpStatus):
            ex = HttpInternalServerError('Internal server error')
            self.__logger__.exception('Internal server error')
        return super()._handle_exception(ex)

    def configure(self, files=None, context=None, **kwargs):
        _context = {
            'process_name': self.process_name,
            'root_path': self.root_path,
            'data_dir': join(self.root_path, 'data'),
            'restfulpy_dir': abspath(dirname(__file__))
        }
        if context:
            _context.update(context)

        files = ([files] if isinstance(files, str) else files) or []
        local_config_file = join(user_config_dir(), '%s.yml' % self.name)
        if exists(local_config_file):  # pragma: no cover
            print('Gathering config file: %s' % local_config_file)
            files.insert(0, local_config_file)

        configure(config=self.builtin_configuration,
                  files=files,
                  context=_context,
                  **kwargs)

    # noinspection PyMethodMayBeStatic
    def register_cli_launchers(self, subparsers):
        """
        This is a template method
        """
        pass

    @classmethod
    def initialize_models(cls):
        init_model(create_engine())

    # Hooks
    def begin_request(self):
        self.__authenticator__.authenticate_request()

    # noinspection PyMethodMayBeStatic
    def begin_response(self):
        if settings.debug:
            context.response_headers.add_header('Access-Control-Allow-Origin',
                                                'http://localhost:8080')
            context.response_headers.add_header(
                'Access-Control-Allow-Methods',
                'GET, POST, PUT, DELETE, UNDELETE, METADATA, PATCH, SEARCH')
            context.response_headers.add_header(
                'Access-Control-Allow-Headers', 'Content-Type, Authorization, '
                'X-HTTP-Verb')
            context.response_headers.add_header(
                'Access-Control-Expose-Headers',
                'Content-Type, X-Pagination-Count, X-Pagination-Skip, '
                'X-Pagination-Take, X-New-JWT-Token')
            context.response_headers.add_header(
                'Access-Control-Allow-Credentials', 'true')

    # noinspection PyMethodMayBeStatic
    def end_response(self):
        DBSession.remove()

    def insert_basedata(self):  # pragma: no cover
        raise NotImplementedError

    def insert_mockup(self):  # pragma: no cover
        raise NotImplementedError
예제 #5
0
from sqlalchemy import Integer, ForeignKey, Unicode, JSON
from sqlalchemy.ext.declarative import declared_attr

from nanohttp import settings
from restfulpy.orm import Field
from restfulpy.taskqueue import Task
from restfulpy.logging_ import get_logger
from .providers import create_messenger

logger = get_logger('messaging')


# noinspection PyAbstractClass
class BaseEmail(Task):
    __abstract__ = True

    from_ = Field(Unicode(100),
                  json='from',
                  default=lambda: settings.messaging.default_sender)
    to = Field(Unicode(100), json='to')
    subject = Field(Unicode(256), json='subject')
    cc = Field(Unicode(100), nullable=True, json='cc')
    bcc = Field(Unicode(100), nullable=True, json='bcc')

    # noinspection PyDefaultArgument,PyMethodParameters
    @declared_attr
    def id(cls):
        return Field(Integer,
                     ForeignKey('task.id'),
                     primary_key=True,
                     json='id')
예제 #6
0
from firebase_admin import App
from nanohttp import settings
import argparse
import json
import requests

from oauth2client.service_account import ServiceAccountCredentials
from restfulpy.logging_ import get_logger

logger = get_logger('FIREBASE')


class FirebaseClient:
    @staticmethod
    def init_firebase():
        import firebase_admin
        from firebase_admin import credentials

        # cred = credentials.Certificate('stacrypt-1c4dc-firebase-adminsdk-hy7hb-ad49502f48.json')
        cred = credentials.Certificate(settings.firebase.service_account_key)
        return firebase_admin.initialize_app(cred)

    _firebase_client = None

    @property
    def instance(self):
        if FirebaseClient._firebase_client is None:
            FirebaseClient._firebase_client = FirebaseClient.init_firebase()
        return self._firebase_client

예제 #7
0
from nanohttp import RestController, json, context, HttpBadRequest
from restfulpy.logging_ import get_logger


logger = get_logger('auth')


class MembersController(RestController):

    @json
    def login(self):
        email = context.form.get('email')
        password = context.form.get('password')

        def bad():
            logger.info('Login failed: %s' % email)
            raise HttpBadRequest('Invalid email or password')

        if not (email and password):
            bad()

        logger.info('Trying to login: %s' % email)
        principal = context.application.__authenticator__.login((email, password))
        if principal is None:
            bad()

        return dict(token=principal.dump())
예제 #8
0
from datetime import datetime

from firebase_admin import messaging
from restfulpy.logging_ import get_logger
from restfulpy.orm import OrderingMixin, FilteringMixin, Field, SoftDeleteMixin, \
    PaginationMixin
from restfulpy.taskqueue import Task
from sqlalchemy import DateTime, Integer, ForeignKey, Unicode, JSON
from sqlalchemy.ext.hybrid import hybrid_property

from stemerald.firebase import FirebaseClient
from stemerald.models import Member

logger = get_logger('NOTIFICATION')


class Notification(SoftDeleteMixin, PaginationMixin, OrderingMixin,
                   FilteringMixin, Task):
    """
    Note: This table is experimental!
    """
    def do_(self, context):  # pragma: no cove
        from stemerald import stemerald

        app = FirebaseClient().instance

        # TODO: Retrieve notifications policy of the user
        # See documentation on defining a message payload.

        # TODO: Retrieve all registered tokens about all user's connected devices
예제 #9
0
 def __init__(self, application):
     self.__application = application
     self.logger = get_logger('middleware')
예제 #10
0
import requests
from nanohttp.configuration import settings
from restfulpy.logging_ import get_logger
from restfulpy.utils import construct_class_by_name

logger = get_logger('PAYMENT')


class ShaparakError(Exception):
    def __init__(self, response):
        super().__init__()
        error = response.text if response else 'NA'
        logger.info(f'Unsuccessful payment: {error}')


class ShaparakProvider:
    def create_transaction(self, batch_id, amount):
        """
        :param batch_id: Id of transaction record in our system
        :param amount: amount
        :return: Transaction id (returned from payment gateway)
        """
        raise NotImplementedError

    def verify_transaction(self, transaction_id):
        """
        :param transaction_id: Id of transaction in pay.ir
        :return: (amount, reference_id, card_address)
        """
        raise NotImplementedError
예제 #11
0
import requests
from nanohttp import settings
from restfulpy.logging_ import get_logger
from restfulpy.utils import construct_class_by_name

logger = get_logger('SMS')


class SmsSendingError(Exception):
    def __init__(self, response):
        logger.info(f'Error sending sms: {response.text}')


class SmsProvider:
    def send(self, to_number, text):
        logger.info('SMS is sending for number : %s with text : %s by : %s' %
                    (to_number, text, self.__class__.__name__))

    def send_as_verification_code(self, to_number, token, template):
        logger.info(
            'SMS is sending for number : %s with token : %s with template %s by : %s'
            % (to_number, token, template, self.__class__.__name__))


class ConsoleSmsProvider(SmsProvider):  # pragma: no cover
    def send(self, to_number, text):
        super().send(to_number, text)
        print('SMS send request received for number : %s with text : %s' %
              (to_number, text))

    def send_as_verification_code(self, to_number, token, template):
예제 #12
0
from decimal import Decimal

from nanohttp import RestController, json, context, HttpNotFound, HttpBadRequest, HttpInternalServerError
from restfulpy.authorization import authorize
from restfulpy.logging_ import get_logger
from restfulpy.validation import validate_form

from stemerald.models import Cryptocurrency
from stemerald.stawallet import stawallet_client, StawalletException, StawalletHttpException
from stemerald.stexchange import StexchangeException, stexchange_client, BalanceNotEnoughException, \
    RepeatUpdateException

logger = get_logger('WALLET')


def deposit_to_dict(currency:Cryptocurrency, deposit):
    return {
        'id': deposit['id'],
        'user': deposit['invoice']['user'],
        'isConfirmed': deposit['confirmed'],
        'netAmount': currency.smallest_unit_to_output(deposit['netAmount']),
        'grossAmount': currency.smallest_unit_to_output(deposit['grossAmount']),
        'toAddress': deposit['invoice']['address'],
        'status': deposit['status'],
        'txHash': deposit['proof']['txHash'],
        'blockHeight': deposit['proof']['blockHeight'],
        'blockHash': deposit['proof']['blockHash'],
        'link': deposit['proof']['link'],
        'confirmationsLeft': deposit['proof']['confirmationsLeft'],
        'error': deposit['proof']['error'],
        'invoice': invoice_to_dict(deposit['invoice']),
예제 #13
0
import requests

from restfulpy.logging_ import get_logger

from stemerald.helpers import DeferredObject

logger = get_logger('STAWALLET_REST_CLIENT')

WALLETS_URL = "wallets"
INVOICES_URL = "invoices"
DEPOSITS_URL = "deposits"
WITHDRAWS_URL = "whitdraws"
QUOTES_URL = "quotes"


class StawalletClient:

    def __init__(self, server_url, headers=None):
        self.server_url = server_url
        self.headers = {'content-type': 'application/x-www-form-urlencoded'}
        self.headers.update(headers or {})

    def _execute(self, method, url, query_string: dict = None, body: dict = None):
        url = '/'.join([self.server_url, url])

        logger.debug(f"Requesting {method} over {url} with query: {query_string} with body: {body}")

        try:
            response = requests.request(
                params=query_string,
                method=method,
예제 #14
0
import time
from decimal import getcontext, Decimal

from nanohttp import settings
from restfulpy.logging_ import get_logger
from restfulpy.orm import session_factory

from stemerald import stawallet_client, stexchange_client
from stemerald.controllers.wallet import deposit_to_dict
from stemerald.models import Cryptocurrency, Notification
from stemerald.stexchange import RepeatUpdateException

logger = get_logger('looper')


def stawallet_sync_looper():
    isolated_session = session_factory(expire_on_commit=False)
    context = {'counter': 0}

    while True:

        logger.info("Trying to sync wallet, Counter: %s" % context['counter'])
        cryptocurrencies = isolated_session.query(Cryptocurrency).all()
        for cryptocurrency in cryptocurrencies:
            # Get latest synced deposit update time
            try:

                page = 0

                while True:
                    new_sync_time = int(time.time())
예제 #15
0
파일: dev.py 프로젝트: shayan-7/restfulpy
 def launch(self):
     from restfulpy.logging_ import get_logger
     getattr(get_logger(self.args.logger),
             self.args.level)(' '.join(self.args.message))
예제 #16
0
import ujson
import time

import requests
from nanohttp import *

from restfulpy.logging_ import get_logger

from stemerald.helpers import DeferredObject

logger = get_logger('STEXCHANGE_RPC_CLIENT')

# from logging import Logger
# logger = Logger('STEXCHANGE_RPC_CLIENT')


class StexchangeClient:
    def __init__(self, server_url, headers=None):
        self.server_url = server_url
        self.headers = {'content-type': 'application/json'}
        self.headers.update(headers or {})
        self.request_id = 0

    def _next_request_id(self):
        self.request_id += 1
        return self.request_id

    def _execute(self, method, params, error_mapper=None):
        _id = self._next_request_id()
        params = list(map(lambda x: x if x is not None else "null", params))
        payload = ujson.dumps({"method": method, "params": params, "id": _id})
예제 #17
0
from nanohttp import settings
from restfulpy.logging_ import get_logger
from requests import request
from requests.exceptions import RequestException

logger = get_logger('webhook')

HTTP_NO_CONTENT = 204


class Webhook:
    def sent_message(self, room_id, member_reference_id):
        try:
            response = request(
                settings.webhooks.sent.verb,
                settings.webhooks.sent.url,
                params=dict(roomId=room_id,
                            memberReferenceId=member_reference_id),
                timeout=settings.webhooks.sent.timeout,
            )
            if response.status_code != HTTP_NO_CONTENT:
                self._bad_thirdparty_response(response.status_code)

        except Exception as ex:
            self._handle_exception(ex)

    def mentioned_member(self, room_id, mentioned_reference_id):
        try:
            response = request(
                settings.webhooks.mentioned.verb,
                settings.webhooks.mentioned.url,