mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Move twofactor to models/login (#17143)
This commit is contained in:
		| @@ -1876,25 +1876,6 @@ func (err ErrTeamNotExist) Error() string { | ||||
| 	return fmt.Sprintf("team does not exist [org_id %d, team_id %d, name: %s]", err.OrgID, err.TeamID, err.Name) | ||||
| } | ||||
|  | ||||
| // | ||||
| // Two-factor authentication | ||||
| // | ||||
|  | ||||
| // ErrTwoFactorNotEnrolled indicates that a user is not enrolled in two-factor authentication. | ||||
| type ErrTwoFactorNotEnrolled struct { | ||||
| 	UID int64 | ||||
| } | ||||
|  | ||||
| // IsErrTwoFactorNotEnrolled checks if an error is a ErrTwoFactorNotEnrolled. | ||||
| func IsErrTwoFactorNotEnrolled(err error) bool { | ||||
| 	_, ok := err.(ErrTwoFactorNotEnrolled) | ||||
| 	return ok | ||||
| } | ||||
|  | ||||
| func (err ErrTwoFactorNotEnrolled) Error() string { | ||||
| 	return fmt.Sprintf("user not enrolled in 2FA [uid: %d]", err.UID) | ||||
| } | ||||
|  | ||||
| //  ____ ___        .__                    .___ | ||||
| // |    |   \______ |  |   _________     __| _/ | ||||
| // |    |   /\____ \|  |  /  _ \__  \   / __ | | ||||
| @@ -1959,28 +1940,6 @@ func (err ErrExternalLoginUserNotExist) Error() string { | ||||
| 	return fmt.Sprintf("external login user link does not exists [userID: %d, loginSourceID: %d]", err.UserID, err.LoginSourceID) | ||||
| } | ||||
|  | ||||
| // ____ ________________________________              .__          __                 __  .__ | ||||
| // |    |   \_____  \_   _____/\______   \ ____   ____ |__| _______/  |_____________ _/  |_|__| ____   ____ | ||||
| // |    |   //  ____/|    __)   |       _// __ \ / ___\|  |/  ___/\   __\_  __ \__  \\   __\  |/  _ \ /    \ | ||||
| // |    |  //       \|     \    |    |   \  ___// /_/  >  |\___ \  |  |  |  | \// __ \|  | |  (  <_> )   |  \ | ||||
| // |______/ \_______ \___  /    |____|_  /\___  >___  /|__/____  > |__|  |__|  (____  /__| |__|\____/|___|  / | ||||
| // \/   \/            \/     \/_____/         \/                   \/                    \/ | ||||
|  | ||||
| // ErrU2FRegistrationNotExist represents a "ErrU2FRegistrationNotExist" kind of error. | ||||
| type ErrU2FRegistrationNotExist struct { | ||||
| 	ID int64 | ||||
| } | ||||
|  | ||||
| func (err ErrU2FRegistrationNotExist) Error() string { | ||||
| 	return fmt.Sprintf("U2F registration does not exist [id: %d]", err.ID) | ||||
| } | ||||
|  | ||||
| // IsErrU2FRegistrationNotExist checks if an error is a ErrU2FRegistrationNotExist. | ||||
| func IsErrU2FRegistrationNotExist(err error) bool { | ||||
| 	_, ok := err.(ErrU2FRegistrationNotExist) | ||||
| 	return ok | ||||
| } | ||||
|  | ||||
| // .___                            ________                                   .___                   .__ | ||||
| // |   | ______ ________ __   ____ \______ \   ____ ______   ____   ____    __| _/____   ____   ____ |__| ____   ______ | ||||
| // |   |/  ___//  ___/  |  \_/ __ \ |    |  \_/ __ \\____ \_/ __ \ /    \  / __ |/ __ \ /    \_/ ___\|  |/ __ \ /  ___/ | ||||
|   | ||||
| @@ -17,5 +17,6 @@ func TestMain(m *testing.M) { | ||||
| 		"oauth2_application.yml", | ||||
| 		"oauth2_authorization_code.yml", | ||||
| 		"oauth2_grant.yml", | ||||
| 		"u2f_registration.yml", | ||||
| 	) | ||||
| } | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
| // Use of this source code is governed by a MIT-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| package models | ||||
| package login | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/md5" | ||||
| @@ -21,6 +21,25 @@ import ( | ||||
| 	"golang.org/x/crypto/pbkdf2" | ||||
| ) | ||||
| 
 | ||||
| // | ||||
| // Two-factor authentication | ||||
| // | ||||
| 
 | ||||
| // ErrTwoFactorNotEnrolled indicates that a user is not enrolled in two-factor authentication. | ||||
| type ErrTwoFactorNotEnrolled struct { | ||||
| 	UID int64 | ||||
| } | ||||
| 
 | ||||
| // IsErrTwoFactorNotEnrolled checks if an error is a ErrTwoFactorNotEnrolled. | ||||
| func IsErrTwoFactorNotEnrolled(err error) bool { | ||||
| 	_, ok := err.(ErrTwoFactorNotEnrolled) | ||||
| 	return ok | ||||
| } | ||||
| 
 | ||||
