For now, log all incoming POST

We want to be able to debug any issue during a command.
Hint: DO MORE TESTS!
This commit is contained in:
Yohan Boniface 2019-04-02 19:51:38 +02:00
parent 8227f1566c
commit 782c08d5ee
6 changed files with 51 additions and 53 deletions

View file

@ -1,16 +1,14 @@
import csv import csv
from datetime import timedelta
from pathlib import Path from pathlib import Path
from time import perf_counter from time import perf_counter
import jwt
import ujson as json import ujson as json
import minicli import minicli
from jinja2 import Environment, PackageLoader, select_autoescape from jinja2 import Environment, PackageLoader, select_autoescape
from roll import Roll, Response from roll import Roll, Response
from roll.extensions import cors, options, traceback, simple_server, static from roll.extensions import cors, options, traceback, simple_server, static
from . import config, reports, session, utils, emails from . import config, reports, session, utils, emails, loggers
from .models import Delivery, Order, Person, Product, ProductOrder from .models import Delivery, Order, Person, Product, ProductOrder
@ -72,46 +70,38 @@ cors(app, methods="*", headers="*")
options(app) options(app)
def auth_required(view): @app.listen("request")
async def redirect(request, response, *a, **k): async def auth_required(request, response):
# FIXME do not return a view when Roll allows it. if not request.route.payload.get("genuine"):
response.redirect = f"/sésame?next={request.path}"
def wrapper(request, response, *args, **kwargs):
token = request.cookies.get("token") token = request.cookies.get("token")
email = None email = None
if token: if token:
decoded = read_token(token) decoded = utils.read_token(token)
email = decoded.get("sub") email = decoded.get("sub")
if not email: if not email:
return redirect(request, response, *args, **kwargs) response.redirect = f"/sésame?next={request.path}"
user = Person(email=email) return response
request["user"] = user user = Person(email=email)
session.user.set(user) request["user"] = user
return view(request, response, *args, **kwargs) session.user.set(user)
return wrapper
def create_token(email):
return jwt.encode(
{"sub": str(email), "exp": utils.utcnow() + timedelta(days=7)},
config.SECRET,
config.JWT_ALGORITHM,
)
def read_token(token):
try:
return jwt.decode(token, config.SECRET, algorithms=[config.JWT_ALGORITHM])
except (jwt.DecodeError, jwt.ExpiredSignatureError):
return {}
@app.listen("request") @app.listen("request")
async def attach_request(request, response): async def attach_request(request, response):
response.request = request response.request = request
@app.listen("request")
async def log_request(request, response):
if request.method == "POST":
message = {
"date": utils.utcnow().isoformat(),
"data": request.form,
"user": request.get("user"),
}
loggers.request_logger.info(
json.dumps(message, sort_keys=True, ensure_ascii=False)
)
@app.listen("startup") @app.listen("startup")
async def on_startup(): async def on_startup():
@ -119,15 +109,15 @@ async def on_startup():
Delivery.init_fs() Delivery.init_fs()
@app.route("/sésame", methods=["GET"]) @app.route("/sésame", methods=["GET"], genuine=True)
async def sesame(request, response): async def sesame(request, response):
response.html("sesame.html") response.html("sesame.html")
@app.route("/sésame", methods=["POST"]) @app.route("/sésame", methods=["POST"])
async def send_sesame(request, response): async def send_sesame(request, response, genuine=True):
email = request.form.get("email") email = request.form.get("email")
token = create_token(email) token = utils.create_token(email)
emails.send( emails.send(
email, email,
"Sésame Copanier", "Sésame Copanier",
@ -137,9 +127,9 @@ async def send_sesame(request, response):
response.redirect = "/" response.redirect = "/"
@app.route("/sésame/{token}", methods=["GET"]) @app.route("/sésame/{token}", methods=["GET"], genuine=True)
async def set_sesame(request, response, token): async def set_sesame(request, response, token):
decoded = read_token(token) decoded = utils.read_token(token)
if not decoded: if not decoded:
response.message("Sésame invalide :(", status="error") response.message("Sésame invalide :(", status="error")
else: else:
@ -151,19 +141,16 @@ async def set_sesame(request, response, token):
@app.route("/", methods=["GET"]) @app.route("/", methods=["GET"])
@auth_required
async def home(request, response): async def home(request, response):
response.html("home.html", incoming=Delivery.incoming(), former=Delivery.former()) response.html("home.html", incoming=Delivery.incoming(), former=Delivery.former())
@app.route("/livraison", methods=["GET"]) @app.route("/livraison", methods=["GET"])
@auth_required
async def new_delivery(request, response): async def new_delivery(request, response):
response.html("edit_delivery.html", delivery={}) response.html("edit_delivery.html", delivery={})
@app.route("/livraison", methods=["POST"]) @app.route("/livraison", methods=["POST"])
@auth_required
async def create_delivery(request, response): async def create_delivery(request, response):
form = request.form form = request.form
data = {} data = {}
@ -179,7 +166,6 @@ async def create_delivery(request, response):
@app.route("/livraison/{id}/importer/produits", methods=["POST"]) @app.route("/livraison/{id}/importer/produits", methods=["POST"])
@auth_required
async def import_products(request, response, id): async def import_products(request, response, id):
delivery = Delivery.load(id) delivery = Delivery.load(id)
delivery.products = [] delivery.products = []
@ -194,14 +180,12 @@ async def import_products(request, response, id):
@app.route("/livraison/{id}/edit", methods=["GET"]) @app.route("/livraison/{id}/edit", methods=["GET"])
@auth_required
async def edit_delivery(request, response, id): async def edit_delivery(request, response, id):
delivery = Delivery.load(id) delivery = Delivery.load(id)
response.html("edit_delivery.html", {"delivery": delivery}) response.html("edit_delivery.html", {"delivery": delivery})
@app.route("/livraison/{id}/edit", methods=["POST"]) @app.route("/livraison/{id}/edit", methods=["POST"])
@auth_required
async def post_delivery(request, response, id): async def post_delivery(request, response, id):
delivery = Delivery.load(id) delivery = Delivery.load(id)
form = request.form form = request.form
@ -216,14 +200,12 @@ async def post_delivery(request, response, id):
@app.route("/livraison/{id}", methods=["GET"]) @app.route("/livraison/{id}", methods=["GET"])
@auth_required
async def view_delivery(request, response, id): async def view_delivery(request, response, id):
delivery = Delivery.load(id) delivery = Delivery.load(id)
response.html("delivery.html", {"delivery": delivery}) response.html("delivery.html", {"delivery": delivery})
@app.route("/livraison/{id}/commander", methods=["POST", "GET"]) @app.route("/livraison/{id}/commander", methods=["POST", "GET"])
@auth_required
async def place_order(request, response, id): async def place_order(request, response, id):
delivery = Delivery.load(id) delivery = Delivery.load(id)
email = request.query.get("email", None) email = request.query.get("email", None)
@ -269,7 +251,6 @@ async def place_order(request, response, id):
@app.route("/livraison/{id}/courriel", methods=["GET"]) @app.route("/livraison/{id}/courriel", methods=["GET"])
@auth_required
async def send_order(request, response, id): async def send_order(request, response, id):
delivery = Delivery.load(id) delivery = Delivery.load(id)
email = request.query.get("email") email = request.query.get("email")
@ -285,14 +266,12 @@ async def send_order(request, response, id):
@app.route("/livraison/{id}/émargement", methods=["GET"]) @app.route("/livraison/{id}/émargement", methods=["GET"])
@auth_required
async def signing_sheet(request, response, id): async def signing_sheet(request, response, id):
delivery = Delivery.load(id) delivery = Delivery.load(id)
response.html("signing_sheet.html", {"delivery": delivery}) response.html("signing_sheet.html", {"delivery": delivery})
@app.route("/livraison/{id}/importer/commande", methods=["POST"]) @app.route("/livraison/{id}/importer/commande", methods=["POST"])
@auth_required
async def import_commande(request, response, id): async def import_commande(request, response, id):
email = request.form.get("email") email = request.form.get("email")
order = Order() order = Order()
@ -311,7 +290,6 @@ async def import_commande(request, response, id):
@app.route("/livraison/{id}/rapport.xlsx", methods=["GET"]) @app.route("/livraison/{id}/rapport.xlsx", methods=["GET"])
@auth_required
async def xls_report(request, response, id): async def xls_report(request, response, id):
delivery = Delivery.load(id) delivery = Delivery.load(id)
response.body = reports.summary(delivery) response.body = reports.summary(delivery)
@ -321,7 +299,6 @@ async def xls_report(request, response, id):
@app.route("/livraison/{id}/rapport-complet.xlsx", methods=["GET"]) @app.route("/livraison/{id}/rapport-complet.xlsx", methods=["GET"])
@auth_required
async def xls_full_report(request, response, id): async def xls_full_report(request, response, id):
delivery = Delivery.load(id) delivery = Delivery.load(id)
response.body = reports.full(delivery) response.body = reports.full(delivery)

View file

@ -2,6 +2,7 @@ import os
from pathlib import Path from pathlib import Path
DATA_ROOT = Path(__file__).parent.parent / "db" DATA_ROOT = Path(__file__).parent.parent / "db"
LOG_ROOT = Path("/tmp")
SECRET = "sikretfordevonly" SECRET = "sikretfordevonly"
JWT_ALGORITHM = "HS256" JWT_ALGORITHM = "HS256"
SEND_EMAILS = False SEND_EMAILS = False

View file

@ -43,7 +43,7 @@ def send_order(env, person, delivery, order):
) )
send( send(
person.email, person.email,
f"Copanier: résumé de la commande {delivery.producer}", f"Copanier: résumé de votre commande {delivery.producer}",
body=txt, body=txt,
html=html, html=html,
) )

