@@ -16,7 +16,7 @@ Please see [Wiki](https://github.com/gogits/gogs/wiki) for project design. | |||||
### Dependencies | ### Dependencies | ||||
- [Go Programming Language](http://golang.org): Main develop language. | - [Go Programming Language](http://golang.org): Main develop language. | ||||
- [libgit2](http://libgit2.github.com/): Git data manipulation. | |||||
- [libgit2](http://libgit2.github.com/)(cgo): Git data manipulation. | |||||
## Acknowledgments | ## Acknowledgments | ||||
@@ -24,4 +24,4 @@ Please see [Wiki](https://github.com/gogits/gogs/wiki) for project design. | |||||
## Contributors | ## Contributors | ||||
This project was launched by [Unknown](https://github.com/Unknwon) and [lunny](https://github.com/lunny). See [contributors page](https://github.com/gogits/gogs/graphs/contributors) for full list of contributors. | |||||
This project was launched by [Unknown](https://github.com/Unknwon), [lunny](https://github.com/lunny) and [fuxiaohei](https://github.com/fuxiaohei). See [contributors page](https://github.com/gogits/gogs/graphs/contributors) for full list of contributors. |
@@ -19,7 +19,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.0.0.0306" | |||||
const APP_VER = "0.0.1.0306" | |||||
func init() { | func init() { | ||||
runtime.GOMAXPROCS(runtime.NumCPU()) | runtime.GOMAXPROCS(runtime.NumCPU()) | ||||
@@ -192,7 +192,7 @@ func GetUserById(id int64) (*User, error) { | |||||
// LoginUserPlain validates user by raw user name and password. | // LoginUserPlain validates user by raw user name and password. | ||||
func LoginUserPlain(name, passwd string) (*User, error) { | func LoginUserPlain(name, passwd string) (*User, error) { | ||||
user := User{Name: name, Passwd: passwd} | |||||
user := User{LowerName: strings.ToLower(name), Passwd: passwd} | |||||
if err := user.EncodePasswd(); err != nil { | if err := user.EncodePasswd(); err != nil { | ||||
return nil, err | return nil, err | ||||
} | } | ||||
@@ -28,7 +28,7 @@ type RegisterForm struct { | |||||
RetypePasswd string `form:"retypepasswd"` | RetypePasswd string `form:"retypepasswd"` | ||||
} | } | ||||
func (r *RegisterForm) Name(field string) string { | |||||
func (f *RegisterForm) Name(field string) string { | |||||
names := map[string]string{ | names := map[string]string{ | ||||
"UserName": "Username", | "UserName": "Username", | ||||
"Email": "E-mail address", | "Email": "E-mail address", | ||||
@@ -38,6 +38,57 @@ func (r *RegisterForm) Name(field string) string { | |||||
return names[field] | return names[field] | ||||
} | } | ||||
func (f *RegisterForm) Validate(errors *binding.Errors, req *http.Request, context martini.Context) { | |||||
if req.Method == "GET" || errors.Count() == 0 { | |||||
return | |||||
} | |||||
data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData) | |||||
data["HasError"] = true | |||||
AssignForm(f, data) | |||||
if len(errors.Overall) > 0 { | |||||
for _, err := range errors.Overall { | |||||
log.Error("RegisterForm.Validate: %v", err) | |||||
} | |||||
return | |||||
} | |||||
validate(errors, data, f) | |||||
} | |||||
type LogInForm struct { | |||||
UserName string `form:"username" binding:"Required;AlphaDash;MinSize(5);MaxSize(30)"` | |||||
Password string `form:"passwd" binding:"Required;MinSize(6);MaxSize(30)"` | |||||
} | |||||
func (f *LogInForm) Name(field string) string { | |||||
names := map[string]string{ | |||||
"UserName": "Username", | |||||
"Password": "Password", | |||||
} | |||||
return names[field] | |||||
} | |||||
func (f *LogInForm) Validate(errors *binding.Errors, req *http.Request, context martini.Context) { | |||||
if req.Method == "GET" || errors.Count() == 0 { | |||||
return | |||||
} | |||||
data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData) | |||||
data["HasError"] = true | |||||
AssignForm(f, data) | |||||
if len(errors.Overall) > 0 { | |||||
for _, err := range errors.Overall { | |||||
log.Error("LogInForm.Validate: %v", err) | |||||
} | |||||
return | |||||
} | |||||
validate(errors, data, f) | |||||
} | |||||
func getMinMaxSize(field reflect.StructField) string { | func getMinMaxSize(field reflect.StructField) string { | ||||
for _, rule := range strings.Split(field.Tag.Get("binding"), ";") { | for _, rule := range strings.Split(field.Tag.Get("binding"), ";") { | ||||
if strings.HasPrefix(rule, "MinSize(") || strings.HasPrefix(rule, "MaxSize(") { | if strings.HasPrefix(rule, "MinSize(") || strings.HasPrefix(rule, "MaxSize(") { | ||||
@@ -86,25 +137,6 @@ func validate(errors *binding.Errors, data base.TmplData, form Form) { | |||||
} | } | ||||
} | } | ||||
func (r *RegisterForm) Validate(errors *binding.Errors, req *http.Request, context martini.Context) { | |||||
if req.Method == "GET" || errors.Count() == 0 { | |||||
return | |||||
} | |||||
data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData) | |||||
data["HasError"] = true | |||||
AssignForm(r, data) | |||||
if len(errors.Overall) > 0 { | |||||
for _, err := range errors.Overall { | |||||
log.Error("RegisterForm.Validate: %v", err) | |||||
} | |||||
return | |||||
} | |||||
validate(errors, data, r) | |||||
} | |||||
// AssignForm assign form values back to the template data. | // AssignForm assign form values back to the template data. | ||||
func AssignForm(form interface{}, data base.TmplData) { | func AssignForm(form interface{}, data base.TmplData) { | ||||
typ := reflect.TypeOf(form) | typ := reflect.TypeOf(form) | ||||
@@ -79,36 +79,45 @@ func SignedInUser(session sessions.Session) *models.User { | |||||
return user | return user | ||||
} | } | ||||
func SignIn(req *http.Request, r render.Render, session sessions.Session) { | |||||
func SignIn(form auth.LogInForm, data base.TmplData, req *http.Request, r render.Render, session sessions.Session) { | |||||
// if logged, do not show login page | // if logged, do not show login page | ||||
if IsSignedIn(session) { | if IsSignedIn(session) { | ||||
r.Redirect("/") | r.Redirect("/") | ||||
return | return | ||||
} | } | ||||
var ( | |||||
errString string | |||||
account string | |||||
) | |||||
// if post, do login action | |||||
if req.Method == "POST" { | |||||
account = req.FormValue("account") | |||||
user, err := models.LoginUserPlain(account, req.FormValue("passwd")) | |||||
if err == nil { | |||||
// login success | |||||
session.Set("userId", user.Id) | |||||
session.Set("userName", user.Name) | |||||
r.Redirect("/") | |||||
data["Title"] = "Log In" | |||||
if req.Method == "GET" { | |||||
r.HTML(200, "user/signin", data) | |||||
return | |||||
} | |||||
if hasErr, ok := data["HasError"]; ok && hasErr.(bool) { | |||||
r.HTML(200, "user/signin", data) | |||||
return | |||||
} | |||||
user, err := models.LoginUserPlain(form.UserName, form.Password) | |||||
if err != nil { | |||||
if err.Error() == models.ErrUserNotExist.Error() { | |||||
data["HasError"] = true | |||||
data["ErrorMsg"] = "Username or password is not correct" | |||||
auth.AssignForm(form, data) | |||||
r.HTML(200, "user/signin", data) | |||||
return | return | ||||
} | } | ||||
// login fail | |||||
errString = fmt.Sprintf("%v", err) | |||||
} | |||||
// if get or error post, show login page | |||||
r.HTML(200, "user/signin", map[string]interface{}{ | |||||
"Title": "Log In", | |||||
"Error": errString, | |||||
"Account": account, | |||||
}) | |||||
data["ErrorMsg"] = err | |||||
log.Error("user.SignIn: %v", data) | |||||
r.HTML(500, "base/error", nil) | |||||
return | |||||
} | |||||
// login success | |||||
session.Set("userId", user.Id) | |||||
session.Set("userName", user.Name) | |||||
r.Redirect("/") | |||||
} | } | ||||
func SignUp(form auth.RegisterForm, data base.TmplData, req *http.Request, r render.Render) { | func SignUp(form auth.RegisterForm, data base.TmplData, req *http.Request, r render.Render) { | ||||
@@ -2,33 +2,35 @@ | |||||
{{template "base/navbar" .}} | {{template "base/navbar" .}} | ||||
<div class="container" id="gogs-body"> | <div class="container" id="gogs-body"> | ||||
<form action="/user/login" method="post" class="form-horizontal gogs-card" id="gogs-login-card"> | <form action="/user/login" method="post" class="form-horizontal gogs-card" id="gogs-login-card"> | ||||
<h3>Log in</h3>{{if .Error}} | |||||
<div class="form-group"> | |||||
<div class="col-md-6 col-md-offset-3 alert alert-danger text-center"><strong>{{.Error}}</strong></div> | |||||
</div>{{end}} | |||||
<div class="form-group"> | |||||
<label class="col-md-4 control-label">Username or Email: </label> | |||||
<h3>Log in</h3> | |||||
<div class="alert alert-danger form-error{{if .HasError}}{{else}} hidden{{end}}">{{.ErrorMsg}}</div> | |||||
<div class="form-group {{if .Err_UserName}}has-error has-feedback{{end}}"> | |||||
<label class="col-md-4 control-label">Username: </label> | |||||
<div class="col-md-6"> | <div class="col-md-6"> | ||||
<input name="account" class="form-control" placeholder="Type your username or e-mail address" value="{{.Account}}" required="required"> | |||||
<input name="username" class="form-control" placeholder="Type your username" value="{{.username}}" required="required"> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="form-group"> | |||||
<div class="form-group {{if .Err_Password}}has-error has-feedback{{end}}"> | |||||
<label class="col-md-4 control-label">Password: </label> | <label class="col-md-4 control-label">Password: </label> | ||||
<div class="col-md-6"> | <div class="col-md-6"> | ||||
<input name="passwd" type="password" class="form-control" placeholder="Type your password" required="required"> | <input name="passwd" type="password" class="form-control" placeholder="Type your password" required="required"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="form-group"> | <div class="form-group"> | ||||
<div class="col-md-offset-4 col-md-6"> | <div class="col-md-offset-4 col-md-6"> | ||||
<button type="submit" class="btn btn-lg btn-primary">Log In</button> | <button type="submit" class="btn btn-lg btn-primary">Log In</button> | ||||
<a href="/forget-password/">Forgot your password?</a> | <a href="/forget-password/">Forgot your password?</a> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="form-group"> | <div class="form-group"> | ||||
<div class="col-md-offset-4 col-md-6"> | <div class="col-md-offset-4 col-md-6"> | ||||
<a href="/user/sign_up">Need an account? Sign up free.</a> | |||||
<a href="/user/sign_up">Need an account? Sign up now.</a> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="form-group text-center" id="gogs-social-login"> | <div class="form-group text-center" id="gogs-social-login"> | ||||
<a class="btn btn-default btn-lg">Social Login</a> | <a class="btn btn-default btn-lg">Social Login</a> | ||||
</div> | </div> | ||||
@@ -4,12 +4,13 @@ | |||||
<form action="/user/sign_up" method="post" class="form-horizontal gogs-card" id="gogs-login-card"> | <form action="/user/sign_up" method="post" class="form-horizontal gogs-card" id="gogs-login-card"> | ||||
<h3>Sign Up</h3> | <h3>Sign Up</h3> | ||||
<div class="alert alert-danger form-error{{if .HasError}}{{else}} hidden{{end}}">{{.ErrorMsg}}</div> | <div class="alert alert-danger form-error{{if .HasError}}{{else}} hidden{{end}}">{{.ErrorMsg}}</div> | ||||
<div class="form-group {{if .Err_Username}}has-error has-feedback{{end}}"> | |||||
<div class="form-group {{if .Err_UserName}}has-error has-feedback{{end}}"> | |||||
<label class="col-md-4 control-label">Username: </label> | <label class="col-md-4 control-label">Username: </label> | ||||
<div class="col-md-6"> | <div class="col-md-6"> | ||||
<input name="username" class="form-control" placeholder="Type your username" value="{{.username}}" required="required" title="Username must contain at least has 5 characters"> | <input name="username" class="form-control" placeholder="Type your username" value="{{.username}}" required="required" title="Username must contain at least has 5 characters"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> | <div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> | ||||
<label class="col-md-4 control-label">Email: </label> | <label class="col-md-4 control-label">Email: </label> | ||||
<div class="col-md-6"> | <div class="col-md-6"> | ||||
@@ -23,17 +24,20 @@ | |||||
<input name="passwd" type="password" class="form-control" placeholder="Type your password" required="required" title="Password must contain at least has 6 characters"> | <input name="passwd" type="password" class="form-control" placeholder="Type your password" required="required" title="Password must contain at least has 6 characters"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="form-group {{if .Err_RetypePasswd}}has-error has-feedback{{end}}"> | <div class="form-group {{if .Err_RetypePasswd}}has-error has-feedback{{end}}"> | ||||
<label class="col-md-4 control-label">Re-type: </label> | <label class="col-md-4 control-label">Re-type: </label> | ||||
<div class="col-md-6"> | <div class="col-md-6"> | ||||
<input name="re-passwd" type="password" class="form-control" placeholder="Re-type your password" required="required" title="Re-type Password must be same to Password"> | <input name="re-passwd" type="password" class="form-control" placeholder="Re-type your password" required="required" title="Re-type Password must be same to Password"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="form-group"> | <div class="form-group"> | ||||
<div class="col-md-offset-4 col-md-6"> | <div class="col-md-offset-4 col-md-6"> | ||||
<button type="submit" class="btn btn-lg btn-primary">Create an account</button> | <button type="submit" class="btn btn-lg btn-primary">Create an account</button> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="form-group"> | <div class="form-group"> | ||||
<div class="col-md-offset-4 col-md-6"> | <div class="col-md-offset-4 col-md-6"> | ||||
<a href="/user/login">Already have an account? Sign in now!</a> | <a href="/user/login">Already have an account? Sign in now!</a> | ||||
@@ -58,8 +58,7 @@ func runWeb(*cli.Context) { | |||||
// Routers. | // Routers. | ||||
m.Get("/", routers.Home) | m.Get("/", routers.Home) | ||||
m.Any("/user/login", user.SignIn) | |||||
m.Any("/user/login", binding.BindIgnErr(auth.LogInForm{}), user.SignIn) | |||||
m.Any("/user/sign_up", binding.BindIgnErr(auth.RegisterForm{}), user.SignUp) | m.Any("/user/sign_up", binding.BindIgnErr(auth.RegisterForm{}), user.SignUp) | ||||
m.Get("/user/profile", user.Profile) // should be /username | m.Get("/user/profile", user.Profile) // should be /username | ||||