README.md updated and reorganized, Improved error handling for configparser and ldap manager, requirements.txt added

This commit is contained in:
ahmadbilalkhalid 2020-02-19 11:59:54 +05:00
parent 347843cb24
commit e37592bdc6
9 changed files with 72 additions and 31 deletions

1
.gitignore vendored
View file

@ -4,4 +4,3 @@ __pycache__/
pay.conf pay.conf
log.txt log.txt
test.py

View file

@ -16,7 +16,7 @@ Currently handles very basic features, such as:
#### 1. Adding of products #### 1. Adding of products
```shell script ```shell script
http --json http://[::]:5000/product/add email=your_email_here password=your_password_here specs:=@ipv6-only-vm.json http --json http://[::]:5000/product/add username=your_username_here password=your_password_here specs:=@ipv6-only-vm.json
``` ```
#### 2. Listing of products #### 2. Listing of products
@ -24,20 +24,26 @@ http --json http://[::]:5000/product/add email=your_email_here password=your_pas
http --json http://[::]:5000/product/list http --json http://[::]:5000/product/list
``` ```
#### 3. Ordering products #### 3. Registering user's payment method (credit card for now using Stripe)
```shell script
http --json http://[::]:5000/product/order email=your_email_here password=your_password_here product_id=5332cb89453d495381e2b2167f32c842 cpu=1 ram=1gb os-disk-space=10gb os=alpine
```
#### 4. Listing users orders
```shell script ```shell script
http --json GET http://[::]:5000/order/list email=your_email_here password=your_password_here http --json http://[::]:5000/user/register_payment card_number=4111111111111111 cvc=123 expiry_year=2020 expiry_month=8 card_holder_name="The test user" username=your_username_here password=your_password_here line1="your_billing_address" city="your_city" country="your_country"
``` ```
#### 4. Ordering products
#### 5. Registering user's payment method (credit card for now using Stripe) First of all, user have to buy the membership first.
```shell script ```shell script
http --json http://[::]:5000/user/register_payment card_number=4111111111111111 cvc=123 expiry_year=2020 expiry_month=8 card_holder_name="The test user" email=your_email_here password=your_password_here http --json http://[::]:5000/product/order username=your_username_here password=your_password_here product_id=membership pay=True
```
```shell script
http --json http://[::]:5000/product/order username=your_username_here password=your_password_here product_id=ipv6-only-vm cpu=1 ram=1 os-disk-space=10 os=alpine pay=True
```
#### 5. Listing users orders
```shell script
http --json POST http://[::]:5000/order/list username=your_username_here password=your_password_here
``` ```

View file

@ -1,11 +1,28 @@
import configparser import configparser
import sys
import os
from etcd_wrapper import EtcdWrapper from etcd_wrapper import EtcdWrapper
from ldap_manager import LdapManager from ldap_manager import LdapManager
config_file = os.environ.get('meow-pay-config-file', default='pay.conf')
config = configparser.ConfigParser() config = configparser.ConfigParser()
config.read('pay.conf')
etcd_client = EtcdWrapper(host=config['etcd']['host'], port=config['etcd']['port']) try:
successfully_read_files = config.read(config_file)
except configparser.Error as err:
sys.exit(err)
ldap_manager = LdapManager(server=config['ldap']['server'], admin_dn=config['ldap']['admin_dn'], if not successfully_read_files:
admin_password=config['ldap']['admin_password']) sys.exit(f'Config file {config_file} couldn\'t be read.')
try:
etcd_client = EtcdWrapper(host=config.get('etcd', 'host'), port=config.get('etcd', 'port'))
ldap_manager = LdapManager(
server=config.get('ldap', 'server'), admin_dn=config.get('ldap', 'admin_dn'),
admin_password=config.get('ldap', 'admin_password')
)
except configparser.Error as err:
sys.exit(f'{err} in config file {config_file}.')

View file

