diff --git a/README.md b/README.md index 34f8b66f0..20dc8806d 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Gogs(Go Git Service) is a Self Hosted Git Service in the Go Programming Language ![Demo](http://gowalker.org/public/gogs_demo.gif) -##### Current version: 0.2.8 Alpha +##### Current version: 0.2.9 Alpha ### NOTICES @@ -40,6 +40,7 @@ More importantly, Gogs only needs one binary to setup your own project hosting o - Mail service(register, issue). - Administration panel. - Supports MySQL, PostgreSQL and SQLite3. +- Social account login(GitHub, Google, QQ, Weibo) ## Installation diff --git a/README_ZH.md b/README_ZH.md index beb5a1050..97ab07ff2 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -5,7 +5,7 @@ Gogs(Go Git Service) 是一个由 Go 语言编写的自助 Git 托管服务。 ![Demo](http://gowalker.org/public/gogs_demo.gif) -##### 当前版本:0.2.8 Alpha +##### 当前版本:0.2.9 Alpha ## 开发目的 @@ -31,6 +31,7 @@ Gogs 完全使用 Go 语言来实现对 Git 数据的操作,实现 **零** 依 - 邮件服务(注册、Issue) - 管理员面板 - 支持 MySQL、PostgreSQL 以及 SQLite3 +- 社交帐号登录(GitHub、Google、QQ、微博) ## 安装部署 diff --git a/conf/app.ini b/conf/app.ini index 4eaf0a33c..c70919961 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -109,6 +109,14 @@ SCOPES = all AUTH_URL = https://api.twitter.com/oauth/authorize TOKEN_URL = https://api.twitter.com/oauth/access_token +[oauth.weibo] +ENABLED = false +CLIENT_ID = +CLIENT_SECRET = +SCOPES = all +AUTH_URL = https://api.weibo.com/oauth2/authorize +TOKEN_URL = https://api.weibo.com/oauth2/access_token + [cache] ; Either "memory", "redis", or "memcache", default is "memory" ADAPTER = memory diff --git a/gogs.go b/gogs.go index 7a7d3ac87..de2bbc777 100644 --- a/gogs.go +++ b/gogs.go @@ -19,7 +19,7 @@ import ( // Test that go1.2 tag above is included in builds. main.go refers to this definition. const go12tag = true -const APP_VER = "0.2.8.0413 Alpha" +const APP_VER = "0.2.9.0413 Alpha" func init() { base.AppVer = APP_VER diff --git a/models/action.go b/models/action.go index a642a82c9..3edb884e2 100644 --- a/models/action.go +++ b/models/action.go @@ -8,6 +8,8 @@ import ( "encoding/json" "time" + // "github.com/gogits/git" + "github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/log" ) @@ -22,6 +24,7 @@ const ( OP_CREATE_ISSUE OP_PULL_REQUEST OP_TRANSFER_REPO + OP_PUSH_TAG ) // Action represents user operation type and other information to repository., @@ -67,7 +70,14 @@ func (a Action) GetContent() string { // CommitRepoAction adds new action for committing repository. func CommitRepoAction(userId int64, userName, actEmail string, repoId int64, repoName string, refName string, commit *base.PushCommits) error { - log.Trace("action.CommitRepoAction(start): %d/%s", userId, repoName) + // log.Trace("action.CommitRepoAction(start): %d/%s", userId, repoName) + + opType := OP_COMMIT_REPO + // Check it's tag push or branch. + // if git.IsTagExist(RepoPath(userName, repoName), refName) { + // opType = OP_PUSH_TAG + // commit = &base.PushCommits{} + // } bs, err := json.Marshal(commit) if err != nil { @@ -76,7 +86,7 @@ func CommitRepoAction(userId int64, userName, actEmail string, } if err = NotifyWatchers(&Action{ActUserId: userId, ActUserName: userName, ActEmail: actEmail, - OpType: OP_COMMIT_REPO, Content: string(bs), RepoId: repoId, RepoName: repoName, RefName: refName}); err != nil { + OpType: opType, Content: string(bs), RepoId: repoId, RepoName: repoName, RefName: refName}); err != nil { log.Error("action.CommitRepoAction(notify watchers): %d/%s", userId, repoName) return err } diff --git a/models/oauth2.go b/models/oauth2.go index 38d21fda1..d1ae4611b 100644 --- a/models/oauth2.go +++ b/models/oauth2.go @@ -68,3 +68,9 @@ func GetOauth2ById(id int64) (oa *Oauth2, err error) { } return oa, nil } + +// GetOauthByUserId returns list of oauthes that are releated to given user. +func GetOauthByUserId(uid int64) (oas []*Oauth2, err error) { + err = orm.Find(&oas, Oauth2{Uid: uid}) + return oas, err +} diff --git a/models/repo.go b/models/repo.go index 1a5a95f04..bb0c164e2 100644 --- a/models/repo.go +++ b/models/repo.go @@ -75,9 +75,9 @@ type Repository struct { NumStars int NumForks int NumIssues int - NumReleases int `xorm:"NOT NULL"` NumClosedIssues int NumOpenIssues int `xorm:"-"` + NumTags int `xorm:"-"` IsPrivate bool IsMirror bool IsBare bool diff --git a/modules/base/conf.go b/modules/base/conf.go index 0eca5f4fc..957ec57b4 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -38,7 +38,7 @@ type OauthInfo struct { // Oauther represents oauth service. type Oauther struct { GitHub, Google, Tencent bool - Twitter bool + Twitter, Weibo bool OauthInfos map[string]*OauthInfo } diff --git a/modules/base/template.go b/modules/base/template.go index 624149796..79aeeb9d7 100644 --- a/modules/base/template.go +++ b/modules/base/template.go @@ -92,6 +92,7 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{ "DiffTypeToStr": DiffTypeToStr, "DiffLineTypeToStr": DiffLineTypeToStr, "ShortSha": ShortSha, + "Oauth2Icon": Oauth2Icon, } type Actioner interface { @@ -109,7 +110,7 @@ func ActionIcon(opType int) string { switch opType { case 1: // Create repository. return "plus-circle" - case 5: // Commit repository. + case 5, 9: // Commit repository. return "arrow-circle-o-right" case 6: // Create issue. return "exclamation-circle" @@ -127,6 +128,7 @@ const ( TPL_CREATE_ISSUE = `%s opened issue %s#%s
%s
to %s`
+ TPL_PUSH_TAG = `%s pushed tag %s at %s`
)
type PushCommit struct {
@@ -174,6 +176,8 @@ func ActionDesc(act Actioner) string {
case 8: // Transfer repository.
newRepoLink := content + "/" + repoName
return fmt.Sprintf(TPL_TRANSFER_REPO, actUserName, actUserName, repoLink, newRepoLink, newRepoLink)
+ case 9: // Push tag.
+ return fmt.Sprintf(TPL_PUSH_TAG, actUserName, actUserName, repoLink, branch, branch, repoLink, repoLink)
default:
return "invalid type"
}
@@ -197,3 +201,19 @@ func DiffLineTypeToStr(diffType int) string {
}
return "same"
}
+
+func Oauth2Icon(t int) string {
+ switch t {
+ case 1:
+ return "fa-github-square"
+ case 2:
+ return "fa-google-plus-square"
+ case 3:
+ return "fa-twitter-square"
+ case 4:
+ return "fa-linux"
+ case 5:
+ return "fa-weibo"
+ }
+ return ""
+}
diff --git a/modules/middleware/repo.go b/modules/middleware/repo.go
index 1e79ce987..82c1c2dbf 100644
--- a/modules/middleware/repo.go
+++ b/modules/middleware/repo.go
@@ -123,6 +123,13 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler {
ctx.Repo.GitRepo = gitRepo
ctx.Repo.RepoLink = "/" + user.Name + "/" + repo.Name
+ tags, err := ctx.Repo.GitRepo.GetTags()
+ if err != nil {
+ ctx.Handle(500, "RepoAssignment(GetTags))", err)
+ return
+ }
+ ctx.Repo.Repository.NumTags = len(tags)
+
ctx.Data["Title"] = user.Name + "/" + repo.Name
ctx.Data["Repository"] = repo
ctx.Data["Owner"] = user
diff --git a/modules/social/social.go b/modules/social/social.go
index 230f478fe..c2ee54177 100644
--- a/modules/social/social.go
+++ b/modules/social/social.go
@@ -48,7 +48,7 @@ func NewOauthService() {
base.OauthService.OauthInfos = make(map[string]*base.OauthInfo)
socialConfigs := make(map[string]*oauth.Config)
- allOauthes := []string{"github", "google", "qq", "twitter"}
+ allOauthes := []string{"github", "google", "qq", "twitter", "weibo"}
// Load all OAuth config data.
for _, name := range allOauthes {
base.OauthService.OauthInfos[name] = &base.OauthInfo{
@@ -98,6 +98,13 @@ func NewOauthService() {
enabledOauths = append(enabledOauths, "Twitter")
}
+ // Weibo.
+ if base.Cfg.MustBool("oauth.weibo", "ENABLED") {
+ base.OauthService.Weibo = true
+ newWeiboOauth(socialConfigs["weibo"])
+ enabledOauths = append(enabledOauths, "Weibo")
+ }
+
log.Info("Oauth Service Enabled %s", enabledOauths)
}
@@ -331,3 +338,56 @@ func (s *SocialTwitter) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo
// }, nil
return nil, nil
}
+
+// __ __ ._____.
+// / \ / \ ____ |__\_ |__ ____
+// \ \/\/ // __ \| || __ \ / _ \
+// \ /\ ___/| || \_\ ( <_> )
+// \__/\ / \___ >__||___ /\____/
+// \/ \/ \/
+
+type SocialWeibo struct {
+ Token *oauth.Token
+ *oauth.Transport
+}
+
+func (s *SocialWeibo) Type() int {
+ return models.OT_WEIBO
+}
+
+func newWeiboOauth(config *oauth.Config) {
+ SocialMap["weibo"] = &SocialWeibo{
+ Transport: &oauth.Transport{
+ Config: config,
+ Transport: http.DefaultTransport,
+ },
+ }
+}
+
+func (s *SocialWeibo) SetRedirectUrl(url string) {
+ s.Transport.Config.RedirectURL = url
+}
+
+func (s *SocialWeibo) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) {
+ transport := &oauth.Transport{Token: token}
+ var data struct {
+ Id string `json:"id"`
+ Name string `json:"name"`
+ }
+ var err error
+
+ reqUrl := "https://api.weibo.com/2/users/show.json"
+ r, err := transport.Client().Get(reqUrl)
+ if err != nil {
+ return nil, err
+ }
+ defer r.Body.Close()
+ if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
+ return nil, err
+ }
+ return &BasicUserInfo{
+ Identity: data.Id,
+ Name: data.Name,
+ }, nil
+ return nil, nil
+}
diff --git a/routers/admin/admin.go b/routers/admin/admin.go
index 18a43ff81..d0f737e64 100644
--- a/routers/admin/admin.go
+++ b/routers/admin/admin.go
@@ -153,6 +153,12 @@ func Config(ctx *middleware.Context) {
ctx.Data["Mailer"] = base.MailService
}
+ ctx.Data["OauthEnabled"] = false
+ if base.OauthService != nil {
+ ctx.Data["OauthEnabled"] = true
+ ctx.Data["Oauther"] = base.OauthService
+ }
+
ctx.Data["CacheAdapter"] = base.CacheAdapter
ctx.Data["CacheConfig"] = base.CacheConfig
diff --git a/routers/user/setting.go b/routers/user/setting.go
index 7e66ad359..a8fdc116c 100644
--- a/routers/user/setting.go
+++ b/routers/user/setting.go
@@ -69,6 +69,20 @@ func SettingPost(ctx *middleware.Context, form auth.UpdateProfileForm) {
ctx.Redirect("/user/setting")
}
+func SettingSocial(ctx *middleware.Context) {
+ ctx.Data["Title"] = "Social Account"
+ ctx.Data["PageIsUserSetting"] = true
+ ctx.Data["IsUserPageSettingSocial"] = true
+ socials, err := models.GetOauthByUserId(ctx.User.Id)
+ if err != nil {
+ ctx.Handle(500, "user.SettingSocial", err)
+ return
+ }
+
+ ctx.Data["Socials"] = socials
+ ctx.HTML(200, "user/social")
+}
+
func SettingPassword(ctx *middleware.Context) {
ctx.Data["Title"] = "Password"
ctx.Data["PageIsUserSetting"] = true
@@ -147,7 +161,7 @@ func SettingSSHKeys(ctx *middleware.Context, form auth.AddSSHKeyForm) {
// Add new SSH key.
if ctx.Req.Method == "POST" {
- if hasErr, ok := ctx.Data["HasError"]; ok && hasErr.(bool) {
+ if ctx.HasError() {
ctx.HTML(200, "user/publickey")
return
}
@@ -162,11 +176,13 @@ func SettingSSHKeys(ctx *middleware.Context, form auth.AddSSHKeyForm) {
ctx.RenderWithErr("Public key name has been used", "user/publickey", &form)
return
}
- ctx.Handle(200, "ssh.AddPublicKey", err)
- log.Trace("%s User SSH key added: %s", ctx.Req.RequestURI, ctx.User.LowerName)
+ ctx.Handle(500, "ssh.AddPublicKey", err)
return
} else {
- ctx.Data["AddSSHKeySuccess"] = true
+ log.Trace("%s User SSH key added: %s", ctx.Req.RequestURI, ctx.User.LowerName)
+ ctx.Flash.Success("New SSH Key has been added!")
+ ctx.Redirect("/user/setting/ssh")
+ return
}
}
diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl
index 31cfb77ba..757a800c2 100644
--- a/templates/admin/config.tmpl
+++ b/templates/admin/config.tmpl
@@ -88,12 +88,34 @@
New SSH Key has been added !
{{else if .HasError}}{{.ErrorMsg}}
{{end}} +