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
log.txt
test.py

View file

@ -16,7 +16,7 @@ Currently handles very basic features, such as:
#### 1. Adding of products
```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
@ -24,20 +24,26 @@ http --json http://[::]:5000/product/add email=your_email_here password=your_pas
http --json http://[::]:5000/product/list
```
#### 3. Ordering products
```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
#### 3. Registering user's payment method (credit card for now using Stripe)
```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
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 sys
import os
from etcd_wrapper import EtcdWrapper
from ldap_manager import LdapManager
config_file = os.environ.get('meow-pay-config-file', default='pay.conf')
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'],
admin_password=config['ldap']['admin_password'])
if not successfully_read_files:
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 random
import base64
import sys
from ldap3 import Server, Connection, ObjectDef, Reader, ALL
from ldap3.core import exceptions
SALT_BYTES = 15
class LdapManager:
def __init__(self, server, admin_dn, admin_password):
self.server = Server(server, get_info=ALL)
try:
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)
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
base64 or decoding it to unicode from ``ascii``.
"""
SALT_BYTES = 15
sha1 = hashlib.sha1()
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
admin_dn = ldap_admin_dn
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 math
from config import ldap_manager
from config import ldap_manager, etcd_client
from helper import resolve_product
etcd_client = config.etcd_client
class ValidationException(Exception):
"""Validation Error"""
@ -105,7 +103,7 @@ class AddProductSchema(BaseSchema):
user = self.objects['user']
user = json.loads(user.entry_to_json())
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.')
product = resolve_product(self.specs.value['usable-id'], etcd_client)

View file

@ -1,12 +1,16 @@
import json
import re
import stripe
import stripe.error
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):
@ -291,7 +295,7 @@ class StripeUtils(object):
returns the new object.
: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
created. Use get_stripe_plan_id_string function to
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_restful import Resource, Api
from werkzeug.exceptions import HTTPException
from config import etcd_client as client, config as config
from stripe_utils import StripeUtils
from schemas import (
@ -322,4 +322,15 @@ if __name__ == '__main__':
api.add_resource(UserRegisterPayment, '/user/register_payment')
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