code.gitea.io/gitea@v1.21.7/services/auth/signin.go (about) 1 // Copyright 2021 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package auth 5 6 import ( 7 "context" 8 "strings" 9 10 "code.gitea.io/gitea/models/auth" 11 "code.gitea.io/gitea/models/db" 12 user_model "code.gitea.io/gitea/models/user" 13 "code.gitea.io/gitea/modules/log" 14 "code.gitea.io/gitea/services/auth/source/oauth2" 15 "code.gitea.io/gitea/services/auth/source/smtp" 16 17 _ "code.gitea.io/gitea/services/auth/source/db" // register the sources (and below) 18 _ "code.gitea.io/gitea/services/auth/source/ldap" // register the ldap source 19 _ "code.gitea.io/gitea/services/auth/source/pam" // register the pam source 20 _ "code.gitea.io/gitea/services/auth/source/sspi" // register the sspi source 21 ) 22 23 // UserSignIn validates user name and password. 24 func UserSignIn(ctx context.Context, username, password string) (*user_model.User, *auth.Source, error) { 25 var user *user_model.User 26 isEmail := false 27 if strings.Contains(username, "@") { 28 isEmail = true 29 emailAddress := user_model.EmailAddress{LowerEmail: strings.ToLower(strings.TrimSpace(username))} 30 // check same email 31 has, err := db.GetEngine(ctx).Get(&emailAddress) 32 if err != nil { 33 return nil, nil, err 34 } 35 if has { 36 if !emailAddress.IsActivated { 37 return nil, nil, user_model.ErrEmailAddressNotExist{ 38 Email: username, 39 } 40 } 41 user = &user_model.User{ID: emailAddress.UID} 42 } 43 } else { 44 trimmedUsername := strings.TrimSpace(username) 45 if len(trimmedUsername) == 0 { 46 return nil, nil, user_model.ErrUserNotExist{Name: username} 47 } 48 49 user = &user_model.User{LowerName: strings.ToLower(trimmedUsername)} 50 } 51 52 if user != nil { 53 hasUser, err := user_model.GetUser(ctx, user) 54 if err != nil { 55 return nil, nil, err 56 } 57 58 if hasUser { 59 source, err := auth.GetSourceByID(user.LoginSource) 60 if err != nil { 61 return nil, nil, err 62 } 63 64 if !source.IsActive { 65 return nil, nil, oauth2.ErrAuthSourceNotActivated 66 } 67 68 authenticator, ok := source.Cfg.(PasswordAuthenticator) 69 if !ok { 70 return nil, nil, smtp.ErrUnsupportedLoginType 71 } 72 73 user, err := authenticator.Authenticate(ctx, user, user.LoginName, password) 74 if err != nil { 75 return nil, nil, err 76 } 77 78 // WARN: DON'T check user.IsActive, that will be checked on reqSign so that 79 // user could be hint to resend confirm email. 80 if user.ProhibitLogin { 81 return nil, nil, user_model.ErrUserProhibitLogin{UID: user.ID, Name: user.Name} 82 } 83 84 return user, source, nil 85 } 86 } 87 88 sources, err := auth.AllActiveSources() 89 if err != nil { 90 return nil, nil, err 91 } 92 93 for _, source := range sources { 94 if !source.IsActive { 95 // don't try to authenticate non-active sources 96 continue 97 } 98 99 authenticator, ok := source.Cfg.(PasswordAuthenticator) 100 if !ok { 101 continue 102 } 103 104 authUser, err := authenticator.Authenticate(ctx, nil, username, password) 105 106 if err == nil { 107 if !authUser.ProhibitLogin { 108 return authUser, source, nil 109 } 110 err = user_model.ErrUserProhibitLogin{UID: authUser.ID, Name: authUser.Name} 111 } 112 113 if user_model.IsErrUserNotExist(err) { 114 log.Debug("Failed to login '%s' via '%s': %v", username, source.Name, err) 115 } else { 116 log.Warn("Failed to login '%s' via '%s': %v", username, source.Name, err) 117 } 118 } 119 120 if isEmail { 121 return nil, nil, user_model.ErrEmailAddressNotExist{Email: username} 122 } 123 124 return nil, nil, user_model.ErrUserNotExist{Name: username} 125 }