From 5dc50b297f5eab98d30d598cc30bb6cdfd0866a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=8B=E5=AD=90=E6=A1=93=F0=9F=8C=88?= Date: Thu, 20 Mar 2025 23:23:29 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=93=E5=85=A5=E8=A1=A5=E4=B8=81=EF=BC=9A9F?= =?UTF-8?q?1436E39C95D59E.patch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 1 + go.sum | 2 + internal/database/issue_mail.go | 11 -- internal/database/migrations/main_test.go | 2 +- internal/database/migrations/migrations.go | 14 +-- internal/database/migrations/v20.go | 2 +- internal/database/migrations/v20_test.go | 2 +- internal/database/migrations/v21.go | 2 +- internal/database/migrations/v21_test.go | 2 +- internal/database/migrations/v23.go | 14 ++- internal/database/migrations/v24.go | 22 ++-- internal/database/migrations/v25.go | 6 +- internal/database/models.go | 2 +- internal/database/users.go | 1 + internal/email/email.go | 26 ++++- internal/route/user/auth.go | 116 +++++++++------------ internal/tool/jwt.go | 102 ++++++++++++++++++ internal/tool/tool.go | 62 ----------- internal/userutil/userutil.go | 24 +---- internal/userutil/userutil_test.go | 13 --- public/img/logo-text.png | Bin 59080 -> 0 bytes templates/explore/repos.tmpl | 2 +- templates/home.tmpl | 2 +- templates/user/dashboard/dashboard.tmpl | 2 +- 24 files changed, 230 insertions(+), 202 deletions(-) create mode 100644 internal/tool/jwt.go delete mode 100644 public/img/logo-text.png diff --git a/go.mod b/go.mod index 0d7b7e894..a93ef85ba 100644 --- a/go.mod +++ b/go.mod @@ -73,6 +73,7 @@ require ( github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/denisenkom/go-mssqldb v0.12.0 // indirect + github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/djherbis/buffer v1.2.0 // indirect github.com/djherbis/nio/v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index ef6566445..dcc3b5f62 100644 --- a/go.sum +++ b/go.sum @@ -58,6 +58,8 @@ github.com/denisenkom/go-mssqldb v0.12.0 h1:VtrkII767ttSPNRfFekePK3sctr+joXgO58s github.com/denisenkom/go-mssqldb v0.12.0/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfzrpArPY/aFvc9yU= github.com/derision-test/go-mockgen v1.3.7 h1:b/DXAXL2FkaRPpnbYK3ODdZzklmJAwox0tkc6yyXx74= github.com/derision-test/go-mockgen v1.3.7/go.mod h1:/TXUePlhtHmDDCaDAi/a4g6xOHqMDz3Wf0r2NPGskB4= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/djherbis/buffer v1.1.0/go.mod h1:VwN8VdFkMY0DCALdY8o00d3IZ6Amz/UNVMWcSaJT44o= diff --git a/internal/database/issue_mail.go b/internal/database/issue_mail.go index 7e6d79bd0..311b97bdf 100644 --- a/internal/database/issue_mail.go +++ b/internal/database/issue_mail.go @@ -15,7 +15,6 @@ import ( "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/email" "gogs.io/gogs/internal/markup" - "gogs.io/gogs/internal/userutil" ) func (issue *Issue) MailSubject() string { @@ -43,16 +42,6 @@ func (this mailerUser) PublicEmail() string { return this.user.PublicEmail } -func (this mailerUser) GenerateEmailActivateCode(email string) string { - return userutil.GenerateActivateCode( - this.user.ID, - email, - this.user.Name, - this.user.Password, - this.user.Rands, - ) -} - func NewMailerUser(u *User) email.User { return mailerUser{u} } diff --git a/internal/database/migrations/main_test.go b/internal/database/migrations/main_test.go index 14e4d7bed..ee13c3e3e 100644 --- a/internal/database/migrations/main_test.go +++ b/internal/database/migrations/main_test.go @@ -1,6 +1,6 @@ // Copyright 2022 The Gogs Authors. All rights reserved. // Use of this source code is governed by a MIT-style -// license that can be found in the LICENSE.gogs file. +// license that can be found in the LICENSE file. package migrations diff --git a/internal/database/migrations/migrations.go b/internal/database/migrations/migrations.go index d7a50b753..105d87e50 100644 --- a/internal/database/migrations/migrations.go +++ b/internal/database/migrations/migrations.go @@ -1,6 +1,6 @@ // Copyright 2015 The Gogs Authors. All rights reserved. // Use of this source code is governed by a MIT-style -// license that can be found in the LICENSE.gogs file. +// license that can be found in the LICENSE file. package migrations @@ -52,22 +52,22 @@ var migrations = []Migration{ // v18 -> v19:v0.11.55 // NewMigration("clean unlinked webhook and hook_tasks", cleanUnlinkedWebhookAndHookTasks), - // v19 -> v20:v0.13.0 + // v19 -> v20:v0.13.0(Gogs) NewMigration("migrate access tokens to store SHA56", migrateAccessTokenToSHA256), - // v20 -> v21:v0.13.0 + // v20 -> v21:v0.13.0(Gogs) NewMigration("add index to action.user_id", addIndexToActionUserID), - // v21 -> v22:v0.13.0 + // v21 -> v22:v0.13.0(Gogs) // // NOTE: There was a bug in calculating the value of the `version.version` // column after a migration is done, thus some instances are on v21 but some are // on v22. Let's make a noop v22 to make sure every instance will not miss a // real future migration. NewMigration("noop", func(*gorm.DB) error { return nil }), - // v22 -> v23:v0.14.0 + // v22 -> v23:v0.14.0(Gogs) NewMigration("add user.public_email column", addUserPublicEmail), - // v23 -> v24:v0.14.0 + // v23 -> v24:v0.14.0(Gogs) NewMigration("add user.local_email column", addUserLocalEmail), - // v24 -> v25:v0.14.0 + // v24 -> v25:v0.14.0(Gogs) v24:v1.0.0(Gogs) NewMigration("insert user primary to database", insertUserPrimaryEmail), } diff --git a/internal/database/migrations/v20.go b/internal/database/migrations/v20.go index 7873e05ed..bf58db5e3 100644 --- a/internal/database/migrations/v20.go +++ b/internal/database/migrations/v20.go @@ -1,6 +1,6 @@ // Copyright 2022 The Gogs Authors. All rights reserved. // Use of this source code is governed by a MIT-style -// license that can be found in the LICENSE.gogs file. +// license that can be found in the LICENSE file. package migrations diff --git a/internal/database/migrations/v20_test.go b/internal/database/migrations/v20_test.go index c1d8885c0..9bbf283fd 100644 --- a/internal/database/migrations/v20_test.go +++ b/internal/database/migrations/v20_test.go @@ -1,6 +1,6 @@ // Copyright 2022 The Gogs Authors. All rights reserved. // Use of this source code is governed by a MIT-style -// license that can be found in the LICENSE.gogs file. +// license that can be found in the LICENSE file. package migrations diff --git a/internal/database/migrations/v21.go b/internal/database/migrations/v21.go index a2ba85a51..7eb97a7fa 100644 --- a/internal/database/migrations/v21.go +++ b/internal/database/migrations/v21.go @@ -1,6 +1,6 @@ // Copyright 2022 The Gogs Authors. All rights reserved. // Use of this source code is governed by a MIT-style -// license that can be found in the LICENSE.gogs file. +// license that can be found in the LICENSE file. package migrations diff --git a/internal/database/migrations/v21_test.go b/internal/database/migrations/v21_test.go index 500952a4c..866e9074f 100644 --- a/internal/database/migrations/v21_test.go +++ b/internal/database/migrations/v21_test.go @@ -1,6 +1,6 @@ // Copyright 2022 The Gogs Authors. All rights reserved. // Use of this source code is governed by a MIT-style -// license that can be found in the LICENSE.gogs file. +// license that can be found in the LICENSE file. package migrations diff --git a/internal/database/migrations/v23.go b/internal/database/migrations/v23.go index 8a5c4a1de..f92d1b6bc 100644 --- a/internal/database/migrations/v23.go +++ b/internal/database/migrations/v23.go @@ -1,11 +1,16 @@ package migrations import ( + "fmt" "gorm.io/gorm" ) func addUserPublicEmail(db *gorm.DB) error { type User struct { + PublicEmail string // 不能使用NOT NULL + } + + type UserNotNull struct { PublicEmail string `xorm:"NOT NULL" gorm:"not null"` } @@ -16,12 +21,17 @@ func addUserPublicEmail(db *gorm.DB) error { return db.Transaction(func(tx *gorm.DB) error { err := tx.Migrator().AddColumn(&User{}, "PublicEmail") if err != nil { - return err + return fmt.Errorf("add column user.public_email error: %s", err.Error()) } err = tx.Exec("UPDATE `user` SET `public_email` = `email` WHERE `public_email` = '' AND `type` = 0").Error if err != nil { - return err + return fmt.Errorf("update public_email error: %s", err.Error()) + } + + err = tx.Debug().Migrator().AlterColumn(&UserNotNull{}, "PublicEmail") + if err != nil { + return fmt.Errorf("alter column user.public_email error: %s", err.Error()) } return nil diff --git a/internal/database/migrations/v24.go b/internal/database/migrations/v24.go index 14aec9b5b..33025c830 100644 --- a/internal/database/migrations/v24.go +++ b/internal/database/migrations/v24.go @@ -1,15 +1,20 @@ package migrations import ( - "github.com/pkg/errors" + "fmt" gouuid "github.com/satori/go.uuid" "gorm.io/gorm" ) func addUserLocalEmail(db *gorm.DB) error { type User struct { - ID int64 `gorm:"primaryKey"` - LocalEmail string `xorm:"NOT NULL" gorm:"not null"` + ID int64 `gorm:"primaryKey"` + LocalEmail string + } + + type UserNotNULL struct { + ID int64 `gorm:"primaryKey"` + LocalEmail string } if db.Migrator().HasColumn(&User{}, "LocalEmail") { @@ -19,7 +24,7 @@ func addUserLocalEmail(db *gorm.DB) error { return db.Transaction(func(tx *gorm.DB) error { err := tx.Migrator().AddColumn(&User{}, "LocalEmail") if err != nil { - return err + return fmt.Errorf("add column user.local_email error: %s", err.Error()) } const limit = 100 @@ -27,14 +32,14 @@ func addUserLocalEmail(db *gorm.DB) error { var res []User err := tx.Table("user").Where("type = ?", 0).Where("local_email = ''").Limit(limit).Find(&res).Error if err != nil { - return errors.Wrap(err, "query user") + return fmt.Errorf("query user error: %s", err.Error()) } for _, r := range res { r.LocalEmail = gouuid.NewV4().String() + "@fake.localhost" err = tx.Save(&r).Error if err != nil { - return errors.Wrap(err, "save user") + return fmt.Errorf("save column user.local_email error: %s", err) } } @@ -43,6 +48,11 @@ func addUserLocalEmail(db *gorm.DB) error { } } + err = tx.Migrator().AlterColumn(&User{}, "LocalEmail") + if err != nil { + return fmt.Errorf("alter column user.local_email error: %s", err.Error()) + } + return nil }) } diff --git a/internal/database/migrations/v25.go b/internal/database/migrations/v25.go index 9f7af652e..12fac24fe 100644 --- a/internal/database/migrations/v25.go +++ b/internal/database/migrations/v25.go @@ -1,7 +1,7 @@ package migrations import ( - "github.com/pkg/errors" + "fmt" "gorm.io/gorm" ) @@ -26,7 +26,7 @@ func insertUserPrimaryEmail(db *gorm.DB) error { var res []User err := tx.Table("user").Where("type = ?", 0).Offset(offset).Limit(limit).Find(&res).Error if err != nil { - return errors.Wrap(err, "query user") + return fmt.Errorf("query user error: %s", err.Error()) } for _, r := range res { @@ -37,7 +37,7 @@ func insertUserPrimaryEmail(db *gorm.DB) error { } err := tx.Table("email_address").Where("uid = ? AND email = ?", record.UserID, record.Email).FirstOrCreate(record).Error if err != nil { - return errors.Wrap(err, "insert email") + return fmt.Errorf("insert email error: %s", err.Error()) } } diff --git a/internal/database/models.go b/internal/database/models.go index 9f53974b7..167e52099 100644 --- a/internal/database/models.go +++ b/internal/database/models.go @@ -1,6 +1,6 @@ // Copyright 2014 The Gogs Authors. All rights reserved. // Use of this source code is governed by a MIT-style -// license that can be found in the LICENSE.gogs file. +// license that can be found in the LICENSE file. package database diff --git a/internal/database/users.go b/internal/database/users.go index a363e7da1..0e96514d0 100644 --- a/internal/database/users.go +++ b/internal/database/users.go @@ -1149,6 +1149,7 @@ func (s *UsersStore) Active(ctx context.Context, userID int64) error { user.UpdatedUnix = s.db.NowFunc().Unix() user.Rands = rands + user.IsActive = true err = tx.Save(user).Error if err != nil { diff --git a/internal/email/email.go b/internal/email/email.go index e3ed0906c..877f28497 100644 --- a/internal/email/email.go +++ b/internal/email/email.go @@ -6,6 +6,7 @@ package email import ( "fmt" + "gogs.io/gogs/internal/tool" "html/template" "path/filepath" "sync" @@ -88,7 +89,6 @@ type User interface { DisplayName() string Email() string PublicEmail() string - GenerateEmailActivateCode(string) string } type Repository interface { @@ -123,19 +123,37 @@ func SendUserMail(_ *macaron.Context, u User, tpl, code, subject, info string) { } func SendActivateAccountMail(c *macaron.Context, u User) { - SendUserMail(c, u, MAIL_AUTH_ACTIVATE, u.GenerateEmailActivateCode(u.Email()), c.Tr("mail.activate_account"), "activate account") + token, err := tool.NewClaims(u.ID(), u.Email(), tool.SubjectActiveAccount).ToToken() + if err != nil { + log.Error("Create token error: %s", err.Error()) + return + } + + SendUserMail(c, u, MAIL_AUTH_ACTIVATE, token, c.Tr("mail.activate_account"), "activate account") } func SendResetPasswordMail(c *macaron.Context, u User) { - SendUserMail(c, u, MAIL_AUTH_RESET_PASSWORD, u.GenerateEmailActivateCode(u.Email()), c.Tr("mail.reset_password"), "reset password") + token, err := tool.NewClaims(u.ID(), u.Email(), tool.SubjectForgetPasswd).ToToken() + if err != nil { + log.Error("Create token error: %s", err.Error()) + return + } + + SendUserMail(c, u, MAIL_AUTH_RESET_PASSWORD, token, c.Tr("mail.reset_password"), "reset password") } // SendActivateAccountMail sends confirmation email. func SendActivateEmailMail(c *macaron.Context, u User, email string) { + token, err := tool.NewClaims(u.ID(), email, tool.SubjectActiveEmail).ToToken() + if err != nil { + log.Error("Create token error: %s", err.Error()) + return + } + data := map[string]any{ "Username": u.DisplayName(), "ActiveCodeLives": conf.Auth.ActivateCodeLives / 60, - "Code": u.GenerateEmailActivateCode(email), + "Code": token, "Email": email, } body, err := render(MAIL_AUTH_ACTIVATE_EMAIL, data) diff --git a/internal/route/user/auth.go b/internal/route/user/auth.go index 6bbfe06e5..b8a058c70 100644 --- a/internal/route/user/auth.go +++ b/internal/route/user/auth.go @@ -6,13 +6,10 @@ package user import ( gocontext "context" - "encoding/hex" "fmt" + "github.com/go-macaron/captcha" "net/http" "net/url" - "strings" - - "github.com/go-macaron/captcha" log "unknwon.dev/clog/v2" "gogs.io/gogs/internal/auth" @@ -395,66 +392,51 @@ func SignUpPost(c *context.Context, cpt *captcha.Captcha, f form.Register) { c.RedirectSubpath("/user/login") } -// parseUserFromCode returns user by username encoded in code. -// It returns nil if code or username is invalid. -func parseUserFromCode(code string) (user *database.User) { - if len(code) <= tool.TIME_LIMIT_CODE_LENGTH { +// verify active code when active account +func verifyUserActiveCode(code string) (user *database.User) { + data, err := tool.ParseToken(code) + if err != nil || data.Valid() != nil { return nil } - // Use tail hex username to query user - hexStr := code[tool.TIME_LIMIT_CODE_LENGTH:] - if b, err := hex.DecodeString(hexStr); err == nil { - if user, err = database.Handle.Users().GetByUsername(gocontext.TODO(), string(b)); user != nil { - return user - } else if !database.IsErrUserNotExist(err) { - log.Error("Failed to get user by name %q: %v", string(b), err) + if user, err = database.Handle.Users().GetByID(gocontext.TODO(), data.Id); err != nil { + if !database.IsErrUserNotExist(err) { + log.Error("Failed to get user by id %d: %v", data.Id, err) } + return nil } - return nil -} - -// verify active code when active account -func verifyUserActiveCode(code string) (user *database.User) { - minutes := conf.Auth.ActivateCodeLives - - if user = parseUserFromCode(code); user != nil { - // time limit code - prefix := code[:tool.TIME_LIMIT_CODE_LENGTH] - data := fmt.Sprintf("%d%s%s%s%s", user.ID, user.Email, strings.ToLower(user.Name), user.Password, user.Rands) - - if tool.VerifyTimeLimitCode(data, minutes, prefix) { - return user - } - } - return nil + return user } // verify active code when active account func verifyActiveEmailCode(code, email string) *database.EmailAddress { - minutes := conf.Auth.ActivateCodeLives - - if user := parseUserFromCode(code); user != nil { - // time limit code - prefix := code[:tool.TIME_LIMIT_CODE_LENGTH] - data := fmt.Sprintf("%d%s%s%s%s", user.ID, email, strings.ToLower(user.Name), user.Password, user.Rands) - - if tool.VerifyTimeLimitCode(data, minutes, prefix) { - emailAddress, err := database.Handle.Users().GetEmail(gocontext.TODO(), user.ID, email, false) - if err == nil { - return emailAddress - } - } + data, err := tool.ParseToken(code) + if err != nil { + return nil + } else if data.Valid() != nil { + return nil } - return nil + + user, err := database.Handle.Users().GetByID(gocontext.TODO(), data.Id) + if err != nil || user == nil { + log.Error("Failed to get user by id %d: %v", data.Id, err) + return nil + } + + emailAddress, err := database.Handle.Users().GetEmail(gocontext.TODO(), user.ID, email, false) + if err != nil { + return nil + } + + return emailAddress } func Activate(c *context.Context) { code := c.Query("code") if code == "" { c.Data["IsActivatePage"] = true - if c.User.IsActive { + if c.User == nil || c.User.IsActive { c.NotFound() return } @@ -602,25 +584,31 @@ func ResetPasswdPost(c *context.Context) { } c.Data["Code"] = code - if u := verifyUserActiveCode(code); u != nil { - // Validate password length. - password := c.Query("password") - if len(password) < 6 { - c.Data["IsResetForm"] = true - c.Data["Err_Password"] = true - c.RenderWithErr(c.Tr("auth.password_too_short"), RESET_PASSWORD, nil) - return - } + data, err := tool.ParseToken(code) + if err == nil && data.Valid() == nil { + user, err := database.Handle.Users().GetByID(gocontext.TODO(), data.Id) + if err == nil && user != nil { + // Validate password length. + password := c.Query("password") + if len(password) < 6 { + c.Data["IsResetForm"] = true + c.Data["Err_Password"] = true + c.RenderWithErr(c.Tr("auth.password_too_short"), RESET_PASSWORD, nil) + return + } - err := database.Handle.Users().Update(c.Req.Context(), u.ID, database.UpdateUserOptions{Password: &password}) - if err != nil { - c.Error(err, "update user") - return - } + err := database.Handle.Users().Update(c.Req.Context(), user.ID, database.UpdateUserOptions{Password: &password}) + if err != nil { + c.Error(err, "update user") + return + } - log.Trace("User password reset: %s", u.Name) - c.RedirectSubpath("/user/login") - return + log.Trace("User password reset: %s", user.Name) + c.RedirectSubpath("/user/login") + return + } else if user == nil { + log.Error("Failed to get user by id %d: %v", data.Id, err) + } } c.Data["IsResetFailed"] = true diff --git a/internal/tool/jwt.go b/internal/tool/jwt.go new file mode 100644 index 000000000..760f1d429 --- /dev/null +++ b/internal/tool/jwt.go @@ -0,0 +1,102 @@ +package tool + +import ( + "crypto/rand" + "fmt" + "github.com/dgrijalva/jwt-go" + "gogs.io/gogs/internal/conf" + "time" +) + +type Subject int + +const ( + SubjectActiveAccount Subject = 1 + SubjectActiveEmail Subject = 2 + SubjectForgetPasswd Subject = 3 +) + +var secretKey = make([]byte, 32) + +func init() { + if _, err := rand.Read(secretKey); err != nil { + panic(err) + } +} + +type Claims struct { + Audience string `json:"aud,omitempty"` + ExpiresAt int64 `json:"exp,omitempty"` + Id int64 `json:"jti,omitempty"` + Email string `json:"email,omitempty"` + IssuedAt int64 `json:"iat,omitempty"` + Issuer string `json:"iss,omitempty"` + NotBefore int64 `json:"nbf,omitempty"` + Subject Subject `json:"sub,omitempty"` +} + +func (c *Claims) Valid() error { + now := time.Now() + + if now.After(time.Unix(c.ExpiresAt, 0)) { + return fmt.Errorf("error") + } + + if now.Before(time.Unix(c.NotBefore, 0)) { + return fmt.Errorf("error") + } + + if now.Before(time.Unix(c.IssuedAt, 0)) { + return fmt.Errorf("error") + } + + if c.Audience != c.Email { + return fmt.Errorf("error") + } + + return nil +} + +func NewClaims(id int64, email string, subject Subject) *Claims { + now := time.Now() + return &Claims{ + Audience: email, + ExpiresAt: now.Add(time.Duration(conf.Auth.ActivateCodeLives) * time.Minute).Unix(), + Id: id, + Email: email, + IssuedAt: now.Unix(), + Issuer: conf.Server.ExternalURL, + NotBefore: now.Unix(), + Subject: subject, + } +} + +func (c *Claims) ToToken() (string, error) { + token := jwt.NewWithClaims(jwt.SigningMethodHS256, c) + //使用指定的secret签名并获得完成的编码后的字符串token + + return token.SignedString(secretKey) +} + +func ParseToken(t string) (*Claims, error) { + //解析token + token, err := jwt.ParseWithClaims(t, &Claims{}, func(token *jwt.Token) (i interface{}, err error) { + return secretKey, nil + }) + if err != nil { + return nil, err + } + if claims, ok := token.Claims.(*Claims); ok && claims != nil && token.Valid { + return claims, nil + } else if err := claims.Valid(); err != nil { + return nil, err + } + + if claims, ok := token.Claims.(*Claims); ok && claims != nil && token.Valid { + if err := claims.Valid(); err != nil { + return nil, err + } + return claims, nil + } + return nil, fmt.Errorf("invalid token") +} diff --git a/internal/tool/tool.go b/internal/tool/tool.go index 64c20569d..242747c05 100644 --- a/internal/tool/tool.go +++ b/internal/tool/tool.go @@ -5,9 +5,7 @@ package tool import ( - "crypto/sha1" "encoding/base64" - "encoding/hex" "fmt" "html/template" "strings" @@ -62,66 +60,6 @@ func BasicAuthDecode(encoded string) (string, string, error) { return auth[0], auth[1], nil } -// verify time limit code -func VerifyTimeLimitCode(data string, minutes int, code string) bool { - if len(code) <= 18 { - return false - } - - // split code - start := code[:12] - lives := code[12:18] - if d, err := com.StrTo(lives).Int(); err == nil { - minutes = d - } - - // right active code - retCode := CreateTimeLimitCode(data, minutes, start) - if retCode == code && minutes > 0 { - // check time is expired or not - before, _ := time.ParseInLocation("200601021504", start, time.Local) - now := time.Now() - if before.Add(time.Minute*time.Duration(minutes)).Unix() > now.Unix() { - return true - } - } - - return false -} - -const TIME_LIMIT_CODE_LENGTH = 12 + 6 + 40 - -// CreateTimeLimitCode generates a time limit code based on given input data. -// Format: 12 length date time string + 6 minutes string + 40 sha1 encoded string -func CreateTimeLimitCode(data string, minutes int, startInf any) string { - format := "200601021504" - - var start, end time.Time - var startStr, endStr string - - if startInf == nil { - // Use now time create code - start = time.Now() - startStr = start.Format(format) - } else { - // use start string create code - startStr = startInf.(string) - start, _ = time.ParseInLocation(format, startStr, time.Local) - startStr = start.Format(format) - } - - end = start.Add(time.Minute * time.Duration(minutes)) - endStr = end.Format(format) - - // create sha1 encode string - sh := sha1.New() - _, _ = sh.Write([]byte(data + conf.Security.SecretKey + startStr + endStr + com.ToStr(minutes))) - encoded := hex.EncodeToString(sh.Sum(nil)) - - code := fmt.Sprintf("%s%06d%s", startStr, minutes, encoded) - return code -} - // HashEmail hashes email address to MD5 string. // https://en.gravatar.com/site/implement/hash/ func HashEmail(email string) string { diff --git a/internal/userutil/userutil.go b/internal/userutil/userutil.go index 9de597dd2..9b522b20a 100644 --- a/internal/userutil/userutil.go +++ b/internal/userutil/userutil.go @@ -8,23 +8,19 @@ import ( "bytes" "crypto/sha256" "crypto/subtle" - "encoding/hex" "fmt" + "github.com/nfnt/resize" + "github.com/pkg/errors" + "golang.org/x/crypto/pbkdf2" "image" "image/png" "os" "path/filepath" "strconv" - "strings" - - "github.com/nfnt/resize" - "github.com/pkg/errors" - "golang.org/x/crypto/pbkdf2" "gogs.io/gogs/internal/avatar" "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/strutil" - "gogs.io/gogs/internal/tool" ) // DashboardURLPath returns the URL path to the user or organization dashboard. @@ -35,20 +31,6 @@ func DashboardURLPath(name string, isOrganization bool) string { return conf.Server.Subpath + "/" } -// GenerateActivateCode generates an activate code based on user information and -// the given email. -func GenerateActivateCode(userID int64, email, name, password, rands string) string { - code := tool.CreateTimeLimitCode( - fmt.Sprintf("%d%s%s%s%s", userID, email, strings.ToLower(name), password, rands), - conf.Auth.ActivateCodeLives, - nil, - ) - - // Add tailing hex username - code += hex.EncodeToString([]byte(strings.ToLower(name))) - return code -} - // CustomAvatarPath returns the absolute path of the user custom avatar file. func CustomAvatarPath(userID int64) string { return filepath.Join(conf.Picture.AvatarUploadPath, strconv.FormatInt(userID, 10)) diff --git a/internal/userutil/userutil_test.go b/internal/userutil/userutil_test.go index ee1ccb3c9..14549b8be 100644 --- a/internal/userutil/userutil_test.go +++ b/internal/userutil/userutil_test.go @@ -14,7 +14,6 @@ import ( "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/osutil" - "gogs.io/gogs/internal/tool" "gogs.io/gogs/public" ) @@ -32,18 +31,6 @@ func TestDashboardURLPath(t *testing.T) { }) } -func TestGenerateActivateCode(t *testing.T) { - conf.SetMockAuth(t, - conf.AuthOpts{ - ActivateCodeLives: 10, - }, - ) - - code := GenerateActivateCode(1, "alice@example.com", "Alice", "123456", "rands") - got := tool.VerifyTimeLimitCode("1alice@example.comalice123456rands", conf.Auth.ActivateCodeLives, code[:tool.TIME_LIMIT_CODE_LENGTH]) - assert.True(t, got) -} - func TestCustomAvatarPath(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("Skipping testing on Windows") diff --git a/public/img/logo-text.png b/public/img/logo-text.png deleted file mode 100644 index 6e5593930ca574adfb300f4fd0b8edd4d83f128b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59080 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≧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 ZqvW>q&Gq9dgF7DX(p1w`t$u17@qY#Mt~>w$ diff --git a/templates/explore/repos.tmpl b/templates/explore/repos.tmpl index 6e4b7142f..d89942e6e 100644 --- a/templates/explore/repos.tmpl +++ b/templates/explore/repos.tmpl @@ -5,7 +5,7 @@

diff --git a/templates/home.tmpl b/templates/home.tmpl index 9e7ee86e7..a73a3101c 100644 --- a/templates/home.tmpl +++ b/templates/home.tmpl @@ -3,7 +3,7 @@

diff --git a/templates/user/dashboard/dashboard.tmpl b/templates/user/dashboard/dashboard.tmpl index 3ea43551a..ee76d5d73 100644 --- a/templates/user/dashboard/dashboard.tmpl +++ b/templates/user/dashboard/dashboard.tmpl @@ -4,7 +4,7 @@