View file

@ -1,5 +1,24 @@
from datetime import datetime, timezone from datetime import datetime, timezone, timedelta
import jwt
from . import config
def utcnow(): def utcnow():
return datetime.now(timezone.utc) return datetime.now(timezone.utc)
def create_token(email):
return jwt.encode(
{"sub": str(email), "exp": utcnow() + timedelta(days=7)},
config.SECRET,
config.JWT_ALGORITHM,
)
def read_token(token):
try:
return jwt.decode(token, config.SECRET, algorithms=[config.JWT_ALGORITHM])
except (jwt.DecodeError, jwt.ExpiredSignatureError):
return {}

View file

@ -173,6 +173,7 @@ def upload_env():
""" """
vars_ = { vars_ = {
"COPANIER_DATA_ROOT": "/srv/copanier/data", "COPANIER_DATA_ROOT": "/srv/copanier/data",
"COPANIER_LOG_ROOT": "/srv/copanier/log",
"COPANIER_SEND_EMAILS": "1", "COPANIER_SEND_EMAILS": "1",
"COPANIER_SMTP_PASSWORD": None, "COPANIER_SMTP_PASSWORD": None,
"COPANIER_SMTP_LOGIN": None, "COPANIER_SMTP_LOGIN": None,

View file

@ -7,7 +7,7 @@ from roll.testing import Client as BaseClient
from copanier import app as copanier_app from copanier import app as copanier_app
from copanier import config as kconfig from copanier import config as kconfig
from copanier import create_token from copanier.utils import create_token
from copanier.models import Delivery, Person, Product from copanier.models import Delivery, Person, Product