mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00:00 
			
		
		
		
	Working on register mail confirmation
This commit is contained in:
		
							
								
								
									
										12
									
								
								conf/app.ini
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								conf/app.ini
									
									
									
									
									
								
							| @@ -1,5 +1,6 @@ | ||||
| ; App name that shows on every page title | ||||
| APP_NAME = Gogs: Go Git Service | ||||
| APP_LOGO = img/favicon.png | ||||
| ; !!MUST CHANGE TO YOUR USER NAME!! | ||||
| RUN_USER = lunny | ||||
| ; Either "dev", "prod" or "test", default is "dev" | ||||
| @@ -11,7 +12,8 @@ LANG_IGNS = Google Go|C|Python|Ruby|C Sharp | ||||
| LICENSES = Apache v2 License|GPL v2|MIT License|Affero GPL|BSD (3-Clause) License | ||||
|  | ||||
| [server] | ||||
| DOMAIN = gogits.org | ||||
| DOMAIN = localhost | ||||
| ROOT_URL = http://%(DOMAIN)s:%(HTTP_PORT)s/ | ||||
| HTTP_ADDR =  | ||||
| HTTP_PORT = 3000 | ||||
|  | ||||
| @@ -27,7 +29,13 @@ SSL_MODE = disable | ||||
|  | ||||
| [security] | ||||
| ; !!CHANGE THIS TO KEEP YOUR USER DATA SAFE!! | ||||
| USER_PASSWD_SALT = !#@FDEWREWR&*( | ||||
| SECRET_KEY = !#@FDEWREWR&*( | ||||
|  | ||||
| [service] | ||||
| ACTIVE_CODE_LIVE_MINUTES = 180 | ||||
| RESET_PASSWD_CODE_LIVE_MINUTES = 180 | ||||
| ; User need to confirm e-mail for registration | ||||
| REGISTER_EMAIL_CONFIRM = true | ||||
|  | ||||
| [mailer] | ||||
| ENABLED = false | ||||
|   | ||||
| @@ -19,14 +19,6 @@ import ( | ||||
| 	"github.com/gogits/gogs/modules/base" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	UserPasswdSalt string | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	UserPasswdSalt = base.Cfg.MustValue("security", "USER_PASSWD_SALT") | ||||
| } | ||||
|  | ||||
| // User types. | ||||
| const ( | ||||
| 	UT_INDIVIDUAL = iota + 1 | ||||
| @@ -56,6 +48,9 @@ type User struct { | ||||
| 	AvatarEmail   string `xorm:"not null"` | ||||
| 	Location      string | ||||
| 	Website       string | ||||
| 	IsActive      bool | ||||
| 	Rands         string `xorm:"VARCHAR(10)"` | ||||
| 	Expired       time.Time | ||||
| 	Created       time.Time `xorm:"created"` | ||||
| 	Updated       time.Time `xorm:"updated"` | ||||
| } | ||||
| @@ -104,6 +99,11 @@ func (user *User) NewGitSig() *git.Signature { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // return a user salt token | ||||
| func GetUserSalt() string { | ||||
| 	return base.GetRandomString(10) | ||||
| } | ||||
|  | ||||
| // RegisterUser creates record of a new user. | ||||
| func RegisterUser(user *User) (err error) { | ||||
| 	isExist, err := IsUserExist(user.Name) | ||||
| @@ -123,6 +123,8 @@ func RegisterUser(user *User) (err error) { | ||||
| 	user.LowerName = strings.ToLower(user.Name) | ||||
| 	user.Avatar = base.EncodeMd5(user.Email) | ||||
| 	user.AvatarEmail = user.Email | ||||
| 	user.Expired = time.Now().Add(3 * 24 * time.Hour) | ||||
| 	user.Rands = GetUserSalt() | ||||
| 	if err = user.EncodePasswd(); err != nil { | ||||
| 		return err | ||||
| 	} else if _, err = orm.Insert(user); err != nil { | ||||
| @@ -134,6 +136,11 @@ func RegisterUser(user *User) (err error) { | ||||
| 		} | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Send confirmation e-mail. | ||||
| 	if base.Service.RegisterEmailConfitm { | ||||
|  | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @@ -183,7 +190,7 @@ func DeleteUser(user *User) error { | ||||
|  | ||||
| // EncodePasswd encodes password to safe format. | ||||
| func (user *User) EncodePasswd() error { | ||||
| 	newPasswd, err := scrypt.Key([]byte(user.Passwd), []byte(UserPasswdSalt), 16384, 8, 1, 64) | ||||
| 	newPasswd, err := scrypt.Key([]byte(user.Passwd), []byte(base.SecretKey), 16384, 8, 1, 64) | ||||
| 	user.Passwd = fmt.Sprintf("%x", newPasswd) | ||||
| 	return err | ||||
| } | ||||
|   | ||||
							
								
								
									
										42
									
								
								modules/auth/mail.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								modules/auth/mail.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| // 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 file. | ||||
|  | ||||
| package auth | ||||
|  | ||||
| import ( | ||||
| 	"encoding/hex" | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/gogits/gogs/models" | ||||
| 	"github.com/gogits/gogs/modules/base" | ||||
| 	"github.com/gogits/gogs/modules/mailer" | ||||
| ) | ||||
|  | ||||
| // create a time limit code for user active | ||||
| func CreateUserActiveCode(user *models.User, startInf interface{}) string { | ||||
| 	hours := base.Service.ActiveCodeLives / 60 | ||||
| 	data := fmt.Sprintf("%d", user.Id) + user.Email + user.LowerName + user.Passwd + user.Rands | ||||
| 	code := base.CreateTimeLimitCode(data, hours, startInf) | ||||
|  | ||||
| 	// add tail hex username | ||||
| 	code += hex.EncodeToString([]byte(user.LowerName)) | ||||
| 	return code | ||||
| } | ||||
|  | ||||
| // Send user register mail with active code | ||||
| func SendRegisterMail(user *models.User) { | ||||
| 	code := CreateUserActiveCode(user, nil) | ||||
| 	subject := "Register success, Welcome" | ||||
|  | ||||
| 	data := mailer.GetMailTmplData(user) | ||||
| 	data["Code"] = code | ||||
| 	body := base.RenderTemplate("mail/auth/register_success.html", data) | ||||
| 	_, _, _ = code, subject, body | ||||
|  | ||||
| 	// msg := mailer.NewMailMessage([]string{user.Email}, subject, body) | ||||
| 	// msg.Info = fmt.Sprintf("UID: %d, send register mail", user.Id) | ||||
|  | ||||
| 	// // async send mail | ||||
| 	// mailer.SendAsync(msg) | ||||
| } | ||||
| @@ -28,11 +28,20 @@ type Mailer struct { | ||||
| var ( | ||||
| 	AppVer      string | ||||
| 	AppName     string | ||||
| 	AppLogo     string | ||||
| 	AppUrl      string | ||||
| 	Domain      string | ||||
| 	SecretKey   string | ||||
| 	Cfg         *goconfig.ConfigFile | ||||
| 	MailService *Mailer | ||||
| ) | ||||
|  | ||||
| var Service struct { | ||||
| 	RegisterEmailConfitm bool | ||||
| 	ActiveCodeLives      int | ||||
| 	ResetPwdCodeLives    int | ||||
| } | ||||
|  | ||||
| func exeDir() (string, error) { | ||||
| 	file, err := exec.LookPath(os.Args[0]) | ||||
| 	if err != nil { | ||||
| @@ -54,6 +63,11 @@ var logLevels = map[string]string{ | ||||
| 	"Critical": "5", | ||||
| } | ||||
|  | ||||
| func newService() { | ||||
| 	Service.ActiveCodeLives = Cfg.MustInt("service", "ACTIVE_CODE_LIVE_MINUTES", 180) | ||||
| 	Service.ResetPwdCodeLives = Cfg.MustInt("service", "RESET_PASSWD_CODE_LIVE_MINUTES", 180) | ||||
| } | ||||
|  | ||||
| func newLogService() { | ||||
| 	// Get and check log mode. | ||||
| 	mode := Cfg.MustValue("log", "MODE", "console") | ||||
| @@ -117,6 +131,17 @@ func newMailService() { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func newRegisterService() { | ||||
| 	if !Cfg.MustBool("service", "REGISTER_EMAIL_CONFIRM") { | ||||
| 		return | ||||
| 	} else if MailService == nil { | ||||
| 		log.Warn("Register Service: Mail Service is not enabled") | ||||
| 		return | ||||
| 	} | ||||
| 	Service.RegisterEmailConfitm = true | ||||
| 	log.Info("Register Service Enabled") | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	var err error | ||||
| 	workDir, err := exeDir() | ||||
| @@ -143,9 +168,13 @@ func init() { | ||||
| 	Cfg.BlockMode = false | ||||
|  | ||||
| 	AppName = Cfg.MustValue("", "APP_NAME", "Gogs: Go Git Service") | ||||
| 	AppLogo = Cfg.MustValue("", "APP_LOGO", "img/favicon.png") | ||||
| 	AppUrl = Cfg.MustValue("server", "ROOT_URL") | ||||
| 	Domain = Cfg.MustValue("server", "DOMAIN") | ||||
| 	SecretKey = Cfg.MustValue("security", "SECRET_KEY") | ||||
|  | ||||
| 	// Extensions. | ||||
| 	newLogService() | ||||
| 	newMailService() | ||||
| 	newRegisterService() | ||||
| } | ||||
|   | ||||
| @@ -7,6 +7,8 @@ package base | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"crypto/md5" | ||||
| 	"crypto/rand" | ||||
| 	"crypto/sha1" | ||||
| 	"encoding/hex" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| @@ -22,6 +24,66 @@ func EncodeMd5(str string) string { | ||||
| 	return hex.EncodeToString(m.Sum(nil)) | ||||
| } | ||||
|  | ||||
| // Random generate string | ||||
| func GetRandomString(n int) string { | ||||
| 	const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" | ||||
| 	var bytes = make([]byte, n) | ||||
| 	rand.Read(bytes) | ||||
| 	for i, b := range bytes { | ||||
| 		bytes[i] = alphanum[b%byte(len(alphanum))] | ||||
| 	} | ||||
| 	return string(bytes) | ||||
| } | ||||
|  | ||||
| // create a time limit code | ||||
| // code format: 12 length date time string + 6 minutes string + 40 sha1 encoded string | ||||
| func CreateTimeLimitCode(data string, minutes int, startInf interface{}) string { | ||||
| 	format := "YmdHi" | ||||
|  | ||||
| 	var start, end time.Time | ||||
| 	var startStr, endStr string | ||||
|  | ||||
| 	if startInf == nil { | ||||
| 		// Use now time create code | ||||
| 		start = time.Now() | ||||
| 		startStr = DateFormat(start, format) | ||||
| 	} else { | ||||
| 		// use start string create code | ||||
| 		startStr = startInf.(string) | ||||
| 		start, _ = DateParse(startStr, format) | ||||
| 		startStr = DateFormat(start, format) | ||||
| 	} | ||||
|  | ||||
| 	end = start.Add(time.Minute * time.Duration(minutes)) | ||||
| 	endStr = DateFormat(end, format) | ||||
|  | ||||
| 	// create sha1 encode string | ||||
| 	sh := sha1.New() | ||||
| 	sh.Write([]byte(data + SecretKey + startStr + endStr + fmt.Sprintf("%d", minutes))) | ||||
| 	encoded := hex.EncodeToString(sh.Sum(nil)) | ||||
|  | ||||
| 	code := fmt.Sprintf("%s%06d%s", startStr, minutes, encoded) | ||||
| 	return code | ||||
| } | ||||
|  | ||||
| func RenderTemplate(TplNames string, Data map[interface{}]interface{}) string { | ||||
| 	// if beego.RunMode == "dev" { | ||||
| 	// 	beego.BuildTemplate(beego.ViewsPath) | ||||
| 	// } | ||||
|  | ||||
| 	// ibytes := bytes.NewBufferString("") | ||||
| 	// if _, ok := beego.BeeTemplates[TplNames]; !ok { | ||||
| 	// 	panic("can't find templatefile in the path:" + TplNames) | ||||
| 	// } | ||||
| 	// err := beego.BeeTemplates[TplNames].ExecuteTemplate(ibytes, TplNames, Data) | ||||
| 	// if err != nil { | ||||
| 	// 	beego.Trace("template Execute err:", err) | ||||
| 	// } | ||||
| 	// icontent, _ := ioutil.ReadAll(ibytes) | ||||
| 	// return string(icontent) | ||||
| 	return "not implement yet" | ||||
| } | ||||
|  | ||||
| // AvatarLink returns avatar link by given e-mail. | ||||
| func AvatarLink(email string) string { | ||||
| 	return "http://1.gravatar.com/avatar/" + EncodeMd5(email) | ||||
|   | ||||
							
								
								
									
										24
									
								
								modules/mailer/mail.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								modules/mailer/mail.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| // 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 file. | ||||
|  | ||||
| package mailer | ||||
|  | ||||
| import ( | ||||
| 	"github.com/gogits/gogs/models" | ||||
| 	"github.com/gogits/gogs/modules/base" | ||||
| ) | ||||
|  | ||||
| func GetMailTmplData(user *models.User) map[interface{}]interface{} { | ||||
| 	data := make(map[interface{}]interface{}, 10) | ||||
| 	data["AppName"] = base.AppName | ||||
| 	data["AppVer"] = base.AppVer | ||||
| 	data["AppUrl"] = base.AppUrl | ||||
| 	data["AppLogo"] = base.AppLogo | ||||
| 	data["ActiveCodeLives"] = base.Service.ActiveCodeLives | ||||
| 	data["ResetPwdCodeLives"] = base.Service.ResetPwdCodeLives | ||||
| 	if user != nil { | ||||
| 		data["User"] = user | ||||
| 	} | ||||
| 	return data | ||||
| } | ||||
| @@ -37,6 +37,8 @@ func Logger() martini.Handler { | ||||
| 				content = fmt.Sprintf("\033[1;33m%s\033[0m", content) | ||||
| 			case 404: | ||||
| 				content = fmt.Sprintf("\033[1;31m%s\033[0m", content) | ||||
| 			case 500: | ||||
| 				content = fmt.Sprintf("\033[1;36m%s\033[0m", content) | ||||
| 			} | ||||
| 		} | ||||
| 		log.Println(content) | ||||
|   | ||||
| @@ -131,9 +131,10 @@ func SignUp(ctx *middleware.Context, form auth.RegisterForm) { | ||||
| 	} | ||||
|  | ||||
| 	u := &models.User{ | ||||
| 		Name:   form.UserName, | ||||
| 		Email:  form.Email, | ||||
| 		Passwd: form.Password, | ||||
| 		Name:     form.UserName, | ||||
| 		Email:    form.Email, | ||||
| 		Passwd:   form.Password, | ||||
| 		IsActive: !base.Service.RegisterEmailConfitm, | ||||
| 	} | ||||
|  | ||||
| 	if err := models.RegisterUser(u); err != nil { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Unknown
					Unknown