Initial commit
This commit is contained in:
12
ldap/provider.go
Normal file
12
ldap/provider.go
Normal file
@ -0,0 +1,12 @@
|
||||
package ldap
|
||||
|
||||
import "forge.cadoles.com/wpetit/goweb/service"
|
||||
|
||||
func ServiceProvider(url string) service.Provider {
|
||||
srv := &Service{
|
||||
url: url,
|
||||
}
|
||||
return func(ctn *service.Container) (interface{}, error) {
|
||||
return srv, nil
|
||||
}
|
||||
}
|
65
ldap/search.go
Normal file
65
ldap/search.go
Normal file
@ -0,0 +1,65 @@
|
||||
package ldap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
ldap "gopkg.in/ldap.v3"
|
||||
)
|
||||
|
||||
type SearchOptions struct {
|
||||
BaseDN string
|
||||
Scope int
|
||||
DerefAliases int
|
||||
SizeLimit int
|
||||
TimeLimit int
|
||||
TypesOnly bool
|
||||
Attributes []string
|
||||
Controls []ldap.Control
|
||||
}
|
||||
|
||||
type SearchOptionFunc func(opts *SearchOptions)
|
||||
|
||||
func WithBaseDN(dn string) SearchOptionFunc {
|
||||
return func(opts *SearchOptions) {
|
||||
opts.BaseDN = dn
|
||||
}
|
||||
}
|
||||
|
||||
func WithSizeLimit(sizeLimit int) SearchOptionFunc {
|
||||
return func(opts *SearchOptions) {
|
||||
opts.SizeLimit = sizeLimit
|
||||
}
|
||||
}
|
||||
|
||||
func WithAttributes(attributes ...string) SearchOptionFunc {
|
||||
return func(opts *SearchOptions) {
|
||||
opts.Attributes = attributes
|
||||
}
|
||||
}
|
||||
|
||||
func WithScope(scope int) SearchOptionFunc {
|
||||
return func(opts *SearchOptions) {
|
||||
opts.Scope = scope
|
||||
}
|
||||
}
|
||||
|
||||
func EscapeFilter(pattern string, values ...string) string {
|
||||
escapedValues := make([]interface{}, len(values))
|
||||
for i, v := range values {
|
||||
escapedValues[i] = ldap.EscapeFilter(v)
|
||||
}
|
||||
return fmt.Sprintf(pattern, escapedValues...)
|
||||
}
|
||||
|
||||
func defaultSearchOptions() *SearchOptions {
|
||||
return &SearchOptions{
|
||||
BaseDN: "",
|
||||
Scope: ldap.ScopeSingleLevel,
|
||||
DerefAliases: ldap.NeverDerefAliases,
|
||||
SizeLimit: 0,
|
||||
TimeLimit: 0,
|
||||
TypesOnly: false,
|
||||
Attributes: make([]string, 0),
|
||||
Controls: make([]ldap.Control, 0),
|
||||
}
|
||||
}
|
91
ldap/service.go
Normal file
91
ldap/service.go
Normal file
@ -0,0 +1,91 @@
|
||||
package ldap
|
||||
|
||||
import (
|
||||
"forge.cadoles.com/wpetit/goweb/service"
|
||||
"github.com/pkg/errors"
|
||||
ldap "gopkg.in/ldap.v3"
|
||||
)
|
||||
|
||||
const ServiceName service.Name = "ldap"
|
||||
|
||||
type Service struct {
|
||||
url string
|
||||
}
|
||||
|
||||
func (s *Service) Search(filter string, opts ...SearchOptionFunc) (*ldap.SearchResult, error) {
|
||||
conn, err := s.Connect()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error while connecting to ldap server")
|
||||
}
|
||||
defer conn.Close()
|
||||
return s.SearchConn(conn, filter, opts...)
|
||||
}
|
||||
|
||||
func (s *Service) SearchConn(conn *ldap.Conn, filter string, opts ...SearchOptionFunc) (*ldap.SearchResult, error) {
|
||||
options := defaultSearchOptions()
|
||||
for _, optFunc := range opts {
|
||||
optFunc(options)
|
||||
}
|
||||
req := ldap.NewSearchRequest(
|
||||
options.BaseDN,
|
||||
options.Scope,
|
||||
options.DerefAliases,
|
||||
options.SizeLimit,
|
||||
options.TimeLimit,
|
||||
options.TypesOnly,
|
||||
filter,
|
||||
options.Attributes,
|
||||
options.Controls,
|
||||
)
|
||||
result, err := conn.Search(req)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error while executing ldap search")
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *Service) Bind(dn, password string) error {
|
||||
conn, err := s.Connect()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error while connecting to ldap server")
|
||||
}
|
||||
defer conn.Close()
|
||||
return s.BindConn(conn, dn, password)
|
||||
}
|
||||
|
||||
func (s *Service) BindConn(conn *ldap.Conn, dn, password string) error {
|
||||
if err := conn.Bind(dn, password); err != nil {
|
||||
return errors.Wrap(err, "error while executing ldap bind")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) Connect() (*ldap.Conn, error) {
|
||||
conn, err := ldap.DialURL(s.url)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error while dialing ldap url '%s'", s.url)
|
||||
}
|
||||
return conn, err
|
||||
}
|
||||
|
||||
// From retrieves the ldap service in the given container
|
||||
func From(container *service.Container) (*Service, error) {
|
||||
service, err := container.Service(ServiceName)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error while retrieving '%s' service", ServiceName)
|
||||
}
|
||||
srv, ok := service.(*Service)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("retrieved service is not a valid '%s' service", ServiceName)
|
||||
}
|
||||
return srv, nil
|
||||
}
|
||||
|
||||
// Must retrieves the ldap service in the given container or panic otherwise
|
||||
func Must(container *service.Container) *Service {
|
||||
srv, err := From(container)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return srv
|
||||
}
|
Reference in New Issue
Block a user