Skip to content

Commit

Permalink
v1.1.2 add config.LogDebugFunc function to define debug level logging
Browse files Browse the repository at this point in the history
  • Loading branch information
vodolaz095 committed May 14, 2023
1 parent f3e974e commit a9a2565
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 17 deletions.
56 changes: 43 additions & 13 deletions authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package ldap4gin
import (
"context"
"fmt"
"log"
"math"
"strings"
"time"
Expand All @@ -25,13 +26,27 @@ func timeOut(ctx context.Context) (timeout int) {
return
}

type LogDebugFunc func(ctx context.Context, format string, a ...any)

var DefaultLogDebugFunc = func(ctx context.Context, format string, a ...any) {
log.Default().Printf("ldap4gin: "+format+"\n", a...)
}

// Authenticator links ldap and gin context together
type Authenticator struct {
fields []string
// Options are runtime options as received from New
Options *Options
// LDAPConn is ldap connection being used
LDAPConn *ldap.Conn
// LogDebugFunc is function to log debug information
LogDebugFunc LogDebugFunc
}

func (a *Authenticator) debug(ctx context.Context, format string, data ...any) {
if a.Options.Debug {
a.LogDebugFunc(ctx, format, data...)
}
}

func (a *Authenticator) bindAsUser(ctx context.Context, username, password string) (user *User, err error) {
Expand All @@ -48,6 +63,8 @@ func (a *Authenticator) bindAsUser(ctx context.Context, username, password strin
}
return
}
a.debug(ctx, "bind succeeded as %s", dn)

// Search info about given username
timeout := timeOut(ctx)
searchRequest := ldap.NewSearchRequest(
Expand All @@ -66,17 +83,19 @@ func (a *Authenticator) bindAsUser(ctx context.Context, username, password strin
return
}
if a.Options.Debug {
fmt.Println("ldap4gin: user profile found")
res.PrettyPrint(2)
}
if len(res.Entries) == 0 {
a.debug(ctx, "no user profile found for %s", username)
err = ErrNotFound
return
}
if len(res.Entries) > 1 {
a.debug(ctx, "multiple user profile found for %s", username)
err = ErrMultipleAccount
return
}
a.debug(ctx, "user's profile found for %s", username)
user, err = loadUserFromEntry(res.Entries[0])
return
}
Expand Down Expand Up @@ -134,15 +153,12 @@ func (a *Authenticator) attachGroups(ctx context.Context, user *User) (err error

func (a *Authenticator) reload(ctx context.Context, user *User) (err error) {
if !user.Expired() {
if a.Options.Debug {
fmt.Printf("ldap4gin: user %s will expire in %s\n",
user.UID, user.ExpiresAt.Sub(time.Now()).String())
}
a.debug(ctx, "user's profile %s not expired", user.UID)
return nil
}
if a.Options.Debug {
fmt.Printf("ldap4gin: user %s expired\n", user.UID)
}
a.debug(ctx, "user's profile %s expired on %s",
user.UID, user.ExpiresAt.Format(time.Stamp),
)
if a.Options.ReadonlyDN == "" {
err = fmt.Errorf("readonly distinguished name is not configured")
return
Expand Down Expand Up @@ -170,8 +186,9 @@ func (a *Authenticator) reload(ctx context.Context, user *User) (err error) {
if err != nil {
return
}
a.debug(ctx, "user %s profile is loaded from ldap", user.UID)

if a.Options.Debug {
fmt.Println("ldap4gin: user profile found")
res.PrettyPrint(2)
}
if len(res.Entries) == 0 {
Expand All @@ -186,6 +203,13 @@ func (a *Authenticator) reload(ctx context.Context, user *User) (err error) {
if err != nil {
return
}
if a.Options.TTL > 0 {
user.ExpiresAt = time.Now().Add(a.Options.TTL)
a.debug(ctx, "user %s session will expire on %s",
user.UID,
user.ExpiresAt.Format("15:04:05"),
)
}
if a.Options.ExtractGroups {
err = a.attachGroups(ctx, user)
}
Expand Down Expand Up @@ -229,11 +253,17 @@ func (a *Authenticator) Extract(c *gin.Context) (user *User, err error) {
err = fmt.Errorf("unknown type")
return
}
if a.Options.Debug {
fmt.Printf("ldap4gin: user %s is extracted from session of %v using %s\n",
user.UID, c.ClientIP(), c.GetHeader("User-Agent"))
}
a.debug(c.Request.Context(), "user %s is extracted from session of %v using %s",
user.UID, c.ClientIP(), c.GetHeader("User-Agent"))
err = a.reload(c.Request.Context(), user)
if err != nil {
return
}
if user.ExpiresAt.IsZero() {
a.debug(c.Request.Context(), "user %s session will expire at %s",
user.UID, user.ExpiresAt.Format(time.Stamp),
)
}
} else {
err = ErrUnauthorized
}
Expand Down
5 changes: 5 additions & 0 deletions new.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,10 @@ func New(opts *Options) (a *Authenticator, err error) {
}
}
a.LDAPConn = conn
if opts.LogDebugFunc != nil {
a.LogDebugFunc = opts.LogDebugFunc
} else {
a.LogDebugFunc = DefaultLogDebugFunc
}
return
}
7 changes: 4 additions & 3 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,11 @@ type Options struct {
// NOTICE - if you add too many fields, it can hit session size limits!
ExtraFields []string

/*
Used for extracting groups of user
*/
// ExtractGroups toggles extracting groups of user
ExtractGroups bool
// GroupsOU depicts organization unit for groups, usually "ou=groups,dc=vodolaz095,dc=ru"
GroupsOU string

// LogDebugFunc is called to log debug events
LogDebugFunc LogDebugFunc
}
3 changes: 2 additions & 1 deletion user.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package ldap4gin

import (
"fmt"
"github.com/go-ldap/ldap/v3"
"regexp"
"strconv"
"time"

"github.com/go-ldap/ldap/v3"
)

// User depicts profile of authorized user
Expand Down

0 comments on commit a9a2565

Please sign in to comment.