| func (err ErrTwoFactorNotEnrolled) Error() string { | ||||
| 	return fmt.Sprintf("user not enrolled in 2FA [uid: %d]", err.UID) | ||||
| } | ||||
| 
 | ||||
| // TwoFactor represents a two-factor authentication token. | ||||
| type TwoFactor struct { | ||||
| 	ID               int64 `xorm:"pk autoincr"` | ||||
| @@ -44,11 +63,12 @@ func (t *TwoFactor) GenerateScratchToken() (string, error) { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	t.ScratchSalt, _ = util.RandomString(10) | ||||
| 	t.ScratchHash = hashToken(token, t.ScratchSalt) | ||||
| 	t.ScratchHash = HashToken(token, t.ScratchSalt) | ||||
| 	return token, nil | ||||
| } | ||||
| 
 | ||||
| func hashToken(token, salt string) string { | ||||
| // HashToken return the hashable salt | ||||
| func HashToken(token, salt string) string { | ||||
| 	tempHash := pbkdf2.Key([]byte(token), []byte(salt), 10000, 50, sha256.New) | ||||
| 	return fmt.Sprintf("%x", tempHash) | ||||
| } | ||||
| @@ -58,7 +78,7 @@ func (t *TwoFactor) VerifyScratchToken(token string) bool { | ||||
| 	if len(token) == 0 { | ||||
| 		return false | ||||
| 	} | ||||
| 	tempHash := hashToken(token, t.ScratchSalt) | ||||
| 	tempHash := HashToken(token, t.ScratchSalt) | ||||
| 	return subtle.ConstantTimeCompare([]byte(t.ScratchHash), []byte(tempHash)) == 1 | ||||
| } | ||||
| 
 | ||||
| @@ -2,9 +2,11 @@ | ||||
| // Use of this source code is governed by a MIT-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| package models | ||||
| package login | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"code.gitea.io/gitea/models/db" | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"code.gitea.io/gitea/modules/timeutil" | ||||
| @@ -12,6 +14,28 @@ import ( | ||||
| 	"github.com/tstranex/u2f" | ||||
| ) | ||||
| 
 | ||||
| // ____ ________________________________              .__          __                 __  .__ | ||||
| // |    |   \_____  \_   _____/\______   \ ____   ____ |__| _______/  |_____________ _/  |_|__| ____   ____ | ||||
| // |    |   //  ____/|    __)   |       _// __ \ / ___\|  |/  ___/\   __\_  __ \__  \\   __\  |/  _ \ /    \ | ||||
| // |    |  //       \|     \    |    |   \  ___// /_/  >  |\___ \  |  |  |  | \// __ \|  | |  (  <_> )   |  \ | ||||
| // |______/ \_______ \___  /    |____|_  /\___  >___  /|__/____  > |__|  |__|  (____  /__| |__|\____/|___|  / | ||||
| // \/   \/            \/     \/_____/         \/                   \/                    \/ | ||||
| 
 | ||||
| // ErrU2FRegistrationNotExist represents a "ErrU2FRegistrationNotExist" kind of error. | ||||
| type ErrU2FRegistrationNotExist struct { | ||||
| 	ID int64 | ||||
| } | ||||
| 
 | ||||
| func (err ErrU2FRegistrationNotExist) Error() string { | ||||
| 	return fmt.Sprintf("U2F registration does not exist [id: %d]", err.ID) | ||||
| } | ||||
| 
 | ||||
| // IsErrU2FRegistrationNotExist checks if an error is a ErrU2FRegistrationNotExist. | ||||
| func IsErrU2FRegistrationNotExist(err error) bool { | ||||
| 	_, ok := err.(ErrU2FRegistrationNotExist) | ||||
| 	return ok | ||||
| } | ||||
| 
 | ||||
| // U2FRegistration represents the registration data and counter of a security key | ||||
| type U2FRegistration struct { | ||||
| 	ID          int64 `xorm:"pk autoincr"` | ||||
| @@ -91,13 +115,13 @@ func GetU2FRegistrationsByUID(uid int64) (U2FRegistrationList, error) { | ||||
| 	return getU2FRegistrationsByUID(db.GetEngine(db.DefaultContext), uid) | ||||
| } | ||||
| 
 | ||||
| func createRegistration(e db.Engine, user *User, name string, reg *u2f.Registration) (*U2FRegistration, error) { | ||||
| func createRegistration(e db.Engine, userID int64, name string, reg *u2f.Registration) (*U2FRegistration, error) { | ||||
| 	raw, err := reg.MarshalBinary() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	r := &U2FRegistration{ | ||||
| 		UserID:  user.ID, | ||||
| 		UserID:  userID, | ||||
| 		Name:    name, | ||||
| 		Counter: 0, | ||||
| 		Raw:     raw, | ||||
| @@ -110,8 +134,8 @@ func createRegistration(e db.Engine, user *User, name string, reg *u2f.Registrat | ||||
| } | ||||
| 
 | ||||
| // CreateRegistration will create a new U2FRegistration from the given Registration | ||||
| func CreateRegistration(user *User, name string, reg *u2f.Registration) (*U2FRegistration, error) { | ||||
| 	return createRegistration(db.GetEngine(db.DefaultContext), user, name, reg) | ||||
| func CreateRegistration(userID int64, name string, reg *u2f.Registration) (*U2FRegistration, error) { | ||||
| 	return createRegistration(db.GetEngine(db.DefaultContext), userID, name, reg) | ||||
| } | ||||
| 
 | ||||
| // DeleteRegistration will delete U2FRegistration | ||||
| @@ -2,12 +2,13 @@ | ||||
| // Use of this source code is governed by a MIT-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| package models | ||||
| package login | ||||
| 
 | ||||
| import ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"code.gitea.io/gitea/models/db" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"github.com/tstranex/u2f" | ||||
| ) | ||||
| @@ -55,14 +56,13 @@ func TestU2FRegistration_UpdateLargeCounter(t *testing.T) { | ||||
| 
 | ||||
| func TestCreateRegistration(t *testing.T) { | ||||
| 	assert.NoError(t, db.PrepareTestDatabase()) | ||||
| 	user := db.AssertExistsAndLoadBean(t, &User{ID: 1}).(*User) | ||||
| 
 | ||||
| 	res, err := CreateRegistration(user, "U2F Created Key", &u2f.Registration{Raw: []byte("Test")}) | ||||
| 	res, err := CreateRegistration(1, "U2F Created Key", &u2f.Registration{Raw: []byte("Test")}) | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.Equal(t, "U2F Created Key", res.Name) | ||||
| 	assert.Equal(t, []byte("Test"), res.Raw) | ||||
| 
 | ||||
| 	db.AssertExistsIf(t, true, &U2FRegistration{Name: "U2F Created Key", UserID: user.ID}) | ||||
| 	db.AssertExistsIf(t, true, &U2FRegistration{Name: "U2F Created Key", UserID: 1}) | ||||
| } | ||||
| 
 | ||||
| func TestDeleteRegistration(t *testing.T) { | ||||
| @@ -6,6 +6,7 @@ package models | ||||
|  | ||||
| import ( | ||||
| 	"code.gitea.io/gitea/models/db" | ||||
| 	"code.gitea.io/gitea/models/login" | ||||
| 	"code.gitea.io/gitea/modules/git" | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| @@ -44,8 +45,8 @@ Loop: | ||||
| 				return false, "", nil, &ErrWontSign{pubkey} | ||||
| 			} | ||||
| 		case twofa: | ||||
| 			twofaModel, err := GetTwoFactorByUID(u.ID) | ||||
| 			if err != nil && !IsErrTwoFactorNotEnrolled(err) { | ||||
| 			twofaModel, err := login.GetTwoFactorByUID(u.ID) | ||||
| 			if err != nil && !login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 				return false, "", nil, err | ||||
| 			} | ||||
| 			if twofaModel == nil { | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models/db" | ||||
| 	"code.gitea.io/gitea/models/login" | ||||
| 	"code.gitea.io/gitea/modules/git" | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"code.gitea.io/gitea/modules/process" | ||||
| @@ -129,8 +130,8 @@ Loop: | ||||
| 				return false, "", nil, &ErrWontSign{pubkey} | ||||
| 			} | ||||
| 		case twofa: | ||||
| 			twofaModel, err := GetTwoFactorByUID(u.ID) | ||||
| 			if err != nil && !IsErrTwoFactorNotEnrolled(err) { | ||||
| 			twofaModel, err := login.GetTwoFactorByUID(u.ID) | ||||
| 			if err != nil && !login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 				return false, "", nil, err | ||||
| 			} | ||||
| 			if twofaModel == nil { | ||||
| @@ -165,8 +166,8 @@ Loop: | ||||
| 				return false, "", nil, &ErrWontSign{pubkey} | ||||
| 			} | ||||
| 		case twofa: | ||||
| 			twofaModel, err := GetTwoFactorByUID(u.ID) | ||||
| 			if err != nil && !IsErrTwoFactorNotEnrolled(err) { | ||||
| 			twofaModel, err := login.GetTwoFactorByUID(u.ID) | ||||
| 			if err != nil && !login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 				return false, "", nil, err | ||||
| 			} | ||||
| 			if twofaModel == nil { | ||||
| @@ -218,8 +219,8 @@ Loop: | ||||
| 				return false, "", nil, &ErrWontSign{pubkey} | ||||
| 			} | ||||
| 		case twofa: | ||||
| 			twofaModel, err := GetTwoFactorByUID(u.ID) | ||||
| 			if err != nil && !IsErrTwoFactorNotEnrolled(err) { | ||||
| 			twofaModel, err := login.GetTwoFactorByUID(u.ID) | ||||
| 			if err != nil && !login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 				return false, "", nil, err | ||||
| 			} | ||||
| 			if twofaModel == nil { | ||||
|   | ||||
| @@ -11,6 +11,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models/db" | ||||
| 	"code.gitea.io/gitea/models/login" | ||||
| 	"code.gitea.io/gitea/modules/base" | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| 	"code.gitea.io/gitea/modules/timeutil" | ||||
| @@ -67,7 +68,7 @@ func NewAccessToken(t *AccessToken) error { | ||||
| 	} | ||||
| 	t.TokenSalt = salt | ||||
| 	t.Token = base.EncodeSha1(gouuid.New().String()) | ||||
| 	t.TokenHash = hashToken(t.Token, t.TokenSalt) | ||||
| 	t.TokenHash = login.HashToken(t.Token, t.TokenSalt) | ||||
| 	t.TokenLastEight = t.Token[len(t.Token)-8:] | ||||
| 	_, err = db.GetEngine(db.DefaultContext).Insert(t) | ||||
| 	return err | ||||
| @@ -129,7 +130,7 @@ func GetAccessTokenBySHA(token string) (*AccessToken, error) { | ||||
| 	} | ||||
|  | ||||
| 	for _, t := range tokens { | ||||
| 		tempHash := hashToken(token, t.TokenSalt) | ||||
| 		tempHash := login.HashToken(token, t.TokenSalt) | ||||
| 		if subtle.ConstantTimeCompare([]byte(t.TokenHash), []byte(tempHash)) == 1 { | ||||
| 			if successfulAccessTokenCache != nil { | ||||
| 				successfulAccessTokenCache.Add(token, t.ID) | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models/db" | ||||
| 	"code.gitea.io/gitea/models/login" | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| ) | ||||
|  | ||||
| @@ -79,13 +80,13 @@ func (users UserList) GetTwoFaStatus() map[int64]bool { | ||||
| 	return results | ||||
| } | ||||
|  | ||||
| func (users UserList) loadTwoFactorStatus(e db.Engine) (map[int64]*TwoFactor, error) { | ||||
| func (users UserList) loadTwoFactorStatus(e db.Engine) (map[int64]*login.TwoFactor, error) { | ||||
| 	if len(users) == 0 { | ||||
| 		return nil, nil | ||||
| 	} | ||||
|  | ||||
| 	userIDs := users.getUserIDs() | ||||
| 	tokenMaps := make(map[int64]*TwoFactor, len(userIDs)) | ||||
| 	tokenMaps := make(map[int64]*login.TwoFactor, len(userIDs)) | ||||
| 	err := e. | ||||
| 		In("uid", userIDs). | ||||
| 		Find(&tokenMaps) | ||||
|   | ||||
| @@ -14,6 +14,7 @@ import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models" | ||||
| 	"code.gitea.io/gitea/models/login" | ||||
| 	"code.gitea.io/gitea/modules/git" | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| @@ -219,9 +220,9 @@ func (ctx *APIContext) CheckForOTP() { | ||||
| 	} | ||||
|  | ||||
| 	otpHeader := ctx.Req.Header.Get("X-Gitea-OTP") | ||||
| 	twofa, err := models.GetTwoFactorByUID(ctx.Context.User.ID) | ||||
| 	twofa, err := login.GetTwoFactorByUID(ctx.Context.User.ID) | ||||
| 	if err != nil { | ||||
| 		if models.IsErrTwoFactorNotEnrolled(err) { | ||||
| 		if login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 			return // No 2FA enrollment for this user | ||||
| 		} | ||||
| 		ctx.Context.Error(http.StatusInternalServerError) | ||||
|   | ||||
| @@ -8,7 +8,7 @@ package context | ||||
| import ( | ||||
| 	"net/http" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models" | ||||
| 	"code.gitea.io/gitea/models/login" | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| 	"code.gitea.io/gitea/modules/web/middleware" | ||||
| @@ -154,9 +154,9 @@ func ToggleAPI(options *ToggleOptions) func(ctx *APIContext) { | ||||
| 				if skip, ok := ctx.Data["SkipLocalTwoFA"]; ok && skip.(bool) { | ||||
| 					return // Skip 2FA | ||||
| 				} | ||||
| 				twofa, err := models.GetTwoFactorByUID(ctx.User.ID) | ||||
| 				twofa, err := login.GetTwoFactorByUID(ctx.User.ID) | ||||
| 				if err != nil { | ||||
| 					if models.IsErrTwoFactorNotEnrolled(err) { | ||||
| 					if login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 						return // No 2FA enrollment for this user | ||||
| 					} | ||||
| 					ctx.InternalServerError(err) | ||||
|   | ||||
| @@ -195,9 +195,9 @@ func prepareUserInfo(ctx *context.Context) *models.User { | ||||
| 	ctx.Data["Sources"] = sources | ||||
|  | ||||
| 	ctx.Data["TwoFactorEnabled"] = true | ||||
| 	_, err = models.GetTwoFactorByUID(u.ID) | ||||
| 	_, err = login.GetTwoFactorByUID(u.ID) | ||||
| 	if err != nil { | ||||
| 		if !models.IsErrTwoFactorNotEnrolled(err) { | ||||
| 		if !login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 			ctx.ServerError("IsErrTwoFactorNotEnrolled", err) | ||||
| 			return nil | ||||
| 		} | ||||
| @@ -295,13 +295,13 @@ func EditUserPost(ctx *context.Context) { | ||||
| 	} | ||||
|  | ||||
| 	if form.Reset2FA { | ||||
| 		tf, err := models.GetTwoFactorByUID(u.ID) | ||||
| 		if err != nil && !models.IsErrTwoFactorNotEnrolled(err) { | ||||
| 		tf, err := login.GetTwoFactorByUID(u.ID) | ||||
| 		if err != nil && !login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 			ctx.ServerError("GetTwoFactorByUID", err) | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		if err = models.DeleteTwoFactorByID(tf.ID, u.ID); err != nil { | ||||
| 		if err = login.DeleteTwoFactorByID(tf.ID, u.ID); err != nil { | ||||
| 			ctx.ServerError("DeleteTwoFactorByID", err) | ||||
| 			return | ||||
| 		} | ||||
|   | ||||
| @@ -21,6 +21,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models" | ||||
| 	"code.gitea.io/gitea/models/login" | ||||
| 	"code.gitea.io/gitea/modules/context" | ||||
| 	"code.gitea.io/gitea/modules/git" | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| @@ -174,12 +175,12 @@ func httpBase(ctx *context.Context) (h *serviceHandler) { | ||||
| 		} | ||||
|  | ||||
| 		if ctx.IsBasicAuth && ctx.Data["IsApiToken"] != true { | ||||
| 			_, err = models.GetTwoFactorByUID(ctx.User.ID) | ||||
| 			_, err = login.GetTwoFactorByUID(ctx.User.ID) | ||||
| 			if err == nil { | ||||
| 				// TODO: This response should be changed to "invalid credentials" for security reasons once the expectation behind it (creating an app token to authenticate) is properly documented | ||||
| 				ctx.HandleText(http.StatusUnauthorized, "Users with two-factor authentication enabled cannot perform HTTP/HTTPS operations via plain username and password. Please create and use a personal access token on the user settings page") | ||||
| 				return | ||||
| 			} else if !models.IsErrTwoFactorNotEnrolled(err) { | ||||
| 			} else if !login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 				ctx.ServerError("IsErrTwoFactorNotEnrolled", err) | ||||
| 				return | ||||
| 			} | ||||
|   | ||||
| @@ -213,9 +213,9 @@ func SignInPost(ctx *context.Context) { | ||||
|  | ||||
| 	// If this user is enrolled in 2FA, we can't sign the user in just yet. | ||||
| 	// Instead, redirect them to the 2FA authentication page. | ||||
| 	_, err = models.GetTwoFactorByUID(u.ID) | ||||
| 	_, err = login.GetTwoFactorByUID(u.ID) | ||||
| 	if err != nil { | ||||
| 		if models.IsErrTwoFactorNotEnrolled(err) { | ||||
| 		if login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 			handleSignIn(ctx, u, form.Remember) | ||||
| 		} else { | ||||
| 			ctx.ServerError("UserSignIn", err) | ||||
| @@ -237,7 +237,7 @@ func SignInPost(ctx *context.Context) { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	regs, err := models.GetU2FRegistrationsByUID(u.ID) | ||||
| 	regs, err := login.GetU2FRegistrationsByUID(u.ID) | ||||
| 	if err == nil && len(regs) > 0 { | ||||
| 		ctx.Redirect(setting.AppSubURL + "/user/u2f") | ||||
| 		return | ||||
| @@ -277,7 +277,7 @@ func TwoFactorPost(ctx *context.Context) { | ||||
| 	} | ||||
|  | ||||
| 	id := idSess.(int64) | ||||
| 	twofa, err := models.GetTwoFactorByUID(id) | ||||
| 	twofa, err := login.GetTwoFactorByUID(id) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("UserSignIn", err) | ||||
| 		return | ||||
| @@ -313,7 +313,7 @@ func TwoFactorPost(ctx *context.Context) { | ||||
| 		} | ||||
|  | ||||
| 		twofa.LastUsedPasscode = form.Passcode | ||||
| 		if err = models.UpdateTwoFactor(twofa); err != nil { | ||||
| 		if err = login.UpdateTwoFactor(twofa); err != nil { | ||||
| 			ctx.ServerError("UserSignIn", err) | ||||
| 			return | ||||
| 		} | ||||
| @@ -356,7 +356,7 @@ func TwoFactorScratchPost(ctx *context.Context) { | ||||
| 	} | ||||
|  | ||||
| 	id := idSess.(int64) | ||||
| 	twofa, err := models.GetTwoFactorByUID(id) | ||||
| 	twofa, err := login.GetTwoFactorByUID(id) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("UserSignIn", err) | ||||
| 		return | ||||
| @@ -370,7 +370,7 @@ func TwoFactorScratchPost(ctx *context.Context) { | ||||
| 			ctx.ServerError("UserSignIn", err) | ||||
| 			return | ||||
| 		} | ||||
| 		if err = models.UpdateTwoFactor(twofa); err != nil { | ||||
| 		if err = login.UpdateTwoFactor(twofa); err != nil { | ||||
| 			ctx.ServerError("UserSignIn", err) | ||||
| 			return | ||||
| 		} | ||||
| @@ -418,7 +418,7 @@ func U2FChallenge(ctx *context.Context) { | ||||
| 		return | ||||
| 	} | ||||
| 	id := idSess.(int64) | ||||
| 	regs, err := models.GetU2FRegistrationsByUID(id) | ||||
| 	regs, err := login.GetU2FRegistrationsByUID(id) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("UserSignIn", err) | ||||
| 		return | ||||
| @@ -454,7 +454,7 @@ func U2FSign(ctx *context.Context) { | ||||
| 	} | ||||
| 	challenge := challSess.(*u2f.Challenge) | ||||
| 	id := idSess.(int64) | ||||
| 	regs, err := models.GetU2FRegistrationsByUID(id) | ||||
| 	regs, err := login.GetU2FRegistrationsByUID(id) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("UserSignIn", err) | ||||
| 		return | ||||
| @@ -717,8 +717,8 @@ func handleOAuth2SignIn(ctx *context.Context, source *login.Source, u *models.Us | ||||
|  | ||||
| 	needs2FA := false | ||||
| 	if !source.Cfg.(*oauth2.Source).SkipLocalTwoFA { | ||||
| 		_, err := models.GetTwoFactorByUID(u.ID) | ||||
| 		if err != nil && !models.IsErrTwoFactorNotEnrolled(err) { | ||||
| 		_, err := login.GetTwoFactorByUID(u.ID) | ||||
| 		if err != nil && !login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 			ctx.ServerError("UserSignIn", err) | ||||
| 			return | ||||
| 		} | ||||
| @@ -775,7 +775,7 @@ func handleOAuth2SignIn(ctx *context.Context, source *login.Source, u *models.Us | ||||
| 	} | ||||
|  | ||||
| 	// If U2F is enrolled -> Redirect to U2F instead | ||||
| 	regs, err := models.GetU2FRegistrationsByUID(u.ID) | ||||
| 	regs, err := login.GetU2FRegistrationsByUID(u.ID) | ||||
| 	if err == nil && len(regs) > 0 { | ||||
| 		ctx.Redirect(setting.AppSubURL + "/user/u2f") | ||||
| 		return | ||||
| @@ -935,9 +935,9 @@ func linkAccount(ctx *context.Context, u *models.User, gothUser goth.User, remem | ||||
| 	// If this user is enrolled in 2FA, we can't sign the user in just yet. | ||||
| 	// Instead, redirect them to the 2FA authentication page. | ||||
| 	// We deliberately ignore the skip local 2fa setting here because we are linking to a previous user here | ||||
| 	_, err := models.GetTwoFactorByUID(u.ID) | ||||
| 	_, err := login.GetTwoFactorByUID(u.ID) | ||||
| 	if err != nil { | ||||
| 		if !models.IsErrTwoFactorNotEnrolled(err) { | ||||
| 		if !login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 			ctx.ServerError("UserLinkAccount", err) | ||||
| 			return | ||||
| 		} | ||||
| @@ -967,7 +967,7 @@ func linkAccount(ctx *context.Context, u *models.User, gothUser goth.User, remem | ||||
| 	} | ||||
|  | ||||
| 	// If U2F is enrolled -> Redirect to U2F instead | ||||
| 	regs, err := models.GetU2FRegistrationsByUID(u.ID) | ||||
| 	regs, err := login.GetU2FRegistrationsByUID(u.ID) | ||||
| 	if err == nil && len(regs) > 0 { | ||||
| 		ctx.Redirect(setting.AppSubURL + "/user/u2f") | ||||
| 		return | ||||
| @@ -1561,7 +1561,7 @@ func ForgotPasswdPost(ctx *context.Context) { | ||||
| 	ctx.HTML(http.StatusOK, tplForgotPassword) | ||||
| } | ||||
|  | ||||
| func commonResetPassword(ctx *context.Context) (*models.User, *models.TwoFactor) { | ||||
| func commonResetPassword(ctx *context.Context) (*models.User, *login.TwoFactor) { | ||||
| 	code := ctx.FormString("code") | ||||
|  | ||||
| 	ctx.Data["Title"] = ctx.Tr("auth.reset_password") | ||||
| @@ -1583,9 +1583,9 @@ func commonResetPassword(ctx *context.Context) (*models.User, *models.TwoFactor) | ||||
| 		return nil, nil | ||||
| 	} | ||||
|  | ||||
| 	twofa, err := models.GetTwoFactorByUID(u.ID) | ||||
| 	twofa, err := login.GetTwoFactorByUID(u.ID) | ||||
| 	if err != nil { | ||||
| 		if !models.IsErrTwoFactorNotEnrolled(err) { | ||||
| 		if !login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 			ctx.Error(http.StatusInternalServerError, "CommonResetPassword", err.Error()) | ||||
| 			return nil, nil | ||||
| 		} | ||||
| @@ -1680,7 +1680,7 @@ func ResetPasswdPost(ctx *context.Context) { | ||||
| 			} | ||||
|  | ||||
| 			twofa.LastUsedPasscode = passcode | ||||
| 			if err = models.UpdateTwoFactor(twofa); err != nil { | ||||
| 			if err = login.UpdateTwoFactor(twofa); err != nil { | ||||
| 				ctx.ServerError("ResetPasswdPost: UpdateTwoFactor", err) | ||||
| 				return | ||||
| 			} | ||||
| @@ -1712,7 +1712,7 @@ func ResetPasswdPost(ctx *context.Context) { | ||||
| 			ctx.ServerError("UserSignIn", err) | ||||
| 			return | ||||
| 		} | ||||
| 		if err = models.UpdateTwoFactor(twofa); err != nil { | ||||
| 		if err = login.UpdateTwoFactor(twofa); err != nil { | ||||
| 			ctx.ServerError("UserSignIn", err) | ||||
| 			return | ||||
| 		} | ||||
|   | ||||
| @@ -56,9 +56,9 @@ func DeleteAccountLink(ctx *context.Context) { | ||||
|  | ||||
| func loadSecurityData(ctx *context.Context) { | ||||
| 	enrolled := true | ||||
| 	_, err := models.GetTwoFactorByUID(ctx.User.ID) | ||||
| 	_, err := login.GetTwoFactorByUID(ctx.User.ID) | ||||
| 	if err != nil { | ||||
| 		if models.IsErrTwoFactorNotEnrolled(err) { | ||||
| 		if login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 			enrolled = false | ||||
| 		} else { | ||||
| 			ctx.ServerError("SettingsTwoFactor", err) | ||||
| @@ -67,7 +67,7 @@ func loadSecurityData(ctx *context.Context) { | ||||
| 	} | ||||
| 	ctx.Data["TwofaEnrolled"] = enrolled | ||||
| 	if enrolled { | ||||
| 		ctx.Data["U2FRegistrations"], err = models.GetU2FRegistrationsByUID(ctx.User.ID) | ||||
| 		ctx.Data["U2FRegistrations"], err = login.GetU2FRegistrationsByUID(ctx.User.ID) | ||||
| 		if err != nil { | ||||
| 			ctx.ServerError("GetU2FRegistrationsByUID", err) | ||||
| 			return | ||||
|   | ||||
| @@ -13,7 +13,7 @@ import ( | ||||
| 	"net/http" | ||||
| 	"strings" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models" | ||||
| 	"code.gitea.io/gitea/models/login" | ||||
| 	"code.gitea.io/gitea/modules/context" | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| @@ -29,9 +29,9 @@ func RegenerateScratchTwoFactor(ctx *context.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsSecurity"] = true | ||||
|  | ||||
| 	t, err := models.GetTwoFactorByUID(ctx.User.ID) | ||||
| 	t, err := login.GetTwoFactorByUID(ctx.User.ID) | ||||
| 	if err != nil { | ||||
| 		if models.IsErrTwoFactorNotEnrolled(err) { | ||||
| 		if login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 			ctx.Flash.Error(ctx.Tr("setting.twofa_not_enrolled")) | ||||
| 			ctx.Redirect(setting.AppSubURL + "/user/settings/security") | ||||
| 		} | ||||
| @@ -45,7 +45,7 @@ func RegenerateScratchTwoFactor(ctx *context.Context) { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if err = models.UpdateTwoFactor(t); err != nil { | ||||
| 	if err = login.UpdateTwoFactor(t); err != nil { | ||||
| 		ctx.ServerError("SettingsTwoFactor: Failed to UpdateTwoFactor", err) | ||||
| 		return | ||||
| 	} | ||||
| @@ -59,9 +59,9 @@ func DisableTwoFactor(ctx *context.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsSecurity"] = true | ||||
|  | ||||
| 	t, err := models.GetTwoFactorByUID(ctx.User.ID) | ||||
| 	t, err := login.GetTwoFactorByUID(ctx.User.ID) | ||||
| 	if err != nil { | ||||
| 		if models.IsErrTwoFactorNotEnrolled(err) { | ||||
| 		if login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 			ctx.Flash.Error(ctx.Tr("setting.twofa_not_enrolled")) | ||||
| 			ctx.Redirect(setting.AppSubURL + "/user/settings/security") | ||||
| 		} | ||||
| @@ -69,8 +69,8 @@ func DisableTwoFactor(ctx *context.Context) { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if err = models.DeleteTwoFactorByID(t.ID, ctx.User.ID); err != nil { | ||||
| 		if models.IsErrTwoFactorNotEnrolled(err) { | ||||
| 	if err = login.DeleteTwoFactorByID(t.ID, ctx.User.ID); err != nil { | ||||
| 		if login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 			// There is a potential DB race here - we must have been disabled by another request in the intervening period | ||||
| 			ctx.Flash.Success(ctx.Tr("settings.twofa_disabled")) | ||||
| 			ctx.Redirect(setting.AppSubURL + "/user/settings/security") | ||||
| @@ -146,7 +146,7 @@ func EnrollTwoFactor(ctx *context.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsSecurity"] = true | ||||
|  | ||||
| 	t, err := models.GetTwoFactorByUID(ctx.User.ID) | ||||
| 	t, err := login.GetTwoFactorByUID(ctx.User.ID) | ||||
| 	if t != nil { | ||||
| 		// already enrolled - we should redirect back! | ||||
| 		log.Warn("Trying to re-enroll %-v in twofa when already enrolled", ctx.User) | ||||
| @@ -154,7 +154,7 @@ func EnrollTwoFactor(ctx *context.Context) { | ||||
| 		ctx.Redirect(setting.AppSubURL + "/user/settings/security") | ||||
| 		return | ||||
| 	} | ||||
| 	if err != nil && !models.IsErrTwoFactorNotEnrolled(err) { | ||||
| 	if err != nil && !login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 		ctx.ServerError("SettingsTwoFactor: GetTwoFactorByUID", err) | ||||
| 		return | ||||
| 	} | ||||
| @@ -172,14 +172,14 @@ func EnrollTwoFactorPost(ctx *context.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsSecurity"] = true | ||||
|  | ||||
| 	t, err := models.GetTwoFactorByUID(ctx.User.ID) | ||||
| 	t, err := login.GetTwoFactorByUID(ctx.User.ID) | ||||
| 	if t != nil { | ||||
| 		// already enrolled | ||||
| 		ctx.Flash.Error(ctx.Tr("setting.twofa_is_enrolled")) | ||||
| 		ctx.Redirect(setting.AppSubURL + "/user/settings/security") | ||||
| 		return | ||||
| 	} | ||||
| 	if err != nil && !models.IsErrTwoFactorNotEnrolled(err) { | ||||
| 	if err != nil && !login.IsErrTwoFactorNotEnrolled(err) { | ||||
| 		ctx.ServerError("SettingsTwoFactor: Failed to check if already enrolled with GetTwoFactorByUID", err) | ||||
| 		return | ||||
| 	} | ||||
| @@ -209,7 +209,7 @@ func EnrollTwoFactorPost(ctx *context.Context) { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	t = &models.TwoFactor{ | ||||
| 	t = &login.TwoFactor{ | ||||
| 		UID: ctx.User.ID, | ||||
| 	} | ||||
| 	err = t.SetSecret(secret) | ||||
| @@ -238,7 +238,7 @@ func EnrollTwoFactorPost(ctx *context.Context) { | ||||
| 		log.Error("Unable to save changes to the session: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	if err = models.NewTwoFactor(t); err != nil { | ||||
| 	if err = login.NewTwoFactor(t); err != nil { | ||||
| 		// FIXME: We need to handle a unique constraint fail here it's entirely possible that another request has beaten us. | ||||
| 		// If there is a unique constraint fail we should just tolerate the error | ||||
| 		ctx.ServerError("SettingsTwoFactor: Failed to save two factor", err) | ||||
|   | ||||
| @@ -8,7 +8,7 @@ import ( | ||||
| 	"errors" | ||||
| 	"net/http" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models" | ||||
| 	"code.gitea.io/gitea/models/login" | ||||
| 	"code.gitea.io/gitea/modules/context" | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| @@ -34,7 +34,7 @@ func U2FRegister(ctx *context.Context) { | ||||
| 		ctx.ServerError("Unable to set session key for u2fChallenge", err) | ||||
| 		return | ||||
| 	} | ||||
| 	regs, err := models.GetU2FRegistrationsByUID(ctx.User.ID) | ||||
| 	regs, err := login.GetU2FRegistrationsByUID(ctx.User.ID) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("GetU2FRegistrationsByUID", err) | ||||
| 		return | ||||
| @@ -78,7 +78,7 @@ func U2FRegisterPost(ctx *context.Context) { | ||||
| 		ctx.ServerError("u2f.Register", err) | ||||
| 		return | ||||
| 	} | ||||
| 	if _, err = models.CreateRegistration(ctx.User, name, reg); err != nil { | ||||
| 	if _, err = login.CreateRegistration(ctx.User.ID, name, reg); err != nil { | ||||
| 		ctx.ServerError("u2f.Register", err) | ||||
| 		return | ||||
| 	} | ||||
| @@ -88,9 +88,9 @@ func U2FRegisterPost(ctx *context.Context) { | ||||
| // U2FDelete deletes an security key by id | ||||
| func U2FDelete(ctx *context.Context) { | ||||
| 	form := web.GetForm(ctx).(*forms.U2FDeleteForm) | ||||
| 	reg, err := models.GetU2FRegistrationByID(form.ID) | ||||
| 	reg, err := login.GetU2FRegistrationByID(form.ID) | ||||
| 	if err != nil { | ||||
| 		if models.IsErrU2FRegistrationNotExist(err) { | ||||
| 		if login.IsErrU2FRegistrationNotExist(err) { | ||||
| 			ctx.Status(200) | ||||
| 			return | ||||
| 		} | ||||
| @@ -101,7 +101,7 @@ func U2FDelete(ctx *context.Context) { | ||||
| 		ctx.Status(401) | ||||
| 		return | ||||
| 	} | ||||
| 	if err := models.DeleteRegistration(reg); err != nil { | ||||
| 	if err := login.DeleteRegistration(reg); err != nil { | ||||
| 		ctx.ServerError("DeleteRegistration", err) | ||||
| 		return | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user