From 91e21d4fca8b867614d08537e92bc6c8fc7b0444 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 25 Sep 2021 21:00:12 +0800 Subject: [PATCH] Move twofactor to models/login (#17143) --- models/error.go | 41 ---------------------- models/login/main_test.go | 1 + models/{ => login}/twofactor.go | 28 ++++++++++++--- models/{ => login}/u2f.go | 34 +++++++++++++++--- models/{ => login}/u2f_test.go | 8 ++--- models/pull_sign.go | 5 +-- models/repo_sign.go | 13 +++---- models/token.go | 5 +-- models/userlist.go | 5 +-- modules/context/api.go | 5 +-- modules/context/auth.go | 6 ++-- routers/web/admin/users.go | 10 +++--- routers/web/repo/http.go | 5 +-- routers/web/user/auth.go | 40 ++++++++++----------- routers/web/user/setting/security.go | 6 ++-- routers/web/user/setting/security_twofa.go | 28 +++++++-------- routers/web/user/setting/security_u2f.go | 12 +++---- 17 files changed, 131 insertions(+), 121 deletions(-) rename models/{ => login}/twofactor.go (83%) rename models/{ => login}/u2f.go (71%) rename models/{ => login}/u2f_test.go (91%) diff --git a/models/error.go b/models/error.go index 956b240097..1179fa6eb7 100644 --- a/models/error.go +++ b/models/error.go @@ -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 -} - // .___ ________ .___ .__ // | | ______ ________ __ ____ \______ \ ____ ______ ____ ____ __| _/____ ____ ____ |__| ____ ______ // | |/ ___// ___/ | \_/ __ \ | | \_/ __ \\____ \_/ __ \ / \ / __ |/ __ \ / \_/ ___\| |/ __ \ / ___/ diff --git a/models/login/main_test.go b/models/login/main_test.go index ef4b5907bf..141952a594 100644 --- a/models/login/main_test.go +++ b/models/login/main_test.go @@ -17,5 +17,6 @@ func TestMain(m *testing.M) { "oauth2_application.yml", "oauth2_authorization_code.yml", "oauth2_grant.yml", + "u2f_registration.yml", ) } diff --git a/models/twofactor.go b/models/login/twofactor.go similarity index 83% rename from models/twofactor.go rename to models/login/twofactor.go index dd7fde77e2..1c4d2734fc 100644 --- a/models/twofactor.go +++ b/models/login/twofactor.go @@ -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 } diff --git a/models/u2f.go b/models/login/u2f.go similarity index 71% rename from models/u2f.go rename to models/login/u2f.go index 17b8295626..64b1fb322a 100644 --- a/models/u2f.go +++ b/models/login/u2f.go @@ -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 diff --git a/models/u2f_test.go b/models/login/u2f_test.go similarity index 91% rename from models/u2f_test.go rename to models/login/u2f_test.go index 44eca6953d..b0305775ca 100644 --- a/models/u2f_test.go +++ b/models/login/u2f_test.go @@ -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) { diff --git a/models/pull_sign.go b/models/pull_sign.go index 2e7cbff48b..028a3e5c3b 100644 --- a/models/pull_sign.go +++ b/models/pull_sign.go @@ -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 { diff --git a/models/repo_sign.go b/models/repo_sign.go index ae0895df76..f7a303b0c1 100644 --- a/models/repo_sign.go +++ b/models/repo_sign.go @@ -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 { diff --git a/models/token.go b/models/token.go index 07d013ac8e..3cffdd9ba2 100644 --- a/models/token.go +++ b/models/token.go @@ -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) diff --git a/models/userlist.go b/models/userlist.go index bfa7ea1e2e..aebdb4f48c 100644 --- a/models/userlist.go +++ b/models/userlist.go @@ -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) diff --git a/modules/context/api.go b/modules/context/api.go index e80e63cd96..e5216d911f 100644 --- a/modules/context/api.go +++ b/modules/context/api.go @@ -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) diff --git a/modules/context/auth.go b/modules/context/auth.go index 0a62b2741e..7faa93d78b 100644 --- a/modules/context/auth.go +++ b/modules/context/auth.go @@ -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) diff --git a/routers/web/admin/users.go b/routers/web/admin/users.go index 2556cae3a8..ea666ab4d4 100644 --- a/routers/web/admin/users.go +++ b/routers/web/admin/users.go @@ -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 } diff --git a/routers/web/repo/http.go b/routers/web/repo/http.go index fbd1e19a82..162338a959 100644 --- a/routers/web/repo/http.go +++ b/routers/web/repo/http.go @@ -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 } diff --git a/routers/web/user/auth.go b/routers/web/user/auth.go index 733ace81b0..12328e46a1 100644 --- a/routers/web/user/auth.go +++ b/routers/web/user/auth.go @@ -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 } diff --git a/routers/web/user/setting/security.go b/routers/web/user/setting/security.go index d4abe84d96..53f672282d 100644 --- a/routers/web/user/setting/security.go +++ b/routers/web/user/setting/security.go @@ -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 diff --git a/routers/web/user/setting/security_twofa.go b/routers/web/user/setting/security_twofa.go index 7b08a05939..5b1cbab17f 100644 --- a/routers/web/user/setting/security_twofa.go +++ b/routers/web/user/setting/security_twofa.go @@ -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) diff --git a/routers/web/user/setting/security_u2f.go b/routers/web/user/setting/security_u2f.go index f9e35549fb..d1d6d1e8ca 100644 --- a/routers/web/user/setting/security_u2f.go +++ b/routers/web/user/setting/security_u2f.go @@ -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 }