diff options
author | Lunny Xiao <xiaolunwen@gmail.com> | 2014-04-10 22:21:12 +0800 |
---|---|---|
committer | Lunny Xiao <xiaolunwen@gmail.com> | 2014-04-10 22:21:12 +0800 |
commit | 94c7278194694fec728b518d4390b03ba6c237a4 (patch) | |
tree | 2aebf5fe63423b7b2eb14d58697bab1c95ffb3bb /routers | |
parent | 16b6e5d50b665c5376b61ca7d02e3716a1c05ead (diff) | |
parent | 2577940c30f6a6d15390974ab36f8c3d1e00f9f4 (diff) |
Merge branch 'master' of github.com:gogits/gogs into dev
Conflicts:
web.go
Diffstat (limited to 'routers')
-rw-r--r-- | routers/api/v1/miscellaneous.go | 2 | ||||
-rw-r--r-- | routers/install.go | 6 | ||||
-rw-r--r-- | routers/repo/http.go | 14 | ||||
-rw-r--r-- | routers/repo/issue.go | 36 | ||||
-rw-r--r-- | routers/repo/release.go | 8 | ||||
-rw-r--r-- | routers/user/setting.go | 7 | ||||
-rw-r--r-- | routers/user/social.go | 115 | ||||
-rw-r--r-- | routers/user/user.go | 86 |
8 files changed, 229 insertions, 45 deletions
diff --git a/routers/api/v1/miscellaneous.go b/routers/api/v1/miscellaneous.go index 0ff1eb04..babdfce9 100644 --- a/routers/api/v1/miscellaneous.go +++ b/routers/api/v1/miscellaneous.go @@ -13,6 +13,6 @@ func Markdown(ctx *middleware.Context) { content := ctx.Query("content") ctx.Render.JSON(200, map[string]interface{}{ "ok": true, - "content": string(base.RenderMarkdown([]byte(content), "")), + "content": string(base.RenderMarkdown([]byte(content), ctx.Query("repoLink"))), }) } diff --git a/routers/install.go b/routers/install.go index 032af480..1c4e6181 100644 --- a/routers/install.go +++ b/routers/install.go @@ -6,13 +6,13 @@ package routers import ( "errors" - "fmt" "os" "strings" "github.com/Unknwon/goconfig" "github.com/go-martini/martini" "github.com/lunny/xorm" + qlog "github.com/qiniu/log" "github.com/gogits/gogs/models" "github.com/gogits/gogs/modules/auth" @@ -43,8 +43,7 @@ func GlobalInit() { if base.InstallLock { if err := models.NewEngine(); err != nil { - fmt.Println(err) - os.Exit(2) + qlog.Fatal(err) } models.HasEngine = true @@ -183,6 +182,7 @@ func Install(ctx *middleware.Context, form auth.InstallForm) { if _, err := models.RegisterUser(&models.User{Name: form.AdminName, Email: form.AdminEmail, Passwd: form.AdminPasswd, IsAdmin: true, IsActive: true}); err != nil { if err != models.ErrUserAlreadyExist { + base.InstallLock = false ctx.RenderWithErr("Admin account setting is invalid: "+err.Error(), "install", &form) return } diff --git a/routers/repo/http.go b/routers/repo/http.go index d3699f3a..993de51f 100644 --- a/routers/repo/http.go +++ b/routers/repo/http.go @@ -135,10 +135,11 @@ type route struct { } type Config struct { - ReposRoot string - GitBinPath string - UploadPack bool - ReceivePack bool + ReposRoot string + GitBinPath string + UploadPack bool + ReceivePack bool + OnPushSucceed func() } type handler struct { @@ -223,21 +224,26 @@ func serviceRpc(rpc string, hr handler) { in, err := cmd.StdinPipe() if err != nil { log.Print(err) + return } stdout, err := cmd.StdoutPipe() if err != nil { log.Print(err) + return } err = cmd.Start() if err != nil { log.Print(err) + return } in.Write(input) io.Copy(w, stdout) cmd.Wait() + + hr.Config.OnPushSucceed() } func getInfoRefs(hr handler) { diff --git a/routers/repo/issue.go b/routers/repo/issue.go index be925426..9688fd4d 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -9,6 +9,7 @@ import ( "net/url" "strings" + "github.com/Unknwon/com" "github.com/go-martini/martini" "github.com/gogits/gogs/models" @@ -99,7 +100,7 @@ func CreateIssue(ctx *middleware.Context, params martini.Params, form auth.Creat issue, err := models.CreateIssue(ctx.User.Id, ctx.Repo.Repository.Id, form.MilestoneId, form.AssigneeId, ctx.Repo.Repository.NumIssues, form.IssueName, form.Labels, form.Content, false) if err != nil { - ctx.Handle(200, "issue.CreateIssue", err) + ctx.Handle(200, "issue.CreateIssue(CreateIssue)", err) return } @@ -107,14 +108,31 @@ func CreateIssue(ctx *middleware.Context, params martini.Params, form auth.Creat if err = models.NotifyWatchers(&models.Action{ActUserId: ctx.User.Id, ActUserName: ctx.User.Name, ActEmail: ctx.User.Email, OpType: models.OP_CREATE_ISSUE, Content: fmt.Sprintf("%d|%s", issue.Index, issue.Name), RepoId: ctx.Repo.Repository.Id, RepoName: ctx.Repo.Repository.Name, RefName: ""}); err != nil { - ctx.Handle(200, "issue.CreateIssue", err) + ctx.Handle(200, "issue.CreateIssue(NotifyWatchers)", err) return } - // Mail watchers. + // Mail watchers and mentions. if base.Service.NotifyMail { - if err = mailer.SendNotifyMail(ctx.User, ctx.Repo.Owner, ctx.Repo.Repository, issue); err != nil { - ctx.Handle(200, "issue.CreateIssue", err) + tos, err := mailer.SendIssueNotifyMail(ctx.User, ctx.Repo.Owner, ctx.Repo.Repository, issue) + if err != nil { + ctx.Handle(200, "issue.CreateIssue(SendIssueNotifyMail)", err) + return + } + + tos = append(tos, ctx.User.LowerName) + ms := base.MentionPattern.FindAllString(issue.Content, -1) + newTos := make([]string, 0, len(ms)) + for _, m := range ms { + if com.IsSliceContainsStr(tos, m[1:]) { + continue + } + + newTos = append(newTos, m[1:]) + } + if err = mailer.SendIssueMentionMail(ctx.User, ctx.Repo.Owner, ctx.Repo.Repository, + issue, models.GetUserEmailsByNames(newTos)); err != nil { + ctx.Handle(200, "issue.CreateIssue(SendIssueMentionMail)", err) return } } @@ -147,7 +165,7 @@ func ViewIssue(ctx *middleware.Context, params martini.Params) { return } issue.Poster = u - issue.RenderedContent = string(base.RenderMarkdown([]byte(issue.Content), "")) + issue.RenderedContent = string(base.RenderMarkdown([]byte(issue.Content), ctx.Repo.RepoLink)) // Get comments. comments, err := models.GetIssueComments(issue.Id) @@ -164,7 +182,7 @@ func ViewIssue(ctx *middleware.Context, params martini.Params) { return } comments[i].Poster = u - comments[i].Content = string(base.RenderMarkdown([]byte(comments[i].Content), "")) + comments[i].Content = string(base.RenderMarkdown([]byte(comments[i].Content), ctx.Repo.RepoLink)) } ctx.Data["Title"] = issue.Name @@ -193,7 +211,7 @@ func UpdateIssue(ctx *middleware.Context, params martini.Params, form auth.Creat return } - if ctx.User.Id != issue.PosterId { + if ctx.User.Id != issue.PosterId && !ctx.Repo.IsOwner { ctx.Handle(404, "issue.UpdateIssue", nil) return } @@ -211,7 +229,7 @@ func UpdateIssue(ctx *middleware.Context, params martini.Params, form auth.Creat ctx.JSON(200, map[string]interface{}{ "ok": true, "title": issue.Name, - "content": string(base.RenderMarkdown([]byte(issue.Content), "")), + "content": string(base.RenderMarkdown([]byte(issue.Content), ctx.Repo.RepoLink)), }) } diff --git a/routers/repo/release.go b/routers/repo/release.go index 8e8b93c9..279fc169 100644 --- a/routers/repo/release.go +++ b/routers/repo/release.go @@ -12,6 +12,7 @@ import ( func Releases(ctx *middleware.Context) { ctx.Data["Title"] = "Releases" ctx.Data["IsRepoToolbarReleases"] = true + ctx.Data["IsRepoReleaseNew"] = false tags, err := models.GetTags(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name) if err != nil { ctx.Handle(404, "repo.Releases(GetTags)", err) @@ -20,3 +21,10 @@ func Releases(ctx *middleware.Context) { ctx.Data["Releases"] = tags ctx.HTML(200, "release/list") } + +func ReleasesNew(ctx *middleware.Context) { + ctx.Data["Title"] = "New Release" + ctx.Data["IsRepoToolbarReleases"] = true + ctx.Data["IsRepoReleaseNew"] = true + ctx.HTML(200, "release/new") +} diff --git a/routers/user/setting.go b/routers/user/setting.go index 4b6d88a3..ea779e85 100644 --- a/routers/user/setting.go +++ b/routers/user/setting.go @@ -73,11 +73,7 @@ func SettingPassword(ctx *middleware.Context, form auth.UpdatePasswdForm) { user := ctx.User newUser := &models.User{Passwd: form.NewPasswd} - if err := newUser.EncodePasswd(); err != nil { - ctx.Handle(200, "setting.SettingPassword", err) - return - } - + newUser.EncodePasswd() if user.Passwd != newUser.Passwd { ctx.Data["HasError"] = true ctx.Data["ErrorMsg"] = "Old password is not correct" @@ -85,6 +81,7 @@ func SettingPassword(ctx *middleware.Context, form auth.UpdatePasswdForm) { ctx.Data["HasError"] = true ctx.Data["ErrorMsg"] = "New password and re-type password are not same" } else { + newUser.Salt = models.GetUserSalt() user.Passwd = newUser.Passwd if err := models.UpdateUser(user); err != nil { ctx.Handle(200, "setting.SettingPassword", err) diff --git a/routers/user/social.go b/routers/user/social.go index b59f4963..08cfcd83 100644 --- a/routers/user/social.go +++ b/routers/user/social.go @@ -1,49 +1,122 @@ // 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 user import ( "encoding/json" + "strconv" "code.google.com/p/goauth2/oauth" + + "github.com/gogits/gogs/models" + "github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/log" + "github.com/gogits/gogs/modules/middleware" "github.com/gogits/gogs/modules/oauth2" ) -// github && google && ... -func SocialSignIn(tokens oauth2.Tokens) { - transport := &oauth.Transport{} - transport.Token = &oauth.Token{ - AccessToken: tokens.Access(), - RefreshToken: tokens.Refresh(), - Expiry: tokens.ExpiryTime(), - Extra: tokens.ExtraData(), - } +type SocialConnector interface { + Identity() string + Type() int + Name() string + Email() string + Token() string +} - // Github API refer: https://developer.github.com/v3/users/ - // FIXME: need to judge url - type GithubUser struct { +type SocialGithub struct { + data struct { Id int `json:"id"` Name string `json:"login"` Email string `json:"email"` } + WebToken *oauth.Token +} + +func (s *SocialGithub) Identity() string { + return strconv.Itoa(s.data.Id) +} + +func (s *SocialGithub) Type() int { + return models.OT_GITHUB +} + +func (s *SocialGithub) Name() string { + return s.data.Name +} + +func (s *SocialGithub) Email() string { + return s.data.Email +} + +func (s *SocialGithub) Token() string { + data, _ := json.Marshal(s.WebToken) + return string(data) +} - // Make the request. +// Github API refer: https://developer.github.com/v3/users/ +func (s *SocialGithub) Update() error { scope := "https://api.github.com/user" + transport := &oauth.Transport{ + Token: s.WebToken, + } + log.Debug("update github info") r, err := transport.Client().Get(scope) if err != nil { - log.Error("connect with github error: %s", err) - // FIXME: handle error page - return + return err } defer r.Body.Close() + return json.NewDecoder(r.Body).Decode(&s.data) +} - user := &GithubUser{} - err = json.NewDecoder(r.Body).Decode(user) - if err != nil { - log.Error("Get: %s", err) +// github && google && ... +func SocialSignIn(ctx *middleware.Context, tokens oauth2.Tokens) { + gh := &SocialGithub{ + WebToken: &oauth.Token{ + AccessToken: tokens.Access(), + RefreshToken: tokens.Refresh(), + Expiry: tokens.ExpiryTime(), + Extra: tokens.ExtraData(), + }, } - log.Info("login: %s", user.Name) + if len(tokens.Access()) == 0 { + log.Error("empty access") + return + } + var err error + var u *models.User + if err = gh.Update(); err != nil { + // FIXME: handle error page + log.Error("connect with github error: %s", err) + return + } + var soc SocialConnector = gh + log.Info("login: %s", soc.Name()) // FIXME: login here, user email to check auth, if not registe, then generate a uniq username + if u, err = models.GetOauth2User(soc.Identity()); err != nil { + u = &models.User{ + Name: soc.Name(), + Email: soc.Email(), + Passwd: "123456", + IsActive: !base.Service.RegisterEmailConfirm, + } + if u, err = models.RegisterUser(u); err != nil { + log.Error("register user: %v", err) + return + } + oa := &models.Oauth2{} + oa.Uid = u.Id + oa.Type = soc.Type() + oa.Token = soc.Token() + oa.Identity = soc.Identity() + log.Info("oa: %v", oa) + if err = models.AddOauth2(oa); err != nil { + log.Error("add oauth2 %v", err) + return + } + } + ctx.Session.Set("userId", u.Id) + ctx.Session.Set("userName", u.Name) + ctx.Redirect("/") } diff --git a/routers/user/user.go b/routers/user/user.go index 08930e22..f6a39b86 100644 --- a/routers/user/user.go +++ b/routers/user/user.go @@ -78,6 +78,11 @@ func SignIn(ctx *middleware.Context, form auth.LogInForm) { ctx.Data["Title"] = "Log In" if ctx.Req.Method == "GET" { + if base.OauthService != nil { + ctx.Data["OauthEnabled"] = true + ctx.Data["OauthGitHubEnabled"] = base.OauthService.GitHub.Enabled + } + // Check auto-login. userName := ctx.GetCookie(base.CookieUserName) if len(userName) == 0 { @@ -403,9 +408,12 @@ func Activate(ctx *middleware.Context) { if user := models.VerifyUserActiveCode(code); user != nil { user.IsActive = true user.Rands = models.GetUserSalt() - models.UpdateUser(user) + if err := models.UpdateUser(user); err != nil { + ctx.Handle(404, "user.Activate", err) + return + } - log.Trace("%s User activated: %s", ctx.Req.RequestURI, user.LowerName) + log.Trace("%s User activated: %s", ctx.Req.RequestURI, user.Name) ctx.Session.Set("userId", user.Id) ctx.Session.Set("userName", user.Name) @@ -416,3 +424,77 @@ func Activate(ctx *middleware.Context) { ctx.Data["IsActivateFailed"] = true ctx.HTML(200, "user/active") } + +func ForgotPasswd(ctx *middleware.Context) { + ctx.Data["Title"] = "Forgot Password" + + if base.MailService == nil { + ctx.Data["IsResetDisable"] = true + ctx.HTML(200, "user/forgot_passwd") + return + } + + ctx.Data["IsResetRequest"] = true + if ctx.Req.Method == "GET" { + ctx.HTML(200, "user/forgot_passwd") + return + } + + email := ctx.Query("email") + u, err := models.GetUserByEmail(email) + if err != nil { + if err == models.ErrUserNotExist { + ctx.RenderWithErr("This e-mail address does not associate to any account.", "user/forgot_passwd", nil) + } else { + ctx.Handle(404, "user.ResetPasswd(check existence)", err) + } + return + } + + mailer.SendResetPasswdMail(ctx.Render, u) + ctx.Data["Email"] = email + ctx.Data["Hours"] = base.Service.ActiveCodeLives / 60 + ctx.Data["IsResetSent"] = true + ctx.HTML(200, "user/forgot_passwd") +} + +func ResetPasswd(ctx *middleware.Context) { + code := ctx.Query("code") + if len(code) == 0 { + ctx.Error(404) + return + } + ctx.Data["Code"] = code + + if ctx.Req.Method == "GET" { + ctx.Data["IsResetForm"] = true + ctx.HTML(200, "user/reset_passwd") + return + } + + if u := models.VerifyUserActiveCode(code); u != nil { + // Validate password length. + passwd := ctx.Query("passwd") + if len(passwd) < 6 || len(passwd) > 30 { + ctx.Data["IsResetForm"] = true + ctx.RenderWithErr("Password length should be in 6 and 30.", "user/reset_passwd", nil) + return + } + + u.Passwd = passwd + u.Rands = models.GetUserSalt() + u.Salt = models.GetUserSalt() + u.EncodePasswd() + if err := models.UpdateUser(u); err != nil { + ctx.Handle(404, "user.ResetPasswd(UpdateUser)", err) + return + } + + log.Trace("%s User password reset: %s", ctx.Req.RequestURI, u.Name) + ctx.Redirect("/user/login") + return + } + + ctx.Data["IsResetFailed"] = true + ctx.HTML(200, "user/reset_passwd") +} |