Files
Pivot/blueprints/handtekeningen_bp.py
T
2026-10-14 12:29:29 +02:00

180 lines
7.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Gmail › Handtekeningen: sjabloon, logo, OU's, functie/telefoon (Google) en toepassen in Gmail."""
import time
from flask import Blueprint, render_template, request, redirect, url_for, flash, session, jsonify, Response, abort
from blueprints.auth import login_required
from rechten import recht_vereist, log
from services import handtekening_service as hs
from tenancy import huidige_school, school_op_code, in_school
handtekeningen_bp = Blueprint('handtekeningen', __name__)
handtekening_logo_bp = Blueprint('handtekening_logo', __name__) # publiek (Gmail haalt het logo op)
CACHE_SECONDEN = 5 * 60
def _door():
return session.get('naam') or session.get('user')
def _gebruikers(inst, vernieuw=False):
school = huidige_school()
sleutel = ('handtekening_gebruikers', tuple(inst['ous']), bool(inst.get('Met_sub_ous')))
bewaard = school.cache.get('handtekening_gebruikers')
if bewaard and not vernieuw and bewaard[0] == sleutel and time.time() - bewaard[1] < CACHE_SECONDEN:
return bewaard[2]
lijst = hs.gebruikers(inst['ous'], bool(inst.get('Met_sub_ous')))
school.cache['handtekening_gebruikers'] = (sleutel, time.time(), lijst)
return lijst
@handtekeningen_bp.route('/', methods=['GET'])
@login_required
@recht_vereist('gmail_handtekeningen')
def overzicht():
inst = hs.instellingen()
fout_ou = fout_gebruikers = None
try:
ous = hs.ou_lijst()
except hs.HandtekeningFout as e:
ous, fout_ou = inst['ous'], str(e)
gebruikers = []
if inst['ous']:
try:
gebruikers = _gebruikers(inst, vernieuw=bool(request.args.get('vernieuw')))
except Exception as e:
fout_gebruikers = str(e)
if request.args.get('vernieuw'):
return redirect(url_for('handtekeningen.overzicht'))
logboek = hs.logboek()
return render_template('handtekeningen.html', inst=inst, ous=ous, fout_ou=fout_ou, gebruikers=gebruikers,
fout_gebruikers=fout_gebruikers, logboek=logboek, velden=hs.VELDEN,
standaard_sjabloon=hs.STANDAARD_SJABLOON, max_tekens=hs.MAX_TEKENS,
publiek_voorstel=request.host_url.rstrip('/'), status=hs.Toepasser().status,
school_gegevens=hs.gegevens({}))
@handtekeningen_bp.route('/sjabloon', methods=['POST'])
@login_required
@recht_vereist('gmail_handtekeningen')
def sjabloon():
hs.ensure_tables()
try:
hs.bewaar(request.form.get('sjabloon'), request.form.getlist('ou'), request.form.get('met_sub') == '1',
request.form.get('logo_url'), request.form.get('logo_breedte') or 120,
request.form.get('publiek_adres'), _door())
bestand = request.files.get('logo')
if bestand and bestand.filename:
hs.bewaar_logo(bestand.read(), bestand.mimetype)
elif request.form.get('logo_wissen') == '1':
hs.verwijder_logo()
huidige_school().cache.pop('handtekening_gebruikers', None)
log("Gmail-handtekening: sjabloon en instellingen bewaard")
flash("Handtekening en instellingen bewaard. Klik op ▶ Toepassen om ze in Gmail te zetten.", "success")
except hs.HandtekeningFout as e:
flash(str(e), "error")
except Exception as e:
flash(f"Bewaren mislukt: {e}", "error")
return redirect(url_for('handtekeningen.overzicht'))
@handtekeningen_bp.route('/voorbeeld', methods=['POST'])
@login_required
@recht_vereist('gmail_handtekeningen')
def voorbeeld():
"""Live voorbeeld met het (nog niet bewaarde) sjabloon uit de editor en de gegevens van één gebruiker."""
d = request.get_json(silent=True) or {}
inst = hs.instellingen()
if d.get('logo_url') is not None:
inst['Logo_url'] = (d.get('logo_url') or '').strip() or None
if d.get('publiek_adres') is not None:
inst['Publiek_adres'] = (d.get('publiek_adres') or '').strip().rstrip('/') or None
try:
inst['Logo_breedte'] = int(d.get('logo_breedte') or inst.get('Logo_breedte') or 120)
except ValueError:
pass
inst['logo_link'] = hs.logo_link(inst)
# In het voorbeeld het geüploade logo via de eigen (ingelogde) sessie tonen, ook als het publiek adres nog niet klopt
if not inst.get('Logo_url') and inst.get('heeft_logo') and inst.get('Logo_sleutel'):
inst['logo_link'] = url_for('handtekening_logo.logo', code=huidige_school().code, sleutel=inst['Logo_sleutel'],
ext=hs.LOGO_TYPES.get(inst.get('Logo_type'), 'png'))
g = d.get('gebruiker') or {}
tekst = hs.vul_in(d.get('sjabloon') if d.get('sjabloon') is not None else inst.get('Sjabloon'), hs.gegevens(g), inst)
return jsonify(ok=True, html=tekst, tekens=len(tekst))
@handtekeningen_bp.route('/gebruiker', methods=['POST'])
@login_required
@recht_vereist('gmail_handtekeningen')
def gebruiker():
"""Functie en telefoon van één gebruiker in Google bewaren."""
d = request.get_json(silent=True) or {}
email = (d.get('email') or '').strip().lower()
functie, telefoon = (d.get('functie') or '').strip()[:100], (d.get('telefoon') or '').strip()[:40]
if not email:
return jsonify(ok=False, fout="Geen gebruiker."), 400
try:
hs.bewaar_in_google(email, functie, telefoon)
except hs.HandtekeningFout as e:
return jsonify(ok=False, fout=str(e)), 400
bewaard = huidige_school().cache.get('handtekening_gebruikers')
if bewaard:
for u in bewaard[2]:
if u['email'] == email:
u.update(functie=functie, telefoon=telefoon)
log(f"Gmail-handtekening: functie/telefoon van {email} aangepast in Google")
return jsonify(ok=True)
@handtekeningen_bp.route('/toepassen', methods=['POST'])
@login_required
@recht_vereist('gmail_handtekeningen')
def toepassen():
d = request.get_json(silent=True) or {}
emails = None if d.get('alle') else [e for e in (d.get('emails') or []) if isinstance(e, str)]
if emails is not None and not emails:
return jsonify(ok=False, fout="Niemand geselecteerd."), 400
if not hs.Toepasser().start(emails, _door()):
return jsonify(ok=False, fout="Er loopt al een opdracht."), 409
log(f"Gmail-handtekening toepassen ({'iedereen' if emails is None else len(emails)})")
return jsonify(ok=True)
@handtekeningen_bp.route('/status.json', methods=['GET'])
@login_required
@recht_vereist('gmail_handtekeningen')
def status():
s = dict(hs.Toepasser().status)
if not s['bezig']:
s['logboek'] = {k: {'ok': bool(v['Ok']), 'melding': v['Melding'] or '',
'op': v['Toegepast'].strftime('%d-%m-%Y %H:%M')} for k, v in hs.logboek().items()}
return jsonify(s)
@handtekeningen_bp.route('/nachtelijk', methods=['POST'])
@login_required
@recht_vereist('gmail_handtekeningen')
def nachtelijk():
aan = request.form.get('aan') == '1'
hs.zet_nacht(aan, _door())
log(f"Gmail-handtekening: nachtelijk opnieuw toepassen {'aan' if aan else 'uit'}")
flash("Elke nacht wordt de handtekening opnieuw gezet bij wie ze gewijzigd heeft." if aan
else "Het nachtelijk opnieuw toepassen staat uit.", "success")
return redirect(url_for('handtekeningen.overzicht'))
# ---------------------------------------------------------------------
# Publiek: het logo (Gmail haalt het op via een link; geen aanmelding)
# ---------------------------------------------------------------------
@handtekening_logo_bp.route('/handtekening-logo/<code>/<sleutel>.<ext>', methods=['GET'])
def logo(code, sleutel, ext):
school = school_op_code(code)
if not school or not sleutel.isalnum():
abort(404)
with in_school(school):
data, soort = hs.logo_bestand(sleutel)
if not data:
abort(404)
return Response(bytes(data), mimetype=soort, headers={'Cache-Control': 'public, max-age=86400'})