@ -1,14 +1,22 @@
import hashlib import hashlib
import random import random
import base64 import base64
import sys
from ldap3 import Server, Connection, ObjectDef, Reader, ALL from ldap3 import Server, Connection, ObjectDef, Reader, ALL
from ldap3.core import exceptions
SALT_BYTES = 15
class LdapManager: class LdapManager:
def __init__(self, server, admin_dn, admin_password): def __init__(self, server, admin_dn, admin_password):
self.server = Server(server, get_info=ALL) self.server = Server(server, get_info=ALL)
try:
self.conn = Connection(server, admin_dn, admin_password, auto_bind=True) self.conn = Connection(server, admin_dn, admin_password, auto_bind=True)
except exceptions.LDAPException as err:
sys.exit(f'LDAP Error: {err}')
self.person_obj_def = ObjectDef('inetOrgPerson', self.conn) self.person_obj_def = ObjectDef('inetOrgPerson', self.conn)
def get(self, query=None, search_base='dc=ungleich,dc=ch'): def get(self, query=None, search_base='dc=ungleich,dc=ch'):
@ -57,7 +65,6 @@ class LdapManager:
which can be used as LDAP value, e.g. after armoring it once more using which can be used as LDAP value, e.g. after armoring it once more using
base64 or decoding it to unicode from ``ascii``. base64 or decoding it to unicode from ``ascii``.
""" """
SALT_BYTES = 15
sha1 = hashlib.sha1() sha1 = hashlib.sha1()
salt = random.SystemRandom().getrandbits(SALT_BYTES * 8).to_bytes(SALT_BYTES, 'little') salt = random.SystemRandom().getrandbits(SALT_BYTES * 8).to_bytes(SALT_BYTES, 'little')

4
requirements.txt Normal file
View file

@ -0,0 +1,4 @@
ldap3
etcd3
stripe
flask

View file

@ -12,8 +12,3 @@ port = 5000
server = ldap_server_url server = ldap_server_url
admin_dn = ldap_admin_dn admin_dn = ldap_admin_dn
admin_password = ldap_admin_password admin_password = ldap_admin_password
customer_dn = ldap_customer_dn
user_dn = ldap_user_dn
internal_user_ou = users
customer_ou = customer

View file

@ -3,11 +3,9 @@ import config
import json import json
import math import math
from config import ldap_manager from config import ldap_manager, etcd_client
from helper import resolve_product from helper import resolve_product
etcd_client = config.etcd_client
class ValidationException(Exception): class ValidationException(Exception):
"""Validation Error""" """Validation Error"""
@ -105,7 +103,7 @@ class AddProductSchema(BaseSchema):
user = self.objects['user'] user = self.objects['user']
user = json.loads(user.entry_to_json()) user = json.loads(user.entry_to_json())
uid, ou, *dc = user['dn'].replace('ou=', '').replace('dc=', '').replace('uid=', '').split(',') uid, ou, *dc = user['dn'].replace('ou=', '').replace('dc=', '').replace('uid=', '').split(',')
if ou != config.config['ldap']['internal_user_ou']: if ou != config.config.get('ldap', 'internal_user_ou', fallback='users'):
raise ValidationException('You do not have access to create product.') raise ValidationException('You do not have access to create product.')
product = resolve_product(self.specs.value['usable-id'], etcd_client) product = resolve_product(self.specs.value['usable-id'], etcd_client)

View file

@ -1,12 +1,16 @@
import json
import re import re
import stripe import stripe
import stripe.error import stripe.error
import logging import logging
import sys
from config import etcd_client as client, config as config from configparser import Error as ConfigParserError
from config import etcd_client as client, config as config, config_file
stripe.api_key = config['stripe']['private_key'] try:
stripe.api_key = config.get('stripe', 'private_key')
except ConfigParserError as err:
sys.exit(f'{err} in config file {config_file}')
def handle_stripe_error(f): def handle_stripe_error(f):
@ -291,7 +295,7 @@ class StripeUtils(object):
returns the new object. returns the new object.
:param amount: The amount in CHF cents :param amount: The amount in CHF cents
:param name: The name of the Stripe plan to be created. :param product_name: The name of the Stripe plan (product) to be created.
:param stripe_plan_id: The id of the Stripe plan to be :param stripe_plan_id: The id of the Stripe plan to be
created. Use get_stripe_plan_id_string function to created. Use get_stripe_plan_id_string function to
obtain the name of the plan to be created obtain the name of the plan to be created

View file

@ -5,7 +5,7 @@ from uuid import uuid4
from flask import Flask, request from flask import Flask, request
from flask_restful import Resource, Api from flask_restful import Resource, Api
from werkzeug.exceptions import HTTPException
from config import etcd_client as client, config as config from config import etcd_client as client, config as config
from stripe_utils import StripeUtils from stripe_utils import StripeUtils
from schemas import ( from schemas import (
@ -322,4 +322,15 @@ if __name__ == '__main__':
api.add_resource(UserRegisterPayment, '/user/register_payment') api.add_resource(UserRegisterPayment, '/user/register_payment')
api.add_resource(OrderList, '/order/list') api.add_resource(OrderList, '/order/list')
app.run(host='::', port=config['app']['port'], debug=True) app.run(host='::', port=config.get('app', 'port', fallback=5000), debug=True)
@app.errorhandler(Exception)
def handle_exception(e):
app.logger.error(e)
# pass through HTTP errors
if isinstance(e, HTTPException):
return e
# now you're handling non-HTTP exceptions only
return {'message': 'Server Error'}, 500