Two silent failures sitting between Phase A and a working invitation. The compose file never passed MAIL_* through. Compose does not give a container the contents of .env — it only substitutes into the compose file — so the settings could be filled in correctly and read by nobody, with the app reporting mail as unconfigured and the values sitting right there on disk. test_deployment.py now fails the build whenever .env.example and docker-compose.yml drift apart, which is how this happened and how it would happen again. The app's code is baked into the image (COPY apps /srv/apps), so a pull followed by --force-recreate runs the old code and says nothing. Added scripts/deploy-board.sh: rebuild, sync the compose file, restart, print the log, and name any setting present in .env.example and missing from the live .env. It never touches .env itself. Also: "no mail server configured" is now told apart from "the mail server refused". They want different things done about them, and the first one sent an admin looking for an SMTP error that never existed. The new-member form says so before it is filled in rather than after. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NizVpJ2dwzCbjCrTLCjeHn
67 lines
2.4 KiB
HTML
67 lines
2.4 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}Dar de alta{% endblock %}
|
|
|
|
{% block main %}
|
|
<form class="card" method="post" action="{{ url_for('members.new') }}">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
|
<h1>Dar de alta a alguien</h1>
|
|
|
|
<label for="login">Usuario</label>
|
|
<input id="login" name="login" required pattern="[A-Za-z0-9][A-Za-z0-9._\-]*"
|
|
placeholder="maria.lopez">
|
|
<p class="muted small">Letras, números, punto, guion y guion bajo.</p>
|
|
|
|
<label for="display_name">Nombre</label>
|
|
<input id="display_name" name="display_name" placeholder="María López">
|
|
|
|
<label for="email">Correo</label>
|
|
<input id="email" name="email" type="email" placeholder="maria@ejemplo.com">
|
|
|
|
{% if can_create_accounts %}
|
|
<label class="check">
|
|
<input type="checkbox" name="create_account" checked>
|
|
Crear también su cuenta (desmarca si ya tiene una)
|
|
</label>
|
|
{% else %}
|
|
{# Disabled rather than hidden: "you cannot do this here" is more use than
|
|
an option that quietly is not there. The handler refuses it either way. #}
|
|
<label class="check">
|
|
<input type="checkbox" name="create_account" disabled>
|
|
Crear también su cuenta
|
|
</label>
|
|
<p class="muted small">
|
|
Este servidor no puede crear cuentas (no tiene un token de administración
|
|
de Gitea). Crea la cuenta primero en
|
|
<a href="{{ gitea_url }}/admin/users/new">Gitea</a> y luego da de alta
|
|
aquí ese mismo usuario.
|
|
</p>
|
|
{% endif %}
|
|
|
|
{% if can_create_accounts and not can_send_mail %}
|
|
{# Not an error: the account is still created and the invitation still
|
|
issued. But it leaves by hand, and finding that out after filling the
|
|
form is how an invitation ends up believed sent and never delivered. #}
|
|
<p class="muted small">
|
|
Este servidor todavía no envía correo, así que la invitación no se
|
|
enviará sola: al terminar te mostraremos el enlace para que se lo pases.
|
|
</p>
|
|
{% endif %}
|
|
|
|
{% if can_make_admin %}
|
|
<label for="role">Rol</label>
|
|
<select id="role" name="role">
|
|
<option value="user">Usuario</option>
|
|
<option value="admin">Administrador</option>
|
|
</select>
|
|
{% else %}
|
|
<input type="hidden" name="role" value="user">
|
|
<p class="muted small">Los administradores sólo pueden dar de alta usuarios.</p>
|
|
{% endif %}
|
|
|
|
<div class="actions">
|
|
<button class="btn" type="submit">Dar de alta</button>
|
|
<a class="linkish" href="{{ url_for('members.index') }}">Cancelar</a>
|
|
</div>
|
|
</form>
|
|
{% endblock %}
|