minor bug fixes

legacy
Steve Nyemba 3 years ago
parent 9438144772
commit 255e9ede59

@ -1,13 +1,13 @@
""" """
Steve L. Nyemba <steve@the-phi.com> Steve L. Nyemba <steve@the-phi.com>
The Phi Technology, LLC - Store The Phi Technology, LLC - Store
This file handles customer & plans associated with a given product/app This file handles customer & plans associated with a given product/app
We understand that a product will have multiple plans under it and we make sure that we always have a free version: We understand that a product will have multiple plans under it and we make sure that we always have a free version:
- Having a free product insures there is no excuse not to signup users - Having a free product insures there is no excuse not to signup users
- If a product doesn't fall under this model we will find a way to fix it. - If a product doesn't fall under this model we will find a way to fix it.
- -
The store must be prefixed with an authentication module, because customers must be signed in before making a purchase. The store must be prefixed with an authentication module, because customers must be signed in before making a purchase.
""" """
from __future__ import division from __future__ import division
from flask import Flask, request, session, render_template, Response,redirect from flask import Flask, request, session, render_template, Response,redirect
@ -15,7 +15,7 @@ from flask_session import Session
from flask_cors import CORS from flask_cors import CORS
from flask_pymongo import PyMongo from flask_pymongo import PyMongo
from flask_mongo_sessions import MongoDBSessionInterface from flask_mongo_sessions import MongoDBSessionInterface
import transport
import stripe import stripe
import json import json
# from StringIO import StringIO # from StringIO import StringIO
@ -46,419 +46,423 @@ stripe.api_key = stripe_keys['secret_key'].strip()
if 'CLOUDVIEW_CONTEXT' in os.environ and os.environ['CLOUDVIEW_CONTEXT'] not in CONFIG['cloud-view']: if 'CLOUDVIEW_CONTEXT' in os.environ and os.environ['CLOUDVIEW_CONTEXT'] not in CONFIG['cloud-view']:
context = os.environ['CLOUDVIEW_CONTEXT'] context = os.environ['CLOUDVIEW_CONTEXT']
CONFIG['cloud-view'] = CONFIG['cloud-view'].replace('cloud-view',context) CONFIG['cloud-view'] = CONFIG['cloud-view'].replace('cloud-view',context)
app = Flask(__name__) app = Flask(__name__)
CORS(app) CORS(app)
SYS_STORE = CONFIG['store'] SYS_STORE = CONFIG['store']
LOGGER = transport.factory.instance(**SYS_STORE['logger'])
# @app.route("/donate") # @app.route("/donate")
# def _donate() : # def _donate() :
# amount = float(request.args['amount']) if 'amount' in request.args else 5.0 # amount = float(request.args['amount']) if 'amount' in request.args else 5.0
# args = {'amount':amount,'context':CONTEXT} # args = {'amount':amount,'context':CONTEXT}
# return render_template('donate.html',**args) # return render_template('donate.html',**args)
def get_id(id):
return CONFIG['default']['id'] if not id else id
@app.route("/") @app.route("/")
def index(): def index():
if 'default' in CONFIG: if 'default' in CONFIG:
id = CONFIG['default']['id'] id = CONFIG['default']['id']
return get_plans_ui(id) return get_plans_ui(id)
headers = {"content-type":"application/json"}
mystore = store.factory.instance(name='music') headers = {"content-type":"application/json"}
products = mystore.get.products() mystore = store.factory.instance(name='music')
args = {"context":CONTEXT,"products":products} products = mystore.get.products()
return json.dumps(products),headers args = {"context":CONTEXT,"products":products}
return json.dumps(products),headers
# return render_template("index.html",**args)
# return render_template("index.html",**args)
@app.route("/json/<id>") @app.route("/json/<id>")
def get_plans_json(id): def get_plans_json(id):
""" """
This function returns the plans for a given product This function returns the plans for a given product
""" """
HEADER={"Content-type":"application/json"} HEADER={"Content-type":"application/json"}
try: try:
mystore = store.factory.instance(name=id) mystore = store.factory.instance(name=id)
return json.dumps(mystore.get.plans()),HEADER return json.dumps(mystore.get.plans()),HEADER
except Exception as e: except Exception as e:
# #
# Log this shit or not # Log this shit or not
pass pass
return "[]",HEADER return "[]",HEADER
@app.route("/store",methods=['POST','PUT']) @app.route("/store",methods=['POST','PUT'])
def to_session(): def to_session():
""" """
This function will store/persist session variables for reuse This function will store/persist session variables for reuse
""" """
info = request.json info = request.json
if info : if info :
for key in info : for key in info :
session[key] = info[key] session[key] = info[key]
return "{}",200 return "{}",200
@app.route("/signup",methods=['GET','POST']) @app.route("/signup",methods=['GET','POST'])
def signup(): def signup():
""" """
This function will signup a user to a plan or upgrade them if necessary This function will signup a user to a plan or upgrade them if necessary
The assumption here is one product - one plan The assumption here is one product - one plan
:request.form stripeToken (optional) :request.form stripeToken (optional)
""" """
if request.method == 'GET' : if request.method == 'GET' :
if 'auth' not in session : if 'auth' not in session :
return "0",403 return "0",403
_object = {"data-key":CONFIG['stripe']['pub'].strip()} _object = {"data-key":CONFIG['stripe']['pub'].strip()}
return json.dumps(_object),{"Content-Type":"application/json"} return json.dumps(_object),{"Content-Type":"application/json"}
else: else:
# #
# We are receiving a call from stripe framework and we need create a charge for this # We are receiving a call from stripe framework and we need create a charge for this
# @NOTE: https://stripe.com/docs/payments/accept-a-payment-charges#web-create-charge # @NOTE: https://stripe.com/docs/payments/accept-a-payment-charges#web-create-charge
token = request.form['stripeToken'] if 'stripeToken' in request.form else None token = request.form['stripeToken'] if 'stripeToken' in request.form else None
email = session['auth']['user']['uid'] email = session['auth']['user']['uid']
plan_id = session['plan']['id'] plan_id = session['plan']['id']
id = session['product']['name'] id = session['product']['name']
mystore = store.factory.instance(name=id,email=email) mystore = store.factory.instance(name=id,email=email)
user = mystore.user user = mystore.user
plans = user.plan.info() plans = user.plan.info()
plans = [plans] if isinstance(plans,dict) else plans plans = [plans] if isinstance(plans,dict) else plans
has_plan = [1 for item in plans if item['id'] == plan_id] has_plan = [1 for item in plans if item['id'] == plan_id]
if np.sum(has_plan) == 0 and len(plans) == 0: if np.sum(has_plan) == 0 and len(plans) == 0:
mystore.subscribe(id=plan_id,email=email) mystore.subscribe(id=plan_id,email=email)
elif np.sum(has_plan)==0 and len(plans) > 0: elif np.sum(has_plan)==0 and len(plans) > 0:
# #
# We should upgrade/downgrade the current plan # We should upgrade/downgrade the current plan
# #
mystore.plan.upgrade(plan_id,email) mystore.plan.upgrade(plan_id,email)
uri = session['product']['metadata']['uri'] if 'uri' in session['product']['metadata'] else '#status' uri = session['product']['metadata']['uri'] if 'uri' in session['product']['metadata'] else '#status'
# #
# @NOTE: # @NOTE:
# This function assumes one product one plan, operations outside of this scope will require a new function # This function assumes one product one plan, operations outside of this scope will require a new function
return """ return """
<script> <script>
window.location = ':uri' window.location = ':uri'
</script> </script>
""".replace(":uri",uri) """.replace(":uri",uri)
# @app.route("/ui/signup/<id>",methods=['GET','PUT']) # @app.route("/ui/signup/<id>",methods=['GET','PUT'])
@app.route("/<id>/signup",methods=['GET','PUT']) @app.route("/<id>/signup",methods=['GET','PUT'])
def signup_form(id): def signup_form(id):
""" """
This function loads the signup form with cloud-view authentication support This function loads the signup form with cloud-view authentication support
This allows us to know who is signing up or upgrading their plan This allows us to know who is signing up or upgrading their plan
""" """
mystore = store.factory.instance(name=id) mystore = store.factory.instance(name=id)
plans = mystore.get.plans() plans = mystore.get.plans()
index = int(request.args['index']) index = int(request.args['index'])
plan = plans[index] plan = plans[index]
args = {"product":id,"label":mystore.product['statement_descriptor'],"plan":plan,"context":CONTEXT,"now":datetime.now().year} args = {"product":id,"label":mystore.product['statement_descriptor'],"plan":plan,"context":CONTEXT,"now":datetime.now().year}
args['theme'] = 'theme-clouds' args['theme'] = 'theme-clouds'
args['cloud-view'] = CONFIG['cloud-view'] args['cloud-view'] = CONFIG['cloud-view']
return render_template("signup.html",**args) return render_template("signup.html",**args)
@app.route("/me") @app.route("/me")
def me (): def me ():
# #
#{'user': {'uid': 'nyemba@gmail.com', 'uii': 'Steve Nyemba', 'usage': {'used': 1.012175691, 'size': 4.02653184, 'units': 'GB'}, 'sid': 'dropbox'}, 'key': 'nsfCKKUWunUAAAAAAAAAAUMzU6oR6qp9TK7t-_zop-sBOcEaM3eb1mRi_PG8bM69', 'features': {}} #{'user': {'uid': 'nyemba@gmail.com', 'uii': 'Steve Nyemba', 'usage': {'used': 1.012175691, 'size': 4.02653184, 'units': 'GB'}, 'sid': 'dropbox'}, 'key': 'nsfCKKUWunUAAAAAAAAAAUMzU6oR6qp9TK7t-_zop-sBOcEaM3eb1mRi_PG8bM69', 'features': {}}
# mystore = store.factory.instance(name = session['product']['name']) # mystore = store.factory.instance(name = session['product']['name'])
# mystore.init(email=session['auth']['user']['uid']) # mystore.init(email=session['auth']['user']['uid'])
try: try:
if 'auth' in session and 'product' in session : if 'auth' in session and 'product' in session :
email = session['auth']['user']['uid'] email = session['auth']['user']['uid']
name = session['product']['name'] name = session['product']['name']
mystore = store.factory.instance(name=name,email=email) mystore = store.factory.instance(name=name,email=email)
payments = mystore.user.invoices() payments = mystore.user.invoices()
cards = mystore.user.card.html() if mystore.user.card.exists() else None cards = mystore.user.card.html() if mystore.user.card.exists() else None
_args = {'context':CONTEXT,"user":session['auth']['user'],"product":session['product'],"plan":session['plan'],"payments":payments,"cards":cards} _args = {'context':CONTEXT,"user":session['auth']['user'],"product":session['product'],"plan":session['plan'],"payments":payments,"cards":cards}
return render_template('me.html',**_args) return render_template('me.html',**_args)
except Exception as e: except Exception as e:
print (e) print (e)
pass pass
return render_template("none.html",context=CONTEXT) return render_template("none.html",context=CONTEXT)
# return redirect("http://healthcareio.the-phi.com") # return redirect("http://healthcareio.the-phi.com")
@app.route("/me/card",methods=['POST']) @app.route("/me/card",methods=['POST'])
def me_card (): def me_card ():
if 'auth' in session : if 'auth' in session :
email = session['auth']['user']['uid'] email = session['auth']['user']['uid']
name = session['product']['name'] name = session['product']['name']
mystore = store.factory.instance(name=name,email = email) mystore = store.factory.instance(name=name,email = email)
body = request.json body = request.json
try: try:
mystore.user.card.add(card=body) mystore.user.card.add(card=body)
except Exception as e: except Exception as e:
print (e) print (e)
return "0",200 return "0",200
return "1",200 return "1",200
# pricing = mystore.get.checkout() #-- pricing # pricing = mystore.get.checkout() #-- pricing
# pricing = [{"unit_amount":500,"currency":"usd"},{"unit_amount":1000,"currency":"usd"},{"unit_amount":2500,"currency":"usd"}] # pricing = [{"unit_amount":500,"currency":"usd"},{"unit_amount":1000,"currency":"usd"},{"unit_amount":2500,"currency":"usd"}]
# args = {"product":session['product']} # args = {"product":session['product']}
else: else:
return "0",403 return "0",403
return render_template("card.html") return render_template("card.html")
@app.route("/<id>/cancel",methods=['POST']) @app.route("/<id>/cancel",methods=['POST'])
def cancel(id): def cancel(id):
# #
# This function will cancel the user's current plan # This function will cancel the user's current plan
STATUS = "1" STATUS = "1"
try: try:
if 'auth' in session : if 'auth' in session :
email = session['auth']['user']['uid'] email = session['auth']['user']['uid']
mystore = store.factory.instance(name=id,email=email) mystore = store.factory.instance(name=id,email=email)
_id = mystore.user.plan.sub_id() _id = mystore.user.plan.sub_id()
mystore.cancel(_id) mystore.cancel(_id)
session['plan'] = None session['plan'] = None
session['payments'] = mystore.user.invoices() session['payments'] = mystore.user.invoices()
else: else:
STATUS = "0" STATUS = "0"
except Exception as e: except Exception as e:
print (e) print (e)
STATUS = "0" STATUS = "0"
pass pass
return STATUS,200 return STATUS,200
# @app.route("/ui/<id>") # @app.route("/ui/<id>")
@app.route("/<id>/plans") @app.route("/<id>/plans")
def get_plans_ui(id): def get_plans_ui(id):
""" """
This function loads the form for signup and information about the various plans for a given product. This function loads the form for signup and information about the various plans for a given product.
:id name of the products :id name of the products
""" """
mystore = store.factory.instance(name=id) id = get_id(id) #-- will return default if need be
# mystore = store.factory.instance(name=id)
# sort plans by #
# sort plans by
description = mystore.product['metadata']['about'] if 'about' in mystore.product['metadata'] else ''
label = mystore.product['statement_descriptor'] description = mystore.product['metadata']['about'] if 'about' in mystore.product['metadata'] else ''
args = {"product":id,"label":label,"description":description,"context":CONTEXT,"plans":mystore.get.plans(),"now":datetime.now().year} label = mystore.product['statement_descriptor']
args['product'] = mystore.product args = {"product":id,"label":label,"description":description,"context":CONTEXT,"plans":mystore.get.plans(),"now":datetime.now().year}
args['theme'] = 'theme-clouds' args['product'] = mystore.product
# print (mystore.product.keys()) args['theme'] = 'theme-clouds'
session['cloud-view'] = CONFIG['cloud-view'].replace(':id',id) session['cloud-view'] = CONFIG['cloud-view'].replace(':id',id)
session['product'] = mystore.product session['product'] = mystore.product
return render_template('plans.html',**args) return render_template('plans.html',**args)
@app.route("/goto/<id>",methods=['POST','GET']) @app.route("/goto/<id>",methods=['POST','GET'])
def redirect(id ) : def redirect(id ) :
""" """
This function will redirect to a given product page given a payload. The payload is intended to set the a session This function will redirect to a given product page given a payload. The payload is intended to set the a session
:info :info
""" """
mystore = store.factory.instance(name=id) mystore = store.factory.instance(name=id)
args = {"context":CONTEXT,"product":mystore.product} args = {"context":CONTEXT,"product":mystore.product}
HEADER = {"Location":mystore.product['metadata']['uri']} HEADER = {"Location":mystore.product['metadata']['uri']}
info = request.json info = request.json
if info : if info :
session['auth'] = info['auth'] session['auth'] = info['auth']
session['plan'] = info['plan'] session['plan'] = info['plan']
session['product'] = mystore.product session['product'] = mystore.product
return "1",HEADER return "1",HEADER
else: else:
return "0",403 return "0",403
pass pass
@app.route("/<id>/donate") @app.route("/<id>/donate")
def donate (id) : def donate (id) :
""" """
This will charge a given user/card for a given product. i.e it is designed for a one-time payment This will charge a given user/card for a given product. i.e it is designed for a one-time payment
""" """
mystore = store.factory.instance(name=id) mystore = store.factory.instance(name=id)
# pricing = mystore.get.checkout() #-- pricing # pricing = mystore.get.checkout() #-- pricing
pricing = [{"unit_amount":500,"currency":"usd"},{"unit_amount":1000,"currency":"usd"},{"unit_amount":2500,"currency":"usd"}] pricing = [{"unit_amount":500,"currency":"usd"},{"unit_amount":1000,"currency":"usd"},{"unit_amount":2500,"currency":"usd"}]
args = {"product":mystore.product,"plans":mystore.get.plans(),"context":CONTEXT,"pricing":pricing} args = {"product":mystore.product,"plans":mystore.get.plans(),"context":CONTEXT,"pricing":pricing}
return render_template("card.html",**args) return render_template("card.html",**args)
@app.route("/<id>/pay") @app.route("/<id>/pay")
def pay(id): def pay(id):
email = session['auth']['user']['uid'] email = session['auth']['user']['uid']
fname = session['auth']['user']['uii'].split(' ')[0] if 'uii' in session['auth']['user'] else '' fname = session['auth']['user']['uii'].split(' ')[0] if 'uii' in session['auth']['user'] else ''
lname = " ".join(session['auth']['user']['uii'].split(' ')[1:]) if 'uii' in session['auth']['user'] else '' lname = " ".join(session['auth']['user']['uii'].split(' ')[1:]) if 'uii' in session['auth']['user'] else ''
mystore = store.factory.instance(name=id,email=email) #-- mystore = store.factory.instance(name=id,email=email) #--
amount = session['plan']['amount'] amount = session['plan']['amount']
# cards = mystore.user.card.html() if mystore.user.card.exists() else None # cards = mystore.user.card.html() if mystore.user.card.exists() else None
_args = {"product":mystore.product,"pricing":None,"context":CONTEXT,"email":email,"lname":lname,"fname":fname,"amount":amount} #,"cards":cards} _args = {"product":mystore.product,"pricing":None,"context":CONTEXT,"email":email,"lname":lname,"fname":fname,"amount":amount} #,"cards":cards}
return render_template("card.html",**_args) return render_template("card.html",**_args)
@app.route("/html/dialog",methods=['POST']) @app.route("/html/dialog",methods=['POST'])
def get_dialog(): def get_dialog():
info = request.get_json() info = request.get_json()
_args = {"context":CONTEXT} _args = {"context":CONTEXT}
_args = dict(_args,**info) _args = dict(_args,**info)
return render_template('dialog.html',**_args) return render_template('dialog.html',**_args)
@app.route('/<id>/pay',methods=['POST','PUT']) @app.route('/<id>/pay',methods=['POST','PUT'])
def _payme(id) : def _payme(id) :
info = request.get_json() info = request.get_json()
mystore = store.factory.instance(name=id,email=info['email']) mystore = store.factory.instance(name=id,email=info['email'])
user = mystore.user user = mystore.user
# #
# ... Let us massage the data so it can go through properly # ... Let us massage the data so it can go through properly
_args = {} _args = {}
if 'has_card' not in info and not info['has_card'] : if 'has_card' not in info and not info['has_card'] :
card = {"number":info['number'],"cvc":info['cvc']} card = {"number":info['number'],"cvc":info['cvc']}
card['exp_month'] = info['exp'].split("/")[0] card['exp_month'] = info['exp'].split("/")[0]
card['exp_year'] = info['exp'].split("/")[1] card['exp_year'] = info['exp'].split("/")[1]
card['name'] = " ".join([info["fname"],info["lname"]]) card['name'] = " ".join([info["fname"],info["lname"]])
_args = {"email":info['email'],"amount":info['amount'],"currency":"usd"} _args = {"email":info['email'],"amount":info['amount'],"currency":"usd"}
else: else:
# #
# Let us make a payment using the source we already have # Let us make a payment using the source we already have
card = {} card = {}
_args['card'] = card _args['card'] = card
# #
# if a plan information is provided we are running the card for the plan ? # if a plan information is provided we are running the card for the plan ?
# #
if 'plan' in session : if 'plan' in session :
# #
# We are dealing with a subscription here and we should run this through the subscription engine # We are dealing with a subscription here and we should run this through the subscription engine
# and NOT charge the user immediately (handled by stripe) # and NOT charge the user immediately (handled by stripe)
# #
# _args['amount'] = info['plan']['amount'] # _args['amount'] = info['plan']['amount']
plan = session['plan'] plan = session['plan']
_args['metadata'] = {"payment":plan['nickname'],"product":id} _args['metadata'] = {"payment":plan['nickname'],"product":id}
_args['plan'] = plan _args['plan'] = plan
# #
# @TODO: If we have a card we must add it to the cards on file # @TODO: If we have a card we must add it to the cards on file
# #
if card : if card :
user.card.add(card=card) user.card.add(card=card)
if user.plan.info() : if user.plan.info() :
r = mystore.plan.upgrade(plan['id'],info['email']) r = mystore.plan.upgrade(plan['id'],info['email'])
else: else:
r = mystore.plan.subscribe(id=plan['id'],email=info['email']) r = mystore.plan.subscribe(id=plan['id'],email=info['email'])
pass pass
else: else:
# #
# For now we consider this a donation or other payment # For now we consider this a donation or other payment
_args['metadata'] = {"payment":"charge","product":id} _args['metadata'] = {"payment":"charge","product":id}
_args['statement_descriptor'] = " ".join([str(info['amount']),id]) _args['statement_descriptor'] = " ".join([str(info['amount']),id])
r = user.charge(**_args) r = user.charge(**_args)
if not r : if not r :
msg,status = "Payment error enountered",403 msg,status = "Payment error enountered",403
else : else :
msg,status = "Payment accepted, Thank you", 200 msg,status = "Payment accepted, Thank you", 200
return Response(msg,status=status) return Response(msg,status=status)
@app.route("/me/logout",methods=["POST","GET"]) @app.route("/me/logout",methods=["POST","GET"])
def logout(): def logout():
session.clear() session.clear()
return "1",200 return "1",200
@app.route("/init/<product>",methods=['POST']) @app.route("/init/<product>",methods=['POST'])
def init(product): def init(product):
""" """
This function initializes/logs a product to a given user, i.e it will create a session for users/product/plans This function initializes/logs a product to a given user, i.e it will create a session for users/product/plans
if the user has provided a user identifier it will be used as her primary email. The understanding is that a product may have multiple plans under it but always a free one if the user has provided a user identifier it will be used as her primary email. The understanding is that a product may have multiple plans under it but always a free one
@param uid user's email (primary) @param uid user's email (primary)
@param pid plan identifier @param pid plan identifier
""" """
# #
# get product and plans # get product and plans
# #
if 'uid' in request.headers : if 'uid' in request.headers :
uid = request.headers['uid'] uid = request.headers['uid']
plan_id = request.headers['pid'] if 'pid' in request.headers else None plan_id = request.headers['pid'] if 'pid' in request.headers else None
else: else:
_info = request.json() _info = request.json()
mystore = store.factory.instance(name=product,email=uid) mystore = store.factory.instance(name=product,email=uid)
user = mystore.user user = mystore.user
user.init (uid) user.init (uid)
if not user.plan.info() : # prrint (user.plan.info())
mystore.plan.subscribe(email = user.info()['email']) if not user.plan.info() :
mystore.plan.subscribe(email = user.info()['email'])
features = user.plan.info()['metadata']['features'] if 'features' in user.plan.info()['metadata'] else {}
# features = user.plan.info()['metadata']['features'] if 'features' in user.plan.info()['metadata'] else {}
#@TODO: Log that uid, has initiated use of product #
# #@TODO: Log that uid, has initiated use of product
HEADERS ={"content-type":"application/json"} #
HEADERS ={"content-type":"application/json"}
return features,HEADERS return features,HEADERS
@app.route("/<id>/init",methods=['POST','PUT']) @app.route("/<id>/init",methods=['POST','PUT'])
def _init(id): def _init(id):
return init(id) return init(id)
def get_plans(product) : def get_plans(product) :
lproducts = stripe.Product.list() lproducts = stripe.Product.list()
lproducts = [item for item in lproducts.auto_paging_iter() if item.name == product ] lproducts = [item for item in lproducts.auto_paging_iter() if item.name == product ]
if lproducts : if lproducts :
product_id = lproducts[0].id product_id = lproducts[0].id
alias = lproducts[0].statement_descriptor alias = lproducts[0].statement_descriptor
plans = stripe.Plan.list(product=product_id) plans = stripe.Plan.list(product=product_id)
i = 0 i = 0
for plan in plans : for plan in plans :
plan['product_alias'] = alias if alias is not None else '' plan['product_alias'] = alias if alias is not None else ''
if 'features' in plan['metadata']: if 'features' in plan['metadata']:
plan['metadata']['features'] = json.loads(plan['metadata']['features']) plan['metadata']['features'] = json.loads(plan['metadata']['features'])
plans[i] = plan plans[i] = plan
i += 1 i += 1
if plans : if plans :
plans = plans.data plans = plans.data
plans.sort(key = lambda x:x.amount) plans.sort(key = lambda x:x.amount)
return plans return plans
else: else:
return [] return []
# @app.route('/features/<product>') # @app.route('/features/<product>')
@app.route('/<product>/features') @app.route('/<product>/features')
def features(product): def features(product):
""" """
This function returns the plan/features of a user for a given application if provided a uid (email) This function returns the plan/features of a user for a given application if provided a uid (email)
if no uid are provided then the function will return all the plans/features associated with the given product if no uid are provided then the function will return all the plans/features associated with the given product
@header uid user's email @header uid user's email
""" """
plans = [] plans = []
if 'uid' in request.headers : if 'uid' in request.headers :
uid = request.headers['uid'] uid = request.headers['uid']
couchdb = CouchdbReader(uri=CONFIG['couchdb']['uri'],dbname=product,uid=uid,create=False) couchdb = CouchdbReader(uri=CONFIG['couchdb']['uri'],dbname=product,uid=uid,create=False)
key = couchdb.view("users/uid_map",key=uid) key = couchdb.view("users/uid_map",key=uid)
if key : if key :
key = key[0]['value'] key = key[0]['value']
plans = couchdb.view('users/active_plan',key=key) plans = couchdb.view('users/active_plan',key=key)
plans = [plan['value'] for plan in plans if 'value' in plan] plans = [plan['value'] for plan in plans if 'value' in plan]
else: else:
plans = [] plans = []
else: else:
plans = get_plans(product) plans = get_plans(product)
# #
# formatting plans for the output # formatting plans for the output
# #
return json.dumps(plans),{"content-type":"application/json"} return json.dumps(plans),{"content-type":"application/json"}
if __name__ == '__main__' : if __name__ == '__main__' :
# #
# setup mongodb session management (not sure why) # setup mongodb session management (not sure why)
app.config['SESSION_TYPE'] = 'mongodb' #app.config['SESSION_TYPE'] = 'mongodb'
app.config['MONGO_URI'] = 'mongodb://localhost:27017' #app.config['MONGO_URI'] = 'mongodb://localhost:27017'
app.config['SESSION_MONGODB_DB'] = 'sessions' #app.config['SESSION_MONGODB_DB'] = CONFIG['store']['logger']['db']
app.config['SESSION_MONGODB_COLLECT'] = 'store' #app.config['SESSION_MONGODB_COLLECT'] = 'session'
mongo = PyMongo(app) #mongo = PyMongo(app)
app.session_interface = MongoDBSessionInterface(app,mongo.db, 'store') #app.session_interface = MongoDBSessionInterface(app,mongo.db, 'store')
app.debug = True ; app.debug = True ;
app.secret_key = '360-8y-[0v@t10n]+kr81v17y' app.secret_key = '360-8y-[0v@t10n]+kr81v17y'
app.config['MAX_CONTENT_LENGTH'] = 1600 * 1024 * 1024 app.config['MAX_CONTENT_LENGTH'] = 1600 * 1024 * 1024
Session(app) #Session(app)
app.run(port=PORT,threaded=True,host='0.0.0.0') app.run(port=PORT,threaded=True,host='0.0.0.0')
# app.run() #'0.0.0.0',PORT,True,threaded=True) # app.run() #'0.0.0.0',PORT,True,threaded=True)

