mirror of
https://github.com/documize/community.git
synced 2025-07-20 05:39:42 +02:00
Bump Go deps
This commit is contained in:
parent
f2ba294be8
commit
acb59e1b43
91 changed files with 9004 additions and 513 deletions
303
vendor/github.com/go-ldap/ldap/v3/search.go
generated
vendored
303
vendor/github.com/go-ldap/ldap/v3/search.go
generated
vendored
|
@ -1,10 +1,14 @@
|
|||
package ldap
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
ber "github.com/go-asn1-ber/asn1-ber"
|
||||
)
|
||||
|
@ -161,6 +165,155 @@ func (e *Entry) PrettyPrint(indent int) {
|
|||
}
|
||||
}
|
||||
|
||||
// Describe the tag to use for struct field tags
|
||||
const decoderTagName = "ldap"
|
||||
|
||||
// readTag will read the reflect.StructField value for
|
||||
// the key defined in decoderTagName. If omitempty is
|
||||
// specified, the field may not be filled.
|
||||
func readTag(f reflect.StructField) (string, bool) {
|
||||
val, ok := f.Tag.Lookup(decoderTagName)
|
||||
if !ok {
|
||||
return f.Name, false
|
||||
}
|
||||
opts := strings.Split(val, ",")
|
||||
omit := false
|
||||
if len(opts) == 2 {
|
||||
omit = opts[1] == "omitempty"
|
||||
}
|
||||
return opts[0], omit
|
||||
}
|
||||
|
||||
// Unmarshal parses the Entry in the value pointed to by i
|
||||
//
|
||||
// Currently, this methods only supports struct fields of type
|
||||
// string, []string, int, int64, []byte, *DN, []*DN or time.Time. Other field types
|
||||
// will not be regarded. If the field type is a string or int but multiple
|
||||
// attribute values are returned, the first value will be used to fill the field.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type UserEntry struct {
|
||||
// // Fields with the tag key `dn` are automatically filled with the
|
||||
// // objects distinguishedName. This can be used multiple times.
|
||||
// DN string `ldap:"dn"`
|
||||
//
|
||||
// // This field will be filled with the attribute value for
|
||||
// // userPrincipalName. An attribute can be read into a struct field
|
||||
// // multiple times. Missing attributes will not result in an error.
|
||||
// UserPrincipalName string `ldap:"userPrincipalName"`
|
||||
//
|
||||
// // memberOf may have multiple values. If you don't
|
||||
// // know the amount of attribute values at runtime, use a string array.
|
||||
// MemberOf []string `ldap:"memberOf"`
|
||||
//
|
||||
// // ID is an integer value, it will fail unmarshaling when the given
|
||||
// // attribute value cannot be parsed into an integer.
|
||||
// ID int `ldap:"id"`
|
||||
//
|
||||
// // LongID is similar to ID but uses an int64 instead.
|
||||
// LongID int64 `ldap:"longId"`
|
||||
//
|
||||
// // Data is similar to MemberOf a slice containing all attribute
|
||||
// // values.
|
||||
// Data []byte `ldap:"data"`
|
||||
//
|
||||
// // Time is parsed with the generalizedTime spec into a time.Time
|
||||
// Created time.Time `ldap:"createdTimestamp"`
|
||||
//
|
||||
// // *DN is parsed with the ParseDN
|
||||
// Owner *ldap.DN `ldap:"owner"`
|
||||
//
|
||||
// // []*DN is parsed with the ParseDN
|
||||
// Children []*ldap.DN `ldap:"children"`
|
||||
//
|
||||
// // This won't work, as the field is not of type string. For this
|
||||
// // to work, you'll have to temporarily store the result in string
|
||||
// // (or string array) and convert it to the desired type afterwards.
|
||||
// UserAccountControl uint32 `ldap:"userPrincipalName"`
|
||||
// }
|
||||
// user := UserEntry{}
|
||||
//
|
||||
// if err := result.Unmarshal(&user); err != nil {
|
||||
// // ...
|
||||
// }
|
||||
func (e *Entry) Unmarshal(i interface{}) (err error) {
|
||||
// Make sure it's a ptr
|
||||
if vo := reflect.ValueOf(i).Kind(); vo != reflect.Ptr {
|
||||
return fmt.Errorf("ldap: cannot use %s, expected pointer to a struct", vo)
|
||||
}
|
||||
|
||||
sv, st := reflect.ValueOf(i).Elem(), reflect.TypeOf(i).Elem()
|
||||
// Make sure it's pointing to a struct
|
||||
if sv.Kind() != reflect.Struct {
|
||||
return fmt.Errorf("ldap: expected pointer to a struct, got %s", sv.Kind())
|
||||
}
|
||||
|
||||
for n := 0; n < st.NumField(); n++ {
|
||||
// Holds struct field value and type
|
||||
fv, ft := sv.Field(n), st.Field(n)
|
||||
|
||||
// skip unexported fields
|
||||
if ft.PkgPath != "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// omitempty can be safely discarded, as it's not needed when unmarshalling
|
||||
fieldTag, _ := readTag(ft)
|
||||
|
||||
// Fill the field with the distinguishedName if the tag key is `dn`
|
||||
if fieldTag == "dn" {
|
||||
fv.SetString(e.DN)
|
||||
continue
|
||||
}
|
||||
|
||||
values := e.GetAttributeValues(fieldTag)
|
||||
if len(values) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
switch fv.Interface().(type) {
|
||||
case []string:
|
||||
for _, item := range values {
|
||||
fv.Set(reflect.Append(fv, reflect.ValueOf(item)))
|
||||
}
|
||||
case string:
|
||||
fv.SetString(values[0])
|
||||
case []byte:
|
||||
fv.SetBytes([]byte(values[0]))
|
||||
case int, int64:
|
||||
intVal, err := strconv.ParseInt(values[0], 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ldap: could not parse value '%s' into int field", values[0])
|
||||
}
|
||||
fv.SetInt(intVal)
|
||||
case time.Time:
|
||||
t, err := ber.ParseGeneralizedTime([]byte(values[0]))
|
||||
if err != nil {
|
||||
return fmt.Errorf("ldap: could not parse value '%s' into time.Time field", values[0])
|
||||
}
|
||||
fv.Set(reflect.ValueOf(t))
|
||||
case *DN:
|
||||
dn, err := ParseDN(values[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("ldap: could not parse value '%s' into *ldap.DN field", values[0])
|
||||
}
|
||||
fv.Set(reflect.ValueOf(dn))
|
||||
case []*DN:
|
||||
for _, item := range values {
|
||||
dn, err := ParseDN(item)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ldap: could not parse value '%s' into *ldap.DN field", item)
|
||||
}
|
||||
fv.Set(reflect.Append(fv, reflect.ValueOf(dn)))
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("ldap: expected field to be of type string, []string, int, int64, []byte, *DN, []*DN or time.Time, got %v", ft.Type)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// NewEntryAttribute returns a new EntryAttribute with the desired key-value pair
|
||||
func NewEntryAttribute(name string, values []string) *EntryAttribute {
|
||||
var bytes [][]byte
|
||||
|
@ -218,6 +371,35 @@ func (s *SearchResult) PrettyPrint(indent int) {
|
|||
}
|
||||
}
|
||||
|
||||
// appendTo appends all entries of `s` to `r`
|
||||
func (s *SearchResult) appendTo(r *SearchResult) {
|
||||
r.Entries = append(r.Entries, s.Entries...)
|
||||
r.Referrals = append(r.Referrals, s.Referrals...)
|
||||
r.Controls = append(r.Controls, s.Controls...)
|
||||
}
|
||||
|
||||
// SearchSingleResult holds the server's single entry response to a search request
|
||||
type SearchSingleResult struct {
|
||||
// Entry is the returned entry
|
||||
Entry *Entry
|
||||
// Referral is the returned referral
|
||||
Referral string
|
||||
// Controls are the returned controls
|
||||
Controls []Control
|
||||
// Error is set when the search request was failed
|
||||
Error error
|
||||
}
|
||||
|
||||
// Print outputs a human-readable description
|
||||
func (s *SearchSingleResult) Print() {
|
||||
s.Entry.Print()
|
||||
}
|
||||
|
||||
// PrettyPrint outputs a human-readable description with indenting
|
||||
func (s *SearchSingleResult) PrettyPrint(indent int) {
|
||||
s.Entry.PrettyPrint(indent)
|
||||
}
|
||||
|
||||
// SearchRequest represents a search request to send to the server
|
||||
type SearchRequest struct {
|
||||
BaseDN string
|
||||
|
@ -285,10 +467,11 @@ func NewSearchRequest(
|
|||
// SearchWithPaging accepts a search request and desired page size in order to execute LDAP queries to fulfill the
|
||||
// search request. All paged LDAP query responses will be buffered and the final result will be returned atomically.
|
||||
// The following four cases are possible given the arguments:
|
||||
// - given SearchRequest missing a control of type ControlTypePaging: we will add one with the desired paging size
|
||||
// - given SearchRequest contains a control of type ControlTypePaging that isn't actually a ControlPaging: fail without issuing any queries
|
||||
// - given SearchRequest contains a control of type ControlTypePaging with pagingSize equal to the size requested: no change to the search request
|
||||
// - given SearchRequest contains a control of type ControlTypePaging with pagingSize not equal to the size requested: fail without issuing any queries
|
||||
// - given SearchRequest missing a control of type ControlTypePaging: we will add one with the desired paging size
|
||||
// - given SearchRequest contains a control of type ControlTypePaging that isn't actually a ControlPaging: fail without issuing any queries
|
||||
// - given SearchRequest contains a control of type ControlTypePaging with pagingSize equal to the size requested: no change to the search request
|
||||
// - given SearchRequest contains a control of type ControlTypePaging with pagingSize not equal to the size requested: fail without issuing any queries
|
||||
//
|
||||
// A requested pagingSize of 0 is interpreted as no limit by LDAP servers.
|
||||
func (l *Conn) SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32) (*SearchResult, error) {
|
||||
var pagingControl *ControlPaging
|
||||
|
@ -311,23 +494,19 @@ func (l *Conn) SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32)
|
|||
searchResult := new(SearchResult)
|
||||
for {
|
||||
result, err := l.Search(searchRequest)
|
||||
l.Debug.Printf("Looking for Paging Control...")
|
||||
if result != nil {
|
||||
result.appendTo(searchResult)
|
||||
} else {
|
||||
if err == nil {
|
||||
// We have to do this beautifulness in case something absolutely strange happens, which
|
||||
// should only occur in case there is no packet, but also no error.
|
||||
return searchResult, NewError(ErrorNetwork, errors.New("ldap: packet not received"))
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
// If an error occurred, all results that have been received so far will be returned
|
||||
return searchResult, err
|
||||
}
|
||||
if result == nil {
|
||||
return searchResult, NewError(ErrorNetwork, errors.New("ldap: packet not received"))
|
||||
}
|
||||
|
||||
for _, entry := range result.Entries {
|
||||
searchResult.Entries = append(searchResult.Entries, entry)
|
||||
}
|
||||
for _, referral := range result.Referrals {
|
||||
searchResult.Referrals = append(searchResult.Referrals, referral)
|
||||
}
|
||||
for _, control := range result.Controls {
|
||||
searchResult.Controls = append(searchResult.Controls, control)
|
||||
}
|
||||
|
||||
l.Debug.Printf("Looking for Paging Control...")
|
||||
pagingResult := FindControl(result.Controls, ControlTypePaging)
|
||||
|
@ -349,7 +528,9 @@ func (l *Conn) SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32)
|
|||
if pagingControl != nil {
|
||||
l.Debug.Printf("Abandoning Paging...")
|
||||
pagingControl.PagingSize = 0
|
||||
l.Search(searchRequest)
|
||||
if _, err := l.Search(searchRequest); err != nil {
|
||||
return searchResult, err
|
||||
}
|
||||
}
|
||||
|
||||
return searchResult, nil
|
||||
|
@ -366,7 +547,8 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
|
|||
result := &SearchResult{
|
||||
Entries: make([]*Entry, 0),
|
||||
Referrals: make([]string, 0),
|
||||
Controls: make([]Control, 0)}
|
||||
Controls: make([]Control, 0),
|
||||
}
|
||||
|
||||
for {
|
||||
packet, err := l.readPacket(msgCtx)
|
||||
|
@ -402,6 +584,32 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// SearchAsync performs a search request and returns all search results asynchronously.
|
||||
// This means you get all results until an error happens (or the search successfully finished),
|
||||
// e.g. for size / time limited requests all are recieved until the limit is reached.
|
||||
// To stop the search, call cancel function of the context.
|
||||
func (l *Conn) SearchAsync(
|
||||
ctx context.Context, searchRequest *SearchRequest, bufferSize int) Response {
|
||||
r := newSearchResponse(l, bufferSize)
|
||||
r.start(ctx, searchRequest)
|
||||
return r
|
||||
}
|
||||
|
||||
// Syncrepl is a short name for LDAP Sync Replication engine that works on the
|
||||
// consumer-side. This can perform a persistent search and returns an entry
|
||||
// when the entry is updated on the server side.
|
||||
// To stop the search, call cancel function of the context.
|
||||
func (l *Conn) Syncrepl(
|
||||
ctx context.Context, searchRequest *SearchRequest, bufferSize int,
|
||||
mode ControlSyncRequestMode, cookie []byte, reloadHint bool,
|
||||
) Response {
|
||||
control := NewControlSyncRequest(mode, cookie, reloadHint)
|
||||
searchRequest.Controls = append(searchRequest.Controls, control)
|
||||
r := newSearchResponse(l, bufferSize)
|
||||
r.start(ctx, searchRequest)
|
||||
return r
|
||||
}
|
||||
|
||||
// unpackAttributes will extract all given LDAP attributes and it's values
|
||||
// from the ber.Packet
|
||||
func unpackAttributes(children []*ber.Packet) []*EntryAttribute {
|
||||
|
@ -425,3 +633,58 @@ func unpackAttributes(children []*ber.Packet) []*EntryAttribute {
|
|||
|
||||
return entries
|
||||
}
|
||||
|
||||
// DirSync does a Search with dirSync Control.
|
||||
func (l *Conn) DirSync(
|
||||
searchRequest *SearchRequest, flags int64, maxAttrCount int64, cookie []byte,
|
||||
) (*SearchResult, error) {
|
||||
control := FindControl(searchRequest.Controls, ControlTypeDirSync)
|
||||
if control == nil {
|
||||
c := NewRequestControlDirSync(flags, maxAttrCount, cookie)
|
||||
searchRequest.Controls = append(searchRequest.Controls, c)
|
||||
} else {
|
||||
c := control.(*ControlDirSync)
|
||||
if c.Flags != flags {
|
||||
return nil, fmt.Errorf("flags given in search request (%d) conflicts with flags given in search call (%d)", c.Flags, flags)
|
||||
}
|
||||
if c.MaxAttrCount != maxAttrCount {
|
||||
return nil, fmt.Errorf("MaxAttrCnt given in search request (%d) conflicts with maxAttrCount given in search call (%d)", c.MaxAttrCount, maxAttrCount)
|
||||
}
|
||||
}
|
||||
searchResult, err := l.Search(searchRequest)
|
||||
l.Debug.Printf("Looking for result...")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if searchResult == nil {
|
||||
return nil, NewError(ErrorNetwork, errors.New("ldap: packet not received"))
|
||||
}
|
||||
|
||||
l.Debug.Printf("Looking for DirSync Control...")
|
||||
resultControl := FindControl(searchResult.Controls, ControlTypeDirSync)
|
||||
if resultControl == nil {
|
||||
l.Debug.Printf("Could not find dirSyncControl control. Breaking...")
|
||||
return searchResult, nil
|
||||
}
|
||||
|
||||
cookie = resultControl.(*ControlDirSync).Cookie
|
||||
if len(cookie) == 0 {
|
||||
l.Debug.Printf("Could not find cookie. Breaking...")
|
||||
return searchResult, nil
|
||||
}
|
||||
|
||||
return searchResult, nil
|
||||
}
|
||||
|
||||
// DirSyncDirSyncAsync performs a search request and returns all search results
|
||||
// asynchronously. This is efficient when the server returns lots of entries.
|
||||
func (l *Conn) DirSyncAsync(
|
||||
ctx context.Context, searchRequest *SearchRequest, bufferSize int,
|
||||
flags, maxAttrCount int64, cookie []byte,
|
||||
) Response {
|
||||
control := NewRequestControlDirSync(flags, maxAttrCount, cookie)
|
||||
searchRequest.Controls = append(searchRequest.Controls, control)
|
||||
r := newSearchResponse(l, bufferSize)
|
||||
r.start(ctx, searchRequest)
|
||||
return r
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue