skeleton/internal/web/handlers_auth.go
2019-12-14 07:28:56 +01:00

107 lines
2.6 KiB
Go

package web
import (
"net/http"
"strconv"
"golang.org/x/crypto/bcrypt"
"bitmask.me/skeleton/internal/database"
ldap "github.com/go-ldap/ldap/v3"
"github.com/jmoiron/sqlx"
"github.com/pkg/errors"
)
// ErrNotImplemented is returned whenever a feature is not implemented yet.
var ErrNotImplemented = errors.New("Not implemented")
// User interface is provided by all data types that are returned from a
// User store.
type User interface {
GetID() string
GetDisplayName() string
}
// UserRow wraps a user row from the database.
type UserRow struct {
*database.User
}
// GetDisplayName implements User interface by returning the display name.
func (u UserRow) GetDisplayName() string {
return u.GetID()
}
// GetID implements the User interface by returning the user ID.
func (u UserRow) GetID() string {
return strconv.FormatInt(u.ID, 10)
}
// NewLDAPAuthenticator returns a authable function from a LDAP Database.
func NewLDAPAuthenticator(lc *ldap.Conn) func(user, pass string) (User, error) {
return func(user, pass string) (User, error) {
return nil, ErrNotImplemented
}
}
// NewSQLAuthenticator returns a authable function from a Database.
func NewSQLAuthenticator(db *sqlx.DB) func(user, pass string) (User, error) {
return func(user, pass string) (User, error) {
// Fetch email used for login
email, err := database.EmailByAddress(db, user)
if err != nil {
return nil, err
}
row, err := email.User(db)
if err != nil {
return nil, err
}
//u.Password
err = bcrypt.CompareHashAndPassword(row.Password, []byte(pass))
if err != nil {
return nil, err
}
u := UserRow{row}
return u, nil
}
}
// LoginPageHandler renders the login page, and sets session cookies
// on successful authentication.
func (h *Handlers) LoginPageHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodPost {
type LoginForm struct {
Login string
Password string
}
loginForm := LoginForm{
Login: r.PostFormValue("login"),
Password: r.PostFormValue("password"),
}
authenticate := NewSQLAuthenticator(h.App.Database())
user, err := authenticate(loginForm.Login, loginForm.Password)
if err != nil {
context := h.commonRenderContext(r)
context["Errors"] = []string{"Wrong username or password"}
h.Templates().Get("auth_login.tmpl").Execute(w, context)
return
}
sess := h.Session()
sess.Put(r.Context(), SessKeyUserID, user.GetID())
sess.Put(r.Context(), SessKeyUserName, user.GetDisplayName())
http.Redirect(w, r, "/app", http.StatusFound)
return
}
h.Templates().Get("auth_login.tmpl").Execute(w, h.commonRenderContext(r))
}