README.md updated and reorganized, Improved error handling for configparser and ldap manager, requirements.txt added
This commit is contained in:
parent
347843cb24
commit
e37592bdc6
9 changed files with 72 additions and 31 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -3,5 +3,4 @@
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
|
||||||
pay.conf
|
pay.conf
|
||||||
log.txt
|
log.txt
|
||||||
test.py
|
|
22
README.md
22
README.md
|
@ -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
|
```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
|
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. Listing users orders
|
#### 4. Ordering products
|
||||||
|
|
||||||
|
First of all, user have to buy the membership first.
|
||||||
|
|
||||||
```shell script
|
```shell script
|
||||||
http --json GET http://[::]:5000/order/list 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. Registering user's payment method (credit card for now using Stripe)
|
#### 5. Listing users orders
|
||||||
|
|
||||||
```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 POST http://[::]:5000/order/list username=your_username_here password=your_password_here
|
||||||
```
|
```
|
||||||
|
|
25
config.py
25
config.py
|
@ -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}.')
|
||||||
|
|
|
@ -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)
|
||||||
self.conn = Connection(server, admin_dn, admin_password, auto_bind=True)
|
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)
|
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
4
requirements.txt
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
ldap3
|
||||||
|
etcd3
|
||||||
|
stripe
|
||||||
|
flask
|
|
@ -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
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue