Switch to go modules

This commit is contained in:
paul 2019-12-14 07:28:33 +01:00
parent cf455ba7d9
commit 007b2a375f
6 changed files with 261 additions and 5 deletions

108
internal/ldap/ldap.go Normal file
View file

@ -0,0 +1,108 @@
package ldap
import (
"fmt"
"regexp"
ldap "github.com/go-ldap/ldap/v3"
"github.com/pkg/errors"
)
var (
// TimeLimitSeconds is the maximal time that LDAP will spend on a single
// request.
TimeLimitSeconds = 5
// SizeLimitEntries is the biggest number of results that is returned from a
// search request.
SizeLimitEntries = 100
// UserAttributes is the list of LDAP-Attributes that will be used for user
// accounts.
UserAttributes = []string{
"dn", // distinguished name, the unique "path" to a LDAP entry.
"cn", // common name, human readable e.g. "Max Powers".
"uid", // user identified, same as the username/login name.
"uidNumber", // unique user ID, integer.
"createTimestamp", // LDAP timestamp of when this entry was created.
"modifyTimestamp", // LDAP timestemp of when this entry was last modified.
}
)
type Server struct {
Host string
Port int
bindDN string
bindPW string
userBaseDN string
}
func (s *Server) newConn() (*ldap.Conn, error) {
lc, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", s.Host, s.Port))
if err != nil {
return nil, errors.Wrap(err, "Failed to dial LDAP")
}
err = lc.Bind(s.bindDN, s.bindPW)
if err != nil {
return nil, errors.Wrap(err, "Failed to bind service account to LDAP")
}
return lc, nil
}
// buildFilterForID builds an LDAP filter that searches for a user with a
// specific uidNumber.
func (s *Server) buildFilterForUserID(id int) string {
return fmt.Sprintf("(&(objectClass=inetOrgPerson)(uidNumber=%d))", id)
}
func (s *Server) buildFilterForEmail(email string) string {
reg := regexp.MustCompile("[^a-zA-Z0-9-+._@]+")
email = reg.ReplaceAllString(email, "")
return fmt.Sprintf("(&(objectClass=)())")
// Conn is an LDAP connection.
type Conn struct {
*ldap.Conn
}
type User struct {
Entry *ldap.Entry
}
// GetDisplayName implements User interface by returning the display name.
func (u User) GetDisplayName() string {
display := u.Entry.GetAttributeValue("displayName")
if display == "" {
display = u.Entry.GetAttributeValue("givenName")
}
if display == "" {
display = u.Entry.GetAttributeValue("cn")
}
if display == "" {
display = u.GetID()
}
return display
}
// GetID implements the User interface by returning the user ID.
func (u User) GetID() string {
id := u.Entry.GetAttributeValue("uid")
return id
}
func (lc *Conn) UserByID(ID string) (User, error) {
ldap.NewSearchRequest()
}
func (s *Server) UserByEmail(email string) (User, error) {
lc, err := s.newConn()
ldap.NewSearchRequest(
s.userBaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
SizeLimitEntries, TimeLimitSeconds, false,
s.buildFilterForEmail(email), UserAttributes, nil)
}

View file

@ -4,7 +4,7 @@ import (
"net/http"
"bitmask.me/skeleton/internal/app"
"github.com/alexedwards/scs"
scs "github.com/alexedwards/scs/v2"
"github.com/gorilla/csrf"
)

View file

@ -7,6 +7,7 @@ import (
"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"
)
@ -36,8 +37,15 @@ func (u UserRow) GetID() string {
return strconv.FormatInt(u.ID, 10)
}
// NewAuthenticator returns a authable function from a Database.
func NewAuthenticator(db *sqlx.DB) func(user, pass string) (User, error) {
// 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)
@ -77,7 +85,7 @@ func (h *Handlers) LoginPageHandler(w http.ResponseWriter, r *http.Request) {
Password: r.PostFormValue("password"),
}
authenticate := NewAuthenticator(h.App.Database())
authenticate := NewSQLAuthenticator(h.App.Database())
user, err := authenticate(loginForm.Login, loginForm.Password)
if err != nil {

View file

@ -5,7 +5,7 @@ import (
"net/rpc"
"strings"
"github.com/alexedwards/scs"
scs "github.com/alexedwards/scs/v2"
)
// GRPCMiddleware allows a HTTP2 Server to also serve GRPC at the same port.