forked from Nixius/authelia
1
0
Fork 0

Add /resend-reset endpoint so set-password button sends email directly

The welcome page button was linking to Authelia's reset page which
requires an active login session. Now it POSTs to /resend-reset which
calls the Authelia API server-side and sends the email immediately.
Button text updated from "Reset Password" to "Set Password".

Made-with: Cursor
This commit is contained in:
Leopere 2026-03-03 17:30:38 -05:00
parent aa1201560d
commit 91c0411b90
Signed by: colin
SSH Key Fingerprint: SHA256:nRPCQTeMFLdGytxRQmPVK9VXY3/ePKQ5lGRyJhT5DY8
5 changed files with 45 additions and 4 deletions

View File

@ -4,10 +4,27 @@ import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"strings"
)
func (a *App) handleResendReset(w http.ResponseWriter, r *http.Request) {
username := r.FormValue("username")
if username == "" {
http.Error(w, "username required", http.StatusBadRequest)
return
}
if err := a.triggerPasswordReset(username); err != nil {
log.Printf("resend-reset: failed for %s: %v", username, err)
http.Error(w, "failed to send email", http.StatusInternalServerError)
return
}
log.Printf("resend-reset: password reset email sent for %s", username)
w.WriteHeader(http.StatusOK)
w.Write([]byte("Password setup email sent. Check your inbox."))
}
func (a *App) triggerPasswordReset(username string) error {
body, _ := json.Marshal(map[string]string{"username": username})

View File

@ -47,6 +47,7 @@ func NewRouter(cfg *config.Config, sc *ssstripe.Client, lc *ldap.Client, sw *swa
r.Get("/dashboard", app.handleDashboard)
r.Post("/stack-manage", app.handleStackManage)
r.Post("/subscribe", app.handleCreateCheckout)
r.Post("/resend-reset", app.handleResendReset)
r.Post("/portal", app.handlePortal)
r.Post("/resubscribe", app.handleResubscribe)
r.Post("/webhook/stripe", app.handleWebhook)

View File

@ -85,7 +85,6 @@ func (a *App) handleSuccess(w http.ResponseWriter, r *http.Request) {
"IsNew": result.IsNew,
"Email": email,
"LoginURL": a.cfg.AutheliaURL,
"ResetURL": a.cfg.AutheliaURL + "/#/reset-password/step1",
"ActivateURL": a.cfg.AppURL + "/activate",
"DashboardURL": a.cfg.AppURL + "/dashboard",
"InstanceURL": "https://" + result.Username + "." + a.cfg.CustomerDomain,

View File

@ -177,7 +177,8 @@
</div>
<div class="actions">
<a href="{{.ResetURL}}" class="btn">Resend / Set Password</a>
<button type="button" class="btn" id="reset-btn-new"
onclick="sendReset(this,'{{.Username}}')">Resend Set Password Email</button>
<a href="{{.ActivateURL}}" class="btn btn-outline">Activate Stack</a>
</div>
{{else}}
@ -204,11 +205,34 @@
</div>
<div class="actions">
<a href="{{.ResetURL}}" class="btn">Reset Password</a>
<button type="button" class="btn" id="reset-btn-returning"
onclick="sendReset(this,'{{.Username}}')">Resend Set Password Email</button>
<a href="{{.LoginURL}}" class="btn btn-outline">Sign In</a>
<a href="{{.DashboardURL}}" class="btn btn-outline">Dashboard</a>
</div>
{{end}}
</div>
<script>
function sendReset(btn, username) {
btn.disabled = true;
btn.textContent = 'Sending…';
fetch('/resend-reset', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: 'username=' + encodeURIComponent(username)
}).then(function(r) {
if (r.ok) {
btn.textContent = 'Email sent — check your inbox';
btn.style.background = 'var(--green)';
} else {
btn.textContent = 'Failed — try again';
btn.disabled = false;
}
}).catch(function() {
btn.textContent = 'Failed — try again';
btn.disabled = false;
});
}
</script>
</body>
</html>

View File

@ -77,7 +77,7 @@ services:
echo "$${CLIENT_SECRET_HEADADMIN}" > /run/secrets/CLIENT_SECRET_HEADADMIN
echo "$${CLIENT_SECRET_PORTAINER}" > /run/secrets/CLIENT_SECRET_PORTAINER
echo "$${CLIENT_SECRET_GITEA}" > /run/secrets/CLIENT_SECRET_GITEA
{ echo 'access_control:'; echo ' default_policy: deny'; echo ' rules:'; echo ' - domain: login.bc.a250.ca'; echo ' policy: bypass'; echo ' - domain: app.bc.a250.ca'; echo ' policy: bypass'; echo ' resources:'; echo " - '^/$$'"; echo " - '^/subscribe$$'"; echo " - '^/success(\\?.*)?$$'"; echo " - '^/webhook/stripe$$'"; echo " - '^/health$$'"; echo " - '^/version$$'"; echo ' - domain: app.bc.a250.ca'; echo ' policy: one_factor'; echo ' resources:'; echo " - '^/dashboard$$'"; echo " - '^/activate$$'"; echo " - '^/portal$$'"; echo " - '^/resubscribe$$'"; echo " - '^/stack-manage$$'"; echo ' - domain:'; echo ' - lldap.bc.a250.ca'; echo ' - whoami.bc.a250.ca'; echo ' policy: bypass'; echo ' - domain: "{user}.bc.a250.ca"'; echo ' policy: one_factor'; echo ' - domain: "*.bc.a250.ca"'; echo ' policy: deny'; } > /config/configuration.acl.yml
{ echo 'access_control:'; echo ' default_policy: deny'; echo ' rules:'; echo ' - domain: login.bc.a250.ca'; echo ' policy: bypass'; echo ' - domain: app.bc.a250.ca'; echo ' policy: bypass'; echo ' resources:'; echo " - '^/$$'"; echo " - '^/subscribe$$'"; echo " - '^/success(\\?.*)?$$'"; echo " - '^/webhook/stripe$$'"; echo " - '^/resend-reset$$'"; echo " - '^/health$$'"; echo " - '^/version$$'"; echo ' - domain: app.bc.a250.ca'; echo ' policy: one_factor'; echo ' resources:'; echo " - '^/dashboard$$'"; echo " - '^/activate$$'"; echo " - '^/portal$$'"; echo " - '^/resubscribe$$'"; echo " - '^/stack-manage$$'"; echo ' - domain:'; echo ' - lldap.bc.a250.ca'; echo ' - whoami.bc.a250.ca'; echo ' policy: bypass'; echo ' - domain: "{user}.bc.a250.ca"'; echo ' policy: one_factor'; echo ' - domain: "*.bc.a250.ca"'; echo ' policy: deny'; } > /config/configuration.acl.yml
exec authelia --config=/config/configuration.server.yml --config=/config/configuration.ldap.yml --config=/config/configuration.acl.yml --config=/config/configuration.notifier.yml --config=/config/configuration.identity.providers.yml --config=/config/configuration.oidc.clients.yml
environment:
X_AUTHELIA_EMAIL: authelia@a250.ca