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}
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',
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
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
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')
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
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())
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
def __init__(self, application): self.__application = application self.logger = get_logger('middleware')
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
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):
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']),
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,
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())
def launch(self): from restfulpy.logging_ import get_logger getattr(get_logger(self.args.logger), self.args.level)(' '.join(self.args.message))
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})
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,