1
0
Эх сурвалжийг харах

打入补丁:9F1436E39C95D59E.patch

SongZihuan 1 сар өмнө
parent
commit
5dc50b297f

+ 1 - 0
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

+ 2 - 0
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=

+ 0 - 11
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}
 }

+ 1 - 1
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
 

+ 7 - 7
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),
 }
 

+ 1 - 1
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
 

+ 1 - 1
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
 

+ 1 - 1
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
 

+ 1 - 1
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
 

+ 12 - 2
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

+ 16 - 6
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
 	})
 }

+ 3 - 3
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())
 				}
 			}
 

+ 1 - 1
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
 

+ 1 - 0
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 {

+ 22 - 4
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)

+ 49 - 61
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
+	data, err := tool.ParseToken(code)
+	if err != nil {
+		return nil
+	} else if data.Valid() != nil {
+		return nil
+	}
 
-	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)
+	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
+	}
 
-		if tool.VerifyTimeLimitCode(data, minutes, prefix) {
-			emailAddress, err := database.Handle.Users().GetEmail(gocontext.TODO(), user.ID, email, false)
-			if err == nil {
-				return emailAddress
-			}
-		}
+	emailAddress, err := database.Handle.Users().GetEmail(gocontext.TODO(), user.ID, email, false)
+	if err != nil {
+		return 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")
+			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", user.Name)
+			c.RedirectSubpath("/user/login")
 			return
+		} else if user == nil {
+			log.Error("Failed to get user by id %d: %v", data.Id, err)
 		}
-
-		log.Trace("User password reset: %s", u.Name)
-		c.RedirectSubpath("/user/login")
-		return
 	}
 
 	c.Data["IsResetFailed"] = true

+ 102 - 0
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")
+}

+ 0 - 62
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 {

+ 3 - 21
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))

+ 0 - 13
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")

BIN
public/img/logo-text.png


+ 1 - 1
templates/explore/repos.tmpl

@@ -5,7 +5,7 @@
 			<div class="ui middle very relaxed page grid">
 				<div class="sixteen wide center aligned centered column">
 					<div class="explore-logo">
-						<img alt="logo" src="{{AppSubURL}}/img/logo-text.png" />
+						<img alt="logo" src="{{AppSubURL}}/img/gogs-hero.png" />
 					</div>
 					<div class="export-hero">
 						<h1>

+ 1 - 1
templates/home.tmpl

@@ -3,7 +3,7 @@
 	<div class="ui stackable middle very relaxed page grid">
 		<div class="sixteen wide center aligned centered column">
 			<div class="logo">
-				<img alt="logo" src="{{AppSubURL}}/img/logo-text.png" />
+				<img alt="logo" src="{{AppSubURL}}/img/gogs-hero.png" />
 			</div>
 			<div class="hero">
 				<h2>

+ 1 - 1
templates/user/dashboard/dashboard.tmpl

@@ -4,7 +4,7 @@
 		<div class="ui stackable middle very relaxed page grid">
 			<div class="sixteen wide center aligned centered column">
 				<div class="dashboard-logo">
-					<img alt="logo" src="{{AppSubURL}}/img/logo-text.png" />
+					<img alt="logo" src="{{AppSubURL}}/img/gogs-hero.png" />
 				</div>
 				<div class="dashboard-hero">
 					<h1>