Working on register mail confirmation

This commit is contained in:
Unknown 2014-03-19 07:21:23 -04:00
parent 9a666f3377
commit fbbae2b721
8 changed files with 189 additions and 14 deletions

View file

@ -1,5 +1,6 @@
; App name that shows on every page title ; App name that shows on every page title
APP_NAME = Gogs: Go Git Service APP_NAME = Gogs: Go Git Service
APP_LOGO = img/favicon.png
; !!MUST CHANGE TO YOUR USER NAME!! ; !!MUST CHANGE TO YOUR USER NAME!!
RUN_USER = lunny RUN_USER = lunny
; Either "dev", "prod" or "test", default is "dev" ; 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 LICENSES = Apache v2 License|GPL v2|MIT License|Affero GPL|BSD (3-Clause) License
[server] [server]
DOMAIN = gogits.org DOMAIN = localhost
ROOT_URL = http://%(DOMAIN)s:%(HTTP_PORT)s/
HTTP_ADDR = HTTP_ADDR =
HTTP_PORT = 3000 HTTP_PORT = 3000
@ -27,7 +29,13 @@ SSL_MODE = disable
[security] [security]
; !!CHANGE THIS TO KEEP YOUR USER DATA SAFE!! ; !!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] [mailer]
ENABLED = false ENABLED = false

View file

@ -19,14 +19,6 @@ import (
"github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/base"
) )
var (
UserPasswdSalt string
)
func init() {
UserPasswdSalt = base.Cfg.MustValue("security", "USER_PASSWD_SALT")
}
// User types. // User types.
const ( const (
UT_INDIVIDUAL = iota + 1 UT_INDIVIDUAL = iota + 1
@ -56,6 +48,9 @@ type User struct {
AvatarEmail string `xorm:"not null"` AvatarEmail string `xorm:"not null"`
Location string Location string
Website string Website string
IsActive bool
Rands string `xorm:"VARCHAR(10)"`
Expired time.Time
Created time.Time `xorm:"created"` Created time.Time `xorm:"created"`
Updated time.Time `xorm:"updated"` 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. // RegisterUser creates record of a new user.
func RegisterUser(user *User) (err error) { func RegisterUser(user *User) (err error) {
isExist, err := IsUserExist(user.Name) isExist, err := IsUserExist(user.Name)
@ -123,6 +123,8 @@ func RegisterUser(user *User) (err error) {
user.LowerName = strings.ToLower(user.Name) user.LowerName = strings.ToLower(user.Name)
user.Avatar = base.EncodeMd5(user.Email) user.Avatar = base.EncodeMd5(user.Email)
user.AvatarEmail = user.Email user.AvatarEmail = user.Email
user.Expired = time.Now().Add(3 * 24 * time.Hour)
user.Rands = GetUserSalt()
if err = user.EncodePasswd(); err != nil { if err = user.EncodePasswd(); err != nil {
return err return err
} else if _, err = orm.Insert(user); err != nil { } else if _, err = orm.Insert(user); err != nil {
@ -134,6 +136,11 @@ func RegisterUser(user *User) (err error) {
} }
return err return err
} }
// Send confirmation e-mail.
if base.Service.RegisterEmailConfitm {
}
return nil return nil
} }
@ -183,7 +190,7 @@ func DeleteUser(user *User) error {
// EncodePasswd encodes password to safe format. // EncodePasswd encodes password to safe format.
func (user *User) EncodePasswd() error { 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) user.Passwd = fmt.Sprintf("%x", newPasswd)
return err return err
} }

42
modules/auth/mail.go Normal file
View 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)
}

View file

@ -28,11 +28,20 @@ type Mailer struct {
var ( var (
AppVer string AppVer string
AppName string AppName string
AppLogo string
AppUrl string
Domain string Domain string
SecretKey string
Cfg *goconfig.ConfigFile Cfg *goconfig.ConfigFile
MailService *Mailer MailService *Mailer
) )
var Service struct {
RegisterEmailConfitm bool
ActiveCodeLives int
ResetPwdCodeLives int
}
func exeDir() (string, error) { func exeDir() (string, error) {
file, err := exec.LookPath(os.Args[0]) file, err := exec.LookPath(os.Args[0])
if err != nil { if err != nil {
@ -54,6 +63,11 @@ var logLevels = map[string]string{
"Critical": "5", "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() { func newLogService() {
// Get and check log mode. // Get and check log mode.
mode := Cfg.MustValue("log", "MODE", "console") 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() { func init() {
var err error var err error
workDir, err := exeDir() workDir, err := exeDir()
@ -143,9 +168,13 @@ func init() {
Cfg.BlockMode = false Cfg.BlockMode = false
AppName = Cfg.MustValue("", "APP_NAME", "Gogs: Go Git Service") 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") Domain = Cfg.MustValue("server", "DOMAIN")
SecretKey = Cfg.MustValue("security", "SECRET_KEY")
// Extensions. // Extensions.
newLogService() newLogService()
newMailService() newMailService()
newRegisterService()
} }

View file

@ -7,6 +7,8 @@ package base
import ( import (
"bytes" "bytes"
"crypto/md5" "crypto/md5"
"crypto/rand"
"crypto/sha1"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -22,6 +24,66 @@ func EncodeMd5(str string) string {
return hex.EncodeToString(m.Sum(nil)) 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. // AvatarLink returns avatar link by given e-mail.
func AvatarLink(email string) string { func AvatarLink(email string) string {
return "http://1.gravatar.com/avatar/" + EncodeMd5(email) return "http://1.gravatar.com/avatar/" + EncodeMd5(email)

24
modules/mailer/mail.go Normal file
View 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
}

View file

@ -37,6 +37,8 @@ func Logger() martini.Handler {
content = fmt.Sprintf("\033[1;33m%s\033[0m", content) content = fmt.Sprintf("\033[1;33m%s\033[0m", content)
case 404: case 404:
content = fmt.Sprintf("\033[1;31m%s\033[0m", content) 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) log.Println(content)

View file

@ -131,9 +131,10 @@ func SignUp(ctx *middleware.Context, form auth.RegisterForm) {
} }
u := &models.User{ u := &models.User{
Name: form.UserName, Name: form.UserName,
Email: form.Email, Email: form.Email,
Passwd: form.Password, Passwd: form.Password,
IsActive: !base.Service.RegisterEmailConfitm,
} }
if err := models.RegisterUser(u); err != nil { if err := models.RegisterUser(u); err != nil {