Merge branch 'master' of github.com:gogits/gogs
This commit is contained in:
commit
8b0f421eb5
20 changed files with 256 additions and 120 deletions
|
@ -5,7 +5,7 @@ Gogs(Go Git Service) is a GitHub-like clone in the Go Programming Language.
|
||||||
|
|
||||||
Since we choose to use pure Go implementation of Git manipulation, Gogs certainly supports **ALL platforms** that Go supports, including Linux, Max OS X, and Windows with **ZERO** dependency.
|
Since we choose to use pure Go implementation of Git manipulation, Gogs certainly supports **ALL platforms** that Go supports, including Linux, Max OS X, and Windows with **ZERO** dependency.
|
||||||
|
|
||||||
##### Current version: 0.1.0 Alpha
|
##### Current version: 0.1.1 Alpha
|
||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ There are some very good products in this category such as [gitlab](http://gitla
|
||||||
- User profile page.
|
- User profile page.
|
||||||
- Repository viewer.
|
- Repository viewer.
|
||||||
- Gravatar support.
|
- Gravatar support.
|
||||||
|
- Mail service(register).
|
||||||
- Supports MySQL and PostgreSQL.
|
- Supports MySQL and PostgreSQL.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
|
@ -39,6 +39,8 @@ REGISTER_EMAIL_CONFIRM = false
|
||||||
|
|
||||||
[mailer]
|
[mailer]
|
||||||
ENABLED = false
|
ENABLED = false
|
||||||
|
; Buffer length of channel, keep it as it is if you don't know what it is.
|
||||||
|
SEND_BUFFER_LEN = 10
|
||||||
; Name displayed in mail title
|
; Name displayed in mail title
|
||||||
SUBJECT = %(APP_NAME)s
|
SUBJECT = %(APP_NAME)s
|
||||||
; Mail server
|
; Mail server
|
||||||
|
|
2
gogs.go
2
gogs.go
|
@ -20,7 +20,7 @@ import (
|
||||||
// Test that go1.1 tag above is included in builds. main.go refers to this definition.
|
// Test that go1.1 tag above is included in builds. main.go refers to this definition.
|
||||||
const go11tag = true
|
const go11tag = true
|
||||||
|
|
||||||
const APP_VER = "0.1.0.0319.1"
|
const APP_VER = "0.1.1.0320.1"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
base.AppVer = APP_VER
|
base.AppVer = APP_VER
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -49,8 +51,7 @@ type User struct {
|
||||||
Location string
|
Location string
|
||||||
Website string
|
Website string
|
||||||
IsActive bool
|
IsActive bool
|
||||||
Rands string `xorm:"VARCHAR(10)"`
|
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"`
|
||||||
}
|
}
|
||||||
|
@ -123,7 +124,6 @@ func RegisterUser(user *User) (*User, 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()
|
user.Rands = GetUserSalt()
|
||||||
if err = user.EncodePasswd(); err != nil {
|
if err = user.EncodePasswd(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -139,9 +139,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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,9 +91,11 @@ func newLogService() {
|
||||||
case "console":
|
case "console":
|
||||||
config = fmt.Sprintf(`{"level":%s}`, level)
|
config = fmt.Sprintf(`{"level":%s}`, level)
|
||||||
case "file":
|
case "file":
|
||||||
|
logPath := Cfg.MustValue(modeSec, "FILE_NAME", "log/gogs.log")
|
||||||
|
os.MkdirAll(path.Dir(logPath), os.ModePerm)
|
||||||
config = fmt.Sprintf(
|
config = fmt.Sprintf(
|
||||||
`{"level":%s,"filename":%s,"rotate":%v,"maxlines":%d,"maxsize",%d,"daily":%v,"maxdays":%d}`, level,
|
`{"level":%s,"filename":%s,"rotate":%v,"maxlines":%d,"maxsize",%d,"daily":%v,"maxdays":%d}`, level,
|
||||||
Cfg.MustValue(modeSec, "FILE_NAME", "log/gogs.log"),
|
logPath,
|
||||||
Cfg.MustBool(modeSec, "LOG_ROTATE", true),
|
Cfg.MustBool(modeSec, "LOG_ROTATE", true),
|
||||||
Cfg.MustInt(modeSec, "MAX_LINES", 1000000),
|
Cfg.MustInt(modeSec, "MAX_LINES", 1000000),
|
||||||
1<<uint(Cfg.MustInt(modeSec, "MAX_SIZE_SHIFT", 28)),
|
1<<uint(Cfg.MustInt(modeSec, "MAX_SIZE_SHIFT", 28)),
|
||||||
|
@ -131,15 +133,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() {
|
||||||
|
@ -172,10 +174,11 @@ func init() {
|
||||||
AppUrl = Cfg.MustValue("server", "ROOT_URL")
|
AppUrl = Cfg.MustValue("server", "ROOT_URL")
|
||||||
Domain = Cfg.MustValue("server", "DOMAIN")
|
Domain = Cfg.MustValue("server", "DOMAIN")
|
||||||
SecretKey = Cfg.MustValue("security", "SECRET_KEY")
|
SecretKey = Cfg.MustValue("security", "SECRET_KEY")
|
||||||
|
}
|
||||||
|
|
||||||
// Extensions.
|
func NewServices() {
|
||||||
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,10 @@ 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]
|
||||||
|
},
|
||||||
|
"SubStr": func(str string, start, length int) string {
|
||||||
|
return str[start : start+length]
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
|
@ -62,19 +62,18 @@ func SendRegisterMail(r *middleware.Render, user *models.User) {
|
||||||
msg := NewMailMessage([]string{user.Email}, subject, body)
|
msg := NewMailMessage([]string{user.Email}, subject, body)
|
||||||
msg.Info = fmt.Sprintf("UID: %d, send register mail", user.Id)
|
msg.Info = fmt.Sprintf("UID: %d, send register mail", user.Id)
|
||||||
|
|
||||||
// async send mail
|
SendAsync(&msg)
|
||||||
SendAsync(msg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send email verify active email.
|
// Send email verify active email.
|
||||||
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
|
||||||
|
@ -83,6 +82,5 @@ func SendActiveMail(r *middleware.Render, user *models.User) {
|
||||||
msg := NewMailMessage([]string{user.Email}, subject, body)
|
msg := NewMailMessage([]string{user.Email}, subject, body)
|
||||||
msg.Info = fmt.Sprintf("UID: %d, send email verify mail", user.Id)
|
msg.Info = fmt.Sprintf("UID: %d, send email verify mail", user.Id)
|
||||||
|
|
||||||
// async send mail
|
SendAsync(&msg)
|
||||||
SendAsync(msg)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,8 +38,34 @@ func (m Message) Content() string {
|
||||||
return content
|
return content
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var mailQueue chan *Message
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
mailQueue = make(chan *Message, base.Cfg.MustInt("mailer", "SEND_BUFFER_LEN", 10))
|
||||||
|
go processMailQueue()
|
||||||
|
}
|
||||||
|
|
||||||
|
func processMailQueue() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case msg := <-mailQueue:
|
||||||
|
num, err := Send(msg)
|
||||||
|
tos := strings.Join(msg.To, "; ")
|
||||||
|
info := ""
|
||||||
|
if err != nil {
|
||||||
|
if len(msg.Info) > 0 {
|
||||||
|
info = ", info: " + msg.Info
|
||||||
|
}
|
||||||
|
log.Error(fmt.Sprintf("Async sent email %d succeed, not send emails: %s%s err: %s", num, tos, info, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Trace(fmt.Sprintf("Async sent email %d succeed, sent emails: %s%s", num, tos, info))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Direct Send mail message
|
// Direct Send mail message
|
||||||
func Send(msg Message) (int, error) {
|
func Send(msg *Message) (int, error) {
|
||||||
log.Trace("Sending mails to: %s", strings.Join(msg.To, "; "))
|
log.Trace("Sending mails to: %s", strings.Join(msg.To, "; "))
|
||||||
host := strings.Split(base.MailService.Host, ":")
|
host := strings.Split(base.MailService.Host, ":")
|
||||||
|
|
||||||
|
@ -82,21 +108,9 @@ func Send(msg Message) (int, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Send mail message
|
// Async Send mail message
|
||||||
func SendAsync(msg Message) {
|
func SendAsync(msg *Message) {
|
||||||
// TODO may be need pools limit concurrent nums
|
|
||||||
go func() {
|
go func() {
|
||||||
num, err := Send(msg)
|
mailQueue <- msg
|
||||||
tos := strings.Join(msg.To, "; ")
|
|
||||||
info := ""
|
|
||||||
if err != nil {
|
|
||||||
if len(msg.Info) > 0 {
|
|
||||||
info = ", info: " + msg.Info
|
|
||||||
}
|
|
||||||
// log failed
|
|
||||||
log.Error(fmt.Sprintf("Async sent email %d succeed, not send emails: %s%s err: %s", num, tos, info, err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Trace(fmt.Sprintf("Async sent email %d succeed, sent emails: %s%s", num, tos, info))
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -13,11 +13,11 @@ import (
|
||||||
|
|
||||||
func Create(ctx *middleware.Context, form auth.CreateRepoForm) {
|
func Create(ctx *middleware.Context, form auth.CreateRepoForm) {
|
||||||
ctx.Data["Title"] = "Create repository"
|
ctx.Data["Title"] = "Create repository"
|
||||||
|
ctx.Data["PageIsNewRepo"] = true // For navbar arrow.
|
||||||
|
ctx.Data["LanguageIgns"] = models.LanguageIgns
|
||||||
|
ctx.Data["Licenses"] = models.Licenses
|
||||||
|
|
||||||
if ctx.Req.Method == "GET" {
|
if ctx.Req.Method == "GET" {
|
||||||
ctx.Data["PageIsNewRepo"] = true // For navbar arrow.
|
|
||||||
ctx.Data["LanguageIgns"] = models.LanguageIgns
|
|
||||||
ctx.Data["Licenses"] = models.Licenses
|
|
||||||
ctx.HTML(200, "repo/create", ctx.Data)
|
ctx.HTML(200, "repo/create", ctx.Data)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
package repo
|
package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/codegangsta/martini"
|
"github.com/codegangsta/martini"
|
||||||
|
@ -137,6 +138,8 @@ func Single(ctx *middleware.Context, params martini.Params) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Println(Paths)
|
||||||
|
|
||||||
ctx.Data["Paths"] = Paths
|
ctx.Data["Paths"] = Paths
|
||||||
ctx.Data["Treenames"] = treenames
|
ctx.Data["Treenames"] = treenames
|
||||||
ctx.Data["IsRepoToolbarSource"] = true
|
ctx.Data["IsRepoToolbarSource"] = true
|
||||||
|
@ -189,6 +192,9 @@ func Commits(ctx *middleware.Context, params martini.Params) {
|
||||||
ctx.Error(404)
|
ctx.Error(404)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
ctx.Data["Username"] = params["username"]
|
||||||
|
ctx.Data["Reponame"] = params["reponame"]
|
||||||
|
ctx.Data["CommitCount"] = commits.Len()
|
||||||
ctx.Data["Commits"] = commits
|
ctx.Data["Commits"] = commits
|
||||||
ctx.HTML(200, "repo/commits", ctx.Data)
|
ctx.HTML(200, "repo/commits", ctx.Data)
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,4 +243,21 @@ 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)
|
||||||
|
|
||||||
|
log.Trace("%s User activated: %s", ctx.Req.RequestURI, user.LowerName)
|
||||||
|
|
||||||
|
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>
|
||||||
|
|
|
@ -9,45 +9,32 @@
|
||||||
<div class="search pull-right form">
|
<div class="search pull-right form">
|
||||||
<input class="form-control search" type="search" placeholder="search commit"/>
|
<input class="form-control search" type="search" placeholder="search commit"/>
|
||||||
</div>
|
</div>
|
||||||
<h4>Commits</h4>
|
<h4>{{.CommitCount}} Commits</h4>
|
||||||
</div>
|
</div>
|
||||||
<table class="panel-footer table commit-list table table-striped">
|
<table class="panel-footer table commit-list table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="author">Author</th>
|
<th class="author">Author</th>
|
||||||
<th class="sha">Commit</th>
|
<th class="sha">Commit</th>
|
||||||
<th class="message">Message</th>
|
<th class="message">Message</th>
|
||||||
<th class="date">Date</th>
|
<th class="date">Date</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
{{ $username := .Username}}
|
||||||
|
{{ $reponame := .Reponame}}
|
||||||
|
{{$r := List .Commits}}
|
||||||
|
{{range $r}}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="author"><img class="avatar" src="#" alt=""/>CommitUser</td>
|
<td class="author"><img class="avatar" src="{{AvatarLink .Committer.Email}}" alt=""/>{{.Committer.Name}}</td>
|
||||||
<td class="sha"><a class="label label-success" href="#">d91b380</a></td>
|
<td class="sha"><a class="label label-success" href="/{{$username}}/{{$reponame}}/commit/{{.Id}} ">{{SubStr .Id.String 0 7}} </a></td>
|
||||||
<td class="message">Fix Synchronize to delete service objects in subduers upon move</td>
|
<td class="message">{{.Message}} </td>
|
||||||
<td class="date">3 years ago</td>
|
<td class="date">{{TimeSince .Committer.When}}</td>
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="author"><img class="avatar" src="#" alt=""/>CommitUser</td>
|
|
||||||
<td class="sha"><a class="label label-success" href="#">d91b380</a></td>
|
|
||||||
<td class="message">Fix Synchronize to delete service objects in subduers upon move</td>
|
|
||||||
<td class="date">3 years ago</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="author"><img class="avatar" src="#" alt=""/>CommitUser</td>
|
|
||||||
<td class="sha"><a class="label label-success" href="#">d91b380</a></td>
|
|
||||||
<td class="message">Fix Synchronize to delete service objects in subduers upon move</td>
|
|
||||||
<td class="date">3 years ago</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
|
||||||
{{$r := List .Commits}}
|
|
||||||
{{range $r}}
|
|
||||||
<li>{{.Committer.Name}} - {{.Id}} - {{.Message}} - {{.Committer.When}}</li>
|
|
||||||
{{end}}
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{template "base/footer" .}}
|
{{template "base/footer" .}}
|
|
@ -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/>
|
||||||
|
|
6
web.go
6
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"
|
||||||
)
|
)
|
||||||
|
@ -57,6 +58,7 @@ func newMartini() *martini.ClassicMartini {
|
||||||
}
|
}
|
||||||
|
|
||||||
func runWeb(*cli.Context) {
|
func runWeb(*cli.Context) {
|
||||||
|
base.NewServices()
|
||||||
checkRunMode()
|
checkRunMode()
|
||||||
log.Info("%s %s", base.AppName, base.AppVer)
|
log.Info("%s %s", base.AppName, base.AppVer)
|
||||||
|
|
||||||
|
@ -113,6 +115,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