]> source.dussan.org Git - gitea.git/commitdiff
Move twofactor to models/login (#17143)
authorLunny Xiao <xiaolunwen@gmail.com>
Sat, 25 Sep 2021 13:00:12 +0000 (21:00 +0800)
committerGitHub <noreply@github.com>
Sat, 25 Sep 2021 13:00:12 +0000 (15:00 +0200)
20 files changed:
models/error.go
models/login/main_test.go
models/login/twofactor.go [new file with mode: 0644]
models/login/u2f.go [new file with mode: 0644]
models/login/u2f_test.go [new file with mode: 0644]
models/pull_sign.go
models/repo_sign.go
models/token.go
models/twofactor.go [deleted file]
models/u2f.go [deleted file]
models/u2f_test.go [deleted file]
models/userlist.go
modules/context/api.go
modules/context/auth.go
routers/web/admin/users.go
routers/web/repo/http.go
routers/web/user/auth.go
routers/web/user/setting/security.go
routers/web/user/setting/security_twofa.go
routers/web/user/setting/security_u2f.go

index 956b240097358d816708c162c3f4b0c272c6f87a..1179fa6eb7515aad323286a089e40b33f3342839 100644 (file)
@@ -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
-}
-
 // .___                            ________                                   .___                   .__
 // |   | ______ ________ __   ____ \______ \   ____ ______   ____   ____    __| _/____   ____   ____ |__| ____   ______
 // |   |/  ___//  ___/  |  \_/ __ \ |    |  \_/ __ \\____ \_/ __ \ /    \  / __ |/ __ \ /    \_/ ___\|  |/ __ \ /  ___/
