1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2024-10-30 11:46:16 +00:00
mycorrhiza/web/auth.go

216 lines
5.6 KiB
Go
Raw Normal View History

package web
2020-11-14 13:03:06 +00:00
import (
2021-07-14 19:51:55 +00:00
"errors"
"fmt"
"io"
2020-11-14 13:03:06 +00:00
"log"
"mime"
2020-11-14 13:03:06 +00:00
"net/http"
2021-07-14 19:51:55 +00:00
"strings"
2020-11-14 13:03:06 +00:00
"github.com/gorilla/mux"
"github.com/bouncepaw/mycorrhiza/cfg"
2021-09-06 17:46:34 +00:00
"github.com/bouncepaw/mycorrhiza/l18n"
2020-11-14 13:03:06 +00:00
"github.com/bouncepaw/mycorrhiza/user"
2021-02-17 18:41:35 +00:00
"github.com/bouncepaw/mycorrhiza/util"
"github.com/bouncepaw/mycorrhiza/views"
2020-11-14 13:03:06 +00:00
)
func initAuth(r *mux.Router) {
r.HandleFunc("/lock", handlerLock)
if !cfg.UseAuth {
return
}
if cfg.AllowRegistration {
r.HandleFunc("/register", handlerRegister)
}
2021-07-14 19:51:55 +00:00
if cfg.TelegramEnabled {
r.HandleFunc("/telegram-login", handlerTelegramLogin)
2021-07-14 19:51:55 +00:00
}
r.HandleFunc("/login", handlerLogin)
r.HandleFunc("/login-data", handlerLoginData)
r.HandleFunc("/logout", handlerLogout)
r.HandleFunc("/logout-confirm", handlerLogoutConfirm)
2020-11-14 13:03:06 +00:00
}
func handlerLock(w http.ResponseWriter, rq *http.Request) {
2021-09-06 17:46:34 +00:00
io.WriteString(w, views.LockHTML(l18n.FromRequest(rq)))
}
// handlerRegister both displays the register form (GET) and registers users (POST).
func handlerRegister(w http.ResponseWriter, rq *http.Request) {
2021-09-06 17:46:34 +00:00
lc := l18n.FromRequest(rq)
util.PrepareRq(rq)
if !cfg.AllowRegistration {
w.WriteHeader(http.StatusForbidden)
}
if rq.Method == http.MethodGet {
io.WriteString(
w,
views.BaseHTML(
2021-09-06 17:46:34 +00:00
lc.Get("auth.register_title"),
views.RegisterHTML(rq),
2021-09-06 17:46:34 +00:00
lc,
user.FromRequest(rq),
),
)
} else if rq.Method == http.MethodPost {
var (
username = rq.PostFormValue("username")
password = rq.PostFormValue("password")
2021-07-14 21:00:35 +00:00
err = user.Register(username, password, "editor", "local", false)
)
if err != nil {
2021-08-12 12:12:53 +00:00
log.Printf("Failed to register %s: %s", username, err.Error())
w.Header().Set("Content-Type", mime.TypeByExtension(".html"))
w.WriteHeader(http.StatusBadRequest)
fmt.Fprint(
w,
views.BaseHTML(
2021-09-06 17:46:34 +00:00
lc.Get("auth.register_title"),
fmt.Sprintf(
2021-09-06 17:46:34 +00:00
`<main class="main-width"><p>%s</p><p><a href="/register">%s<a></p></main>`,
err.Error(),
2021-09-06 17:46:34 +00:00
lc.Get("auth.try_again"),
),
2021-09-06 17:46:34 +00:00
lc,
user.FromRequest(rq),
),
)
} else {
2021-08-12 12:12:53 +00:00
log.Printf("Successfully registered %s", username)
user.LoginDataHTTP(w, rq, username, password)
http.Redirect(w, rq, "/"+rq.URL.RawQuery, http.StatusSeeOther)
}
}
}
// handlerLogout shows the logout form.
2020-11-14 13:03:06 +00:00
func handlerLogout(w http.ResponseWriter, rq *http.Request) {
var (
u = user.FromRequest(rq)
can = u != nil
2021-09-29 14:56:17 +00:00
lc = l18n.FromRequest(rq)
2020-11-14 13:03:06 +00:00
)
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)
}
2021-09-06 17:46:34 +00:00
w.Write([]byte(views.BaseHTML(lc.Get("auth.logout_title"), views.LogoutHTML(can, lc), lc, u)))
2020-11-14 13:03:06 +00:00
}
// handlerLogoutConfirm logs the user out.
//
// TODO: merge into handlerLogout as POST method.
2020-11-14 13:03:06 +00:00
func handlerLogoutConfirm(w http.ResponseWriter, rq *http.Request) {
user.LogoutFromRequest(w, rq)
http.Redirect(w, rq, "/", http.StatusSeeOther)
}
// handlerLogin shows the login form.
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)
}
2021-09-06 17:46:34 +00:00
lc := l18n.FromRequest(rq)
w.Write([]byte(views.BaseHTML(lc.Get("auth.login_title"), views.LoginHTML(lc), lc, user.EmptyUser())))
}
2021-07-14 19:51:55 +00:00
func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) {
// Note there is no lock here.
2021-09-06 17:46:34 +00:00
lc := l18n.FromRequest(rq)
2021-07-14 20:04:52 +00:00
w.Header().Set("Content-Type", "text/html;charset=utf-8")
2021-07-14 19:51:55 +00:00
rq.ParseForm()
var (
values = rq.URL.Query()
username = strings.ToLower(values.Get("username"))
2021-07-14 19:51:55 +00:00
seemsValid = user.TelegramAuthParamsAreValid(values)
err = user.Register(
2021-07-14 19:51:55 +00:00
username,
"", // Password matters not
2021-07-14 21:00:35 +00:00
"editor",
2021-07-14 19:51:55 +00:00
"telegram",
false,
)
)
if user.HasUsername(username) && user.ByName(username).Source == "telegram" {
2021-07-14 19:51:55 +00:00
// Problems is something we put blankets on.
err = nil
}
if !seemsValid {
err = errors.New("Wrong parameters")
}
if err != nil {
log.Printf("Failed to register %s using Telegram: %s", username, err.Error())
w.WriteHeader(http.StatusBadRequest)
fmt.Fprint(
w,
views.BaseHTML(
2021-09-06 17:46:34 +00:00
lc.Get("ui.error"),
2021-07-14 19:51:55 +00:00
fmt.Sprintf(
2021-09-06 17:46:34 +00:00
`<main class="main-width"><p>%s</p><p>%s</p><p><a href="/login">%s<a></p></main>`,
lc.Get("auth.error_telegram"),
2021-07-14 19:51:55 +00:00
err.Error(),
2021-09-06 17:46:34 +00:00
lc.Get("auth.go_login"),
2021-07-14 19:51:55 +00:00
),
2021-09-06 17:46:34 +00:00
lc,
2021-07-14 19:51:55 +00:00
user.FromRequest(rq),
),
)
return
}
errmsg := user.LoginDataHTTP(w, rq, username, "")
if errmsg != "" {
log.Printf("Failed to login %s using Telegram: %s", username, err.Error())
w.WriteHeader(http.StatusBadRequest)
fmt.Fprint(
w,
views.BaseHTML(
"Error",
fmt.Sprintf(
2021-09-06 17:46:34 +00:00
`<main class="main-width"><p>%s</p><p>%s</p><p><a href="/login">%s<a></p></main>`,
lc.Get("auth.error_telegram"),
2021-07-14 19:51:55 +00:00
err.Error(),
2021-09-06 17:46:34 +00:00
lc.Get("auth.go_login"),
2021-07-14 19:51:55 +00:00
),
2021-09-06 17:46:34 +00:00
lc,
2021-07-14 19:51:55 +00:00
user.FromRequest(rq),
),
)
return
}
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.
2020-11-14 13:03:06 +00:00
func handlerLoginData(w http.ResponseWriter, rq *http.Request) {
2021-09-06 17:46:34 +00:00
lc := l18n.FromRequest(rq)
util.PrepareRq(rq)
2020-11-14 13:03:06 +00:00
var (
2021-02-17 18:41:35 +00:00
username = util.CanonicalName(rq.PostFormValue("username"))
2020-11-14 13:03:06 +00:00
password = rq.PostFormValue("password")
err = user.LoginDataHTTP(w, rq, username, password)
)
if err != "" {
2021-09-06 17:46:34 +00:00
w.Write([]byte(views.BaseHTML(err, views.LoginErrorHTML(err, lc), lc, user.EmptyUser())))
2020-11-14 13:03:06 +00:00
} else {
http.Redirect(w, rq, "/", http.StatusSeeOther)
}
}