diff options
-rw-r--r-- | models/login.go | 128 | ||||
-rw-r--r-- | models/user.go | 38 | ||||
-rw-r--r-- | modules/auth/auth.go | 1 | ||||
-rw-r--r-- | modules/auth/ldap/ldap.go | 4 | ||||
-rw-r--r-- | modules/auth/ldap/ldap_test.go | 32 | ||||
-rw-r--r-- | routers/admin/user.go | 3 | ||||
-rw-r--r-- | routers/user/user.go | 5 | ||||
-rw-r--r-- | templates/admin/users/edit.tmpl | 7 | ||||
-rw-r--r-- | templates/admin/users/new.tmpl | 7 |
9 files changed, 183 insertions, 42 deletions
diff --git a/models/login.go b/models/login.go index 21e1ce686a..05ffac2c57 100644 --- a/models/login.go +++ b/models/login.go @@ -7,6 +7,7 @@ package models import ( "encoding/json" "errors" + "strings" "time" "github.com/go-xorm/core" @@ -17,7 +18,8 @@ import ( // Login types. const ( - LT_PLAIN = iota + 1 + LT_NOTYPE = iota + LT_PLAIN LT_LDAP LT_SMTP ) @@ -49,13 +51,14 @@ func (cfg *LDAPConfig) ToDB() ([]byte, error) { } type LoginSource struct { - Id int64 - Type int - Name string `xorm:"unique"` - IsActived bool `xorm:"not null default false"` - Cfg core.Conversion `xorm:"TEXT"` - Created time.Time `xorm:"created"` - Updated time.Time `xorm:"updated"` + Id int64 + Type int + Name string `xorm:"unique"` + IsActived bool `xorm:"not null default false"` + Cfg core.Conversion `xorm:"TEXT"` + Created time.Time `xorm:"created"` + Updated time.Time `xorm:"updated"` + AllowAutoRegisted bool `xorm:"not null default false"` } func (source *LoginSource) TypeString() string { @@ -120,3 +123,112 @@ func DelLoginSource(source *LoginSource) error { _, err = orm.Id(source.Id).Delete(&LoginSource{}) return err } + +// login a user +func LoginUser(uname, passwd string) (*User, error) { + var u *User + var emailLogin bool + if strings.Contains(uname, "@") { + u = &User{Email: uname} + emailLogin = true + } else { + u = &User{LowerName: strings.ToLower(uname)} + } + + has, err := orm.Get(u) + if err != nil { + return nil, err + } + + // if email login, then we cannot auto register + if emailLogin { + if !has { + return nil, ErrUserNotExist + } + } + if u.LoginType == LT_NOTYPE { + u.LoginType = LT_PLAIN + } + + // for plain login, user must have existed. + if u.LoginType == LT_PLAIN { + if !has { + return nil, ErrUserNotExist + } + + newUser := &User{Passwd: passwd, Salt: u.Salt} + newUser.EncodePasswd() + if u.Passwd != newUser.Passwd { + return nil, ErrUserNotExist + } + return u, nil + } else { + if !has { + var sources []LoginSource + cond := &LoginSource{IsActived: true, AllowAutoRegisted: true} + err = orm.UseBool().Find(&sources, cond) + if err != nil { + return nil, err + } + + for _, source := range sources { + u, err := LoginUserLdapSource(nil, u.LoginName, passwd, + source.Id, source.Cfg.(*LDAPConfig), true) + if err == nil { + return u, err + } + } + + return nil, ErrUserNotExist + } + + var source LoginSource + hasSource, err := orm.Id(u.LoginSource).Get(&source) + if err != nil { + return nil, err + } + if !hasSource { + return nil, ErrLoginSourceNotExist + } + + if !source.IsActived { + return nil, ErrLoginSourceNotActived + } + + switch u.LoginType { + case LT_LDAP: + return LoginUserLdapSource(u, u.LoginName, passwd, + source.Id, source.Cfg.(*LDAPConfig), false) + case LT_SMTP: + } + return nil, ErrUnsupportedLoginType + } +} + +// Query if name/passwd can login against the LDAP direcotry pool +// Create a local user if success +// Return the same LoginUserPlain semantic +func LoginUserLdapSource(user *User, name, passwd string, sourceId int64, cfg *LDAPConfig, autoRegister bool) (*User, error) { + mail, logged := cfg.Ldapsource.SearchEntry(name, passwd) + if !logged { + // user not in LDAP, do nothing + return nil, ErrUserNotExist + } + if !autoRegister { + return user, nil + } + + // fake a local user creation + user = &User{ + LowerName: strings.ToLower(name), + Name: strings.ToLower(name), + LoginType: LT_LDAP, + LoginSource: sourceId, + LoginName: name, + IsActive: true, + Passwd: passwd, + Email: mail, + } + + return RegisterUser(user) +} diff --git a/models/user.go b/models/user.go index b2b16f1136..c5c474ee6f 100644 --- a/models/user.go +++ b/models/user.go @@ -27,11 +27,14 @@ const ( ) var ( - ErrUserOwnRepos = errors.New("User still have ownership of repositories") - ErrUserAlreadyExist = errors.New("User already exist") - ErrUserNotExist = errors.New("User does not exist") - ErrEmailAlreadyUsed = errors.New("E-mail already used") - ErrUserNameIllegal = errors.New("User name contains illegal characters") + ErrUserOwnRepos = errors.New("User still have ownership of repositories") + ErrUserAlreadyExist = errors.New("User already exist") + ErrUserNotExist = errors.New("User does not exist") + ErrEmailAlreadyUsed = errors.New("E-mail already used") + ErrUserNameIllegal = errors.New("User name contains illegal characters") + ErrLoginSourceNotExist = errors.New("Login source does not exist") + ErrLoginSourceNotActived = errors.New("Login source is not actived") + ErrUnsupportedLoginType = errors.New("Login source is unknow") ) // User represents the object of individual and member of organization. @@ -44,6 +47,7 @@ type User struct { Passwd string `xorm:"not null"` LoginType int LoginSource int64 `xorm:"not null default 0"` + LoginName string Type int NumFollowers int NumFollowings int @@ -439,30 +443,6 @@ func SearchUserByName(key string, limit int) (us []*User, err error) { return us, err } -// LoginUserPlain validates user by raw user name and password. -func LoginUserPlain(uname, passwd string) (*User, error) { - var u *User - if strings.Contains(uname, "@") { - u = &User{Email: uname} - } else { - u = &User{LowerName: strings.ToLower(uname)} - } - - has, err := orm.Get(u) - if err != nil { - return nil, err - } else if !has { - return nil, ErrUserNotExist - } - - newUser := &User{Passwd: passwd, Salt: u.Salt} - newUser.EncodePasswd() - if u.Passwd != newUser.Passwd { - return nil, ErrUserNotExist - } - return u, nil -} - // Follow is connection request for receiving user notifycation. type Follow struct { Id int64 diff --git a/modules/auth/auth.go b/modules/auth/auth.go index 4587b3835b..eefb5ed6e3 100644 --- a/modules/auth/auth.go +++ b/modules/auth/auth.go @@ -27,6 +27,7 @@ type RegisterForm struct { Password string `form:"passwd" binding:"Required;MinSize(6);MaxSize(30)"` RetypePasswd string `form:"retypepasswd"` LoginType string `form:"logintype"` + LoginName string `form:"loginname"` } func (f *RegisterForm) Name(field string) string { diff --git a/modules/auth/ldap/ldap.go b/modules/auth/ldap/ldap.go index 8578e38a4d..493339cde0 100644 --- a/modules/auth/ldap/ldap.go +++ b/modules/auth/ldap/ldap.go @@ -42,7 +42,7 @@ func AddSource(name string, host string, port int, basedn string, attributes str func LoginUser(name, passwd string) (a string, r bool) { r = false for _, ls := range Authensource { - a, r = ls.searchEntry(name, passwd) + a, r = ls.SearchEntry(name, passwd) if r { return } @@ -51,7 +51,7 @@ func LoginUser(name, passwd string) (a string, r bool) { } // searchEntry : search an LDAP source if an entry (name, passwd) is valide and in the specific filter -func (ls Ldapsource) searchEntry(name, passwd string) (string, bool) { +func (ls Ldapsource) SearchEntry(name, passwd string) (string, bool) { l, err := goldap.Dial("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port)) if err != nil { log.Debug("LDAP Connect error, disabled source %s", ls.Host) diff --git a/modules/auth/ldap/ldap_test.go b/modules/auth/ldap/ldap_test.go new file mode 100644 index 0000000000..8096573782 --- /dev/null +++ b/modules/auth/ldap/ldap_test.go @@ -0,0 +1,32 @@ +package ldap + +import ( + "fmt" + "testing" +) + +var ldapServer = "ldap.itd.umich.edu" +var ldapPort = uint16(389) +var baseDN = "dc=umich,dc=edu" +var filter = []string{ + "(cn=cis-fac)", + "(&(objectclass=rfc822mailgroup)(cn=*Computer*))", + "(&(objectclass=rfc822mailgroup)(cn=*Mathematics*))"} +var attributes = []string{ + "cn", + "description"} +var msadsaformat = "" + +func TestLDAP(t *testing.T) { + AddSource("test", ldapServer, ldapPort, + basedn, attributes, filter, + msadsaformat) + user, err := LoginUserLdap("xiaolunwen", "") + if err != nil { + t.Error(err) + return + } + + fmt.Println(user) + +} diff --git a/routers/admin/user.go b/routers/admin/user.go index 0d60ee9a76..fa98bd32ea 100644 --- a/routers/admin/user.go +++ b/routers/admin/user.go @@ -58,7 +58,8 @@ func NewUserPost(ctx *middleware.Context, form auth.RegisterForm) { fields := strings.Split(form.LoginType, "-") u.LoginType, _ = strconv.Atoi(fields[0]) u.LoginSource, _ = strconv.ParseInt(fields[1], 10, 64) - fmt.Println(u.LoginSource) + u.LoginName = form.LoginName + fmt.Println(u.LoginType, u.LoginSource, u.LoginName) } var err error diff --git a/routers/user/user.go b/routers/user/user.go index e33353abdb..6a7d016612 100644 --- a/routers/user/user.go +++ b/routers/user/user.go @@ -92,7 +92,7 @@ func SignInPost(ctx *middleware.Context, form auth.LogInForm) { var user *models.User var err error - if base.Service.LdapAuth { + /*if base.Service.LdapAuth { user, err = models.LoginUserLdap(form.UserName, form.Password) if err != nil { log.Error("Fail to login through LDAP: %v", err) @@ -101,7 +101,8 @@ func SignInPost(ctx *middleware.Context, form auth.LogInForm) { // try local if not LDAP or it's failed if !base.Service.LdapAuth || err != nil { user, err = models.LoginUserPlain(form.UserName, form.Password) - } + }*/ + user, err = models.LoginUser(form.UserName, form.Password) if err != nil { if err == models.ErrUserNotExist { log.Trace("%s Log in failed: %s/%s", ctx.Req.RequestURI, form.UserName, form.Password) diff --git a/templates/admin/users/edit.tmpl b/templates/admin/users/edit.tmpl index 1fb29234ed..4995856768 100644 --- a/templates/admin/users/edit.tmpl +++ b/templates/admin/users/edit.tmpl @@ -27,6 +27,13 @@ </div> <div class="form-group"> + <label class="col-md-3 control-label">Auth Login Name: </label> + <div class="col-md-7"> + <input name="loginname" class="form-control" placeholder="Type auth login's username" value="{{.loginname}}"> + </div> + </div> + + <div class="form-group"> <label class="col-md-3 control-label">Username: </label> <label class="control-label">{{.User.Name}}</label> </div> diff --git a/templates/admin/users/new.tmpl b/templates/admin/users/new.tmpl index 88da16aa4e..b4843a99ca 100644 --- a/templates/admin/users/new.tmpl +++ b/templates/admin/users/new.tmpl @@ -24,6 +24,13 @@ </select> </div> </div> + + <div class="form-group"> + <label class="col-md-3 control-label">Auth Login Name: </label> + <div class="col-md-7"> + <input name="loginname" class="form-control" placeholder="Type auth login's username" value="{{.loginname}}"> + </div> + </div> <div class="form-group {{if .Err_UserName}}has-error has-feedback{{end}}"> <label class="col-md-3 control-label">Username: </label> |