index ef4b5907bfd4cb69de527835cdb9f4432572cc9b..141952a5941de6196524339dc835b1fb8473597a 100644 (file)
@@ -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/login/twofactor.go b/models/login/twofactor.go
new file mode 100644 (file)
index 0000000..1c4d273
--- /dev/null
@@ -0,0 +1,150 @@
+// Copyright 2017 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 login
+
+import (
+       "crypto/md5"
+       "crypto/sha256"
+       "crypto/subtle"
+       "encoding/base64"
+       "fmt"
+
+       "code.gitea.io/gitea/models/db"
+       "code.gitea.io/gitea/modules/secret"
+       "code.gitea.io/gitea/modules/setting"
+       "code.gitea.io/gitea/modules/timeutil"
+       "code.gitea.io/gitea/modules/util"
+
+       "github.com/pquerna/otp/totp"
+       "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"`
+       UID              int64 `xorm:"UNIQUE"`
+       Secret           string
+       ScratchSalt      string
+       ScratchHash      string
+       LastUsedPasscode string             `xorm:"VARCHAR(10)"`
+       CreatedUnix      timeutil.TimeStamp `xorm:"INDEX created"`
+       UpdatedUnix      timeutil.TimeStamp `xorm:"INDEX updated"`
+}
+
+func init() {
+       db.RegisterModel(new(TwoFactor))
+}
+
+// GenerateScratchToken recreates the scratch token the user is using.
+func (t *TwoFactor) GenerateScratchToken() (string, error) {
+       token, err := util.RandomString(8)
+       if err != nil {
+               return "", err
+       }
+       t.ScratchSalt, _ = util.RandomString(10)
+       t.ScratchHash = HashToken(token, t.ScratchSalt)
+       return token, nil
+}
+
+// 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)
+}
+
+// VerifyScratchToken verifies if the specified scratch token is valid.
+func (t *TwoFactor) VerifyScratchToken(token string) bool {
+       if len(token) == 0 {
+               return false
+       }
+       tempHash := HashToken(token, t.ScratchSalt)
+       return subtle.ConstantTimeCompare([]byte(t.ScratchHash), []byte(tempHash)) == 1
+}
+
+func (t *TwoFactor) getEncryptionKey() []byte {
+       k := md5.Sum([]byte(setting.SecretKey))
+       return k[:]
+}
+
+// SetSecret sets the 2FA secret.
+func (t *TwoFactor) SetSecret(secretString string) error {
+       secretBytes, err := secret.AesEncrypt(t.getEncryptionKey(), []byte(secretString))
+       if err != nil {
+               return err
+       }
+       t.Secret = base64.StdEncoding.EncodeToString(secretBytes)
+       return nil
+}
+
+// ValidateTOTP validates the provided passcode.
+func (t *TwoFactor) ValidateTOTP(passcode string) (bool, error) {
+       decodedStoredSecret, err := base64.StdEncoding.DecodeString(t.Secret)
+       if err != nil {
+               return false, err
+       }
+       secretBytes, err := secret.AesDecrypt(t.getEncryptionKey(), decodedStoredSecret)
+       if err != nil {
+               return false, err
+       }
+       secretStr := string(secretBytes)
+       return totp.Validate(passcode, secretStr), nil
+}
+
+// NewTwoFactor creates a new two-factor authentication token.
+func NewTwoFactor(t *TwoFactor) error {
+       _, err := db.GetEngine(db.DefaultContext).Insert(t)
+       return err
+}
+
+// UpdateTwoFactor updates a two-factor authentication token.
+func UpdateTwoFactor(t *TwoFactor) error {
+       _, err := db.GetEngine(db.DefaultContext).ID(t.ID).AllCols().Update(t)
+       return err
+}
+
+// GetTwoFactorByUID returns the two-factor authentication token associated with
+// the user, if any.
+func GetTwoFactorByUID(uid int64) (*TwoFactor, error) {
+       twofa := &TwoFactor{}
+       has, err := db.GetEngine(db.DefaultContext).Where("uid=?", uid).Get(twofa)
+       if err != nil {
+               return nil, err
+       } else if !has {
+               return nil, ErrTwoFactorNotEnrolled{uid}
+       }
+       return twofa, nil
+}
+
+// DeleteTwoFactorByID deletes two-factor authentication token by given ID.
+func DeleteTwoFactorByID(id, userID int64) error {
+       cnt, err := db.GetEngine(db.DefaultContext).ID(id).Delete(&TwoFactor{
+               UID: userID,
+       })
+       if err != nil {
+               return err
+       } else if cnt != 1 {
+               return ErrTwoFactorNotEnrolled{userID}
+       }
+       return nil
+}
diff --git a/models/login/u2f.go b/models/login/u2f.go
new file mode 100644 (file)
index 0000000..64b1fb3
--- /dev/null
@@ -0,0 +1,149 @@
+// Copyright 2018 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 login
+
+import (
+       "fmt"
+
+       "code.gitea.io/gitea/models/db"
+       "code.gitea.io/gitea/modules/log"
+       "code.gitea.io/gitea/modules/timeutil"
+
+       "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"`
+       Name        string
+       UserID      int64 `xorm:"INDEX"`
+       Raw         []byte
+       Counter     uint32             `xorm:"BIGINT"`
+       CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
+       UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
+}
+
+func init() {
+       db.RegisterModel(new(U2FRegistration))
+}
+
+// TableName returns a better table name for U2FRegistration
+func (reg U2FRegistration) TableName() string {
+       return "u2f_registration"
+}
+
+// Parse will convert the db entry U2FRegistration to an u2f.Registration struct
+func (reg *U2FRegistration) Parse() (*u2f.Registration, error) {
+       r := new(u2f.Registration)
+       return r, r.UnmarshalBinary(reg.Raw)
+}
+
+func (reg *U2FRegistration) updateCounter(e db.Engine) error {
+       _, err := e.ID(reg.ID).Cols("counter").Update(reg)
+       return err
+}
+
+// UpdateCounter will update the database value of counter
+func (reg *U2FRegistration) UpdateCounter() error {
+       return reg.updateCounter(db.GetEngine(db.DefaultContext))
+}
+
+// U2FRegistrationList is a list of *U2FRegistration
+type U2FRegistrationList []*U2FRegistration
+
+// ToRegistrations will convert all U2FRegistrations to u2f.Registrations
+func (list U2FRegistrationList) ToRegistrations() []u2f.Registration {
+       regs := make([]u2f.Registration, 0, len(list))
+       for _, reg := range list {
+               r, err := reg.Parse()
+               if err != nil {
+                       log.Fatal("parsing u2f registration: %v", err)
+                       continue
+               }
+               regs = append(regs, *r)
+       }
+
+       return regs
+}
+
+func getU2FRegistrationsByUID(e db.Engine, uid int64) (U2FRegistrationList, error) {
+       regs := make(U2FRegistrationList, 0)
+       return regs, e.Where("user_id = ?", uid).Find(&regs)
+}
+
+// GetU2FRegistrationByID returns U2F registration by id
+func GetU2FRegistrationByID(id int64) (*U2FRegistration, error) {
+       return getU2FRegistrationByID(db.GetEngine(db.DefaultContext), id)
+}
+
+func getU2FRegistrationByID(e db.Engine, id int64) (*U2FRegistration, error) {
+       reg := new(U2FRegistration)
+       if found, err := e.ID(id).Get(reg); err != nil {
+               return nil, err
+       } else if !found {
+               return nil, ErrU2FRegistrationNotExist{ID: id}
+       }
+       return reg, nil
+}
+
+// GetU2FRegistrationsByUID returns all U2F registrations of the given user
+func GetU2FRegistrationsByUID(uid int64) (U2FRegistrationList, error) {
+       return getU2FRegistrationsByUID(db.GetEngine(db.DefaultContext), uid)
+}
+
+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:  userID,
+               Name:    name,
+               Counter: 0,
+               Raw:     raw,
+       }
+       _, err = e.InsertOne(r)
+       if err != nil {
+               return nil, err
+       }
+       return r, nil
+}
+
+// CreateRegistration will create a new U2FRegistration from the given Registration
+func CreateRegistration(userID int64, name string, reg *u2f.Registration) (*U2FRegistration, error) {
+       return createRegistration(db.GetEngine(db.DefaultContext), userID, name, reg)
+}
+
+// DeleteRegistration will delete U2FRegistration
+func DeleteRegistration(reg *U2FRegistration) error {
+       return deleteRegistration(db.GetEngine(db.DefaultContext), reg)
+}
+
+func deleteRegistration(e db.Engine, reg *U2FRegistration) error {
+       _, err := e.Delete(reg)
+       return err
+}
diff --git a/models/login/u2f_test.go b/models/login/u2f_test.go
new file mode 100644 (file)
index 0000000..b030577
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright 2020 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 login
+
+import (
+       "testing"
+
+       "code.gitea.io/gitea/models/db"
+
+       "github.com/stretchr/testify/assert"
+       "github.com/tstranex/u2f"
+)
+
+func TestGetU2FRegistrationByID(t *testing.T) {
+       assert.NoError(t, db.PrepareTestDatabase())
+
+       res, err := GetU2FRegistrationByID(1)
+       assert.NoError(t, err)
+       assert.Equal(t, "U2F Key", res.Name)
+
+       _, err = GetU2FRegistrationByID(342432)
+       assert.Error(t, err)
+       assert.True(t, IsErrU2FRegistrationNotExist(err))
+}
+
+func TestGetU2FRegistrationsByUID(t *testing.T) {
+       assert.NoError(t, db.PrepareTestDatabase())
+
+       res, err := GetU2FRegistrationsByUID(1)
+       assert.NoError(t, err)
+       assert.Len(t, res, 1)
+       assert.Equal(t, "U2F Key", res[0].Name)
+}
+
+func TestU2FRegistration_TableName(t *testing.T) {
+       assert.Equal(t, "u2f_registration", U2FRegistration{}.TableName())
+}
+
+func TestU2FRegistration_UpdateCounter(t *testing.T) {
+       assert.NoError(t, db.PrepareTestDatabase())
+       reg := db.AssertExistsAndLoadBean(t, &U2FRegistration{ID: 1}).(*U2FRegistration)
+       reg.Counter = 1
+       assert.NoError(t, reg.UpdateCounter())
+       db.AssertExistsIf(t, true, &U2FRegistration{ID: 1, Counter: 1})
+}
+
+func TestU2FRegistration_UpdateLargeCounter(t *testing.T) {
+       assert.NoError(t, db.PrepareTestDatabase())
+       reg := db.AssertExistsAndLoadBean(t, &U2FRegistration{ID: 1}).(*U2FRegistration)
+       reg.Counter = 0xffffffff
+       assert.NoError(t, reg.UpdateCounter())
+       db.AssertExistsIf(t, true, &U2FRegistration{ID: 1, Counter: 0xffffffff})
+}
+
+func TestCreateRegistration(t *testing.T) {
+       assert.NoError(t, db.PrepareTestDatabase())
+
+       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: 1})
+}
+
+func TestDeleteRegistration(t *testing.T) {
+       assert.NoError(t, db.PrepareTestDatabase())
+       reg := db.AssertExistsAndLoadBean(t, &U2FRegistration{ID: 1}).(*U2FRegistration)
+
+       assert.NoError(t, DeleteRegistration(reg))
+       db.AssertNotExistsBean(t, &U2FRegistration{ID: 1})
+}
index 2e7cbff48b4316d354594aafa43c271fe4dade4c..028a3e5c3b6597622573ffbc1c910acd063d81d2 100644 (file)
@@ -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 {
index ae0895df764662d7740354949bfe64ffcbe7d226..f7a303b0c1242f60b17bb8837c472825c7003bf0 100644 (file)
@@ -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 {
index 07d013ac8ed452b862a6bafdafa4c92bc0554481..3cffdd9ba276600413e5f2647ab8cd69c209e126 100644 (file)
@@ -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/twofactor.go b/models/twofactor.go
deleted file mode 100644 (file)
index dd7fde7..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2017 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 models
-
-import (
-       "crypto/md5"
-       "crypto/sha256"
-       "crypto/subtle"
-       "encoding/base64"
-       "fmt"
-
-       "code.gitea.io/gitea/models/db"
-       "code.gitea.io/gitea/modules/secret"
-       "code.gitea.io/gitea/modules/setting"
-       "code.gitea.io/gitea/modules/timeutil"
-       "code.gitea.io/gitea/modules/util"
-
-       "github.com/pquerna/otp/totp"
-       "golang.org/x/crypto/pbkdf2"
-)
-
-// TwoFactor represents a two-factor authentication token.
-type TwoFactor struct {
-       ID               int64 `xorm:"pk autoincr"`
-       UID              int64 `xorm:"UNIQUE"`
-       Secret           string
-       ScratchSalt      string
-       ScratchHash      string
-       LastUsedPasscode string             `xorm:"VARCHAR(10)"`
-       CreatedUnix      timeutil.TimeStamp `xorm:"INDEX created"`
-       UpdatedUnix      timeutil.TimeStamp `xorm:"INDEX updated"`
-}
-
-func init() {
-       db.RegisterModel(new(TwoFactor))
-}
-
-// GenerateScratchToken recreates the scratch token the user is using.
-func (t *TwoFactor) GenerateScratchToken() (string, error) {
-       token, err := util.RandomString(8)
-       if err != nil {
-               return "", err
-       }
-       t.ScratchSalt, _ = util.RandomString(10)
-       t.ScratchHash = hashToken(token, t.ScratchSalt)
-       return token, nil
-}
-
-func hashToken(token, salt string) string {
-       tempHash := pbkdf2.Key([]byte(token), []byte(salt), 10000, 50, sha256.New)
-       return fmt.Sprintf("%x", tempHash)
-}
-
-// VerifyScratchToken verifies if the specified scratch token is valid.
-func (t *TwoFactor) VerifyScratchToken(token string) bool {
-       if len(token) == 0 {
-               return false
-       }
-       tempHash := hashToken(token, t.ScratchSalt)
-       return subtle.ConstantTimeCompare([]byte(t.ScratchHash), []byte(tempHash)) == 1
-}
-
-func (t *TwoFactor) getEncryptionKey() []byte {
-       k := md5.Sum([]byte(setting.SecretKey))
-       return k[:]
-}
-
-// SetSecret sets the 2FA secret.
-func (t *TwoFactor) SetSecret(secretString string) error {
-       secretBytes, err := secret.AesEncrypt(t.getEncryptionKey(), []byte(secretString))
-       if err != nil {
-               return err
-       }
-       t.Secret = base64.StdEncoding.EncodeToString(secretBytes)
-       return nil
-}
-
-// ValidateTOTP validates the provided passcode.
-func (t *TwoFactor) ValidateTOTP(passcode string) (bool, error) {
-       decodedStoredSecret, err := base64.StdEncoding.DecodeString(t.Secret)
-       if err != nil {
-               return false, err
-       }
-       secretBytes, err := secret.AesDecrypt(t.getEncryptionKey(), decodedStoredSecret)
-       if err != nil {
-               return false, err
-       }
-       secretStr := string(secretBytes)
-       return totp.Validate(passcode, secretStr), nil
-}
-
-// NewTwoFactor creates a new two-factor authentication token.
-func NewTwoFactor(t *TwoFactor) error {
-       _, err := db.GetEngine(db.DefaultContext).Insert(t)
-       return err
-}
-
-// UpdateTwoFactor updates a two-factor authentication token.
-func UpdateTwoFactor(t *TwoFactor) error {
-       _, err := db.GetEngine(db.DefaultContext).ID(t.ID).AllCols().Update(t)
-       return err
-}
-
-// GetTwoFactorByUID returns the two-factor authentication token associated with
-// the user, if any.
-func GetTwoFactorByUID(uid int64) (*TwoFactor, error) {
-       twofa := &TwoFactor{}
-       has, err := db.GetEngine(db.DefaultContext).Where("uid=?", uid).Get(twofa)
-       if err != nil {
-               return nil, err
-       } else if !has {
-               return nil, ErrTwoFactorNotEnrolled{uid}
-       }
-       return twofa, nil
-}
-
-// DeleteTwoFactorByID deletes two-factor authentication token by given ID.
-func DeleteTwoFactorByID(id, userID int64) error {
-       cnt, err := db.GetEngine(db.DefaultContext).ID(id).Delete(&TwoFactor{
-               UID: userID,
-       })
-       if err != nil {
-               return err
-       } else if cnt != 1 {
-               return ErrTwoFactorNotEnrolled{userID}
-       }
-       return nil
-}
diff --git a/models/u2f.go b/models/u2f.go
deleted file mode 100644 (file)
index 17b8295..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright 2018 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 models
-
-import (
-       "code.gitea.io/gitea/models/db"
-       "code.gitea.io/gitea/modules/log"
-       "code.gitea.io/gitea/modules/timeutil"
-
-       "github.com/tstranex/u2f"
-)
-
-// U2FRegistration represents the registration data and counter of a security key
-type U2FRegistration struct {
-       ID          int64 `xorm:"pk autoincr"`
-       Name        string
-       UserID      int64 `xorm:"INDEX"`
-       Raw         []byte
-       Counter     uint32             `xorm:"BIGINT"`
-       CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
-       UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
-}
-
-func init() {
-       db.RegisterModel(new(U2FRegistration))
-}
-
-// TableName returns a better table name for U2FRegistration
-func (reg U2FRegistration) TableName() string {
-       return "u2f_registration"
-}
-
-// Parse will convert the db entry U2FRegistration to an u2f.Registration struct
-func (reg *U2FRegistration) Parse() (*u2f.Registration, error) {
-       r := new(u2f.Registration)
-       return r, r.UnmarshalBinary(reg.Raw)
-}
-
-func (reg *U2FRegistration) updateCounter(e db.Engine) error {
-       _, err := e.ID(reg.ID).Cols("counter").Update(reg)
-       return err
-}
-
-// UpdateCounter will update the database value of counter
-func (reg *U2FRegistration) UpdateCounter() error {
-       return reg.updateCounter(db.GetEngine(db.DefaultContext))
-}
-
-// U2FRegistrationList is a list of *U2FRegistration
-type U2FRegistrationList []*U2FRegistration
-
-// ToRegistrations will convert all U2FRegistrations to u2f.Registrations
-func (list U2FRegistrationList) ToRegistrations() []u2f.Registration {
-       regs := make([]u2f.Registration, 0, len(list))
-       for _, reg := range list {
-               r, err := reg.Parse()
-               if err != nil {
-                       log.Fatal("parsing u2f registration: %v", err)
-                       continue
-               }
-               regs = append(regs, *r)
-       }
-
-       return regs
-}
-
-func getU2FRegistrationsByUID(e db.Engine, uid int64) (U2FRegistrationList, error) {
-       regs := make(U2FRegistrationList, 0)
-       return regs, e.Where("user_id = ?", uid).Find(&regs)
-}
-
-// GetU2FRegistrationByID returns U2F registration by id
-func GetU2FRegistrationByID(id int64) (*U2FRegistration, error) {
-       return getU2FRegistrationByID(db.GetEngine(db.DefaultContext), id)
-}
-
-func getU2FRegistrationByID(e db.Engine, id int64) (*U2FRegistration, error) {
-       reg := new(U2FRegistration)
-       if found, err := e.ID(id).Get(reg); err != nil {
-               return nil, err
-       } else if !found {
-               return nil, ErrU2FRegistrationNotExist{ID: id}
-       }
-       return reg, nil
-}
-
-// GetU2FRegistrationsByUID returns all U2F registrations of the given user
-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) {
-       raw, err := reg.MarshalBinary()
-       if err != nil {
-               return nil, err
-       }
-       r := &U2FRegistration{
-               UserID:  user.ID,
-               Name:    name,
-               Counter: 0,
-               Raw:     raw,
-       }
-       _, err = e.InsertOne(r)
-       if err != nil {
-               return nil, err
-       }
-       return r, nil
-}
-
-// 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)
-}
-
-// DeleteRegistration will delete U2FRegistration
-func DeleteRegistration(reg *U2FRegistration) error {
-       return deleteRegistration(db.GetEngine(db.DefaultContext), reg)
-}
-
-func deleteRegistration(e db.Engine, reg *U2FRegistration) error {
-       _, err := e.Delete(reg)
-       return err
-}
diff --git a/models/u2f_test.go b/models/u2f_test.go
deleted file mode 100644 (file)
index 44eca69..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2020 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 models
-
-import (
-       "testing"
-
-       "code.gitea.io/gitea/models/db"
-       "github.com/stretchr/testify/assert"
-       "github.com/tstranex/u2f"
-)
-
-func TestGetU2FRegistrationByID(t *testing.T) {
-       assert.NoError(t, db.PrepareTestDatabase())
-
-       res, err := GetU2FRegistrationByID(1)
-       assert.NoError(t, err)
-       assert.Equal(t, "U2F Key", res.Name)
-
-       _, err = GetU2FRegistrationByID(342432)
-       assert.Error(t, err)
-       assert.True(t, IsErrU2FRegistrationNotExist(err))
-}
-
-func TestGetU2FRegistrationsByUID(t *testing.T) {
-       assert.NoError(t, db.PrepareTestDatabase())
-
-       res, err := GetU2FRegistrationsByUID(1)
-       assert.NoError(t, err)
-       assert.Len(t, res, 1)
-       assert.Equal(t, "U2F Key", res[0].Name)
-}
-
-func TestU2FRegistration_TableName(t *testing.T) {
-       assert.Equal(t, "u2f_registration", U2FRegistration{}.TableName())
-}
-
-func TestU2FRegistration_UpdateCounter(t *testing.T) {
-       assert.NoError(t, db.PrepareTestDatabase())
-       reg := db.AssertExistsAndLoadBean(t, &U2FRegistration{ID: 1}).(*U2FRegistration)
-       reg.Counter = 1
-       assert.NoError(t, reg.UpdateCounter())
-       db.AssertExistsIf(t, true, &U2FRegistration{ID: 1, Counter: 1})
-}
-
-func TestU2FRegistration_UpdateLargeCounter(t *testing.T) {
-       assert.NoError(t, db.PrepareTestDatabase())
-       reg := db.AssertExistsAndLoadBean(t, &U2FRegistration{ID: 1}).(*U2FRegistration)
-       reg.Counter = 0xffffffff
-       assert.NoError(t, reg.UpdateCounter())
-       db.AssertExistsIf(t, true, &U2FRegistration{ID: 1, Counter: 0xffffffff})
-}
-
-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")})
-       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})
-}
-
-func TestDeleteRegistration(t *testing.T) {
-       assert.NoError(t, db.PrepareTestDatabase())
-       reg := db.AssertExistsAndLoadBean(t, &U2FRegistration{ID: 1}).(*U2FRegistration)
-
-       assert.NoError(t, DeleteRegistration(reg))
-       db.AssertNotExistsBean(t, &U2FRegistration{ID: 1})
-}
index bfa7ea1e2ea2f8e1c0d32227fc38ec53dd0ef940..aebdb4f48c253455f737d90d062ccc97529b9c36 100644 (file)
@@ -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)
index e80e63cd96233e72607fcec17c2b7b3f8da2248a..e5216d911f8a6cfdac8fec747307a0029e48dc07 100644 (file)
@@ -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)
index 0a62b2741e4a76589a16af892ec1fdec8f028437..7faa93d78b5947c4f9d9ea7b8f7f1afa007991e9 100644 (file)
@@ -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)
index 2556cae3a87a2bae831d4db7ff4efa28867f42ed..ea666ab4d4dbbc48ecb7f805a7742c93c7897601 100644 (file)
@@ -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
                }
index fbd1e19a8219b6f5533c5773ee8bbcf0c0debbba..162338a9597c094d2c3827b7e26defbeba75101d 100644 (file)
@@ -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
                        }
index 733ace81b02a5490a627f861c85ae06b4c0232a0..12328e46a1657a96363a6056cad6b60f1ac9386d 100644 (file)
@@ -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
                }
index d4abe84d9601c4ccd4bd3353eff8ec7cf4781342..53f672282d1a2f140b3d30de10d6747358d7531c 100644 (file)
@@ -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
index 7b08a05939b30129b89d4c7dc6886029784e0db3..5b1cbab17fe74a31e58964fcfc53998351f60e9d 100644 (file)
@@ -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)
index f9e35549fbfa355bd1b9e273064bc5e2e66c7a9d..d1d6d1e8cad89bac6bd751f05dace425fa3ef042 100644 (file)
@@ -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
        }