diff --git a/bee.json b/bee.json index 40050dd58..e4a0f803d 100644 --- a/bee.json +++ b/bee.json @@ -11,7 +11,8 @@ "controllers": "routers", "models": "", "others": [ - "utils" + "utils", "modules", + "$GOPATH/src/github.com/gogits/binding" ] }, "cmd_args": [ diff --git a/conf/app.ini b/conf/app.ini index dcc58c37f..3d4a25932 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -3,6 +3,7 @@ RUN_USER = lunny [repository] ROOT = /Users/lunny/git/gogs-repositories +ROOT_jiahuachen = /Users/jiahuachen/git/gogs-repositories [server] HTTP_ADDR = diff --git a/gogs.go b/gogs.go index 72a967f01..1ce0f7f98 100644 --- a/gogs.go +++ b/gogs.go @@ -19,7 +19,7 @@ import ( // Test that go1.1 tag above is included in builds. main.go refers to this definition. const go11tag = true -const APP_VER = "0.0.0.0303" +const APP_VER = "0.0.0.0305" func init() { runtime.GOMAXPROCS(runtime.NumCPU()) diff --git a/models/models.go b/models/models.go index d07b1fe38..0dee65478 100644 --- a/models/models.go +++ b/models/models.go @@ -83,6 +83,9 @@ func setEngine() { //log.Trace("Initialized database -> %s", dbName) RepoRootPath = utils.Cfg.MustValue("repository", "ROOT") + if uname.Username == "jiahuachen" { + RepoRootPath = utils.Cfg.MustValue("repository", "ROOT_jiahuachen") + } } func init() { diff --git a/models/user.go b/models/user.go index 820597380..d8469251e 100644 --- a/models/user.go +++ b/models/user.go @@ -15,7 +15,6 @@ import ( "github.com/dchest/scrypt" "github.com/gogits/gogs/utils" - "github.com/gogits/gogs/utils/log" ) // User types. @@ -100,17 +99,15 @@ func RegisterUser(user *User) (err error) { user.LowerName = strings.ToLower(user.Name) user.Avatar = utils.EncodeMd5(user.Email) user.EncodePasswd() - _, err = orm.Insert(user) - if err != nil { + if _, err = orm.Insert(user); err != nil { return err } - err = os.MkdirAll(UserPath(user.Name), os.ModePerm) - if err != nil { - _, err2 := orm.Id(user.Id).Delete(&User{}) - if err2 != nil { - log.Error("create userpath %s failed and delete table record faild", - user.Name) + if err = os.MkdirAll(UserPath(user.Name), os.ModePerm); err != nil { + + if _, err := orm.Id(user.Id).Delete(&User{}); err != nil { + return errors.New(fmt.Sprintf( + "both create userpath %s and delete table record faild", user.Name)) } return err } diff --git a/modules/auth/form.go b/modules/auth/form.go new file mode 100644 index 000000000..9094ef5c3 --- /dev/null +++ b/modules/auth/form.go @@ -0,0 +1,111 @@ +// 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 ( + "net/http" + "reflect" + + "github.com/codegangsta/martini" + + "github.com/gogits/binding" + + "github.com/gogits/gogs/modules/base" + "github.com/gogits/gogs/utils/log" +) + +type RegisterForm struct { + UserName string `form:"username" binding:"Required;AlphaDash;MinSize(5);MaxSize(30)"` + Email string `form:"email" binding:"Required;Email;MaxSize(50)"` + Password string `form:"passwd" binding:"Required;MinSize(6);MaxSize(30)"` +} + +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 + } + + if err, ok := errors.Fields["UserName"]; ok { + data["Err_Username"] = true + switch err { + case binding.RequireError: + data["ErrorMsg"] = "Username cannot be empty" + case binding.AlphaDashError: + data["ErrorMsg"] = "Username must be valid alpha or numeric or dash(-_) characters" + case binding.MinSizeError: + data["ErrorMsg"] = "Username at least has 5 characters" + case binding.MaxSizeError: + data["ErrorMsg"] = "Username at most has 30 characters" + default: + data["ErrorMsg"] = "Unknown error: " + err + } + return + } + + if err, ok := errors.Fields["Email"]; ok { + data["Err_Email"] = true + switch err { + case binding.RequireError: + data["ErrorMsg"] = "E-mail address cannot be empty" + case binding.EmailError: + data["ErrorMsg"] = "E-mail address is not valid" + case binding.MaxSizeError: + data["ErrorMsg"] = "E-mail address at most has 50 characters" + default: + data["ErrorMsg"] = "Unknown error: " + err + } + return + } + + if err, ok := errors.Fields["Password"]; ok { + data["Err_Passwd"] = true + switch err { + case binding.RequireError: + data["ErrorMsg"] = "Password cannot be empty" + case binding.MinSizeError: + data["ErrorMsg"] = "Password at least has 6 characters" + case binding.MaxSizeError: + data["ErrorMsg"] = "Password at most has 30 characters" + default: + data["ErrorMsg"] = "Unknown error: " + err + } + return + } + +} + +// AssignForm assign form values back to the template data. +func AssignForm(form interface{}, data base.TmplData) { + typ := reflect.TypeOf(form) + val := reflect.ValueOf(form) + + if typ.Kind() == reflect.Ptr { + typ = typ.Elem() + val = val.Elem() + } + + for i := 0; i < typ.NumField(); i++ { + field := typ.Field(i) + + fieldName := field.Tag.Get("form") + // Allow ignored fields in the struct + if fieldName == "-" { + continue + } + + data[fieldName] = val.Field(i).Interface() + } +} diff --git a/modules/base/base.go b/modules/base/base.go new file mode 100644 index 000000000..0d305ab45 --- /dev/null +++ b/modules/base/base.go @@ -0,0 +1,20 @@ +// 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 base + +import ( + "github.com/codegangsta/martini" +) + +type ( + // Type TmplData represents data in the templates. + TmplData map[string]interface{} +) + +func InitContext() martini.Handler { + return func(context martini.Context) { + context.Map(TmplData{}) + } +} diff --git a/routers/user/user.go b/routers/user/user.go index a66a7b5f9..503ebf54f 100644 --- a/routers/user/user.go +++ b/routers/user/user.go @@ -8,13 +8,13 @@ import ( "fmt" "net/http" + //"github.com/martini-contrib/binding" "github.com/martini-contrib/render" "github.com/martini-contrib/sessions" - "github.com/gogits/validation" - "github.com/gogits/gogs/models" - "github.com/gogits/gogs/utils/auth" + "github.com/gogits/gogs/modules/auth" + "github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/utils/log" ) @@ -50,42 +50,42 @@ func SignIn(req *http.Request, r render.Render, session sessions.Session) { }) } -func SignUp(req *http.Request, r render.Render) { - data := map[string]interface{}{"Title": "Sign Up"} +func SignUp(form auth.RegisterForm, data base.TmplData, req *http.Request, r render.Render) { + data["Title"] = "Sign Up" + if req.Method == "GET" { r.HTML(200, "user/signup", data) return } - // Front-end should do double check of password. - u := &models.User{ - Name: req.FormValue("username"), - Email: req.FormValue("email"), - Passwd: req.FormValue("passwd"), + if hasErr, ok := data["HasError"]; ok && hasErr.(bool) { + r.HTML(200, "user/signup", data) + return } - valid := validation.Validation{} - ok, err := valid.Valid(u) - if err != nil { - log.Error("user.SignUp -> valid user: %v", err) - return + //Front-end should do double check of password. + u := &models.User{ + Name: form.UserName, + Email: form.Email, + Passwd: form.Password, } - if !ok { - data["HasError"] = true - data["ErrorMsg"] = auth.GenerateErrorMsg(valid.Errors[0]) - r.HTML(200, "user/signup", data) + + if err := models.RegisterUser(u); err != nil { + if err.Error() == models.ErrUserAlreadyExist.Error() { + data["HasError"] = true + data["Err_Username"] = true + data["ErrorMsg"] = "Username has been already taken" + auth.AssignForm(form, data) + r.HTML(200, "user/signup", data) + return + } + + log.Error("user.SignUp: %v", err) + r.HTML(500, "status/500", nil) return } - // err = models.RegisterUser(u) - // if err != nil { - // r.HTML(200, "base/error", map[string]interface{}{ - // "Error": fmt.Sprintf("%v", err), - // }) - // return - // } - - // r.Redirect("/") + r.Redirect("/user/login") } func Delete(req *http.Request, r render.Render) { diff --git a/templates/user/signup.tmpl b/templates/user/signup.tmpl index e8854e4ac..52e8fe181 100644 --- a/templates/user/signup.tmpl +++ b/templates/user/signup.tmpl @@ -6,20 +6,20 @@ {{if .HasError}}
{{.ErrorMsg}}
{{end}} -
+
- +
-
+
- +
-
+
diff --git a/utils/auth/auth.go b/utils/auth/auth.go deleted file mode 100644 index 109910340..000000000 --- a/utils/auth/auth.go +++ /dev/null @@ -1,15 +0,0 @@ -// 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 ( - "fmt" - - "github.com/gogits/validation" -) - -func GenerateErrorMsg(e *validation.ValidationError) string { - return fmt.Sprintf("%v", e.LimitValue) -} diff --git a/web.go b/web.go index ca3b4fcf1..905515107 100644 --- a/web.go +++ b/web.go @@ -14,6 +14,10 @@ import ( "github.com/martini-contrib/render" "github.com/martini-contrib/sessions" + "github.com/gogits/binding" + + "github.com/gogits/gogs/modules/auth" + "github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/routers" "github.com/gogits/gogs/routers/repo" "github.com/gogits/gogs/routers/user" @@ -46,6 +50,7 @@ func runWeb(*cli.Context) { // Middleware. m.Use(render.Renderer(render.Options{Funcs: []template.FuncMap{AppHelpers}})) + m.Use(base.InitContext()) // TODO: should use other store because cookie store is not secure. store := sessions.NewCookieStore([]byte("secret123")) @@ -55,7 +60,7 @@ func runWeb(*cli.Context) { m.Get("/", routers.Dashboard) m.Any("/user/login", user.SignIn) - m.Any("/user/sign_up", user.SignUp) + m.Any("/user/sign_up", binding.BindIgnErr(auth.RegisterForm{}), user.SignUp) m.Get("/user/profile", user.Profile) // should be /username m.Any("/user/delete", user.Delete)