from django import http from rest_framework import response, viewsets from webpay.api.base import BuyerIsLoggedIn from webpay.base.logger import getLogger from webpay.pay import tasks log = getLogger('w.api') class SimulateViewSet(viewsets.ViewSet): permission_classes = (BuyerIsLoggedIn,) def create(self, request): if not request.session.get('is_simulation', False): log.info('Request to simulate without a valid session') return http.HttpResponseForbidden() tasks.simulate_notify.delay(request.session['notes']['issuer_key'], request.session['notes']['pay_request']) return response.Response(status=204)
from django import forms from django.conf import settings from django_paranoia.forms import ParanoidForm import jwt from lib.solitude.constants import ACCESS_SIMULATE from webpay.base import dev_messages as msg from webpay.base.logger import getLogger from .utils import lookup_issuer, UnknownIssuer log = getLogger('w.pay') class NetCodeForm(ParanoidForm): mcc = forms.RegexField(regex='^\d{2,3}$', required=True) mnc = forms.RegexField(regex='^\d{2,3}$', required=True) class VerifyForm(ParanoidForm): req = forms.CharField() # If mcc or mnc are given, we'll accept any value that conforms to the # format. We'll then whitelist actions on particular values. mcc = forms.RegexField(regex='^\d{2,3}$', required=False) mnc = forms.RegexField(regex='^\d{2,3}$', required=False) key = settings.KEY secret = settings.SECRET is_simulation = False
import functools import json import time from django.conf import settings from django.core.cache import cache from django.http import HttpResponse from django.shortcuts import render from cef import log_cef as _log_cef from tower import ugettext as _ from webpay.base import dev_messages as msg from webpay.base.logger import getLogger log = getLogger('w.cef') def invert(data): """ Helper to turn a dict of constants into a choices tuple. """ return [(v, k) for k, v in data.items()] def gmtime(): return calendar.timegm(time.gmtime()) def log_cef(msg, request, **kw): log_cef_meta(msg, request.META.copy(), request.path_info, **kw)
from django import forms from django.conf import settings import jwt from django_paranoia.forms import ParanoidForm from mozpay.exc import InvalidJWT from mozpay.verify import verify_jwt from webpay.base.logger import getLogger from webpay.pay.utils import lookup_issuer, UnknownIssuer log = getLogger('w.services') class SigCheckForm(ParanoidForm): sig_check_jwt = forms.CharField() def clean_sig_check_jwt(self): enc_jwt = self.cleaned_data['sig_check_jwt'].encode('ascii', 'ignore') try: jwt_data = jwt.decode(enc_jwt, verify=False) except jwt.DecodeError, exc: log.info( 'caught sig_check exc: {0.__class__.__name__}: {0}'.format( exc)) raise forms.ValidationError('INVALID_JWT_OR_UNKNOWN_ISSUER') try: secret, active_product = lookup_issuer(jwt_data.get('iss', '')) except UnknownIssuer, exc: log.info(
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_POST from django.utils import translation from curling.lib import HttpClientError from lib.marketplace.api import client as marketplace from lib.solitude.api import client as solitude from webpay.base.decorators import json_view from webpay.base.dev_messages import legend from webpay.base.logger import getLogger from webpay.base.utils import log_cef_meta from .forms import ErrorLegendForm, SigCheckForm log = getLogger("z.services") def monitor(request): content = {} all_good = True # Check that we can talk to the marketplace. msg = "ok" try: perms = marketplace.api.account.permissions.mine.get() except HttpClientError, err: all_good = False msg = "Server error: status %s, content: %s" % (err.response.status_code, err.response.content or "empty") else: if not perms["permissions"].get("webpay", False):
from os.path import abspath from time import time, sleep from django import http from django.conf import settings from django.views.decorators.csrf import csrf_exempt from webpay.base.decorators import json_view from webpay.base.logger import getLogger log = getLogger("w.pay") # When email addressess are prefixed with these values they will trigger login # behavior. OK_USER = "******" TIMEOUT_USER = "******" FAILED_LOGIN = "******" ERROR_LOGIN = "******" def fake_include(request): """Serve up stubbyid.js for testing.""" if not settings.DEV or not settings.TEST_PIN_UI: return http.HttpResponseForbidden() with open(abspath("webpay/testing/stubbyid.js")) as fh: stub_js = fh.read() return http.HttpResponse(stub_js, content_type="text/javascript") @csrf_exempt
from django.views.decorators.debug import sensitive_post_parameters from tower import ugettext as _ from lib.solitude.api import client from lib.solitude.exceptions import ResourceModified from webpay.auth.decorators import enforce_sequence, user_verified from webpay.auth.utils import (get_user, set_user_has_confirmed_pin, set_user_has_pin) from webpay.base import dev_messages as msg from webpay.base.logger import getLogger from webpay.base.utils import system_error from webpay.pay import get_wait_url from . import forms log = getLogger('w.pin') @enforce_sequence @sensitive_post_parameters('pin') def create(request): form = forms.CreatePinForm() if request.method == 'POST': form = forms.CreatePinForm(uuid=get_user(request), data=request.POST) if form.is_valid(): if getattr(form, 'buyer_exists', False): try: res = client.change_pin(form.uuid, form.cleaned_data['pin'], etag=form.buyer_etag) except ResourceModified:
from django import forms from django.conf import settings import jwt from django_paranoia.forms import ParanoidForm from mozpay.exc import InvalidJWT from mozpay.verify import verify_jwt from webpay.base.logger import getLogger from webpay.pay.utils import lookup_issuer, UnknownIssuer log = getLogger('w.services') class SigCheckForm(ParanoidForm): sig_check_jwt = forms.CharField() def clean_sig_check_jwt(self): enc_jwt = self.cleaned_data['sig_check_jwt'].encode('ascii', 'ignore') try: jwt_data = jwt.decode(enc_jwt, verify=False) except jwt.DecodeError, exc: log.info('caught sig_check exc: {0.__class__.__name__}: {0}' .format(exc)) raise forms.ValidationError('INVALID_JWT_OR_UNKNOWN_ISSUER') try: secret, active_product = lookup_issuer(jwt_data.get('iss', '')) except UnknownIssuer, exc: log.info('caught sig_check exc: {0.__class__.__name__}: {0}' .format(exc))
import json from curling.lib import API from slumber.exceptions import HttpClientError from lib.solitude.errors import ERROR_STRINGS from solitude.exceptions import ResourceNotModified from webpay.base.logger import getLogger, get_transaction_id log = getLogger('lib.utils') def add_transaction_id(slumber, headers=None, **kwargs): headers['Transaction-Id'] = get_transaction_id() class SlumberWrapper(object): """ A wrapper around the Slumber API. """ def __init__(self, url, oauth): self.slumber = API(url) self.slumber.activate_oauth(oauth.get('key'), oauth.get('secret')) self.slumber._add_callback({'method': add_transaction_id}) self.api = self.slumber.api.v1 def parse_res(self, res): if res == '': return {} if isinstance(res, (str, unicode)):
from django import http from django.core.exceptions import ObjectDoesNotExist from rest_framework import response, serializers, viewsets from lib.solitude.api import client from lib.solitude.constants import PROVIDERS_INVERTED from webpay.base.logger import getLogger from webpay.pay.views import configure_transaction, process_pay_req, simulate from .base import BuyerIsLoggedIn log = getLogger("w.api") class TransactionSerializer(serializers.Serializer): provider = serializers.CharField() pay_url = serializers.CharField() def __init__(self, data): if "provider" in data and data["provider"] in PROVIDERS_INVERTED: data["provider"] = PROVIDERS_INVERTED[data["provider"]] super(TransactionSerializer, self).__init__(data) class PayViewSet(viewsets.ViewSet): permission_classes = (BuyerIsLoggedIn,) def create(self, request): res = process_pay_req(request, data=request.DATA)
import urlparse from django.conf import settings from django.shortcuts import render from django_paranoia.decorators import require_GET from mozpay.verify import InvalidJWT, _get_issuer, verify_sig from webpay.auth.utils import set_user from webpay.base.helpers import fxa_auth_info from webpay.base.logger import getLogger log = getLogger('w.spa') @require_GET def index(request, view_name=None, start_view=None): """Page that serves the static Single Page App (Spartacus).""" ctx = {} ctx['fxa_state'], ctx['fxa_auth_url'] = fxa_auth_info(request) jwt = request.GET.get('req') if jwt: ctx['mkt_user'] = False # If this is a Marketplace-issued JWT, verify its signature and skip login # for the purchaser named in it. if jwt and _get_issuer(jwt) == settings.KEY: try: data = verify_sig(jwt, settings.SECRET, expected_aud=settings.DOMAIN) data = data['request'].get('productData', '') except InvalidJWT, exc:
from django import http from rest_framework import response, viewsets from webpay.api.base import BuyerIsLoggedIn from webpay.base.logger import getLogger from webpay.pay import tasks log = getLogger('w.api') class SimulateViewSet(viewsets.ViewSet): permission_classes = (BuyerIsLoggedIn, ) def create(self, request): if not request.session.get('is_simulation', False): log.info('Request to simulate without a valid session') return http.HttpResponseForbidden() tasks.simulate_notify.delay(request.session['notes']['issuer_key'], request.session['notes']['pay_request']) return response.Response(status=204)
from django.conf import settings from django.core.exceptions import ObjectDoesNotExist from django.utils.decorators import method_decorator from cache_nuggets.lib import memoize from requests.exceptions import ConnectionError from constants import COUNTRIES from ..utils import SlumberWrapper from lib.solitude.constants import PROVIDER_BANGO, PROVIDERS_INVERTED from webpay.base.logger import getLogger log = getLogger("w.marketplace") NUMBER_ATTEMPTS = 5 class UnknownPricePoint(Exception): pass class ConnectionFailed(ConnectionError): pass class MarketplaceAPI(SlumberWrapper): errors = {} @method_decorator(memoize("marketplace:api:get_price"))
import json import sys import traceback import urlparse from django.conf import settings from django.utils.cache import patch_vary_headers from django.utils.translation.trans_real import parse_accept_lang_header import tower from csp.middleware import CSPMiddleware as BaseCSPMiddleware from webpay.base.logger import getLogger from webpay.base.utils import log_cef log = getLogger('w.middleware') class LogJSONerror: """ If the exception has JSON content, log the JSON message. This is intended to catch and log Solitude error messages such as form errors for 400 errors. """ def process_exception(self, request, exception): etype = type(exception) if hasattr(etype, '__name__'): etype = etype.__name__ if hasattr(exception, 'content'): try: log.error('%s: %s: JSON: %s'
from django.shortcuts import render from django.views.decorators.http import require_POST from curling.lib import HttpClientError from django_browserid import get_audience as get_aud_from_request, verify as verify_assertion from django_browserid.forms import BrowserIDForm from session_csrf import anonymous_csrf_exempt from lib.marketplace.api import client as mkt_client from webpay.base.decorators import json_view from webpay.base.logger import getLogger from webpay.pay import tasks as pay_tasks from webpay.pin.utils import check_pin_status from .utils import get_uuid, set_user log = getLogger("w.auth") @require_POST def reset_user(request): """ Reset the logged in Persona user. This is not meant as a full logout. It's meant to compliment navigator.id.logout() so that both Webpay and Persona think the user is logged out. """ if "logged_in_user" in request.session: log.info("Resetting Persona user %s" % request.session["logged_in_user"]) del request.session["logged_in_user"] if "mkt_permissions" in request.session:
from django.core.urlresolvers import reverse from django.http import HttpResponseForbidden, HttpResponseNotFound, HttpResponse from django.shortcuts import render from django_paranoia.decorators import require_GET from lib.solitude.api import client, ProviderHelper from lib.solitude.constants import PROVIDERS_INVERTED, STATUS_COMPLETED from webpay.base import dev_messages as msg from webpay.base.decorators import json_view from webpay.base.helpers import fxa_auth_info from webpay.base.logger import getLogger from webpay.base.utils import log_cef, system_error from webpay.pay import tasks log = getLogger("w.provider") NoticeClasses = {} @require_GET def wait_to_finish(request, provider_name): """ After the payment provider finishes the pay flow, wait for completion. The provider redirects here so the UI can poll Solitude until the transaction is complete. """ helper = ProviderHelper(provider_name) trans_uuid = helper.provider.transaction_from_notice(request.GET) if not trans_uuid: # This could happen if someone is tampering with the URL or if
import json import sys import traceback import urlparse from django.conf import settings from django.utils.cache import patch_vary_headers from django.utils.translation.trans_real import parse_accept_lang_header import tower from csp.middleware import CSPMiddleware as BaseCSPMiddleware from webpay.base.logger import getLogger from webpay.base.utils import log_cef log = getLogger("w.middleware") class LogJSONerror: """ If the exception has JSON content, log the JSON message. This is intended to catch and log Solitude error messages such as form errors for 400 errors. """ def process_exception(self, request, exception): etype = type(exception) if hasattr(etype, "__name__"): etype = etype.__name__ if hasattr(exception, "content"): try:
from django.http import HttpResponse from django.shortcuts import render from django_paranoia.decorators import require_GET from lib.solitude.api import ProviderHelper from webpay.base import dev_messages as msg from webpay.base.logger import getLogger from webpay.base.utils import system_error from webpay.pay import tasks log = getLogger('w.provider') NoticeClasses = {} @require_GET def success(request, provider_name): provider = ProviderHelper(provider_name) if provider.name != 'reference': raise NotImplementedError( 'only the reference provider is implemented so far') try: transaction_id = provider.prepare_notice(request) except msg.DevMessage as m: return system_error(request, code=m.code) tasks.payment_notify.delay(transaction_id) return render(request, 'provider/success.html')
import urlparse from django import http from django.conf import settings from django.shortcuts import render from django_paranoia.decorators import require_GET from mozpay.verify import InvalidJWT, _get_issuer, verify_sig from webpay.auth.utils import set_user from webpay.base.helpers import fxa_auth_info from webpay.base.logger import getLogger log = getLogger('w.spa') @require_GET def index(request, view_name=None): """Page that serves the static Single Page App (Spartacus).""" if not settings.SPA_ENABLE: return http.HttpResponseForbidden() ctx = {} if settings.USE_FXA: ctx['fxa_state'], ctx['fxa_auth_url'] = fxa_auth_info(request) jwt = request.GET.get('req') # If this is a Marketplace-issued JWT, verify its signature and skip login # for the purchaser named in it. if jwt and _get_issuer(jwt) == settings.KEY: try: data = verify_sig(jwt, settings.SECRET) data = data['request'].get('productData', '') except InvalidJWT: pass else:
import base64 from webpay.base.logger import getLogger log = getLogger('w.bango') class NoHeader(Exception): pass class WrongHeader(Exception): pass def basic(request): header = request.META.get('HTTP_AUTHORIZATION', '') if not header: log.info('No Authorization header') raise NoHeader try: auth_type, data = header.split() except ValueError: log.info("Invalid header, can't split: {0}".format(header)) raise WrongHeader if auth_type.lower() != 'basic': log.info('Authorization type {0} not supported'.format(auth_type)) raise WrongHeader
from django.views.decorators.http import require_POST from django.utils import translation from curling.lib import HttpClientError, HttpServerError from rest_framework import viewsets from lib.marketplace.api import client as marketplace from lib.solitude.api import client as solitude from webpay.base.decorators import json_view from webpay.base.dev_messages import legend from webpay.base.logger import getLogger from webpay.base.utils import log_cef_meta from .forms import ErrorLegendForm, SigCheckForm log = getLogger('z.services') def monitor(request): content = {} all_good = True # Check that we can talk to the marketplace. msg = 'ok' try: perms = marketplace.api.account.permissions.mine.get() except (HttpServerError, HttpClientError), err: all_good = False msg = ('Server error: status {0}, content: {1}'.format( err.response.status_code, err.response.content or 'empty') if err.response else 'Server error: no response')
from webpay.base.decorators import json_view from webpay.base.logger import getLogger from webpay.base.utils import app_error, custom_error, system_error from webpay.pin.forms import VerifyPinForm from webpay.pin.utils import check_pin_status from lib.marketplace.api import client as marketplace, UnknownPricePoint from lib.solitude import constants from lib.solitude.api import client as solitude from lib.solitude.exceptions import ResourceModified from . import tasks from .forms import VerifyForm from .utils import clear_messages, trans_id, verify_urls log = getLogger('w.pay') def process_pay_req(request, data=None): data = request.GET if data is None else data form = VerifyForm(data) if not form.is_valid(): codes = [] for erlist in form.errors.values(): codes.extend(erlist) if len(codes) > 1: # This will probably break something, like maybe paymentFailed(). log.error('multiple error codes: {codes}'.format(codes=codes)) codes = ', '.join(codes) return app_error(request, code=codes)
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_POST from django.utils import translation from curling.lib import HttpClientError, HttpServerError from lib.marketplace.api import client as marketplace from lib.solitude.api import client as solitude from webpay.base.decorators import json_view from webpay.base.dev_messages import legend from webpay.base.logger import getLogger from webpay.base.utils import log_cef_meta from .forms import ErrorLegendForm, SigCheckForm log = getLogger('z.services') def monitor(request): content = {} all_good = True # Check that we can talk to the marketplace. msg = 'ok' try: perms = marketplace.api.account.permissions.mine.get() except (HttpServerError, HttpClientError), err: all_good = False msg = ('Server error: status %s, content: %s' % (err.response.status_code, err.response.content or 'empty')) else:
import functools from django import http from django.conf import settings from django.core.exceptions import PermissionDenied from django.core.urlresolvers import reverse from webpay.base.logger import getLogger from webpay.base.utils import log_cef log = getLogger('w.auth') flow = { 'standard': ['create', 'confirm', 'verify', 'reset_start'], 'locked': ['is_locked', 'was_locked'], 'reset': ['reset_new_pin', 'reset_confirm', 'reset_cancel'], } def log_redirect(request, step, dest): msg = 'Buyer was attempting %s redirecting to: %s' % (step, dest) log.info('enforce_sequence: %s' % msg) log_cef(msg, request, severity=7) def user_verified(f): @functools.wraps(f) def wrapper(request, *args, **kw): if not request.session.get('uuid'): log_cef('No UUID in session, not verified', request, severity=7) raise PermissionDenied
from django.conf import settings from django.http import HttpResponse, HttpResponseForbidden from django.shortcuts import render from django.views.decorators.csrf import csrf_exempt from django_paranoia.decorators import require_GET, require_POST from slumber.exceptions import HttpClientError from tower import ugettext as _ from lib.solitude.api import client from webpay.bango.auth import basic, NoHeader, WrongHeader from webpay.base.logger import getLogger from webpay.base.utils import _error from webpay.pay import tasks log = getLogger("w.bango") class HttpResponseNotAuthenticated(HttpResponse): status_code = 401 def __init__(self, *args): super(HttpResponseNotAuthenticated, self).__init__(*args) self["WWW-Authenticate"] = 'Basic realm="{0}"'.format(settings.DOMAIN) def _record(request): """ Records the request into solitude. If something went wrong it will return False. """
import hashlib import hmac import re from django.conf import settings from django.core.exceptions import PermissionDenied from lib.solitude.api import client from webpay.base.logger import getLogger log = getLogger('w.auth') def check_whitelist(email): whitelist = settings.USER_WHITELIST if not whitelist: return True for email_re in whitelist: if re.match(email_re, email): return True return False def get_uuid(email): """ Given an email returns an email token for this site. This will be consistent for each email for this site and can be used as the uuid in solitude. The email is protected by HMAC for privacy purposes.
import json from curling.lib import API from slumber.exceptions import HttpClientError from solitude.exceptions import ResourceModified, ResourceNotModified from webpay.base.logger import getLogger, get_transaction_id log = getLogger('lib.utils') def add_transaction_id(slumber, headers=None, **kwargs): headers['Transaction-Id'] = get_transaction_id() class SlumberWrapper(object): """ A wrapper around the Slumber API. """ def __init__(self, url, oauth): self.slumber = API(url) self.slumber.activate_oauth(oauth.get('key'), oauth.get('secret')) self.slumber._add_callback({'method': add_transaction_id}) self.api = self.slumber.api.v1 def parse_res(self, res): if res == '': return {} if isinstance(res, (str, unicode)): try: return json.loads(res)
from django.views.decorators.debug import sensitive_post_parameters from tower import ugettext as _ from lib.solitude.api import client from lib.solitude.exceptions import ResourceModified from webpay.auth.decorators import enforce_sequence, user_verified from webpay.auth.utils import (get_user, set_user_has_confirmed_pin, set_user_has_pin) from webpay.base import dev_messages as msg from webpay.base.logger import getLogger from webpay.base.utils import system_error from webpay.pay import get_payment_url from . import forms log = getLogger('w.pin') @enforce_sequence @sensitive_post_parameters('pin') def create(request): form = forms.CreatePinForm() if request.method == 'POST': form = forms.CreatePinForm(uuid=get_user(request), data=request.POST) if form.is_valid(): if getattr(form, 'buyer_exists', False): try: res = client.change_pin(form.uuid, form.cleaned_data['pin'], etag=form.buyer_etag) except ResourceModified:
from django.core.urlresolvers import reverse from django.http import (HttpResponseForbidden, HttpResponseNotFound, HttpResponse) from django.shortcuts import render from django_paranoia.decorators import require_GET from lib.solitude.api import client, ProviderHelper from lib.solitude.constants import PROVIDERS_INVERTED, STATUS_COMPLETED from webpay.base import dev_messages as msg from webpay.base.decorators import json_view from webpay.base.logger import getLogger from webpay.base.utils import log_cef, system_error from webpay.pay import tasks log = getLogger('w.provider') NoticeClasses = {} @require_GET def wait_to_finish(request, provider_name): """ After the payment provider finishes the pay flow, wait for completion. The provider redirects here so the UI can poll Solitude until the transaction is complete. """ helper = ProviderHelper(provider_name) trans_uuid = helper.provider.transaction_from_notice(request.GET) if not trans_uuid: # This could happen if someone is tampering with the URL or if
from django.conf import settings from django.http import HttpResponse, HttpResponseForbidden from django.shortcuts import render from django.views.decorators.csrf import csrf_exempt from django_paranoia.decorators import require_GET, require_POST from slumber.exceptions import HttpClientError from lib.solitude.api import client from webpay.bango.auth import basic, NoHeader, WrongHeader from webpay.base import dev_messages as msg from webpay.base.logger import getLogger from webpay.base.utils import system_error from webpay.pay import tasks log = getLogger('w.bango') RECORDED_OK = 'RECORDED_OK' class HttpResponseNotAuthenticated(HttpResponse): status_code = 401 def __init__(self, *args): super(HttpResponseNotAuthenticated, self).__init__(*args) self['WWW-Authenticate'] = 'Basic realm="{0}"'.format(settings.DOMAIN) def _record(request): """ Records the request into solitude.
import json from curling.lib import API from slumber.exceptions import HttpClientError from solitude.exceptions import ResourceModified, ResourceNotModified from webpay.base.logger import getLogger, get_transaction_id log = getLogger("lib.utils") def add_transaction_id(slumber, headers=None, **kwargs): headers["Transaction-Id"] = get_transaction_id() class SlumberWrapper(object): """ A wrapper around the Slumber API. """ def __init__(self, url, oauth): self.slumber = API(url) self.slumber.activate_oauth(oauth.get("key"), oauth.get("secret")) self.slumber._add_callback({"method": add_transaction_id}) self.api = self.slumber.api.v1 def parse_res(self, res): if res == "": return {} if isinstance(res, (str, unicode)): return json.loads(res)