package testclient
import (
"crypto/tls"
"time"
"gopkg.in/ldap.v2"
)
// Fake is a mock client for an LDAP server
// The following methods define safe defaults for the return values. In order to adapt this test client
// for a specific test, anonymously include it and override the method being tested. In the over-riden
// method, if you are not covering all method calls with your override, defer to the parent for handling.
type Fake struct {
SimpleBindResponse *ldap.SimpleBindResult
PasswordModifyResponse *ldap.PasswordModifyResult
SearchResponse *ldap.SearchResult
}
var _ ldap.Client = &Fake{}
// NewTestClient returns a new test client with safe default return values
func New() *Fake {
return &Fake{
SimpleBindResponse: &ldap.SimpleBindResult{
Controls: []ldap.Control{},
},
PasswordModifyResponse: &ldap.PasswordModifyResult{
GeneratedPassword: "",
},
SearchResponse: &ldap.SearchResult{
Entries: []*ldap.Entry{},
Referrals: []string{},
Controls: []ldap.Control{},
},
}
}
// Start starts the LDAP connection
func (c *Fake) Start() {
return
}
// StartTLS begins a TLS-wrapped LDAP connection
func (c *Fake) StartTLS(config *tls.Config) error {
return nil
}
// Close closes an LDAP connection
func (c *Fake) Close() {
return
}
// Bind binds to the LDAP server with a bind DN and password
func (c *Fake) Bind(username, password string) error {
return nil
}
// SimpleBind binds to the LDAP server using the Simple Bind mechanism
func (c *Fake) SimpleBind(simpleBindRequest *ldap.SimpleBindRequest) (*ldap.SimpleBindResult, error) {
return c.SimpleBindResponse, nil
}
// Add forwards an addition request to the LDAP server
func (c *Fake) Add(addRequest *ldap.AddRequest) error {
return nil
}
// Del forwards a deletion request to the LDAP server
func (c *Fake) Del(delRequest *ldap.DelRequest) error {
return nil
}
// Modify forwards a modification request to the LDAP server
func (c *Fake) Modify(modifyRequest *ldap.ModifyRequest) error {
return nil
}
// Compare ... ?
func (c *Fake) Compare(dn, attribute, value string) (bool, error) {
return false, nil
}
// PasswordModify forwards a password modify request to the LDAP server
func (c *Fake) PasswordModify(passwordModifyRequest *ldap.PasswordModifyRequest) (*ldap.PasswordModifyResult, error) {
return c.PasswordModifyResponse, nil
}
// Search forwards a search request to the LDAP server
func (c *Fake) Search(searchRequest *ldap.SearchRequest) (*ldap.SearchResult, error) {
return c.SearchResponse, nil
}
// SearchWithPaging forwards a search request to the LDAP server and pages the response
func (c *Fake) SearchWithPaging(searchRequest *ldap.SearchRequest, pagingSize uint32) (*ldap.SearchResult, error) {
return c.SearchResponse, nil
}
// SetTimeout sets a timeout on the client
func (c *Fake) SetTimeout(d time.Duration) {
}
// NewMatchingSearchErrorClient returns a new MatchingSearchError client sitting on top of the parent
// client. This client returns the given error when a search base DN matches the given base DN, and
// defers to the parent otherwise.
func NewMatchingSearchErrorClient(parent ldap.Client, baseDN string, returnErr error) ldap.Client {
return &MatchingSearchErrClient{
Client: parent,
BaseDN: baseDN,
ReturnErr: returnErr,
}
}
// MatchingSearchErrClient returns the ReturnErr on every Search() where the search base DN matches the given DN
// or defers the search to the parent client
type MatchingSearchErrClient struct {
ldap.Client
BaseDN string
ReturnErr error
}
func (c *MatchingSearchErrClient) Search(searchRequest *ldap.SearchRequest) (*ldap.SearchResult, error) {
if searchRequest.BaseDN == c.BaseDN {
return nil, c.ReturnErr
}
return c.Client.Search(searchRequest)
}
// NewDNMappingClient returns a new DNMappingClient sitting on top of the parent client. This client returns the
// ldap entries mapped to with this DN in its' internal DN map, or defers to the parent if the DN is not mapped.
func NewDNMappingClient(parent ldap.Client, DNMapping map[string][]*ldap.Entry) ldap.Client {
return &DNMappingClient{
Client: parent,
DNMapping: DNMapping,
}
}
// DNMappingClient returns the LDAP entry mapped to by the base dn given, or if no mapping happens, defers to the parent
type DNMappingClient struct {
ldap.Client
DNMapping map[string][]*ldap.Entry
}
func (c *DNMappingClient) Search(searchRequest *ldap.SearchRequest) (*ldap.SearchResult, error) {
if entries, exists := c.DNMapping[searchRequest.BaseDN]; exists {
return &ldap.SearchResult{Entries: entries}, nil
}
return c.Client.Search(searchRequest)
}
// NewPagingOnlyClient returns a new PagingOnlyClient sitting on top of the parent client. This client returns the
// provided search response for any calls to SearchWithPaging, or defers to the parent if the call is not to the
// paged search function.
func NewPagingOnlyClient(parent ldap.Client, response *ldap.SearchResult) ldap.Client {
return &PagingOnlyClient{
Client: parent,
Response: response,
}
}
// PagingOnlyClient responds with a canned search result for any calls to SearchWithPaging
type PagingOnlyClient struct {
ldap.Client
Response *ldap.SearchResult
}
func (c *PagingOnlyClient) SearchWithPaging(searchRequest *ldap.SearchRequest, pagingSize uint32) (*ldap.SearchResult, error) {
return c.Response, nil
}