| @@ -96,7 +96,7 @@ func runWeb(*cli.Context) { | |||||
| m.Get("/avatar/:hash", avt.ServeHTTP) | m.Get("/avatar/:hash", avt.ServeHTTP) | ||||
| m.Group("/user", func(r martini.Router) { | m.Group("/user", func(r martini.Router) { | ||||
| r.Get("/login", user.SignIn) // TODO | |||||
| r.Get("/login", user.SignIn) | |||||
| r.Post("/login", bindIgnErr(auth.LogInForm{}), user.SignInPost) | r.Post("/login", bindIgnErr(auth.LogInForm{}), user.SignInPost) | ||||
| r.Get("/login/:name", user.SocialSignIn) | r.Get("/login/:name", user.SocialSignIn) | ||||
| r.Get("/sign_up", user.SignUp) | r.Get("/sign_up", user.SignUp) | ||||
| @@ -130,7 +130,7 @@ func runWeb(*cli.Context) { | |||||
| m.Get("/user/:username", ignSignIn, user.Profile) | m.Get("/user/:username", ignSignIn, user.Profile) | ||||
| m.Group("/repo", func(r martini.Router) { | m.Group("/repo", func(r martini.Router) { | ||||
| r.Get("/create", repo.Create) | |||||
| r.Get("/create", repo.Create) // TODO | |||||
| r.Post("/create", bindIgnErr(auth.CreateRepoForm{}), repo.CreatePost) | r.Post("/create", bindIgnErr(auth.CreateRepoForm{}), repo.CreatePost) | ||||
| r.Get("/migrate", repo.Migrate) | r.Get("/migrate", repo.Migrate) | ||||
| r.Post("/migrate", bindIgnErr(auth.MigrateRepoForm{}), repo.MigratePost) | r.Post("/migrate", bindIgnErr(auth.MigrateRepoForm{}), repo.MigratePost) | ||||
| @@ -74,3 +74,9 @@ func GetOauthByUserId(uid int64) (oas []*Oauth2, err error) { | |||||
| err = orm.Find(&oas, Oauth2{Uid: uid}) | err = orm.Find(&oas, Oauth2{Uid: uid}) | ||||
| return oas, err | return oas, err | ||||
| } | } | ||||
| // DeleteOauth2ById deletes a oauth2 by ID. | |||||
| func DeleteOauth2ById(id int64) error { | |||||
| _, err := orm.Delete(&Oauth2{Id: id}) | |||||
| return err | |||||
| } | |||||
| @@ -22,19 +22,12 @@ type MarkdownForm struct { | |||||
| Context string `form:"context"` | Context string `form:"context"` | ||||
| } | } | ||||
| func (f *MarkdownForm) Name(field string) string { | |||||
| names := map[string]string{ | |||||
| "Text": "text", | |||||
| } | |||||
| return names[field] | |||||
| } | |||||
| func (f *MarkdownForm) Validate(errs *binding.BindingErrors, req *http.Request, ctx martini.Context) { | func (f *MarkdownForm) Validate(errs *binding.BindingErrors, req *http.Request, ctx martini.Context) { | ||||
| data := ctx.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData) | data := ctx.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData) | ||||
| validateApiReq(errs, data, f) | validateApiReq(errs, data, f) | ||||
| } | } | ||||
| func validateApiReq(errs *binding.BindingErrors, data base.TmplData, f auth.Form) { | |||||
| func validateApiReq(errs *binding.BindingErrors, data base.TmplData, f interface{}) { | |||||
| if errs.Count() == 0 { | if errs.Count() == 0 { | ||||
| return | return | ||||
| } else if len(errs.Overall) > 0 { | } else if len(errs.Overall) > 0 { | ||||
| @@ -64,22 +57,21 @@ func validateApiReq(errs *binding.BindingErrors, data base.TmplData, f auth.Form | |||||
| } | } | ||||
| if err, ok := errs.Fields[field.Name]; ok { | if err, ok := errs.Fields[field.Name]; ok { | ||||
| data["Err_"+field.Name] = true | |||||
| switch err { | switch err { | ||||
| case binding.BindingRequireError: | case binding.BindingRequireError: | ||||
| data["ErrorMsg"] = f.Name(field.Name) + " cannot be empty" | |||||
| data["ErrorMsg"] = fieldName + " cannot be empty" | |||||
| case binding.BindingAlphaDashError: | case binding.BindingAlphaDashError: | ||||
| data["ErrorMsg"] = f.Name(field.Name) + " must be valid alpha or numeric or dash(-_) characters" | |||||
| data["ErrorMsg"] = fieldName + " must be valid alpha or numeric or dash(-_) characters" | |||||
| case binding.BindingAlphaDashDotError: | case binding.BindingAlphaDashDotError: | ||||
| data["ErrorMsg"] = f.Name(field.Name) + " must be valid alpha or numeric or dash(-_) or dot characters" | |||||
| data["ErrorMsg"] = fieldName + " must be valid alpha or numeric or dash(-_) or dot characters" | |||||
| case binding.BindingMinSizeError: | case binding.BindingMinSizeError: | ||||
| data["ErrorMsg"] = f.Name(field.Name) + " must contain at least " + auth.GetMinMaxSize(field) + " characters" | |||||
| data["ErrorMsg"] = fieldName + " must contain at least " + auth.GetMinMaxSize(field) + " characters" | |||||
| case binding.BindingMaxSizeError: | case binding.BindingMaxSizeError: | ||||
| data["ErrorMsg"] = f.Name(field.Name) + " must contain at most " + auth.GetMinMaxSize(field) + " characters" | |||||
| data["ErrorMsg"] = fieldName + " must contain at most " + auth.GetMinMaxSize(field) + " characters" | |||||
| case binding.BindingEmailError: | case binding.BindingEmailError: | ||||
| data["ErrorMsg"] = f.Name(field.Name) + " is not a valid e-mail address" | |||||
| data["ErrorMsg"] = fieldName + " is not a valid e-mail address" | |||||
| case binding.BindingUrlError: | case binding.BindingUrlError: | ||||
| data["ErrorMsg"] = f.Name(field.Name) + " is not a valid URL" | |||||
| data["ErrorMsg"] = fieldName + " is not a valid URL" | |||||
| default: | default: | ||||
| data["ErrorMsg"] = "Unknown error: " + err | data["ErrorMsg"] = "Unknown error: " + err | ||||
| } | } | ||||
| @@ -39,29 +39,15 @@ func (f *RegisterForm) Name(field string) string { | |||||
| return names[field] | return names[field] | ||||
| } | } | ||||
| func (f *RegisterForm) Validate(errors *binding.BindingErrors, 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) | |||||
| func (f *RegisterForm) Validate(errs *binding.BindingErrors, req *http.Request, ctx martini.Context) { | |||||
| data := ctx.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData) | |||||
| validate(errs, data, f) | |||||
| } | } | ||||
| type LogInForm struct { | type LogInForm struct { | ||||
| UserName string `form:"username" binding:"Required;MaxSize(35)"` | UserName string `form:"username" binding:"Required;MaxSize(35)"` | ||||
| Password string `form:"passwd" binding:"Required;MinSize(6);MaxSize(30)"` | Password string `form:"passwd" binding:"Required;MinSize(6);MaxSize(30)"` | ||||
| Remember string `form:"remember"` | |||||
| Remember bool `form:"remember"` | |||||
| } | } | ||||
| func (f *LogInForm) Name(field string) string { | func (f *LogInForm) Name(field string) string { | ||||
| @@ -72,23 +58,9 @@ func (f *LogInForm) Name(field string) string { | |||||
| return names[field] | return names[field] | ||||
| } | } | ||||
| func (f *LogInForm) Validate(errors *binding.BindingErrors, 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 (f *LogInForm) Validate(errs *binding.BindingErrors, req *http.Request, ctx martini.Context) { | |||||
| data := ctx.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData) | |||||
| validate(errs, data, f) | |||||
| } | } | ||||
| func GetMinMaxSize(field reflect.StructField) string { | func GetMinMaxSize(field reflect.StructField) string { | ||||
| @@ -100,9 +72,21 @@ func GetMinMaxSize(field reflect.StructField) string { | |||||
| return "" | return "" | ||||
| } | } | ||||
| func validate(errors *binding.BindingErrors, data base.TmplData, form Form) { | |||||
| typ := reflect.TypeOf(form) | |||||
| val := reflect.ValueOf(form) | |||||
| func validate(errs *binding.BindingErrors, data base.TmplData, f Form) { | |||||
| if errs.Count() == 0 { | |||||
| return | |||||
| } else if len(errs.Overall) > 0 { | |||||
| for _, err := range errs.Overall { | |||||
| log.Error("%s: %v", reflect.TypeOf(f), err) | |||||
| } | |||||
| return | |||||
| } | |||||
| data["HasError"] = true | |||||
| AssignForm(f, data) | |||||
| typ := reflect.TypeOf(f) | |||||
| val := reflect.ValueOf(f) | |||||
| if typ.Kind() == reflect.Ptr { | if typ.Kind() == reflect.Ptr { | ||||
| typ = typ.Elem() | typ = typ.Elem() | ||||
| @@ -118,23 +102,23 @@ func validate(errors *binding.BindingErrors, data base.TmplData, form Form) { | |||||
| continue | continue | ||||
| } | } | ||||
| if err, ok := errors.Fields[field.Name]; ok { | |||||
| if err, ok := errs.Fields[field.Name]; ok { | |||||
| data["Err_"+field.Name] = true | data["Err_"+field.Name] = true | ||||
| switch err { | switch err { | ||||
| case binding.BindingRequireError: | case binding.BindingRequireError: | ||||
| data["ErrorMsg"] = form.Name(field.Name) + " cannot be empty" | |||||
| data["ErrorMsg"] = f.Name(field.Name) + " cannot be empty" | |||||
| case binding.BindingAlphaDashError: | case binding.BindingAlphaDashError: | ||||
| data["ErrorMsg"] = form.Name(field.Name) + " must be valid alpha or numeric or dash(-_) characters" | |||||
| data["ErrorMsg"] = f.Name(field.Name) + " must be valid alpha or numeric or dash(-_) characters" | |||||
| case binding.BindingAlphaDashDotError: | case binding.BindingAlphaDashDotError: | ||||
| data["ErrorMsg"] = form.Name(field.Name) + " must be valid alpha or numeric or dash(-_) or dot characters" | |||||
| data["ErrorMsg"] = f.Name(field.Name) + " must be valid alpha or numeric or dash(-_) or dot characters" | |||||
| case binding.BindingMinSizeError: | case binding.BindingMinSizeError: | ||||
| data["ErrorMsg"] = form.Name(field.Name) + " must contain at least " + GetMinMaxSize(field) + " characters" | |||||
| data["ErrorMsg"] = f.Name(field.Name) + " must contain at least " + GetMinMaxSize(field) + " characters" | |||||
| case binding.BindingMaxSizeError: | case binding.BindingMaxSizeError: | ||||
| data["ErrorMsg"] = form.Name(field.Name) + " must contain at most " + GetMinMaxSize(field) + " characters" | |||||
| data["ErrorMsg"] = f.Name(field.Name) + " must contain at most " + GetMinMaxSize(field) + " characters" | |||||
| case binding.BindingEmailError: | case binding.BindingEmailError: | ||||
| data["ErrorMsg"] = form.Name(field.Name) + " is not a valid e-mail address" | |||||
| data["ErrorMsg"] = f.Name(field.Name) + " is not a valid e-mail address" | |||||
| case binding.BindingUrlError: | case binding.BindingUrlError: | ||||
| data["ErrorMsg"] = form.Name(field.Name) + " is not a valid URL" | |||||
| data["ErrorMsg"] = f.Name(field.Name) + " is not a valid URL" | |||||
| default: | default: | ||||
| data["ErrorMsg"] = "Unknown error: " + err | data["ErrorMsg"] = "Unknown error: " + err | ||||
| } | } | ||||
| @@ -7,12 +7,10 @@ package auth | |||||
| import ( | import ( | ||||
| "net/http" | "net/http" | ||||
| "reflect" | "reflect" | ||||
| "strings" | |||||
| "github.com/go-martini/martini" | "github.com/go-martini/martini" | ||||
| "github.com/gogits/gogs/modules/base" | "github.com/gogits/gogs/modules/base" | ||||
| "github.com/gogits/gogs/modules/log" | |||||
| "github.com/gogits/gogs/modules/middleware/binding" | "github.com/gogits/gogs/modules/middleware/binding" | ||||
| ) | ) | ||||
| @@ -31,24 +29,5 @@ func (f *AddSSHKeyForm) Name(field string) string { | |||||
| func (f *AddSSHKeyForm) Validate(errors *binding.BindingErrors, req *http.Request, context martini.Context) { | func (f *AddSSHKeyForm) Validate(errors *binding.BindingErrors, req *http.Request, context martini.Context) { | ||||
| data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData) | data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData) | ||||
| AssignForm(f, data) | |||||
| if req.Method == "GET" || errors.Count() == 0 { | |||||
| if req.Method == "POST" && | |||||
| (len(f.KeyContent) < 100 || !strings.HasPrefix(f.KeyContent, "ssh-rsa")) { | |||||
| data["HasError"] = true | |||||
| data["ErrorMsg"] = "SSH key content is not valid" | |||||
| } | |||||
| return | |||||
| } | |||||
| data["HasError"] = true | |||||
| if len(errors.Overall) > 0 { | |||||
| for _, err := range errors.Overall { | |||||
| log.Error("AddSSHKeyForm.Validate: %v", err) | |||||
| } | |||||
| return | |||||
| } | |||||
| validate(errors, data, f) | validate(errors, data, f) | ||||
| } | } | ||||
| @@ -78,7 +78,7 @@ type UpdateProfileForm struct { | |||||
| UserName string `form:"username" binding:"Required;AlphaDash;MaxSize(30)"` | UserName string `form:"username" binding:"Required;AlphaDash;MaxSize(30)"` | ||||
| FullName string `form:"fullname" binding:"MaxSize(40)"` | FullName string `form:"fullname" binding:"MaxSize(40)"` | ||||
| Email string `form:"email" binding:"Required;Email;MaxSize(50)"` | Email string `form:"email" binding:"Required;Email;MaxSize(50)"` | ||||
| Website string `form:"website" binding:"MaxSize(50)"` | |||||
| Website string `form:"website" binding:"Url;MaxSize(50)"` | |||||
| Location string `form:"location" binding:"MaxSize(50)"` | Location string `form:"location" binding:"MaxSize(50)"` | ||||
| Avatar string `form:"avatar" binding:"Required;Email;MaxSize(50)"` | Avatar string `form:"avatar" binding:"Required;Email;MaxSize(50)"` | ||||
| } | } | ||||
| @@ -94,22 +94,9 @@ func (f *UpdateProfileForm) Name(field string) string { | |||||
| return names[field] | return names[field] | ||||
| } | } | ||||
| func (f *UpdateProfileForm) Validate(errors *binding.BindingErrors, 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 | |||||
| if len(errors.Overall) > 0 { | |||||
| for _, err := range errors.Overall { | |||||
| log.Error("UpdateProfileForm.Validate: %v", err) | |||||
| } | |||||
| return | |||||
| } | |||||
| validate(errors, data, f) | |||||
| func (f *UpdateProfileForm) Validate(errs *binding.BindingErrors, req *http.Request, ctx martini.Context) { | |||||
| data := ctx.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData) | |||||
| validate(errs, data, f) | |||||
| } | } | ||||
| type UpdatePasswdForm struct { | type UpdatePasswdForm struct { | ||||
| @@ -127,20 +114,7 @@ func (f *UpdatePasswdForm) Name(field string) string { | |||||
| return names[field] | return names[field] | ||||
| } | } | ||||
| func (f *UpdatePasswdForm) Validate(errors *binding.BindingErrors, 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 | |||||
| if len(errors.Overall) > 0 { | |||||
| for _, err := range errors.Overall { | |||||
| log.Error("UpdatePasswdForm.Validate: %v", err) | |||||
| } | |||||
| return | |||||
| } | |||||
| validate(errors, data, f) | |||||
| func (f *UpdatePasswdForm) Validate(errs *binding.BindingErrors, req *http.Request, ctx martini.Context) { | |||||
| data := ctx.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData) | |||||
| validate(errs, data, f) | |||||
| } | } | ||||
| @@ -93,6 +93,7 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{ | |||||
| "DiffLineTypeToStr": DiffLineTypeToStr, | "DiffLineTypeToStr": DiffLineTypeToStr, | ||||
| "ShortSha": ShortSha, | "ShortSha": ShortSha, | ||||
| "Oauth2Icon": Oauth2Icon, | "Oauth2Icon": Oauth2Icon, | ||||
| "Oauth2Name": Oauth2Name, | |||||
| } | } | ||||
| type Actioner interface { | type Actioner interface { | ||||
| @@ -217,3 +218,19 @@ func Oauth2Icon(t int) string { | |||||
| } | } | ||||
| return "" | return "" | ||||
| } | } | ||||
| func Oauth2Name(t int) string { | |||||
| switch t { | |||||
| case 1: | |||||
| return "GitHub" | |||||
| case 2: | |||||
| return "Google" | |||||
| case 3: | |||||
| return "Twitter" | |||||
| case 4: | |||||
| return "Tencent QQ" | |||||
| case 5: | |||||
| return "Weibo" | |||||
| } | |||||
| return "" | |||||
| } | |||||
| @@ -1,6 +1,4 @@ | |||||
| var Gogits = { | |||||
| "PageIsSignup": false | |||||
| }; | |||||
| var Gogits = {}; | |||||
| (function ($) { | (function ($) { | ||||
| // extend jQuery ajax, set csrf token value | // extend jQuery ajax, set csrf token value | ||||
| @@ -333,32 +331,6 @@ function initCore() { | |||||
| Gogits.renderCodeView(); | Gogits.renderCodeView(); | ||||
| } | } | ||||
| function initRegister() { | |||||
| $.getScript("/js/jquery.validate.min.js", function () { | |||||
| Gogits.validateForm("#login-card", { | |||||
| rules: { | |||||
| "username": { | |||||
| required: true, | |||||
| maxlength: 30 | |||||
| }, | |||||
| "email": { | |||||
| required: true, | |||||
| email: true | |||||
| }, | |||||
| "passwd": { | |||||
| required: true, | |||||
| minlength: 6, | |||||
| maxlength: 30 | |||||
| }, | |||||
| "re-passwd": { | |||||
| required: true, | |||||
| equalTo: "input[name=passwd]" | |||||
| } | |||||
| } | |||||
| }); | |||||
| }); | |||||
| } | |||||
| function initUserSetting() { | function initUserSetting() { | ||||
| // ssh confirmation | // ssh confirmation | ||||
| $('#ssh-keys .delete').confirmation({ | $('#ssh-keys .delete').confirmation({ | ||||
| @@ -626,9 +598,6 @@ function initRepoSetting() { | |||||
| $(function () { | $(function () { | ||||
| initCore(); | initCore(); | ||||
| var body = $("#body"); | var body = $("#body"); | ||||
| if (body.data("page") == "user-signup") { | |||||
| initRegister(); | |||||
| } | |||||
| if (body.data("page") == "user") { | if (body.data("page") == "user") { | ||||
| initUserSetting(); | initUserSetting(); | ||||
| } | } | ||||
| @@ -5,7 +5,7 @@ | |||||
| package user | package user | ||||
| import ( | import ( | ||||
| "strconv" | |||||
| "strings" | |||||
| "github.com/gogits/gogs/models" | "github.com/gogits/gogs/models" | ||||
| "github.com/gogits/gogs/modules/auth" | "github.com/gogits/gogs/modules/auth" | ||||
| @@ -22,11 +22,10 @@ func Setting(ctx *middleware.Context) { | |||||
| ctx.HTML(200, "user/setting") | ctx.HTML(200, "user/setting") | ||||
| } | } | ||||
| // Render user setting page (email, website modify) | |||||
| func SettingPost(ctx *middleware.Context, form auth.UpdateProfileForm) { | func SettingPost(ctx *middleware.Context, form auth.UpdateProfileForm) { | ||||
| ctx.Data["Title"] = "Setting" | ctx.Data["Title"] = "Setting" | ||||
| ctx.Data["PageIsUserSetting"] = true // For navbar arrow. | |||||
| ctx.Data["IsUserPageSetting"] = true // For setting nav highlight. | |||||
| ctx.Data["PageIsUserSetting"] = true | |||||
| ctx.Data["IsUserPageSetting"] = true | |||||
| user := ctx.User | user := ctx.User | ||||
| ctx.Data["Owner"] = user | ctx.Data["Owner"] = user | ||||
| @@ -74,9 +73,22 @@ func SettingSocial(ctx *middleware.Context) { | |||||
| ctx.Data["Title"] = "Social Account" | ctx.Data["Title"] = "Social Account" | ||||
| ctx.Data["PageIsUserSetting"] = true | ctx.Data["PageIsUserSetting"] = true | ||||
| ctx.Data["IsUserPageSettingSocial"] = true | ctx.Data["IsUserPageSettingSocial"] = true | ||||
| // Unbind social account. | |||||
| remove, _ := base.StrTo(ctx.Query("remove")).Int64() | |||||
| if remove > 0 { | |||||
| if err := models.DeleteOauth2ById(remove); err != nil { | |||||
| ctx.Handle(500, "user.SettingSocial(DeleteOauth2ById)", err) | |||||
| return | |||||
| } | |||||
| ctx.Flash.Success("OAuth2 has been unbinded.") | |||||
| ctx.Redirect("/user/settings/social") | |||||
| return | |||||
| } | |||||
| socials, err := models.GetOauthByUserId(ctx.User.Id) | socials, err := models.GetOauthByUserId(ctx.User.Id) | ||||
| if err != nil { | if err != nil { | ||||
| ctx.Handle(500, "user.SettingSocial", err) | |||||
| ctx.Handle(500, "user.SettingSocial(GetOauthByUserId)", err) | |||||
| return | return | ||||
| } | } | ||||
| @@ -108,9 +120,9 @@ func SettingPasswordPost(ctx *middleware.Context, form auth.UpdatePasswdForm) { | |||||
| } | } | ||||
| tmpUser.EncodePasswd() | tmpUser.EncodePasswd() | ||||
| if user.Passwd != tmpUser.Passwd { | if user.Passwd != tmpUser.Passwd { | ||||
| ctx.Flash.Error("Old password is not correct") | |||||
| ctx.Flash.Error("Old password is not correct.") | |||||
| } else if form.NewPasswd != form.RetypePasswd { | } else if form.NewPasswd != form.RetypePasswd { | ||||
| ctx.Flash.Error("New password and re-type password are not same") | |||||
| ctx.Flash.Error("New password and re-type password are not same.") | |||||
| } else { | } else { | ||||
| user.Passwd = form.NewPasswd | user.Passwd = form.NewPasswd | ||||
| user.Salt = models.GetUserSalt() | user.Salt = models.GetUserSalt() | ||||
| @@ -128,10 +140,12 @@ func SettingPasswordPost(ctx *middleware.Context, form auth.UpdatePasswdForm) { | |||||
| func SettingSSHKeys(ctx *middleware.Context, form auth.AddSSHKeyForm) { | func SettingSSHKeys(ctx *middleware.Context, form auth.AddSSHKeyForm) { | ||||
| ctx.Data["Title"] = "SSH Keys" | ctx.Data["Title"] = "SSH Keys" | ||||
| ctx.Data["PageIsUserSetting"] = true | |||||
| ctx.Data["IsUserPageSettingSSH"] = true | |||||
| // Delete SSH key. | // Delete SSH key. | ||||
| if ctx.Req.Method == "DELETE" || ctx.Query("_method") == "DELETE" { | if ctx.Req.Method == "DELETE" || ctx.Query("_method") == "DELETE" { | ||||
| id, err := strconv.ParseInt(ctx.Query("id"), 10, 64) | |||||
| id, err := base.StrTo(ctx.Query("id")).Int64() | |||||
| if err != nil { | if err != nil { | ||||
| log.Error("ssh.DelPublicKey: %v", err) | log.Error("ssh.DelPublicKey: %v", err) | ||||
| ctx.JSON(200, map[string]interface{}{ | ctx.JSON(200, map[string]interface{}{ | ||||
| @@ -160,6 +174,14 @@ func SettingSSHKeys(ctx *middleware.Context, form auth.AddSSHKeyForm) { | |||||
| return | return | ||||
| } | } | ||||
| // List existed SSH keys. | |||||
| keys, err := models.ListPublicKey(ctx.User.Id) | |||||
| if err != nil { | |||||
| ctx.Handle(500, "ssh.ListPublicKey", err) | |||||
| return | |||||
| } | |||||
| ctx.Data["Keys"] = keys | |||||
| // Add new SSH key. | // Add new SSH key. | ||||
| if ctx.Req.Method == "POST" { | if ctx.Req.Method == "POST" { | ||||
| if ctx.HasError() { | if ctx.HasError() { | ||||
| @@ -167,6 +189,12 @@ func SettingSSHKeys(ctx *middleware.Context, form auth.AddSSHKeyForm) { | |||||
| return | return | ||||
| } | } | ||||
| if len(form.KeyContent) < 100 || !strings.HasPrefix(form.KeyContent, "ssh-rsa") { | |||||
| ctx.Flash.Error("SSH key content is not valid.") | |||||
| ctx.Redirect("/user/settings/ssh") | |||||
| return | |||||
| } | |||||
| k := &models.PublicKey{ | k := &models.PublicKey{ | ||||
| OwnerId: ctx.User.Id, | OwnerId: ctx.User.Id, | ||||
| Name: form.KeyName, | Name: form.KeyName, | ||||
| @@ -188,16 +216,6 @@ func SettingSSHKeys(ctx *middleware.Context, form auth.AddSSHKeyForm) { | |||||
| } | } | ||||
| } | } | ||||
| // List existed SSH keys. | |||||
| keys, err := models.ListPublicKey(ctx.User.Id) | |||||
| if err != nil { | |||||
| ctx.Handle(200, "ssh.ListPublicKey", err) | |||||
| return | |||||
| } | |||||
| ctx.Data["PageIsUserSetting"] = true | |||||
| ctx.Data["IsUserPageSettingSSH"] = true | |||||
| ctx.Data["Keys"] = keys | |||||
| ctx.HTML(200, "user/publickey") | ctx.HTML(200, "user/publickey") | ||||
| } | } | ||||
| @@ -49,14 +49,14 @@ func SignIn(ctx *middleware.Context) { | |||||
| user, err := models.GetUserByName(userName) | user, err := models.GetUserByName(userName) | ||||
| if err != nil { | if err != nil { | ||||
| ctx.HTML(500, "user/signin") | |||||
| ctx.Handle(500, "user.SignIn(GetUserByName)", err) | |||||
| return | return | ||||
| } | } | ||||
| secret := base.EncodeMd5(user.Rands + user.Passwd) | secret := base.EncodeMd5(user.Rands + user.Passwd) | ||||
| value, _ := ctx.GetSecureCookie(secret, base.CookieRememberName) | value, _ := ctx.GetSecureCookie(secret, base.CookieRememberName) | ||||
| if value != user.Name { | if value != user.Name { | ||||
| ctx.HTML(500, "user/signin") | |||||
| ctx.HTML(200, "user/signin") | |||||
| return | return | ||||
| } | } | ||||
| @@ -85,6 +85,7 @@ func SignInPost(ctx *middleware.Context, form auth.LogInForm) { | |||||
| } | } | ||||
| if ctx.HasError() { | if ctx.HasError() { | ||||
| println("shit") | |||||
| ctx.HTML(200, "user/signin") | ctx.HTML(200, "user/signin") | ||||
| return | return | ||||
| } | } | ||||
| @@ -112,7 +113,7 @@ func SignInPost(ctx *middleware.Context, form auth.LogInForm) { | |||||
| return | return | ||||
| } | } | ||||
| if form.Remember == "on" { | |||||
| if form.Remember { | |||||
| secret := base.EncodeMd5(user.Rands + user.Passwd) | secret := base.EncodeMd5(user.Rands + user.Passwd) | ||||
| days := 86400 * base.LogInRememberDays | days := 86400 * base.LogInRememberDays | ||||
| ctx.SetCookie(base.CookieUserName, user.Name, days) | ctx.SetCookie(base.CookieUserName, user.Name, days) | ||||
| @@ -208,16 +209,15 @@ func SignUpPost(ctx *middleware.Context, form auth.RegisterForm) { | |||||
| ctx.Data["IsSocialLogin"] = true | ctx.Data["IsSocialLogin"] = true | ||||
| } | } | ||||
| if ctx.HasError() { | |||||
| ctx.HTML(200, "user/signup") | |||||
| return | |||||
| } | |||||
| if form.Password != form.RetypePasswd { | if form.Password != form.RetypePasswd { | ||||
| ctx.Data["HasError"] = true | |||||
| ctx.Data["Err_Password"] = true | ctx.Data["Err_Password"] = true | ||||
| ctx.Data["Err_RetypePasswd"] = true | ctx.Data["Err_RetypePasswd"] = true | ||||
| ctx.Data["ErrorMsg"] = "Password and re-type password are not same" | |||||
| auth.AssignForm(form, ctx.Data) | |||||
| } | |||||
| if ctx.HasError() { | |||||
| ctx.HTML(200, "user/signup") | |||||
| ctx.RenderWithErr("Password and re-type password are not same", "user/signup", &form) | |||||
| return | return | ||||
| } | } | ||||
| @@ -415,7 +415,6 @@ func ResetPasswd(ctx *middleware.Context) { | |||||
| return | return | ||||
| } | } | ||||
| ctx.Data["Code"] = code | ctx.Data["Code"] = code | ||||
| ctx.Data["IsResetForm"] = true | ctx.Data["IsResetForm"] = true | ||||
| ctx.HTML(200, "user/reset_passwd") | ctx.HTML(200, "user/reset_passwd") | ||||
| } | } | ||||
| @@ -10,6 +10,7 @@ | |||||
| <div class="panel-heading"> | <div class="panel-heading"> | ||||
| Collaborators | Collaborators | ||||
| </div> | </div> | ||||
| <div class="panel-body"> | <div class="panel-body"> | ||||
| <ul id="repo-collab-list" class="list-unstyled"> | <ul id="repo-collab-list" class="list-unstyled"> | ||||
| {{range .Collaborators}} | {{range .Collaborators}} | ||||
| @@ -24,6 +25,7 @@ | |||||
| {{end}} | {{end}} | ||||
| </ul> | </ul> | ||||
| </div> | </div> | ||||
| <div class="panel-footer"> | <div class="panel-footer"> | ||||
| <form action="{{.RepoLink}}/settings/collaboration" method="post" class="form-horizontal" id="repo-collab-form"> | <form action="{{.RepoLink}}/settings/collaboration" method="post" class="form-horizontal" id="repo-collab-form"> | ||||
| {{.CsrfTokenHtml}} | {{.CsrfTokenHtml}} | ||||
| @@ -2,12 +2,19 @@ | |||||
| {{template "base/navbar" .}} | {{template "base/navbar" .}} | ||||
| <div id="body" class="container" data-page="user"> | <div id="body" class="container" data-page="user"> | ||||
| {{template "user/setting_nav" .}} | {{template "user/setting_nav" .}} | ||||
| <div id="user-setting-container" class="col-md-9"> | |||||
| <h4>Delete Account</h4> | |||||
| <div id="repo-setting-container" class="col-md-10"> | |||||
| {{template "base/alert" .}} | {{template "base/alert" .}} | ||||
| {{if not .Flash.ErrorMsg}}<p class="alert alert-danger">The operation will delete your account permanently. Sorry to see you go, but we know you'll back soon.</p>{{end}} | |||||
| <div class="form-group"> | |||||
| <button type="submit" class="btn btn-danger btn-lg" href="#delete-account-modal" id="delete-account" data-toggle="modal">Delete Account</button> | |||||
| <div class="panel panel-warning"> | |||||
| <div class="panel-heading"> | |||||
| Delete Account | |||||
| </div> | |||||
| <div class="panel-body"> | |||||
| {{if not .Flash.ErrorMsg}}<p class="alert alert-danger">The operation will delete your account permanently. Sorry to see you go, but we know you'll back soon.</p>{{end}} | |||||
| <div class="form-group"> | |||||
| <button type="submit" class="btn btn-danger btn-lg" href="#delete-account-modal" id="delete-account" data-toggle="modal">Delete Account</button> | |||||
| </div> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -2,40 +2,47 @@ | |||||
| {{template "base/navbar" .}} | {{template "base/navbar" .}} | ||||
| <div id="body" class="container" data-page="user"> | <div id="body" class="container" data-page="user"> | ||||
| {{template "user/setting_nav" .}} | {{template "user/setting_nav" .}} | ||||
| <div id="user-setting-container" class="col-md-9"> | |||||
| <div id="setting-pwd"> | |||||
| <h4>Password</h4> | |||||
| <form class="form-horizontal" id="password-form" method="post" action="/user/settings/password"> | |||||
| {{.CsrfTokenHtml}} | |||||
| {{template "base/alert" .}} | |||||
| <div class="form-group"> | |||||
| <label class="col-md-3 control-label">Old Password<strong class="text-danger">*</strong></label> | |||||
| <div class="col-md-7"> | |||||
| <input type="password" name="oldpasswd" class="form-control" placeholder="Type your current password" required="required"> | |||||
| </div> | |||||
| </div> | |||||
| <div id="repo-setting-container" class="col-md-10"> | |||||
| {{template "base/alert" .}} | |||||
| <div class="panel panel-default"> | |||||
| <div class="panel-heading"> | |||||
| Password | |||||
| </div> | |||||
| <div class="form-group"> | |||||
| <label class="col-md-3 control-label">New Password<strong class="text-danger">*</strong></label> | |||||
| <div class="col-md-7"> | |||||
| <input type="password" name="newpasswd" class="form-control" placeholder="Type your new password" required="required"> | |||||
| </div> | |||||
| </div> | |||||
| <div class="panel-body"> | |||||
| <div class="col-md-8"> | |||||
| <form class="form-horizontal" id="password-form" method="post" action="/user/settings/password"> | |||||
| {{.CsrfTokenHtml}} | |||||
| <div class="form-group"> | |||||
| <label class="col-md-3 control-label">Old Password<strong class="text-danger">*</strong></label> | |||||
| <div class="col-md-7"> | |||||
| <input type="password" name="oldpasswd" class="form-control" placeholder="Type your current password" required="required"> | |||||
| </div> | |||||
| </div> | |||||
| <div class="form-group"> | |||||
| <label class="col-md-3 control-label">Re-Type<strong class="text-danger">*</strong></label> | |||||
| <div class="col-md-7"> | |||||
| <input type="password" name="retypepasswd" class="form-control" placeholder="Re-type your new password" required="required"> | |||||
| </div> | |||||
| </div> | |||||
| <div class="form-group"> | |||||
| <label class="col-md-3 control-label">New Password<strong class="text-danger">*</strong></label> | |||||
| <div class="col-md-7"> | |||||
| <input type="password" name="newpasswd" class="form-control" placeholder="Type your new password" required="required"> | |||||
| </div> | |||||
| </div> | |||||
| <div class="form-group"> | |||||
| <label class="col-md-3 control-label">Re-Type<strong class="text-danger">*</strong></label> | |||||
| <div class="col-md-7"> | |||||
| <input type="password" name="retypepasswd" class="form-control" placeholder="Re-type your new password" required="required"> | |||||
| </div> | |||||
| </div> | |||||
| <div class="form-group"> | |||||
| <div class="col-md-offset-3 col-md-7"> | |||||
| <button type="submit" class="btn btn-primary">Change Password</button> | |||||
| <a href="/user/forget_password/">Forgot your password?</a> | |||||
| </div> | |||||
| <div class="form-group"> | |||||
| <div class="col-md-offset-3 col-md-7"> | |||||
| <button type="submit" class="btn btn-primary">Change Password</button> | |||||
| <a href="/user/forget_password/">Forgot your password?</a> | |||||
| </div> | |||||
| </div> | |||||
| </form> | |||||
| </div> | </div> | ||||
| </form> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -9,6 +9,7 @@ | |||||
| {{if .Owner.FullName}}<span id="user-full-name" class="center-block">{{.Owner.FullName}}</span>{{end}} | {{if .Owner.FullName}}<span id="user-full-name" class="center-block">{{.Owner.FullName}}</span>{{end}} | ||||
| <span id="user-name" class="center-block">{{.Owner.Name}}</span> | <span id="user-name" class="center-block">{{.Owner.Name}}</span> | ||||
| </div> | </div> | ||||
| <div class="profile-info"> | <div class="profile-info"> | ||||
| <ul class="list-group"> | <ul class="list-group"> | ||||
| {{if .Owner.Location}} | {{if .Owner.Location}} | ||||
| @@ -2,56 +2,63 @@ | |||||
| {{template "base/navbar" .}} | {{template "base/navbar" .}} | ||||
| <div id="body" class="container" data-page="user"> | <div id="body" class="container" data-page="user"> | ||||
| {{template "user/setting_nav" .}} | {{template "user/setting_nav" .}} | ||||
| <div id="user-setting-container" class="col-md-9"> | |||||
| <div id="ssh-keys"> | |||||
| <h4>SSH Keys</h4> | |||||
| {{template "base/alert" .}} | |||||
| <ul id="ssh-keys-list" class="list-group"> | |||||
| <li class="list-group-item"><span class="name">SSH Key's name</span></li> | |||||
| {{range .Keys}} | |||||
| <li class="list-group-item"> | |||||
| <span class="name">{{.Name}}</span> | |||||
| <span class="print">({{.Fingerprint}})</span> | |||||
| <button href="#" class="btn btn-danger delete pull-right" rel="{{.Id}}" data-del="{{.Id}}">Delete</button> | |||||
| </li> | |||||
| {{end}} | |||||
| <li class="list-group-item"> | |||||
| <a class="btn btn-link btn-primary" href="#ssh-add-modal" id="ssh-add" data-toggle="modal">Add SSH Key</a> | |||||
| </li> | |||||
| </ul> | |||||
| <div class="modal fade" id="ssh-add-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> | |||||
| <div class="modal-dialog"> | |||||
| <form class="modal-content form-horizontal" id="ssh-form" method="post" action="/user/settings/ssh/"> | |||||
| {{.CsrfTokenHtml}} | |||||
| <div class="modal-header"> | |||||
| <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> | |||||
| <h4 class="modal-title" id="myModalLabel">Add SSH Key</h4> | |||||
| </div> | |||||
| <div id="repo-setting-container" class="col-md-10"> | |||||
| {{template "base/alert" .}} | |||||
| <div class="panel panel-default"> | |||||
| <div class="panel-heading"> | |||||
| SSH Keys | |||||
| </div> | |||||
| <div class="modal-body"> | |||||
| <div class="form-group"> | |||||
| <label class="col-md-3 control-label">Key Name<strong class="text-danger">*</strong></label> | |||||
| <div class="col-md-8"> | |||||
| <input name="keyname" class="form-control" placeholder="Type your preferred name" required="required"> | |||||
| <div class="panel-body"> | |||||
| <div id="ssh-keys"> | |||||
| <ul id="ssh-keys-list" class="list-group"> | |||||
| <li class="list-group-item"><span class="name">SSH Key's name</span></li> | |||||
| {{range .Keys}} | |||||
| <li class="list-group-item"> | |||||
| <span class="name">{{.Name}}</span> | |||||
| <span class="print">({{.Fingerprint}})</span> | |||||
| <button href="#" class="btn btn-danger delete pull-right" rel="{{.Id}}" data-del="{{.Id}}">Delete</button> | |||||
| </li> | |||||
| {{end}} | |||||
| <li class="list-group-item"> | |||||
| <a class="btn btn-link btn-primary" href="#ssh-add-modal" id="ssh-add" data-toggle="modal">Add SSH Key</a> | |||||
| </li> | |||||
| </ul> | |||||
| <div class="modal fade" id="ssh-add-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> | |||||
| <div class="modal-dialog"> | |||||
| <form class="modal-content form-horizontal" id="ssh-form" method="post" action="/user/settings/ssh/"> | |||||
| {{.CsrfTokenHtml}} | |||||
| <div class="modal-header"> | |||||
| <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> | |||||
| <h4 class="modal-title" id="myModalLabel">Add SSH Key</h4> | |||||
| </div> | </div> | ||||
| </div> | |||||
| <div class="form-group"> | |||||
| <label class="col-md-3 control-label">SSH Key<strong class="text-danger">*</strong></label> | |||||
| <div class="col-md-8"> | |||||
| <textarea name="key_content" class="form-control" placeholder="Type your key content" required="required"></textarea> | |||||
| <div class="modal-body"> | |||||
| <div class="form-group"> | |||||
| <label class="col-md-3 control-label">Key Name<strong class="text-danger">*</strong></label> | |||||
| <div class="col-md-8"> | |||||
| <input name="keyname" class="form-control" placeholder="Type your preferred name" required="required"> | |||||
| </div> | |||||
| </div> | |||||
| <div class="form-group"> | |||||
| <label class="col-md-3 control-label">SSH Key<strong class="text-danger">*</strong></label> | |||||
| <div class="col-md-8"> | |||||
| <textarea name="key_content" class="form-control" placeholder="Type your key content" required="required"></textarea> | |||||
| </div> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | |||||
| </div> | |||||
| <div class="modal-footer"> | |||||
| <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> | |||||
| <button type="submit" class="btn btn-primary">Save SSH Key</button> | |||||
| <div class="modal-footer"> | |||||
| <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> | |||||
| <button type="submit" class="btn btn-primary">Save SSH Key</button> | |||||
| </div> | |||||
| </form> | |||||
| </div> | </div> | ||||
| </form> | |||||
| </div> | |||||
| <p><strong>Need help?</strong> Check out the guide to <a href="https://help.github.com/articles/generating-ssh-keys" target="_blank">generating SSH keys</a> or troubleshoot <a href="https://help.github.com/ssh-issues/" target="_blank">common SSH Problems</a></p> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <p><strong>Need help?</strong> Check out the guide to <a href="https://help.github.com/articles/generating-ssh-keys" target="_blank">generating SSH keys</a> or troubleshoot <a href="https://help.github.com/ssh-issues/" target="_blank">common SSH Problems</a></p> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -2,62 +2,67 @@ | |||||
| {{template "base/navbar" .}} | {{template "base/navbar" .}} | ||||
| <div id="body" class="container" data-page="user"> | <div id="body" class="container" data-page="user"> | ||||
| {{template "user/setting_nav" .}} | {{template "user/setting_nav" .}} | ||||
| <div id="user-setting-container" class="col-md-9"> | |||||
| <div id="setting-pwd"> | |||||
| <h4>Account Profile</h4> | |||||
| <form class="form-horizontal" id="password-form" method="post" action="/user/settings"> | |||||
| {{.CsrfTokenHtml}} | |||||
| {{template "base/alert" .}} | |||||
| <p>Your Email address is public and will be used for any account related notifications, and any web based operations made via the site.</p> | |||||
| <div class="form-group"> | |||||
| <label class="col-md-2 control-label" for="user-setting-username">Username<strong class="text-danger">*</strong></label> | |||||
| <div class="col-md-8"> | |||||
| <input name="username" class="form-control" placeholder="Type your user name" required="required" value="{{.SignedUser.Name}}" title="{{.SignedUser.Name}}" id="user-setting-username"> | |||||
| <p class="help-block hidden"><span class="text-danger">Caution : </span>your username is changing !</p> | |||||
| <div id="repo-setting-container" class="col-md-10"> | |||||
| {{template "base/alert" .}} | |||||
| <div class="panel panel-default"> | |||||
| <div class="panel-heading"> | |||||
| Account Profile | |||||
| </div> | |||||
| <div class="panel-body"> | |||||
| <form class="form-horizontal" id="password-form" method="post" action="/user/settings"> | |||||
| {{.CsrfTokenHtml}} | |||||
| <p>Your Email address is public and will be used for any account related notifications, and any web based operations made via the site.</p> | |||||
| <div class="form-group {{if .Err_UserName}}has-error has-feedback{{end}}"> | |||||
| <label class="col-md-2 control-label" for="user-setting-username">Username<strong class="text-danger">*</strong></label> | |||||
| <div class="col-md-8"> | |||||
| <input name="username" class="form-control" placeholder="Type your user name" required="required" value="{{.SignedUser.Name}}" title="{{.SignedUser.Name}}" id="user-setting-username"> | |||||
| <p class="help-block hidden"><span class="text-danger">Caution : </span>your username is changing !</p> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | |||||
| <div class="form-group"> | |||||
| <label class="col-md-2 control-label">Full Name</label> | |||||
| <div class="col-md-8"> | |||||
| <input name="fullname" class="form-control" placeholder="Type your full name" value="{{.SignedUser.FullName}}"> | |||||
| <div class="form-group {{if .Err_FullName}}has-error has-feedback{{end}}"> | |||||
| <label class="col-md-2 control-label">Full Name</label> | |||||
| <div class="col-md-8"> | |||||
| <input name="fullname" class="form-control" placeholder="Type your full name" value="{{.SignedUser.FullName}}"> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | |||||
| <div class="form-group"> | |||||
| <label class="col-md-2 control-label">Email<strong class="text-danger">*</strong></label> | |||||
| <div class="col-md-8"> | |||||
| <input name="email" class="form-control" placeholder="Type your e-mail address" required="required" value="{{.SignedUser.Email}}"> | |||||
| <div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> | |||||
| <label class="col-md-2 control-label">Email<strong class="text-danger">*</strong></label> | |||||
| <div class="col-md-8"> | |||||
| <input name="email" class="form-control" placeholder="Type your e-mail address" required="required" value="{{.SignedUser.Email}}"> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | |||||
| <div class="form-group"> | |||||
| <label class="col-md-2 control-label">Website</label> | |||||
| <div class="col-md-8"> | |||||
| <input name="website" class="form-control" placeholder="Type your website URL" value="{{.SignedUser.Website}}"> | |||||
| <div class="form-group {{if .Err_Website}}has-error has-feedback{{end}}"> | |||||
| <label class="col-md-2 control-label">Website</label> | |||||
| <div class="col-md-8"> | |||||
| <input name="website" class="form-control" placeholder="Type your website URL" value="{{.SignedUser.Website}}"> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | |||||
| <div class="form-group"> | |||||
| <label class="col-md-2 control-label">Location</label> | |||||
| <div class="col-md-8"> | |||||
| <input name="location" class="form-control" placeholder="Type your current location" value="{{.SignedUser.Location}}"> | |||||
| <div class="form-group {{if .Err_Location}}has-error has-feedback{{end}}"> | |||||
| <label class="col-md-2 control-label">Location</label> | |||||
| <div class="col-md-8"> | |||||
| <input name="location" class="form-control" placeholder="Type your current location" value="{{.SignedUser.Location}}"> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | |||||
| <div class="form-group {{if .Err_Avatar}}has-error has-feedback{{end}}"> | |||||
| <label class="col-md-2 control-label">Gravatar Email<strong class="text-danger">*</strong></label> | |||||
| <div class="col-md-8"> | |||||
| <input name="avatar" class="form-control" placeholder="Type your Gravatar e-mail address" required="required" value="{{.SignedUser.AvatarEmail}}"> | |||||
| <div class="form-group {{if .Err_Avatar}}has-error has-feedback{{end}}"> | |||||
| <label class="col-md-2 control-label">Gravatar Email<strong class="text-danger">*</strong></label> | |||||
| <div class="col-md-8"> | |||||
| <input name="avatar" class="form-control" placeholder="Type your Gravatar e-mail address" required="required" value="{{.SignedUser.AvatarEmail}}"> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | |||||
| <div class="form-group"> | |||||
| <div class="col-md-offset-2 col-md-8"> | |||||
| <button type="submit" class="btn btn-primary">Update Profile</button> | |||||
| <div class="form-group"> | |||||
| <div class="col-md-offset-2 col-md-8"> | |||||
| <button type="submit" class="btn btn-primary">Update Profile</button> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | |||||
| </form> | |||||
| </form> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -1,12 +1,11 @@ | |||||
| <div id="user-setting-nav" class="col-md-3"> | |||||
| <h4>Account Settings</h4> | |||||
| <div id="user-setting-nav" class="col-md-2 repo-setting-nav"> | |||||
| <ul class="list-group"> | <ul class="list-group"> | ||||
| <li class="list-group-item{{if .IsUserPageSetting}} list-group-item-success{{end}}"><a href="/user/settings">Account Profile</a></li> | |||||
| <li class="list-group-item{{if .IsUserPageSettingSocial}} list-group-item-success{{end}}"><a href="/user/settings/social">Social Account</a></li> | |||||
| <li class="list-group-item{{if .IsUserPageSettingPasswd}} list-group-item-success{{end}}"><a href="/user/settings/password">Password</a></li> | |||||
| <!-- <li class="list-group-item{{if .IsUserPageSettingNotify}} list-group-item-success{{end}}"><a href="/user/setting/notification">Notifications</a></li> --> | |||||
| <li class="list-group-item{{if .IsUserPageSettingSSH}} list-group-item-success{{end}}"><a href="/user/settings/ssh/">SSH Keys</a></li> | |||||
| <!-- <li class="list-group-item{{if .IsUserPageSettingSecurity}} list-group-item-success{{end}}"><a href="/user/setting/security">Security</a></li> --> | |||||
| <li class="list-group-item{{if .IsUserPageSettingDelete}} list-group-item-success{{end}}"><a href="/user/delete">Delete Account</a></li> | |||||
| <li class="list-group-item{{if .IsUserPageSetting}} active{{end}}"><a href="/user/settings">Account Profile</a></li> | |||||
| <li class="list-group-item{{if .IsUserPageSettingSocial}} active{{end}}"><a href="/user/settings/social">Social Account</a></li> | |||||
| <li class="list-group-item{{if .IsUserPageSettingPasswd}} active{{end}}"><a href="/user/settings/password">Password</a></li> | |||||
| <!-- <li class="list-group-item{{if .IsUserPageSettingNotify}} active{{end}}"><a href="/user/setting/notification">Notifications</a></li> --> | |||||
| <li class="list-group-item{{if .IsUserPageSettingSSH}} active{{end}}"><a href="/user/settings/ssh/">SSH Keys</a></li> | |||||
| <!-- <li class="list-group-item{{if .IsUserPageSettingSecurity}} active{{end}}"><a href="/user/setting/security">Security</a></li> --> | |||||
| <li class="list-group-item{{if .IsUserPageSettingDelete}} active{{end}}"><a href="/user/delete">Delete Account</a></li> | |||||
| </ul> | </ul> | ||||
| </div> | </div> | ||||
| @@ -21,21 +21,21 @@ | |||||
| <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"> | ||||
| <input name="email" class="form-control" placeholder="Type your e-mail address" value="{{.email}}" required="required" title="Email is not valid"> | |||||
| <input name="email" class="form-control" placeholder="Type your e-mail address" value="{{.email}}" required="required"> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="form-group {{if .Err_Password}}has-error has-feedback{{end}}"> | <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" title="Password must contain at least 6 characters"> | |||||
| <input name="passwd" type="password" class="form-control" placeholder="Type your password" required="required"> | |||||
| </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="retypepasswd" type="password" class="form-control" placeholder="Re-type your password" required="required" title="Re-type Password must be same to Password"> | |||||
| <input name="retypepasswd" type="password" class="form-control" placeholder="Re-type your password" required="required"> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -2,15 +2,35 @@ | |||||
| {{template "base/navbar" .}} | {{template "base/navbar" .}} | ||||
| <div id="body" class="container" data-page="user"> | <div id="body" class="container" data-page="user"> | ||||
| {{template "user/setting_nav" .}} | {{template "user/setting_nav" .}} | ||||
| <div id="user-setting-container" class="col-md-9"> | |||||
| <div id="ssh-keys"> | |||||
| <h4>Social Account</h4> | |||||
| {{template "base/alert" .}} | |||||
| <ul id="ssh-keys-list" class="list-group"> | |||||
| {{range .Socials}} | |||||
| <i class="fa {{Oauth2Icon .Type}} fa-3x"></i> | |||||
| {{end}} | |||||
| </ul> | |||||
| <div id="repo-setting-container" class="col-md-10"> | |||||
| {{template "base/alert" .}} | |||||
| <div class="panel panel-default"> | |||||
| <div class="panel-heading"> | |||||
| Social Account | |||||
| </div> | |||||
| <div class="panel-body"> | |||||
| <table class="table"> | |||||
| <thead> | |||||
| <tr> | |||||
| <th></th> | |||||
| <th>Name</th> | |||||
| <th>Identity</th> | |||||
| <th>Op.</th> | |||||
| </tr> | |||||
| </thead> | |||||
| <tbody> | |||||
| {{range .Socials}} | |||||
| <tr> | |||||
| <td><i class="fa {{Oauth2Icon .Type}} fa-2x"></i></td> | |||||
| <td>{{Oauth2Name .Type}}</td> | |||||
| <td>{{.Identity}}</td> | |||||
| <td><a href="/user/settings/social?remove={{.Id}}">Unbind</a></td> | |||||
| </tr> | |||||
| {{end}} | |||||
| </tbody> | |||||
| </table> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||