forked from uncloud/uncloud
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__/
|
||||
|
||||
pay.conf
|
||||
log.txt
|
||||
test.py
|
||||
log.txt
|
22
README.md
22
README.md
|
@ -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
|
||||
#### 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
|
||||
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
|
||||
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
|
||||
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 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}.')
|
||||
|
|
|
@ -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)
|
||||
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)
|
||||
|
||||
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
4
requirements.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
ldap3
|
||||
etcd3
|
||||
stripe
|
||||
flask
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue