mirror of
https://github.com/almet/copanier.git
synced 2025-04-28 19:42:37 +02:00
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:
parent
8227f1566c
commit
782c08d5ee
6 changed files with 51 additions and 53 deletions
|
@ -1,16 +1,14 @@
|
|||
import csv
|
||||
from datetime import timedelta
|
||||
from pathlib import Path
|
||||
from time import perf_counter
|
||||
|
||||
import jwt
|
||||
import ujson as json
|
||||
import minicli
|
||||
from jinja2 import Environment, PackageLoader, select_autoescape
|
||||
from roll import Roll, Response
|
||||
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
|
||||
|
||||
|
||||
|
@ -72,46 +70,38 @@ cors(app, methods="*", headers="*")
|
|||
options(app)
|
||||
|
||||
|
||||
def auth_required(view):
|
||||
async def redirect(request, response, *a, **k):
|
||||
# FIXME do not return a view when Roll allows it.
|
||||
response.redirect = f"/sésame?next={request.path}"
|
||||
|
||||
def wrapper(request, response, *args, **kwargs):
|
||||
@app.listen("request")
|
||||
async def auth_required(request, response):
|
||||
if not request.route.payload.get("genuine"):
|
||||
token = request.cookies.get("token")
|
||||
email = None
|
||||
if token:
|
||||
decoded = read_token(token)
|
||||
decoded = utils.read_token(token)
|
||||
email = decoded.get("sub")
|
||||
if not email:
|
||||
return redirect(request, response, *args, **kwargs)
|
||||
response.redirect = f"/sésame?next={request.path}"
|
||||
return response
|
||||
user = Person(email=email)
|
||||
request["user"] = user
|
||||
session.user.set(user)
|
||||
return view(request, response, *args, **kwargs)
|
||||
|
||||
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")
|
||||
async def attach_request(request, response):
|
||||
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")
|
||||
async def on_startup():
|
||||
|
@ -119,15 +109,15 @@ async def on_startup():
|
|||
Delivery.init_fs()
|
||||
|
||||
|
||||
@app.route("/sésame", methods=["GET"])
|
||||
@app.route("/sésame", methods=["GET"], genuine=True)
|
||||
async def sesame(request, response):
|
||||
response.html("sesame.html")
|
||||
|
||||
|
||||
@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")
|
||||
token = create_token(email)
|
||||
token = utils.create_token(email)
|
||||
emails.send(
|
||||
email,
|
||||
"Sésame Copanier",
|
||||
|
@ -137,9 +127,9 @@ async def send_sesame(request, response):
|
|||
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):
|
||||
decoded = read_token(token)
|
||||
decoded = utils.read_token(token)
|
||||
if not decoded:
|
||||
response.message("Sésame invalide :(", status="error")
|
||||
else:
|
||||
|
@ -151,19 +141,16 @@ async def set_sesame(request, response, token):
|
|||
|
||||
|
||||
@app.route("/", methods=["GET"])
|
||||
@auth_required
|
||||
async def home(request, response):
|
||||
response.html("home.html", incoming=Delivery.incoming(), former=Delivery.former())
|
||||
|
||||
|
||||
@app.route("/livraison", methods=["GET"])
|
||||
@auth_required
|
||||
async def new_delivery(request, response):
|
||||
response.html("edit_delivery.html", delivery={})
|
||||
|
||||
|
||||
@app.route("/livraison", methods=["POST"])
|
||||
@auth_required
|
||||
async def create_delivery(request, response):
|
||||
form = request.form
|
||||
data = {}
|
||||
|
@ -179,7 +166,6 @@ async def create_delivery(request, response):
|
|||
|
||||
|
||||
@app.route("/livraison/{id}/importer/produits", methods=["POST"])
|
||||
@auth_required
|
||||
async def import_products(request, response, id):
|
||||
delivery = Delivery.load(id)
|
||||
delivery.products = []
|
||||
|
@ -194,14 +180,12 @@ async def import_products(request, response, id):
|
|||
|
||||
|
||||
@app.route("/livraison/{id}/edit", methods=["GET"])
|
||||
@auth_required
|
||||
async def edit_delivery(request, response, id):
|
||||
delivery = Delivery.load(id)
|
||||
response.html("edit_delivery.html", {"delivery": delivery})
|
||||
|
||||
|
||||
@app.route("/livraison/{id}/edit", methods=["POST"])
|
||||
@auth_required
|
||||
async def post_delivery(request, response, id):
|
||||
delivery = Delivery.load(id)
|
||||
form = request.form
|
||||
|
@ -216,14 +200,12 @@ async def post_delivery(request, response, id):
|
|||
|
||||
|
||||
@app.route("/livraison/{id}", methods=["GET"])
|
||||
@auth_required
|
||||
async def view_delivery(request, response, id):
|
||||
delivery = Delivery.load(id)
|
||||
response.html("delivery.html", {"delivery": delivery})
|
||||
|
||||
|
||||
@app.route("/livraison/{id}/commander", methods=["POST", "GET"])
|
||||
@auth_required
|
||||
async def place_order(request, response, id):
|
||||
delivery = Delivery.load(id)
|
||||
email = request.query.get("email", None)
|
||||
|
@ -269,7 +251,6 @@ async def place_order(request, response, id):
|
|||
|
||||
|
||||
@app.route("/livraison/{id}/courriel", methods=["GET"])
|
||||
@auth_required
|
||||
async def send_order(request, response, id):
|
||||
delivery = Delivery.load(id)
|
||||
email = request.query.get("email")
|
||||
|
@ -285,14 +266,12 @@ async def send_order(request, response, id):
|
|||
|
||||
|
||||
@app.route("/livraison/{id}/émargement", methods=["GET"])
|
||||
@auth_required
|
||||
async def signing_sheet(request, response, id):
|
||||
delivery = Delivery.load(id)
|
||||
response.html("signing_sheet.html", {"delivery": delivery})
|
||||
|
||||
|
||||
@app.route("/livraison/{id}/importer/commande", methods=["POST"])
|
||||
@auth_required
|
||||
async def import_commande(request, response, id):
|
||||
email = request.form.get("email")
|
||||
order = Order()
|
||||
|
@ -311,7 +290,6 @@ async def import_commande(request, response, id):
|
|||
|
||||
|
||||
@app.route("/livraison/{id}/rapport.xlsx", methods=["GET"])
|
||||
@auth_required
|
||||
async def xls_report(request, response, id):
|
||||
delivery = Delivery.load(id)
|
||||
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"])
|
||||
@auth_required
|
||||
async def xls_full_report(request, response, id):
|
||||
delivery = Delivery.load(id)
|
||||
response.body = reports.full(delivery)
|
||||
|
|
|
@ -2,6 +2,7 @@ import os
|
|||
from pathlib import Path
|
||||
|
||||
DATA_ROOT = Path(__file__).parent.parent / "db"
|
||||
LOG_ROOT = Path("/tmp")
|
||||
SECRET = "sikretfordevonly"
|
||||
JWT_ALGORITHM = "HS256"
|
||||
SEND_EMAILS = False
|
||||
|
|
|
@ -43,7 +43,7 @@ def send_order(env, person, delivery, order):
|
|||
)
|
||||
send(
|
||||
person.email,
|
||||
f"Copanier: résumé de la commande {delivery.producer}",
|
||||
f"Copanier: résumé de votre commande {delivery.producer}",
|
||||
body=txt,
|
||||
html=html,
|
||||
)
|
||||
|
|
|
@ -1,5 +1,24 @@
|
|||
from datetime import datetime, timezone
|
||||
from datetime import datetime, timezone, timedelta
|
||||
|
||||
import jwt
|
||||
|
||||
from . import config
|
||||
|
||||
|
||||
def utcnow():
|
||||
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 {}
|
||||
|
|
|
@ -173,6 +173,7 @@ def upload_env():
|
|||
"""
|
||||
vars_ = {
|
||||
"COPANIER_DATA_ROOT": "/srv/copanier/data",
|
||||
"COPANIER_LOG_ROOT": "/srv/copanier/log",
|
||||
"COPANIER_SEND_EMAILS": "1",
|
||||
"COPANIER_SMTP_PASSWORD": None,
|
||||
"COPANIER_SMTP_LOGIN": None,
|
||||
|
|
|
@ -7,7 +7,7 @@ from roll.testing import Client as BaseClient
|
|||
|
||||
from copanier import app as copanier_app
|
||||
from copanier import config as kconfig
|
||||
from copanier import create_token
|
||||
from copanier.utils import create_token
|
||||
from copanier.models import Delivery, Person, Product
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue