1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2025-01-06 10:00:26 +00:00

Auth: Refactor login and logout

GET /login and POST /login-data are merged into /login.

GET /logout and POST /logout-confirm are merged into /logout.

The logout form now looks more consistent with other forms.

Used io.WriteString instead of Fprint where it wasn't like that for some reason.
This commit is contained in:
Timur Ismagilov 2021-12-31 02:07:39 +05:00
parent d75f96d5ce
commit 51f5ebf46d
3 changed files with 124 additions and 124 deletions

View File

@ -45,7 +45,7 @@
<main class="main-width">
<section>
{% if cfg.UseAuth %}
<form class="modal" method="post" action="/login-data" id="login-form" enctype="multipart/form-data" autocomplete="on">
<form class="modal" method="post" action="/login" id="login-form" enctype="multipart/form-data" autocomplete="on">
<fieldset class="modal__fieldset">
<legend class="modal__title">{%s lc.Get("auth.login_header", &l18n.Replacements{"name": cfg.WikiName}) %}</legend>
<label for="login-form__username">{%s lc.Get("auth.username") %}</label>
@ -102,8 +102,10 @@ Telegram auth widget was requested by Yogurt. As you can see, we don't offer use
<section>
{% if can %}
<h1>{%s lc.Get("auth.logout_header") %}</h1>
<p><a href="/logout-confirm"><strong>{%s lc.Get("auth.logout_button") %}</strong></a></p>
<p><a href="/">{%s lc.Get("ui.cancel") %}</a></p>
<form method="POST" action="/logout">
<input class="btn btn_accent" type="submit" value="{%s lc.Get("auth.logout_button") %}"/>
<a class="btn btn_weak" href="/">{%s lc.Get("auth.go_home") %}</a>
</form>
{% else %}
<p>{%s lc.Get("auth.logout_anon") %}</p>
<p><a href="/login">{%s lc.Get("auth.login_title") %}</a></p>
@ -129,7 +131,7 @@ Telegram auth widget was requested by Yogurt. As you can see, we don't offer use
<section class="locked-notice__message">
<p class="locked-notice__lock">🔒</p>
<h1 class="locked-notice__title">{%s lc.Get("auth.lock_title") %}</h1>
<form class="locked-notice__login-form" method="post" action="/login-data" id="login-form" enctype="multipart/form-data" autocomplete="on">
<form class="locked-notice__login-form" method="post" action="/login" id="login-form" enctype="multipart/form-data" autocomplete="on">
<label for="login-form__username">{%s lc.Get("auth.username") %}</label>
<br>
<input type="text" required autofocus id="login-form__username" name="username" autocomplete="username">

View File

@ -190,7 +190,7 @@ func StreamLoginHTML(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
if cfg.UseAuth {
//line views/auth.qtpl:47
qw422016.N().S(`
<form class="modal" method="post" action="/login-data" id="login-form" enctype="multipart/form-data" autocomplete="on">
<form class="modal" method="post" action="/login" id="login-form" enctype="multipart/form-data" autocomplete="on">
<fieldset class="modal__fieldset">
<legend class="modal__title">`)
//line views/auth.qtpl:50
@ -446,77 +446,79 @@ func StreamLogoutHTML(qw422016 *qt422016.Writer, can bool, lc *l18n.Localizer) {
qw422016.E().S(lc.Get("auth.logout_header"))
//line views/auth.qtpl:104
qw422016.N().S(`</h1>
<p><a href="/logout-confirm"><strong>`)
//line views/auth.qtpl:105
<form method="POST" action="/logout">
<input class="btn btn_accent" type="submit" value="`)
//line views/auth.qtpl:106
qw422016.E().S(lc.Get("auth.logout_button"))
//line views/auth.qtpl:105
qw422016.N().S(`</strong></a></p>
<p><a href="/">`)
//line views/auth.qtpl:106
qw422016.E().S(lc.Get("ui.cancel"))
//line views/auth.qtpl:106
qw422016.N().S(`</a></p>
qw422016.N().S(`"/>
<a class="btn btn_weak" href="/">`)
//line views/auth.qtpl:107
qw422016.E().S(lc.Get("auth.go_home"))
//line views/auth.qtpl:107
qw422016.N().S(`</a>
</form>
`)
//line views/auth.qtpl:107
//line views/auth.qtpl:109
} else {
//line views/auth.qtpl:107
//line views/auth.qtpl:109
qw422016.N().S(`
<p>`)
//line views/auth.qtpl:108
//line views/auth.qtpl:110
qw422016.E().S(lc.Get("auth.logout_anon"))
//line views/auth.qtpl:108
//line views/auth.qtpl:110
qw422016.N().S(`</p>
<p><a href="/login">`)
//line views/auth.qtpl:109
//line views/auth.qtpl:111
qw422016.E().S(lc.Get("auth.login_title"))
//line views/auth.qtpl:109
//line views/auth.qtpl:111
qw422016.N().S(`</a></p>
<p><a href="/"> `)
//line views/auth.qtpl:110
//line views/auth.qtpl:112
qw422016.E().S(lc.Get("auth.go_home"))
//line views/auth.qtpl:110
//line views/auth.qtpl:112
qw422016.N().S(`</a></p>
`)
//line views/auth.qtpl:111
//line views/auth.qtpl:113
}
//line views/auth.qtpl:111
//line views/auth.qtpl:113
qw422016.N().S(`
</section>
</main>
</div>
`)
//line views/auth.qtpl:115
//line views/auth.qtpl:117
}
//line views/auth.qtpl:115
//line views/auth.qtpl:117
func WriteLogoutHTML(qq422016 qtio422016.Writer, can bool, lc *l18n.Localizer) {
//line views/auth.qtpl:115
//line views/auth.qtpl:117
qw422016 := qt422016.AcquireWriter(qq422016)
//line views/auth.qtpl:115
//line views/auth.qtpl:117
StreamLogoutHTML(qw422016, can, lc)
//line views/auth.qtpl:115
//line views/auth.qtpl:117
qt422016.ReleaseWriter(qw422016)
//line views/auth.qtpl:115
//line views/auth.qtpl:117
}
//line views/auth.qtpl:115
//line views/auth.qtpl:117
func LogoutHTML(can bool, lc *l18n.Localizer) string {
//line views/auth.qtpl:115
//line views/auth.qtpl:117
qb422016 := qt422016.AcquireByteBuffer()
//line views/auth.qtpl:115
//line views/auth.qtpl:117
WriteLogoutHTML(qb422016, can, lc)
//line views/auth.qtpl:115
//line views/auth.qtpl:117
qs422016 := string(qb422016.B)
//line views/auth.qtpl:115
//line views/auth.qtpl:117
qt422016.ReleaseByteBuffer(qb422016)
//line views/auth.qtpl:115
//line views/auth.qtpl:117
return qs422016
//line views/auth.qtpl:115
//line views/auth.qtpl:117
}
//line views/auth.qtpl:117
//line views/auth.qtpl:119
func StreamLockHTML(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
//line views/auth.qtpl:117
//line views/auth.qtpl:119
qw422016.N().S(`
<!doctype html>
<html>
@ -524,9 +526,9 @@ func StreamLockHTML(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>🔒 `)
//line views/auth.qtpl:123
//line views/auth.qtpl:125
qw422016.E().S(lc.Get("auth.lock_title"))
//line views/auth.qtpl:123
//line views/auth.qtpl:125
qw422016.N().S(`</title>
<link rel="shortcut icon" href="/static/favicon.ico">
<link rel="stylesheet" href="/static/style.css">
@ -536,68 +538,68 @@ func StreamLockHTML(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
<section class="locked-notice__message">
<p class="locked-notice__lock">🔒</p>
<h1 class="locked-notice__title">`)
//line views/auth.qtpl:131
//line views/auth.qtpl:133
qw422016.E().S(lc.Get("auth.lock_title"))
//line views/auth.qtpl:131
//line views/auth.qtpl:133
qw422016.N().S(`</h1>
<form class="locked-notice__login-form" method="post" action="/login-data" id="login-form" enctype="multipart/form-data" autocomplete="on">
<form class="locked-notice__login-form" method="post" action="/login" id="login-form" enctype="multipart/form-data" autocomplete="on">
<label for="login-form__username">`)
//line views/auth.qtpl:133
//line views/auth.qtpl:135
qw422016.E().S(lc.Get("auth.username"))
//line views/auth.qtpl:133
//line views/auth.qtpl:135
qw422016.N().S(`</label>
<br>
<input type="text" required autofocus id="login-form__username" name="username" autocomplete="username">
<br>
<label for="login-form__password">`)
//line views/auth.qtpl:137
//line views/auth.qtpl:139
qw422016.E().S(lc.Get("auth.password"))
//line views/auth.qtpl:137
//line views/auth.qtpl:139
qw422016.N().S(`</label>
<br>
<input type="password" required name="password" autocomplete="current-password">
<br>
<button class="btn" type="submit" value="Log in">`)
//line views/auth.qtpl:141
//line views/auth.qtpl:143
qw422016.E().S(lc.Get("auth.login_button"))
//line views/auth.qtpl:141
//line views/auth.qtpl:143
qw422016.N().S(`</button>
</form>
`)
//line views/auth.qtpl:143
//line views/auth.qtpl:145
streamtelegramWidgetHTML(qw422016, lc)
//line views/auth.qtpl:143
//line views/auth.qtpl:145
qw422016.N().S(`
</section>
</main>
</body>
</html>
`)
//line views/auth.qtpl:148
//line views/auth.qtpl:150
}
//line views/auth.qtpl:148
//line views/auth.qtpl:150
func WriteLockHTML(qq422016 qtio422016.Writer, lc *l18n.Localizer) {
//line views/auth.qtpl:148
//line views/auth.qtpl:150
qw422016 := qt422016.AcquireWriter(qq422016)
//line views/auth.qtpl:148
//line views/auth.qtpl:150
StreamLockHTML(qw422016, lc)
//line views/auth.qtpl:148
//line views/auth.qtpl:150
qt422016.ReleaseWriter(qw422016)
//line views/auth.qtpl:148
//line views/auth.qtpl:150
}
//line views/auth.qtpl:148
//line views/auth.qtpl:150
func LockHTML(lc *l18n.Localizer) string {
//line views/auth.qtpl:148
//line views/auth.qtpl:150
qb422016 := qt422016.AcquireByteBuffer()
//line views/auth.qtpl:148
//line views/auth.qtpl:150
WriteLockHTML(qb422016, lc)
//line views/auth.qtpl:148
//line views/auth.qtpl:150
qs422016 := string(qb422016.B)
//line views/auth.qtpl:148
//line views/auth.qtpl:150
qt422016.ReleaseByteBuffer(qb422016)
//line views/auth.qtpl:148
//line views/auth.qtpl:150
return qs422016
//line views/auth.qtpl:148
//line views/auth.qtpl:150
}

View File

@ -20,6 +20,7 @@ import (
func initAuth(r *mux.Router) {
r.HandleFunc("/lock", handlerLock)
// The check below saves a lot of extra checks and lines of codes in other places in this file.
if !cfg.UseAuth {
return
}
@ -30,24 +31,19 @@ func initAuth(r *mux.Router) {
r.HandleFunc("/telegram-login", handlerTelegramLogin)
}
r.HandleFunc("/login", handlerLogin)
r.HandleFunc("/login-data", handlerLoginData)
r.HandleFunc("/logout", handlerLogout)
r.HandleFunc("/logout-confirm", handlerLogoutConfirm)
}
func handlerLock(w http.ResponseWriter, rq *http.Request) {
io.WriteString(w, views.LockHTML(l18n.FromRequest(rq)))
_, _ = io.WriteString(w, views.LockHTML(l18n.FromRequest(rq)))
}
// handlerRegister both displays the register form (GET) and registers users (POST).
// handlerRegister displays the register form (GET) or registers the user (POST).
func handlerRegister(w http.ResponseWriter, rq *http.Request) {
lc := l18n.FromRequest(rq)
util.PrepareRq(rq)
if !cfg.AllowRegistration {
w.WriteHeader(http.StatusForbidden)
}
if rq.Method == http.MethodGet {
io.WriteString(
_, _ = io.WriteString(
w,
views.BaseHTML(
lc.Get("auth.register_title"),
@ -66,7 +62,7 @@ func handlerRegister(w http.ResponseWriter, rq *http.Request) {
log.Printf("Failed to register %s: %s", username, err.Error())
w.Header().Set("Content-Type", mime.TypeByExtension(".html"))
w.WriteHeader(http.StatusBadRequest)
fmt.Fprint(
_, _ = io.WriteString(
w,
views.BaseHTML(
lc.Get("auth.register_title"),
@ -87,43 +83,61 @@ func handlerRegister(w http.ResponseWriter, rq *http.Request) {
}
}
// handlerLogout shows the logout form.
// handlerLogout shows the logout form (GET) or logs the user out (POST).
func handlerLogout(w http.ResponseWriter, rq *http.Request) {
var (
u = user.FromRequest(rq)
can = u != nil
lc = l18n.FromRequest(rq)
)
w.Header().Set("Content-Type", "text/html;charset=utf-8")
if can {
log.Println("User", u.Name, "tries to log out")
w.WriteHeader(http.StatusOK)
} else {
log.Println("Unknown user tries to log out")
w.WriteHeader(http.StatusForbidden)
if rq.Method == http.MethodGet {
var (
u = user.FromRequest(rq)
can = u != nil
lc = l18n.FromRequest(rq)
)
w.Header().Set("Content-Type", "text/html;charset=utf-8")
if can {
log.Println("User", u.Name, "tries to log out")
w.WriteHeader(http.StatusOK)
} else {
log.Println("Unknown user tries to log out")
w.WriteHeader(http.StatusForbidden)
}
_, _ = io.WriteString(
w,
views.BaseHTML(lc.Get("auth.logout_title"), views.LogoutHTML(can, lc), lc, u),
)
} else if rq.Method == http.MethodPost {
user.LogoutFromRequest(w, rq)
http.Redirect(w, rq, "/", http.StatusSeeOther)
}
w.Write([]byte(views.BaseHTML(lc.Get("auth.logout_title"), views.LogoutHTML(can, lc), lc, u)))
}
// handlerLogoutConfirm logs the user out.
//
// TODO: merge into handlerLogout as POST method.
func handlerLogoutConfirm(w http.ResponseWriter, rq *http.Request) {
user.LogoutFromRequest(w, rq)
http.Redirect(w, rq, "/", http.StatusSeeOther)
}
// handlerLogin shows the login form.
// handlerLogin shows the login form (GET) or logs the user in (POST).
func handlerLogin(w http.ResponseWriter, rq *http.Request) {
util.PrepareRq(rq)
w.Header().Set("Content-Type", "text/html;charset=utf-8")
if cfg.UseAuth {
w.WriteHeader(http.StatusOK)
} else {
w.WriteHeader(http.StatusForbidden)
}
lc := l18n.FromRequest(rq)
w.Write([]byte(views.BaseHTML(lc.Get("auth.login_title"), views.LoginHTML(lc), lc, user.EmptyUser())))
if rq.Method == http.MethodGet {
w.Header().Set("Content-Type", "text/html;charset=utf-8")
w.WriteHeader(http.StatusOK)
_, _ = io.WriteString(
w,
views.BaseHTML(
lc.Get("auth.login_title"),
views.LoginHTML(lc),
lc,
user.EmptyUser(),
),
)
} else if rq.Method == http.MethodPost {
var (
username = util.CanonicalName(rq.PostFormValue("username"))
password = rq.PostFormValue("password")
err = user.LoginDataHTTP(w, rq, username, password)
)
if err != "" {
w.Header().Set("Content-Type", "text/html;charset=utf-8")
w.WriteHeader(http.StatusInternalServerError)
_, _ = io.WriteString(w, views.BaseHTML(err, views.LoginErrorHTML(err, lc), lc, user.EmptyUser()))
return
}
http.Redirect(w, rq, "/", http.StatusSeeOther)
}
}
func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) {
@ -155,7 +169,7 @@ func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) {
if err != nil {
log.Printf("Failed to register %s using Telegram: %s", username, err.Error())
w.WriteHeader(http.StatusBadRequest)
fmt.Fprint(
_, _ = io.WriteString(
w,
views.BaseHTML(
lc.Get("ui.error"),
@ -176,7 +190,7 @@ func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) {
if errmsg != "" {
log.Printf("Failed to login %s using Telegram: %s", username, err.Error())
w.WriteHeader(http.StatusBadRequest)
fmt.Fprint(
_, _ = io.WriteString(
w,
views.BaseHTML(
"Error",
@ -195,21 +209,3 @@ func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) {
log.Printf("Authorize %s from Telegram", username)
http.Redirect(w, rq, "/", http.StatusSeeOther)
}
// handlerLoginData logs the user in.
//
// TODO: merge into handlerLogin as POST method.
func handlerLoginData(w http.ResponseWriter, rq *http.Request) {
lc := l18n.FromRequest(rq)
util.PrepareRq(rq)
var (
username = util.CanonicalName(rq.PostFormValue("username"))
password = rq.PostFormValue("password")
err = user.LoginDataHTTP(w, rq, username, password)
)
if err != "" {
w.Write([]byte(views.BaseHTML(err, views.LoginErrorHTML(err, lc), lc, user.EmptyUser())))
} else {
http.Redirect(w, rq, "/", http.StatusSeeOther)
}
}