2019-08-22 00:48:27 +02:00
|
|
|
package web
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
|
|
|
"strconv"
|
|
|
|
|
|
|
|
"golang.org/x/crypto/bcrypt"
|
|
|
|
|
|
|
|
"bitmask.me/skeleton/internal/database"
|
2019-12-14 07:28:33 +01:00
|
|
|
ldap "github.com/go-ldap/ldap/v3"
|
2019-08-22 00:48:27 +02:00
|
|
|
"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)
|
|
|
|
}
|
|
|
|
|
2019-12-14 07:28:33 +01:00
|
|
|
// 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) {
|
2019-08-22 00:48:27 +02:00
|
|
|
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"),
|
|
|
|
}
|
|
|
|
|
2019-12-14 07:28:33 +01:00
|
|
|
authenticate := NewSQLAuthenticator(h.App.Database())
|
2019-08-22 00:48:27 +02:00
|
|
|
|
|
|
|
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))
|
|
|
|
}
|