@ -364,7 +364,7 @@ $(document).ready(function(){
<div align="center"> <div align="center">
all rights reserved &copy; {{ now }}, The Phi Technologys all rights reserved &copy; {{ now }}, The Phi Technologys
</div> </div>
<div align="center"> <div align="center" class="active" onclick="jx.modal.show({url:'{{context}}/terms'})">
Privacy & Terms Privacy & Terms
</div> </div>

@ -0,0 +1,22 @@
<meta charset="UTF-8">
<!--
(c) 2018 - The Phi Technology LLC
steve@the-phi.comf.ff/'fum 9 mmmmp m87 b
-->
<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1">
<link href="{{ context }}/static/css/default.css" rel="stylesheet" type="text/css">
<link href="{{ context }}/static/css/fa/css/font-awesome.min.css" rel="stylesheet" type="text/css">
<div style="height:100%;">
{% include 'header.html' %}
<p><div class="caption">Terms of Use</div></p>
<p class="border-round text">
The Phi Technology offers a wide range of services and products that are intended to be used to empower end-users.
As such we reserve the rights to cancel/disable/ban any user from using any of our products if we deem they are misusing anyone of our products.
</p>
</div>

@ -7,4 +7,5 @@ stripe
flask-mongo-sessions flask-mongo-sessions
flask-pymongo flask-pymongo
flask-session flask-session
git+https://dev.the-phi.com/git/steve/data-transport.git git+https://dev.the-phi.com/git/steve/data-transport.git
stripe==2.48.0
Loading…
Cancel
Save