__init__.py 2.11 KB
import os
from base64 import b64decode
from pyramid.config import Configurator
from pyramid.authentication import IAuthenticationPolicy
from pyramid.authorization import ACLAuthorizationPolicy
from zope.interface import implementer
from winpay.encrypt import verify_without_salt
from winpay.signature import create_data


def create_sign_data(request):
    return create_data(
            request.json_body, request.headers.get('X-Timestamp'),
            request.method, request.path)


@implementer(IAuthenticationPolicy)
class AuthenticationPolicy:
    def authenticated_userid(self, request):
        partner_id = request.headers.get('X-Partner-Id')
        settings = request.registry.settings
        if partner_id not in settings['public_keys']:
            return None
        user_id, public_key = settings['public_keys'][partner_id]
        signature_b64 = request.headers.get('X-Signature')
        signature_b64 = signature_b64.encode('utf-8')
        signature = b64decode(signature_b64)
        sign_data = create_sign_data(request)
        verify_without_salt(public_key, signature, sign_data)
        return user_id


# Di production public key disimpan di database
def user_public_keys(settings):
    base_dir, _ = os.path.split(settings['config_file'])
    d = {}
    for user in settings['users'].strip().splitlines():
        user_id, partner_id, public_file = user.split(',')
        if not os.path.exists(public_file):
            public_file = os.path.join(base_dir, public_file)
        with open(public_file, 'rb') as f:
            public_bytes = f.read()
        d[partner_id] = (user_id, public_bytes)
    return d


def main(global_config, **settings):
    settings['config_file'] = global_config['__file__']
    settings['public_keys'] = user_public_keys(settings)
    with Configurator(settings=settings) as config:
        authn_policy = AuthenticationPolicy()
        authz_policy = ACLAuthorizationPolicy()
        config.set_authentication_policy(authn_policy)
        config.set_authorization_policy(authz_policy)
        config.include('pyramid_snap')
        config.scan('.views')
        return config.make_wsgi_app()