Files
partsERP/app.py

329 lines
12 KiB
Python

"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: App General
Feature: App
Description:
Initializes the Flask application, sets the configuration based on the environment, and defines two routes (/ and /about) that render templates with the specified titles.
"""
# IMPORTS
# VARIABLE INSTANTIATION
# METHODS
# IMPORTS
# internal
from config import app_config, Config
# from routes import bp_home
from forms import Form_Contact, Form_Supplier, Form_Filters_Permutations
from models.model_view_base import Model_View_Base
from models.model_view_home import Model_View_Home
from models.model_view_contact import Model_View_Contact
from models.model_view_supplier import Model_View_Supplier
from models.model_view_store_permutations import Model_View_Store_Permutations
from business_objects.product import Product, Product_Filters # , Product_Image_Filters, Resolution_Level_Enum
import lib.argument_validation as av
# external
from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy
from flask_mail import Mail, Message
from flask_wtf.csrf import CSRFProtect
import stripe
import json
from dotenv import load_dotenv, find_dotenv
import os
import sys
from urllib.parse import quote_plus, urlencode
from authlib.integrations.flask_client import OAuth
import jwt
# VARIABLE INSTANTIATION
app = Flask(__name__)
csrf = CSRFProtect(app)
CORS(app)
# app.register_blueprint(bp_home, url_prefix=''
# app.config.from_object(app_config)
# app.app_config = app_config
app.DEBUG = Config.DEBUG
app.TESTING = Config.TESTING
app.SECRET_KEY = "007cfbdaaf6d1eb27209720e8a5fc8ba0a334ae0be6fcac132b0a471549cde7c" # Config.SECRET_KEY
app.config['SECRET_KEY'] = app.SECRET_KEY
app.DB_NAME = Config.DB_NAME
app.DB_USER = Config.DB_USER
app.DB_PASSWORD = Config.DB_PASSWORD
app.DB_HOST = Config.DB_HOST
# app.DB_PORT = Config.DB_PORT
app.SQLALCHEMY_DATABASE_URI = Config.SQLALCHEMY_DATABASE_URI
app.SQLALCHEMY_TRACK_MODIFICATIONS = Config.SQLALCHEMY_TRACK_MODIFICATIONS
app.ID_AUTH0_CLIENT = Config.ID_AUTH0_CLIENT
app.ID_AUTH0_CLIENT_SECRET = Config.ID_AUTH0_CLIENT_SECRET
app.DOMAIN_AUTH0 = Config.DOMAIN_AUTH0
app.ID_TOKEN_USER = Config.ID_TOKEN_USER
app.config.SQLALCHEMY_DATABASE_URI = Config.SQLALCHEMY_DATABASE_URI
app.config.SQLALCHEMY_TRACK_MODIFICATIONS = Config.SQLALCHEMY_TRACK_MODIFICATIONS
app.config.ID_AUTH0_CLIENT = Config.ID_AUTH0_CLIENT
app.config.ID_AUTH0_CLIENT_SECRET = Config.ID_AUTH0_CLIENT_SECRET
app.config.DOMAIN_AUTH0 = Config.DOMAIN_AUTH0
app.config.ID_TOKEN_USER = Config.ID_TOKEN_USER
app.config['SQLALCHEMY_DATABASE_URI'] = Config.SQLALCHEMY_DATABASE_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = Config.SQLALCHEMY_TRACK_MODIFICATIONS
app.config['ID_AUTH0_CLIENT'] = Config.ID_AUTH0_CLIENT
app.config['ID_AUTH0_CLIENT_SECRET'] = Config.ID_AUTH0_CLIENT_SECRET
app.config['DOMAIN_AUTH0'] = Config.DOMAIN_AUTH0
app.config['ID_TOKEN_USER'] = Config.ID_TOKEN_USER
app.MAIL_DEBUG = True
app.MAIL_SERVER = Config.MAIL_SERVER
app.MAIL_PORT = Config.MAIL_PORT
app.MAIL_USE_TLS = Config.MAIL_USE_TLS
app.MAIL_USE_SSL = Config.MAIL_USE_SSL
app.MAIL_USERNAME = Config.MAIL_USERNAME
app.MAIL_PASSWORD = Config.MAIL_PASSWORD
app.MAIL_DEFAULT_SENDER = Config.MAIL_DEFAULT_SENDER
app.config.MAIL_DEBUG = True
app.config.MAIL_SERVER = Config.MAIL_SERVER
app.config.MAIL_PORT = Config.MAIL_PORT
app.config.MAIL_USE_TLS = Config.MAIL_USE_TLS
app.config.MAIL_USE_SSL = Config.MAIL_USE_SSL
app.config.MAIL_USERNAME = Config.MAIL_USERNAME
app.config.MAIL_PASSWORD = Config.MAIL_PASSWORD
app.config.MAIL_DEFAULT_SENDER = Config.MAIL_DEFAULT_SENDER
app.config['MAIL_DEBUG'] = True
app.config['MAIL_SERVER'] = Config.MAIL_SERVER
app.config['MAIL_PORT'] = Config.MAIL_PORT
app.config['MAIL_USE_TLS'] = Config.MAIL_USE_TLS
app.config['MAIL_USE_SSL'] = Config.MAIL_USE_SSL
app.config['MAIL_USERNAME'] = Config.MAIL_USERNAME
app.config['MAIL_PASSWORD'] = Config.MAIL_PASSWORD
app.config['MAIL_DEFAULT_SENDER'] = Config.MAIL_DEFAULT_SENDER
app.config['MAIL_CONTACT_PUBLIC'] = Config.MAIL_CONTACT_PUBLIC
# app.RECAPTCHA_PUBLIC_KEY = Config.RECAPTCHA_PUBLIC_KEY
app.config['RECAPTCHA_PUBLIC_KEY'] = Config.RECAPTCHA_PUBLIC_KEY
# app.RECAPTCHA_PRIVATE_KEY = Config.RECAPTCHA_PRIVATE_KEY
app.config['RECAPTCHA_PRIVATE_KEY'] = Config.RECAPTCHA_PRIVATE_KEY
# db = SQLAlchemy(app)
app.config['SQLALCHEMY_DATABASE_URI'] = Config.SQLALCHEMY_DATABASE_URI
"""
oauth = OAuth(app)
oauth.register(
"auth0",
client_id = app.ID_AUTH0_CLIENT,
client_secret = app.ID_AUTH0_CLIENT_SECRET, # =env.get("AUTH0_CLIENT_SECRET"),
client_kwargs={
"scope": "openid profile email",
},
server_metadata_url=f'https://{app.DOMAIN_AUTH0}/.well-known/openid-configuration'
)
# session[app.ID_TOKEN_USER] = {'userinfo': {'sub': ''}}
"""
db = SQLAlchemy()
db.init_app(app)
with app.app_context():
db.create_all()
db.engine.url = app.config.SQLALCHEMY_DATABASE_URI
mail = Mail(app) # ToDo: move to helper
# METHODS
sys.path.insert(0, os.path.dirname(__file__)) # Todo: why?
@app.route('/hello')
def hello():
return "Hello, World!" + f"{app.errors}\n{app.config.SQLALCHEMY_DATABASE_URI == app.SQLALCHEMY_DATABASE_URI}"
@app.route('/goodbye')
def goodbye():
return "Goodbye, cruel World!"
"""
@app.route('/public_html/403.shtml', methods=['GET'])
def forbidden():
return send_from_directory('/home/partsltd/public_html', '403.shtml')
"""
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
message = 'It works!\n'
version = 'Python %s\n' % sys.version.split()[0]
response = '\n'.join([message, version])
return [response.encode()]
# ROUTING
@app.route('/', methods=['GET'])
def home():
try:
model = Model_View_Home(app)
html_body = render_template('_page_home.html', model = model)
except Exception as e:
return str(e)
return html_body
@app.route('/contact', methods=['GET'])
def contact():
try:
form = Form_Contact()
model = Model_View_Contact(db, get_info_user(), app, form)
html_body = render_template('_page_contact.html', model = model)
except Exception as e:
return jsonify(error=str(e)), 403
return html_body
@app.route('/contact', methods=['POST'])
def contact_post():
try:
form = Form_Contact()
if form.validate_on_submit():
# Handle form submission
email = form.email.data
CC = form.CC.data # not in use
name = form.name.data
message = form.message.data
# send email
mailItem = Message("PARTS Website Contact Us Message", recipients=[app.config['MAIL_CONTACT_PUBLIC']])
mailItem.body = f"Dear Lord Edward Middleton-Smith,\n\n{message}\n\nKind regards,\n{name}\n{email}"
mail.send(mailItem)
return "Submitted."
return "Invalid. Failed to submit."
# html_body = render_template('_page_contact.html', model = model)
except Exception as e:
return jsonify(error=str(e)), 403
@app.route('/services', methods=['GET', 'POST'])
# @app.route('/public_html/services', methods=['GET', 'POST'])
def services():
try:
model = Model_View_Home(db, get_info_user(), app)
html_body = render_template('_page_services.html', model = model)
except Exception as e:
return jsonify(error=str(e)), 403
return html_body
# shop management
@app.route('/supplier', methods=['GET'])
def supplier():
try:
data = request.json
except:
data = {}
print(f'data={data}')
form_data = data[Model_View_Supplier.key_form]
print(f'form_data: {form_data}')
form = Form_Supplier(**form_data)
print('form acquired')
print(form.__repr__)
if form.validate_on_submit():
print('valid form')
# model = input_JSON_basket(model, data)
# if not logged in:
try:
model = Model_View_Supplier(db, get_info_user(), app, form)
# print('importing basket')
# model.import_JSON_basket(data)
model.get_basket(data)
permutation_id, quantity = model.import_JSON_basket_item(data, form)
model.basket_item_edit(permutation_id, quantity, False) # new_basket =
except Exception as e:
return jsonify({'status': 'failure', 'Message': f'Bad data received by controller.\n{e}'})
# return jsonify(Success = True, data = { html_block: render_template(), Model_View_Store.key_basket: new_basket })
# html_block = render_template('_block_store_basket.html', model = model)
# print(f'html_block:\n{html_block}')
# return jsonify(Success = True, data = { 'html_block': html_block, 'basket': {'items': model.basket.to_json_list()}})
return render_template('_page_supplier.html', model = model)
return jsonify({'status': 'failure', 'Message': f'Invalid supplier details.\n{form.errors}'})
# product permutations
@app.route('/store/permutations', methods=['GET'])
def permutations_get():
filters = Product_Filters.get_default()
model = Model_View_Store_Permutations(app=app, db=db, filters_product=filters)
return render_template('_page_store_product.html', model = model)
@app.route('/store/permutations', methods=['POST'])
def permutations_post():
try:
data = request.json
except:
data = {}
print(f'data={data}')
form_filters = None
try:
form_data = data[Model_View_Store_Permutations.KEY_FORM_FILTERS]
print(f'form_data: {form_data}')
form_filters = Form_Filters_Permutations(**form_data)
print('form acquired')
print(form_filters.__repr__)
print('valid form')
filters_form = Product_Filters.from_form(form_filters)
model = Model_View_Store_Permutations(app=app, db=db, filters_product=filters_form)
# return render_template('_page_store_product.html', model = model)
return jsonify({'status': 'success', 'data': model.category_list.to_list_rows_permutation()})
except Exception as e:
return jsonify({'status': 'failure', 'Message': f'Bad data received by controller.\n{e}'})
# snore
@app.route('/license', methods=['GET'])
def license():
try:
model = Model_View_Home(db, get_info_user(), app)
html_body = render_template('_page_license.html', model = model)
except Exception as e:
return str(e)
return html_body
@app.route('/accessibility-statement', methods=['GET'])
def accessibility_statement():
try:
model = Model_View_Home(db, get_info_user(), app)
html_body = render_template('_page_accessibility_statement.html', model = model)
except Exception as e:
return str(e)
return html_body
@app.route('/accessibility-report', methods=['GET'])
def accessibility_report():
try:
model = Model_View_Home(db, get_info_user(), app)
html_body = render_template('_page_accessibility_report.html', model = model)
except Exception as e:
return str(e)
return html_body
@app.route('/retention-schedule', methods=['GET'])
def retention_schedule():
try:
model = Model_View_Home(db, get_info_user(), app)
html_body = render_template('_page_retention_schedule.html', model = model)
except Exception as e:
return str(e)
return html_body
@app.route('/privacy-notice', methods=['GET'])
def privacy_notice():
try:
model = Model_View_Home(db, get_info_user(), app)
html_body = render_template('_page_privacy_notice.html', model = model)
except Exception as e:
return str(e)
return html_body
# Onload
if __name__ == '__main__':
app.run()
# app.run(debug=True, host="0.0.0.0", port=5000)