2021-07-24 13:16:34 +03:00
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package auth
import (
"strings"
2022-01-02 16:12:35 +03:00
"code.gitea.io/gitea/models/auth"
2021-09-19 14:49:59 +03:00
"code.gitea.io/gitea/models/db"
2021-11-11 10:03:30 +03:00
user_model "code.gitea.io/gitea/models/user"
2021-07-24 13:16:34 +03:00
"code.gitea.io/gitea/modules/log"
2021-11-27 14:59:51 +03:00
"code.gitea.io/gitea/services/auth/source/oauth2"
"code.gitea.io/gitea/services/auth/source/smtp"
2021-07-24 13:16:34 +03:00
2021-11-24 12:49:20 +03:00
_ "code.gitea.io/gitea/services/auth/source/db" // register the sources (and below)
_ "code.gitea.io/gitea/services/auth/source/ldap" // register the ldap source
2021-11-27 14:59:51 +03:00
_ "code.gitea.io/gitea/services/auth/source/pam" // register the pam source
2021-11-24 12:49:20 +03:00
_ "code.gitea.io/gitea/services/auth/source/sspi" // register the sspi source
2021-07-24 13:16:34 +03:00
)
// UserSignIn validates user name and password.
2022-01-02 16:12:35 +03:00
func UserSignIn ( username , password string ) ( * user_model . User , * auth . Source , error ) {
2021-11-24 12:49:20 +03:00
var user * user_model . User
2022-03-31 16:20:25 +03:00
isEmail := false
2021-07-24 13:16:34 +03:00
if strings . Contains ( username , "@" ) {
2022-03-31 16:20:25 +03:00
isEmail = true
2022-02-18 12:33:00 +03:00
emailAddress := user_model . EmailAddress { LowerEmail : strings . ToLower ( strings . TrimSpace ( username ) ) }
2021-07-24 13:16:34 +03:00
// check same email
2022-03-31 16:20:25 +03:00
has , err := db . GetEngine ( db . DefaultContext ) . Get ( & emailAddress )
2021-07-24 13:16:34 +03:00
if err != nil {
2021-09-17 14:43:47 +03:00
return nil , nil , err
2021-07-24 13:16:34 +03:00
}
2022-03-31 16:20:25 +03:00
if has {
if ! emailAddress . IsActivated {
return nil , nil , user_model . ErrEmailAddressNotExist {
Email : username ,
}
2021-07-24 13:16:34 +03:00
}
2022-03-31 16:20:25 +03:00
user = & user_model . User { ID : emailAddress . UID }
2021-07-24 13:16:34 +03:00
}
} else {
trimmedUsername := strings . TrimSpace ( username )
if len ( trimmedUsername ) == 0 {
2021-11-24 12:49:20 +03:00
return nil , nil , user_model . ErrUserNotExist { Name : username }
2021-07-24 13:16:34 +03:00
}
2021-11-24 12:49:20 +03:00
user = & user_model . User { LowerName : strings . ToLower ( trimmedUsername ) }
2021-07-24 13:16:34 +03:00
}
2022-03-31 16:20:25 +03:00
if user != nil {
hasUser , err := user_model . GetUser ( user )
2021-07-24 13:16:34 +03:00
if err != nil {
2021-09-17 14:43:47 +03:00
return nil , nil , err
2021-07-24 13:16:34 +03:00
}
2022-03-31 16:20:25 +03:00
if hasUser {
source , err := auth . GetSourceByID ( user . LoginSource )
if err != nil {
return nil , nil , err
}
2021-07-24 13:16:34 +03:00
2022-03-31 16:20:25 +03:00
if ! source . IsActive {
return nil , nil , oauth2 . ErrAuthSourceNotActived
}
2021-07-24 13:16:34 +03:00
2022-03-31 16:20:25 +03:00
authenticator , ok := source . Cfg . ( PasswordAuthenticator )
if ! ok {
return nil , nil , smtp . ErrUnsupportedLoginType
}
2021-07-24 13:16:34 +03:00
2022-03-31 16:20:25 +03:00
user , err := authenticator . Authenticate ( user , user . LoginName , password )
if err != nil {
return nil , nil , err
}
2021-07-24 13:16:34 +03:00
2022-03-31 16:20:25 +03:00
// WARN: DON'T check user.IsActive, that will be checked on reqSign so that
// user could be hint to resend confirm email.
if user . ProhibitLogin {
return nil , nil , user_model . ErrUserProhibitLogin { UID : user . ID , Name : user . Name }
}
return user , source , nil
}
2021-07-24 13:16:34 +03:00
}
2022-01-02 16:12:35 +03:00
sources , err := auth . AllActiveSources ( )
2021-07-24 13:16:34 +03:00
if err != nil {
2021-09-17 14:43:47 +03:00
return nil , nil , err
2021-07-24 13:16:34 +03:00
}
for _ , source := range sources {
if ! source . IsActive {
// don't try to authenticate non-active sources
continue
}
authenticator , ok := source . Cfg . ( PasswordAuthenticator )
if ! ok {
continue
}
authUser , err := authenticator . Authenticate ( nil , username , password )
if err == nil {
if ! authUser . ProhibitLogin {
2021-09-17 14:43:47 +03:00
return authUser , source , nil
2021-07-24 13:16:34 +03:00
}
2021-11-24 12:49:20 +03:00
err = user_model . ErrUserProhibitLogin { UID : authUser . ID , Name : authUser . Name }
2021-07-24 13:16:34 +03:00
}
2021-11-24 12:49:20 +03:00
if user_model . IsErrUserNotExist ( err ) {
2021-07-24 13:16:34 +03:00
log . Debug ( "Failed to login '%s' via '%s': %v" , username , source . Name , err )
} else {
log . Warn ( "Failed to login '%s' via '%s': %v" , username , source . Name , err )
}
}
2022-03-31 16:20:25 +03:00
if isEmail {
return nil , nil , user_model . ErrEmailAddressNotExist { Email : username }
}
2021-11-24 12:49:20 +03:00
return nil , nil , user_model . ErrUserNotExist { Name : username }
2021-07-24 13:16:34 +03:00
}