177 lines
4.1 KiB
Go
177 lines
4.1 KiB
Go
package login
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
"librapi/services"
|
|
"librapi/templates"
|
|
)
|
|
|
|
const URL = "/login"
|
|
|
|
var (
|
|
ErrInvalidUsername = errors.New("username must not be empty")
|
|
ErrInvalidPassword = errors.New("password must not be empty")
|
|
ErrInvalidCredentials = errors.New("bad credentials")
|
|
)
|
|
|
|
type LoginField struct {
|
|
Name string
|
|
Value string
|
|
Err string
|
|
}
|
|
|
|
type LoginForm struct {
|
|
Username LoginField
|
|
Password LoginField
|
|
Error error
|
|
Method string
|
|
}
|
|
|
|
func NewLoginForm() LoginForm {
|
|
return LoginForm{
|
|
Username: LoginField{
|
|
Name: "username",
|
|
},
|
|
Password: LoginField{
|
|
Name: "password",
|
|
},
|
|
Method: http.MethodPost,
|
|
}
|
|
}
|
|
|
|
func (lf *LoginForm) HasErrors() bool {
|
|
return lf.Username.Err != "" || lf.Password.Err != ""
|
|
}
|
|
|
|
func (lf *LoginForm) IsSuccess() bool {
|
|
return lf.Method == http.MethodPost && lf.Error != nil && !lf.HasErrors()
|
|
}
|
|
|
|
func Handler(a services.IAuthenticate) func(http.ResponseWriter, *http.Request) {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
switch r.Method {
|
|
case http.MethodGet:
|
|
getLogin(w, r, a)
|
|
case http.MethodPost:
|
|
postLogin(w, r, a)
|
|
default:
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
}
|
|
}
|
|
}
|
|
|
|
func extractLoginForm(r *http.Request) LoginForm {
|
|
lf := NewLoginForm()
|
|
|
|
username := r.FormValue(lf.Username.Name)
|
|
if username == "" {
|
|
lf.Username.Err = ErrInvalidUsername.Error()
|
|
}
|
|
lf.Username.Value = username
|
|
|
|
password := r.FormValue(lf.Password.Name)
|
|
if password == "" {
|
|
lf.Password.Err = ErrInvalidPassword.Error()
|
|
}
|
|
lf.Password.Value = password
|
|
|
|
return lf
|
|
}
|
|
|
|
func postLogin(w http.ResponseWriter, r *http.Request, a services.IAuthenticate) {
|
|
loginForm := templates.GetLoginForm()
|
|
loginSuccess := templates.GetLoginSuccess()
|
|
|
|
if a.IsLogged(r) {
|
|
buf := bytes.NewBufferString("")
|
|
if err := loginSuccess.Execute(buf, nil); err != nil {
|
|
log.Err(err).Msg("unable to generate template")
|
|
http.Error(w, "unexpected error occurred", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
fmt.Fprint(w, buf)
|
|
return
|
|
}
|
|
|
|
lf := extractLoginForm(r)
|
|
if lf.HasErrors() {
|
|
buf := bytes.NewBufferString("")
|
|
if err := loginForm.Execute(buf, &lf); err != nil {
|
|
log.Err(err).Msg("unable to generate template")
|
|
http.Error(w, "unexpected error occurred", http.StatusInternalServerError)
|
|
}
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
fmt.Fprint(w, buf.String())
|
|
return
|
|
}
|
|
|
|
session, err := a.Authenticate(lf.Username.Value, lf.Password.Value)
|
|
if err != nil {
|
|
if errors.Is(err, services.ErrUnauthorized) {
|
|
log.Warn().Str("username", lf.Username.Value).Msg("bad credentials")
|
|
|
|
lf.Error = ErrInvalidCredentials
|
|
|
|
buf := bytes.NewBufferString("")
|
|
if err := loginForm.Execute(buf, &lf); err != nil {
|
|
log.Err(err).Msg("unable to generate template")
|
|
http.Error(w, "unexpected error occurred", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
fmt.Fprint(w, buf.String())
|
|
return
|
|
}
|
|
|
|
http.Error(w, "unexpected error occurred", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
cookie := session.GenerateCookie(a.IsSecure())
|
|
http.SetCookie(w, cookie)
|
|
|
|
buf := bytes.NewBufferString("")
|
|
if err := loginSuccess.Execute(buf, nil); err != nil {
|
|
log.Err(err).Msg("unable to generate template")
|
|
http.Error(w, "unexpected error occurred", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
fmt.Fprint(w, buf)
|
|
}
|
|
|
|
func getLogin(w http.ResponseWriter, r *http.Request, a services.IAuthenticate) {
|
|
loginForm := templates.GetLoginForm()
|
|
|
|
if a.IsLogged(r) {
|
|
loginSuccess := templates.GetLoginSuccess()
|
|
|
|
buf := bytes.NewBufferString("")
|
|
if err := loginSuccess.Execute(buf, nil); err != nil {
|
|
log.Err(err).Msg("unable to generate template")
|
|
http.Error(w, "unexpected error occurred", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
fmt.Fprint(w, buf)
|
|
return
|
|
}
|
|
|
|
buf := bytes.NewBufferString("")
|
|
if err := loginForm.Execute(buf, &LoginForm{}); err != nil {
|
|
log.Err(err).Msg("unable to generate template")
|
|
http.Error(w, "unexpected error occurred", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
fmt.Fprint(w, buf)
|
|
}
|