rustango 0.31.0

Django-shaped batteries-included web framework for Rust: ORM + migrations + auto-admin + multi-tenancy + audit log + auth (sessions, JWT, OAuth2/OIDC, HMAC) + APIs (ViewSet, OpenAPI auto-derive, JSON:API) + jobs (in-mem + Postgres) + email + media (S3 / R2 / B2 / MinIO + presigned uploads + collections + tags) + production middleware (CSRF, CSP, rate-limiting, compression, idempotency, etc.).
Documentation
{% extends "op_layout.html" %}
{% block title %}Change password — {{ brand_name | default(value='Rustango Operator Console') }}{% endblock %}
{% block content %}
<style>
  .pw-card {
    max-width: 480px;
    padding: var(--space-5);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-bg-surface);
    box-shadow: var(--shadow-sm);
  }
  .pw-card h1 { margin: 0 0 var(--space-3) 0; font-size: 1.25rem; }
  .pw-card p.sub {
    color: var(--color-fg-muted);
    margin: 0 0 var(--space-4) 0;
    font-size: var(--font-size-sm);
  }
  .pw-card label {
    display: block;
    font-size: var(--font-size-xs);
    color: var(--color-fg-muted);
    margin-top: var(--space-3);
    text-transform: uppercase;
    letter-spacing: 0.05em;
  }
  .pw-card input[type=password] {
    width: 100%;
    padding: 0.5rem 0.6rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    font: inherit;
    margin-top: var(--space-1);
    box-sizing: border-box;
    background: var(--color-bg-input);
    color: var(--color-fg);
  }
  .pw-card input:focus { outline: 2px solid var(--color-accent); outline-offset: 1px; }
  .pw-card button {
    margin-top: var(--space-5);
    padding: 0.55rem 1.2rem;
    background: var(--color-accent);
    color: var(--color-fg-on-accent);
    border: 0;
    border-radius: var(--radius-sm);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
  }
  .pw-card .error, .pw-card .success {
    padding: 0.6rem 0.8rem;
    border-radius: var(--radius-sm);
    margin-bottom: var(--space-3);
    font-size: var(--font-size-sm);
  }
  .pw-card .error {
    background: var(--color-bg-error, #fdecea);
    color: var(--color-fg-error, #b00020);
    border: 1px solid var(--color-border-error, #f5c2c7);
  }
  .pw-card .success {
    background: var(--color-bg-success, #e6f4ea);
    color: var(--color-fg-success, #1e7d32);
    border: 1px solid var(--color-border-success, #b7dfbe);
  }
</style>
<div class="pw-card">
  <h1>Change your password</h1>
  <p class="sub">Sets a new password on your operator account
    (<strong>{{ operator_username }}</strong>). Existing sessions
    issued before the rotation are invalidated &mdash; you'll be
    bounced to login on your other devices.</p>
  {% if error %}<div class="error">{{ error }}</div>{% endif %}
  {% if success %}<div class="success">{{ success }}</div>{% endif %}
  <form method="post" action="/change-password">
    <label for="current_password">Current password</label>
    <input type="password" id="current_password" name="current_password"
           autocomplete="current-password" required autofocus>
    <label for="new_password">New password</label>
    <input type="password" id="new_password" name="new_password"
           autocomplete="new-password" required minlength="8">
    <label for="confirm_password">Confirm new password</label>
    <input type="password" id="confirm_password" name="confirm_password"
           autocomplete="new-password" required minlength="8">
    <button type="submit">Update password</button>
  </form>
</div>
{% endblock %}