Finish verify email
This commit is contained in:
		
							parent
							
								
									c6e12d2568
								
							
						
					
					
						commit
						35d473f04a
					
				
					 13 changed files with 182 additions and 62 deletions
				
			
		|  | @ -5,6 +5,7 @@ | ||||||
| package models | package models | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"encoding/hex" | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"os" | 	"os" | ||||||
|  | @ -17,6 +18,7 @@ import ( | ||||||
| 	"github.com/gogits/git" | 	"github.com/gogits/git" | ||||||
| 
 | 
 | ||||||
| 	"github.com/gogits/gogs/modules/base" | 	"github.com/gogits/gogs/modules/base" | ||||||
|  | 	"github.com/gogits/gogs/modules/log" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // User types.
 | // User types.
 | ||||||
|  | @ -139,9 +141,43 @@ func RegisterUser(user *User) (*User, error) { | ||||||
| 	return user, nil | 	return user, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // get user by erify code
 | ||||||
|  | func getVerifyUser(code string) (user *User) { | ||||||
|  | 	if len(code) <= base.TimeLimitCodeLength { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// use tail hex username query user
 | ||||||
|  | 	hexStr := code[base.TimeLimitCodeLength:] | ||||||
|  | 	if b, err := hex.DecodeString(hexStr); err == nil { | ||||||
|  | 		if user, err = GetUserByName(string(b)); user != nil { | ||||||
|  | 			return user | ||||||
|  | 		} | ||||||
|  | 		log.Error("user.getVerifyUser: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // verify active code when active account
 | ||||||
|  | func VerifyUserActiveCode(code string) (user *User) { | ||||||
|  | 	minutes := base.Service.ActiveCodeLives | ||||||
|  | 
 | ||||||
|  | 	if user = getVerifyUser(code); user != nil { | ||||||
|  | 		// time limit code
 | ||||||
|  | 		prefix := code[:base.TimeLimitCodeLength] | ||||||
|  | 		data := base.ToStr(user.Id) + user.Email + user.LowerName + user.Passwd + user.Rands | ||||||
|  | 
 | ||||||
|  | 		if base.VerifyTimeLimitCode(data, minutes, prefix) { | ||||||
|  | 			return user | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // UpdateUser updates user's information.
 | // UpdateUser updates user's information.
 | ||||||
| func UpdateUser(user *User) (err error) { | func UpdateUser(user *User) (err error) { | ||||||
| 	_, err = orm.Id(user.Id).Update(user) | 	_, err = orm.Id(user.Id).UseBool().Update(user) | ||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -131,15 +131,15 @@ func newMailService() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func newRegisterService() { | func newRegisterMailService() { | ||||||
| 	if !Cfg.MustBool("service", "REGISTER_EMAIL_CONFIRM") { | 	if !Cfg.MustBool("service", "REGISTER_EMAIL_CONFIRM") { | ||||||
| 		return | 		return | ||||||
| 	} else if MailService == nil { | 	} else if MailService == nil { | ||||||
| 		log.Warn("Register Service: Mail Service is not enabled") | 		log.Warn("Register Mail Service: Mail Service is not enabled") | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	Service.RegisterEmailConfirm = true | 	Service.RegisterEmailConfirm = true | ||||||
| 	log.Info("Register Service Enabled") | 	log.Info("Register Mail Service Enabled") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func init() { | func init() { | ||||||
|  | @ -177,5 +177,5 @@ func init() { | ||||||
| 	newService() | 	newService() | ||||||
| 	newLogService() | 	newLogService() | ||||||
| 	newMailService() | 	newMailService() | ||||||
| 	newRegisterService() | 	newRegisterMailService() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ import ( | ||||||
| 	"container/list" | 	"container/list" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"html/template" | 	"html/template" | ||||||
|  | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -54,4 +55,7 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{ | ||||||
| 	"ActionDesc": ActionDesc, | 	"ActionDesc": ActionDesc, | ||||||
| 	"DateFormat": DateFormat, | 	"DateFormat": DateFormat, | ||||||
| 	"List":       List, | 	"List":       List, | ||||||
|  | 	"Mail2Domain": func(mail string) string { | ||||||
|  | 		return "mail." + strings.Split(mail, "@")[1] | ||||||
|  | 	}, | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -36,6 +36,35 @@ func GetRandomString(n int) string { | ||||||
| 	return string(bytes) | 	return string(bytes) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // 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 := 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, _ := DateParse(start, "YmdHi") | ||||||
|  | 		now := time.Now() | ||||||
|  | 		if before.Add(time.Minute*time.Duration(minutes)).Unix() > now.Unix() { | ||||||
|  | 			return true | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const TimeLimitCodeLength = 12 + 6 + 40 | ||||||
|  | 
 | ||||||
| // create a time limit code
 | // create a time limit code
 | ||||||
| // code format: 12 length date time string + 6 minutes string + 40 sha1 encoded string
 | // code format: 12 length date time string + 6 minutes string + 40 sha1 encoded string
 | ||||||
| func CreateTimeLimitCode(data string, minutes int, startInf interface{}) string { | func CreateTimeLimitCode(data string, minutes int, startInf interface{}) string { | ||||||
|  | @ -283,16 +312,24 @@ func DateFormat(t time.Time, format string) string { | ||||||
| 	return t.Format(format) | 	return t.Format(format) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type argInt []int | // convert string to specify type
 | ||||||
| 
 | 
 | ||||||
| func (a argInt) Get(i int, args ...int) (r int) { | type StrTo string | ||||||
| 	if i >= 0 && i < len(a) { | 
 | ||||||
| 		r = a[i] | func (f StrTo) Exist() bool { | ||||||
|  | 	return string(f) != string(0x1E) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (f StrTo) Int() (int, error) { | ||||||
|  | 	v, err := strconv.ParseInt(f.String(), 10, 32) | ||||||
|  | 	return int(v), err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (f StrTo) String() string { | ||||||
|  | 	if f.Exist() { | ||||||
|  | 		return string(f) | ||||||
| 	} | 	} | ||||||
| 	if len(args) > 0 { | 	return "" | ||||||
| 		r = args[0] |  | ||||||
| 	} |  | ||||||
| 	return |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // convert any type to string
 | // convert any type to string
 | ||||||
|  | @ -334,6 +371,18 @@ func ToStr(value interface{}, args ...int) (s string) { | ||||||
| 	return s | 	return s | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type argInt []int | ||||||
|  | 
 | ||||||
|  | func (a argInt) Get(i int, args ...int) (r int) { | ||||||
|  | 	if i >= 0 && i < len(a) { | ||||||
|  | 		r = a[i] | ||||||
|  | 	} | ||||||
|  | 	if len(args) > 0 { | ||||||
|  | 		r = args[0] | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
| type Actioner interface { | type Actioner interface { | ||||||
| 	GetOpType() int | 	GetOpType() int | ||||||
| 	GetActUserName() string | 	GetActUserName() string | ||||||
|  |  | ||||||
|  | @ -37,9 +37,9 @@ func GetMailTmplData(user *models.User) map[interface{}]interface{} { | ||||||
| 
 | 
 | ||||||
| // create a time limit code for user active
 | // create a time limit code for user active
 | ||||||
| func CreateUserActiveCode(user *models.User, startInf interface{}) string { | func CreateUserActiveCode(user *models.User, startInf interface{}) string { | ||||||
| 	hours := base.Service.ActiveCodeLives / 60 | 	minutes := base.Service.ActiveCodeLives | ||||||
| 	data := base.ToStr(user.Id) + user.Email + user.LowerName + user.Passwd + user.Rands | 	data := base.ToStr(user.Id) + user.Email + user.LowerName + user.Passwd + user.Rands | ||||||
| 	code := base.CreateTimeLimitCode(data, hours, startInf) | 	code := base.CreateTimeLimitCode(data, minutes, startInf) | ||||||
| 
 | 
 | ||||||
| 	// add tail hex username
 | 	// add tail hex username
 | ||||||
| 	code += hex.EncodeToString([]byte(user.LowerName)) | 	code += hex.EncodeToString([]byte(user.LowerName)) | ||||||
|  | @ -70,11 +70,11 @@ func SendRegisterMail(r *middleware.Render, user *models.User) { | ||||||
| func SendActiveMail(r *middleware.Render, user *models.User) { | func SendActiveMail(r *middleware.Render, user *models.User) { | ||||||
| 	code := CreateUserActiveCode(user, nil) | 	code := CreateUserActiveCode(user, nil) | ||||||
| 
 | 
 | ||||||
| 	subject := "Verify your email address" | 	subject := "Verify your e-mail address" | ||||||
| 
 | 
 | ||||||
| 	data := GetMailTmplData(user) | 	data := GetMailTmplData(user) | ||||||
| 	data["Code"] = code | 	data["Code"] = code | ||||||
| 	body, err := r.HTMLString("mail/auth/active_email.html", data) | 	body, err := r.HTMLString("mail/auth/active_email", data) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Error("mail.SendActiveMail(fail to render): %v", err) | 		log.Error("mail.SendActiveMail(fail to render): %v", err) | ||||||
| 		return | 		return | ||||||
|  |  | ||||||
|  | @ -6,6 +6,8 @@ package middleware | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"github.com/codegangsta/martini" | 	"github.com/codegangsta/martini" | ||||||
|  | 
 | ||||||
|  | 	"github.com/gogits/gogs/modules/base" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // SignInRequire requires user to sign in.
 | // SignInRequire requires user to sign in.
 | ||||||
|  | @ -16,10 +18,10 @@ func SignInRequire(redirect bool) martini.Handler { | ||||||
| 				ctx.Redirect("/") | 				ctx.Redirect("/") | ||||||
| 			} | 			} | ||||||
| 			return | 			return | ||||||
| 		} else if !ctx.User.IsActive { | 		} else if !ctx.User.IsActive && base.Service.RegisterEmailConfirm { | ||||||
| 			// ctx.Data["Title"] = "Activate Your Account"
 | 			ctx.Data["Title"] = "Activate Your Account" | ||||||
| 			// ctx.Render.HTML(200, "user/active", ctx.Data)
 | 			ctx.Render.HTML(200, "user/active", ctx.Data) | ||||||
| 			// return
 | 			return | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										25
									
								
								routers/dev/template.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								routers/dev/template.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | ||||||
|  | // 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 dev | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"github.com/codegangsta/martini" | ||||||
|  | 
 | ||||||
|  | 	"github.com/gogits/gogs/models" | ||||||
|  | 	"github.com/gogits/gogs/modules/base" | ||||||
|  | 	"github.com/gogits/gogs/modules/middleware" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TemplatePreview(ctx *middleware.Context, params martini.Params) { | ||||||
|  | 	ctx.Data["User"] = models.User{Name: "Unknown"} | ||||||
|  | 	ctx.Data["AppName"] = base.AppName | ||||||
|  | 	ctx.Data["AppVer"] = base.AppVer | ||||||
|  | 	ctx.Data["AppUrl"] = base.AppUrl | ||||||
|  | 	ctx.Data["AppLogo"] = base.AppLogo | ||||||
|  | 	ctx.Data["Code"] = "2014031910370000009fff6782aadb2162b4a997acb69d4400888e0b9274657374" | ||||||
|  | 	ctx.Data["ActiveCodeLives"] = base.Service.ActiveCodeLives / 60 | ||||||
|  | 	ctx.Data["ResetPwdCodeLives"] = base.Service.ResetPwdCodeLives / 60 | ||||||
|  | 	ctx.HTML(200, params["_1"], ctx.Data) | ||||||
|  | } | ||||||
|  | @ -243,4 +243,18 @@ func Activate(ctx *middleware.Context) { | ||||||
| 		ctx.Render.HTML(200, "user/active", ctx.Data) | 		ctx.Render.HTML(200, "user/active", ctx.Data) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	// Verify code.
 | ||||||
|  | 	if user := models.VerifyUserActiveCode(code); user != nil { | ||||||
|  | 		user.IsActive = true | ||||||
|  | 		user.Rands = models.GetUserSalt() | ||||||
|  | 		models.UpdateUser(user) | ||||||
|  | 		ctx.Session.Set("userId", user.Id) | ||||||
|  | 		ctx.Session.Set("userName", user.Name) | ||||||
|  | 		ctx.Redirect("/", 302) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ctx.Data["IsActivateFailed"] = true | ||||||
|  | 	ctx.Render.HTML(200, "user/active", ctx.Data) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,25 +0,0 @@ | ||||||
| {{template "mail/base.html" .}} |  | ||||||
| {{define "title"}} |  | ||||||
| 	{{if eq .Lang "zh-CN"}} |  | ||||||
| 		 {{.User.NickName}},激活你的账户 |  | ||||||
| 	{{end}} |  | ||||||
| 	{{if eq .Lang "en-US"}} |  | ||||||
| 		 {{.User.NickName}}, please active your account |  | ||||||
| 	{{end}} |  | ||||||
| {{end}} |  | ||||||
| {{define "body"}} |  | ||||||
| 	{{if eq .Lang "zh-CN"}} |  | ||||||
| 		<p style="margin:0;padding:0 0 9px 0;">点击链接验证email,{{.ActiveCodeLives}} 分钟内有效</p> |  | ||||||
| 		<p style="margin:0;padding:0 0 9px 0;"> |  | ||||||
| 			<a href="{{.AppUrl}}active/{{.Code}}">{{.AppUrl}}active/{{.Code}}</a> |  | ||||||
| 		</p> |  | ||||||
| 		<p style="margin:0;padding:0 0 9px 0;">如果链接点击无反应,请复制到浏览器打开。</p> |  | ||||||
| 	{{end}} |  | ||||||
| 	{{if eq .Lang "en-US"}} |  | ||||||
| 		<p style="margin:0;padding:0 0 9px 0;">Please click following link to verify your e-mail in {{.ActiveCodeLives}} hours</p> |  | ||||||
| 		<p style="margin:0;padding:0 0 9px 0;"> |  | ||||||
| 			<a href="{{.AppUrl}}active/{{.Code}}">{{.AppUrl}}active/{{.Code}}</a> |  | ||||||
| 		</p> |  | ||||||
| 		<p style="margin:0;padding:0 0 9px 0;">Copy and paste it to your browser if it's not working.</p> |  | ||||||
| 	{{end}} |  | ||||||
| {{end}} |  | ||||||
|  | @ -2,26 +2,30 @@ | ||||||
| <html> | <html> | ||||||
| <head> | <head> | ||||||
| <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | ||||||
| <title>{{.Title}} - {{AppName}}</title> | <title>{{.User.Name}}, please activate your account</title> | ||||||
| </head> | </head> | ||||||
| <body style="background:#eee;"> | <body style="background:#eee;"> | ||||||
| <div style="color:#555; font:12px/1.5 Tahoma,Arial,sans-serif;; text-shadow:1px 1px #fff; padding:0; margin:0;"> | <div style="color:#333; font:12px/1.5 Tahoma,Arial,sans-serif;; text-shadow:1px 1px #fff; padding:0; margin:0;"> | ||||||
|     <div style="width:600px;margin:0 auto; padding:40px 0 20px;"> |     <div style="width:600px;margin:0 auto; padding:40px 0 20px;"> | ||||||
|         <div style="border:1px solid #d9d9d9;border-radius:3px; background:#fff; box-shadow: 0px 2px 5px rgba(0, 0, 0,.05); -webkit-box-shadow: 0px 2px 5px rgba(0, 0, 0,.05);"> |         <div style="border:1px solid #d9d9d9;border-radius:3px; background:#fff; box-shadow: 0px 2px 5px rgba(0, 0, 0,.05); -webkit-box-shadow: 0px 2px 5px rgba(0, 0, 0,.05);"> | ||||||
|             <div style="padding: 20px 15px;"> |             <div style="padding: 20px 15px;"> | ||||||
|                 <h1 style="font-size:20px; padding:10px 0 20px; margin:0; border-bottom:1px solid #ddd;"><a style="color:#333;text-decoration:none;" target="_blank" href="{{.AppUrl}}">{{AppName}}</a></h1> |                 <h1 style="font-size:20px; padding:10px 0 20px; margin:0; border-bottom:1px solid #ddd;"><img src="{{.AppUrl}}/{{.AppLogo}}" style="height: 32px; margin-bottom: -10px;"> <a style="color:#333;text-decoration:none;" target="_blank" href="{{.AppUrl}}">{{.AppName}}</a></h1> | ||||||
|                 <div style="padding:40px 15px;"> |                 <div style="padding:40px 15px;"> | ||||||
|                     <div style="font-size:16px; padding-bottom:30px; font-weight:bold;"> |                     <div style="font-size:16px; padding-bottom:30px; font-weight:bold;"> | ||||||
|                         {{.Title}} |                         Hi <span style="color: #00BFFF;">{{.User.Name}}</span>, | ||||||
|                     </div> |                     </div> | ||||||
|                     <div style="font-size:14px; padding:0 15px;"> |                     <div style="font-size:14px; padding:0 15px;"> | ||||||
|                         {{template "body" .}} | 						<p style="margin:0;padding:0 0 9px 0;">Please click following link to verify your e-mail address within <b>{{.ActiveCodeLives}} hours</b>.</p> | ||||||
|  | 						<p style="margin:0;padding:0 0 9px 0;"> | ||||||
|  | 							<a href="{{.AppUrl}}user/activate?code={{.Code}}">{{.AppUrl}}user/activate?code={{.Code}}</a> | ||||||
|  | 						</p> | ||||||
|  | 						<p style="margin:0;padding:0 0 9px 0;">Copy and paste it to your browser if the link is not working.</p> | ||||||
|                     </div> |                     </div> | ||||||
|                 </div> |                 </div> | ||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
|         <div style="color:#aaa;padding:10px;text-align:center;"> |         <div style="color:#aaa;padding:10px;text-align:center;"> | ||||||
|             © 2014 <a style="color:#888;text-decoration:none;" target="_blank" href="{{.AppUrl}}">{{AppName}} |             © 2014 <a style="color:#888;text-decoration:none;" target="_blank" href="http://gogits.org">Gogs: Go Git Service</a> | ||||||
|         </div> |         </div> | ||||||
|     </div> |     </div> | ||||||
| </div> | </div> | ||||||
|  | @ -5,27 +5,27 @@ | ||||||
| <title>{{.User.Name}}, welcome to {{.AppName}}</title> | <title>{{.User.Name}}, welcome to {{.AppName}}</title> | ||||||
| </head> | </head> | ||||||
| <body style="background:#eee;"> | <body style="background:#eee;"> | ||||||
| <div style="color:#555; font:12px/1.5 Tahoma,Arial,sans-serif;; text-shadow:1px 1px #fff; padding:0; margin:0;"> | <div style="color:#333; font:12px/1.5 Tahoma,Arial,sans-serif;; text-shadow:1px 1px #fff; padding:0; margin:0;"> | ||||||
|     <div style="width:600px;margin:0 auto; padding:40px 0 20px;"> |     <div style="width:600px;margin:0 auto; padding:40px 0 20px;"> | ||||||
|         <div style="border:1px solid #d9d9d9;border-radius:3px; background:#fff; box-shadow: 0px 2px 5px rgba(0, 0, 0,.05); -webkit-box-shadow: 0px 2px 5px rgba(0, 0, 0,.05);"> |         <div style="border:1px solid #d9d9d9;border-radius:3px; background:#fff; box-shadow: 0px 2px 5px rgba(0, 0, 0,.05); -webkit-box-shadow: 0px 2px 5px rgba(0, 0, 0,.05);"> | ||||||
|             <div style="padding: 20px 15px;"> |             <div style="padding: 20px 15px;"> | ||||||
|                 <h1 style="font-size:20px; padding:10px 0 20px; margin:0; border-bottom:1px solid #ddd;"><a style="color:#333;text-decoration:none;" target="_blank" href="{{.AppUrl}}">{{.AppName}}</a></h1> |                 <h1 style="font-size:20px; padding:10px 0 20px; margin:0; border-bottom:1px solid #ddd;"><img src="{{.AppUrl}}/{{.AppLogo}}" style="height: 32px; margin-bottom: -10px;"> <a style="color:#333;text-decoration:none;" target="_blank" href="{{.AppUrl}}">{{.AppName}}</a></h1> | ||||||
|                 <div style="padding:40px 15px;"> |                 <div style="padding:40px 15px;"> | ||||||
|                     <div style="font-size:16px; padding-bottom:30px; font-weight:bold;"> |                     <div style="font-size:16px; padding-bottom:30px; font-weight:bold;"> | ||||||
|                         {{.User.Name}}, welcome to {{.AppName}} |                         Hi <span style="color: #00BFFF;">{{.User.Name}}</span>, welcome to register {{.AppName}}! | ||||||
|                     </div> |                     </div> | ||||||
|                     <div style="font-size:14px; padding:0 15px;"> |                     <div style="font-size:14px; padding:0 15px;"> | ||||||
| 						<p style="margin:0;padding:0 0 9px 0;">Please click following link to verify your e-mail in {{.ActiveCodeLives}} hours</p> | 						<p style="margin:0;padding:0 0 9px 0;">Please click following link to verify your e-mail address within <b>{{.ActiveCodeLives}} hours</b>.</p> | ||||||
| 						<p style="margin:0;padding:0 0 9px 0;"> | 						<p style="margin:0;padding:0 0 9px 0;"> | ||||||
| 							<a href="{{.AppUrl}}activate/code={{.Code}}">{{.AppUrl}}active/{{.Code}}</a> | 							<a href="{{.AppUrl}}user/activate?code={{.Code}}">{{.AppUrl}}user/activate?code={{.Code}}</a> | ||||||
| 						</p> | 						</p> | ||||||
| 						<p style="margin:0;padding:0 0 9px 0;">Copy and paste it to your browser if it's not working.</p> | 						<p style="margin:0;padding:0 0 9px 0;">Copy and paste it to your browser if the link is not working.</p> | ||||||
|                     </div> |                     </div> | ||||||
|                 </div> |                 </div> | ||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
|         <div style="color:#aaa;padding:10px;text-align:center;"> |         <div style="color:#aaa;padding:10px;text-align:center;"> | ||||||
|             © 2014 <a style="color:#888;text-decoration:none;" target="_blank" href="{{.AppUrl}}">{{AppName}}</a> |             © 2014 <a style="color:#888;text-decoration:none;" target="_blank" href="http://gogits.org">Gogs: Go Git Service</a> | ||||||
|         </div> |         </div> | ||||||
|     </div> |     </div> | ||||||
| </div> | </div> | ||||||
|  |  | ||||||
|  | @ -1,17 +1,23 @@ | ||||||
| {{template "base/head" .}} | {{template "base/head" .}} | ||||||
| {{template "base/navbar" .}} | {{template "base/navbar" .}} | ||||||
| <div id="gogs-body" class="container"> | <div id="gogs-body" class="container"> | ||||||
|     <form action="/user/activate" method="post" class="form-horizontal gogs-card" id="gogs-login-card"> |     <form action="/user/activate" method="get" class="form-horizontal gogs-card" id="gogs-login-card"> | ||||||
|         <h3>Activate Your Account</h3> |         <h3>Activate Your Account</h3> | ||||||
|         {{if .IsActivatePage}} |         {{if .IsActivatePage}} | ||||||
|             {{if .ServiceNotEnabled}} |             {{if .ServiceNotEnabled}} | ||||||
|             <p>Sorry, Register Mail Confirmation has been disabled.</p> |             <p>Sorry, Register Mail Confirmation has been disabled.</p> | ||||||
|             {{else}} |             {{else}} | ||||||
|             <p>New confirmation e-mail has been sent to <b>{{.SignedUser.Email}}</b>, please check your inbox within {{.Hours}} hours.</p> |             <p>New confirmation e-mail has been sent to <b>{{.SignedUser.Email}}</b>, please check your inbox within {{.Hours}} hours to complete your registeration.</p> | ||||||
|  |             <hr/> | ||||||
|  |             <a href="http://{{Mail2Domain .SignedUser.Email}}" class="btn btn-lg btn-success">Sign in to your e-mail</a> | ||||||
|             {{end}} |             {{end}} | ||||||
|         {{else}} |         {{else}} | ||||||
|             {{if .IsSendRegisterMail}} |             {{if .IsSendRegisterMail}} | ||||||
|             <p>A confirmation e-mail has been sent to <b>{{.Email}}</b>, please check your inbox within {{.Hours}} hours.</p> |             <p>A confirmation e-mail has been sent to <b>{{.Email}}</b>, please check your inbox within {{.Hours}} hours to complete your registeration.</p> | ||||||
|  |             <hr/> | ||||||
|  |             <a href="http://{{Mail2Domain .Email}}" class="btn btn-lg btn-success">Sign in to your e-mail</a> | ||||||
|  |             {{else if .IsActivateFailed}} | ||||||
|  |             <p>Sorry, your confirmation code has been exipired or not valid.</p> | ||||||
|             {{else}} |             {{else}} | ||||||
|     		<p>Hi, {{.SignedUser.Name}}, you have an unconfirmed email address(<b>{{.SignedUser.Email}}</b>). If you haven't received a confirmation e-mail or need to resend a new one, please click botton below.</p> |     		<p>Hi, {{.SignedUser.Name}}, you have an unconfirmed email address(<b>{{.SignedUser.Email}}</b>). If you haven't received a confirmation e-mail or need to resend a new one, please click botton below.</p> | ||||||
|     		<hr/> |     		<hr/> | ||||||
|  |  | ||||||
							
								
								
									
										5
									
								
								web.go
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								web.go
									
									
									
									
									
								
							|  | @ -21,6 +21,7 @@ import ( | ||||||
| 	"github.com/gogits/gogs/modules/log" | 	"github.com/gogits/gogs/modules/log" | ||||||
| 	"github.com/gogits/gogs/modules/middleware" | 	"github.com/gogits/gogs/modules/middleware" | ||||||
| 	"github.com/gogits/gogs/routers" | 	"github.com/gogits/gogs/routers" | ||||||
|  | 	"github.com/gogits/gogs/routers/dev" | ||||||
| 	"github.com/gogits/gogs/routers/repo" | 	"github.com/gogits/gogs/routers/repo" | ||||||
| 	"github.com/gogits/gogs/routers/user" | 	"github.com/gogits/gogs/routers/user" | ||||||
| ) | ) | ||||||
|  | @ -113,6 +114,10 @@ func runWeb(*cli.Context) { | ||||||
| 
 | 
 | ||||||
| 	m.Get("/:username/:reponame", ignSignIn, middleware.RepoAssignment(true), repo.Single) | 	m.Get("/:username/:reponame", ignSignIn, middleware.RepoAssignment(true), repo.Single) | ||||||
| 
 | 
 | ||||||
|  | 	if martini.Env == martini.Dev { | ||||||
|  | 		m.Get("/template/**", dev.TemplatePreview) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	listenAddr := fmt.Sprintf("%s:%s", | 	listenAddr := fmt.Sprintf("%s:%s", | ||||||
| 		base.Cfg.MustValue("server", "HTTP_ADDR"), | 		base.Cfg.MustValue("server", "HTTP_ADDR"), | ||||||
| 		base.Cfg.MustValue("server", "HTTP_PORT", "3000")) | 		base.Cfg.MustValue("server", "HTTP_PORT", "3000")) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue