diff options
-rw-r--r-- | .gopmfile | 1 | ||||
-rw-r--r-- | cmd/web.go | 10 | ||||
-rw-r--r-- | conf/app.ini | 14 | ||||
-rw-r--r-- | conf/locale/TRANSLATORS | 6 | ||||
-rw-r--r-- | gogs.go | 2 | ||||
-rw-r--r-- | modules/setting/setting.go | 6 | ||||
-rw-r--r-- | modules/social/social.go | 292 | ||||
-rw-r--r-- | routers/user/social.go | 50 | ||||
-rw-r--r-- | templates/.VERSION | 2 | ||||
-rw-r--r-- | templates/admin/repo/list.tmpl | 4 | ||||
-rw-r--r-- | templates/ng/base/social.tmpl | 8 | ||||
-rw-r--r-- | templates/repo/issue/list.tmpl | 2 | ||||
-rw-r--r-- | templates/repo/issue/view.tmpl | 24 | ||||
-rw-r--r-- | templates/repo/release/list.tmpl | 2 | ||||
-rw-r--r-- | templates/user/auth/signin.tmpl | 4 | ||||
-rw-r--r-- | templates/user/issues.tmpl | 2 | ||||
-rw-r--r-- | templates/user/settings/profile.tmpl | 2 |
17 files changed, 183 insertions, 248 deletions
@@ -21,6 +21,7 @@ github.com/macaron-contrib/cache = commit:0bb9e6c9ef github.com/macaron-contrib/captcha = commit:3567dc48b8 github.com/macaron-contrib/csrf = commit:422b79675c github.com/macaron-contrib/i18n = +github.com/macaron-contrib/oauth2 = github.com/macaron-contrib/session = commit:f00d48fd4f github.com/macaron-contrib/toolbox = commit:57127bcc89 github.com/mattn/go-sqlite3 = commit:a80c27ba33 @@ -21,6 +21,7 @@ import ( "github.com/macaron-contrib/captcha" "github.com/macaron-contrib/csrf" "github.com/macaron-contrib/i18n" + "github.com/macaron-contrib/oauth2" "github.com/macaron-contrib/session" "github.com/macaron-contrib/toolbox" @@ -140,6 +141,11 @@ func newMacaron() *macaron.Macaron { }, }, })) + + // OAuth 2. + for _, info := range setting.OauthService.OauthInfos { + m.Use(oauth2.NewOAuth2Provider(info.Options, info.AuthUrl, info.TokenUrl)) + } m.Use(middleware.Contexter()) return m } @@ -213,7 +219,7 @@ func runWeb(*cli.Context) { m.Group("/user", func() { m.Get("/login", user.SignIn) m.Post("/login", bindIgnErr(auth.SignInForm{}), user.SignInPost) - m.Get("/login/:name", user.SocialSignIn) + m.Get("/info/:name", user.SocialSignIn) m.Get("/sign_up", user.SignUp) m.Post("/sign_up", bindIgnErr(auth.RegisterForm{}), user.SignUpPost) m.Get("/reset_password", user.ResetPasswd) @@ -406,7 +412,7 @@ func runWeb(*cli.Context) { m.Get("/issues2/", repo.Issues2) m.Get("/pulls2/", repo.PullRequest2) m.Get("/labels2/", repo.Labels2) - m.Get("/milestone2/",repo.Milestones2) + m.Get("/milestone2/", repo.Milestones2) m.Group("", func() { m.Get("/src/*", repo.Home) diff --git a/conf/app.ini b/conf/app.ini index e0620f31..dba75ed1 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -22,6 +22,11 @@ DISABLE_ROUTER_LOG = false ; Generate steps: ; $ cd path/to/gogs/custom/https ; $ ./gogs cert -ca=true -duration=8760h0m0s -host=myhost.example.com +; +; Or from a .pfx file exported from the Windows certificate store (do +; not forget to export the private key): +; $ openssl pkcs12 -in cert.pfx -out cert.pem -nokeys +; $ openssl pkcs12 -in cert.pfx -out key.pem -nocerts -nodes CERT_FILE = custom/https/cert.pem KEY_FILE = custom/https/key.pem ; Upper level of template and static file path @@ -120,13 +125,10 @@ TOKEN_URL = https://accounts.google.com/o/oauth2/token ENABLED = false CLIENT_ID = CLIENT_SECRET = -SCOPES = all +SCOPES = get_user_info ; QQ 互联 -; AUTH_URL = https://graph.qq.com/oauth2.0/authorize -; TOKEN_URL = https://graph.qq.com/oauth2.0/token -; Tencent weibo -AUTH_URL = https://open.t.qq.com/cgi-bin/oauth2/authorize -TOKEN_URL = https://open.t.qq.com/cgi-bin/oauth2/access_token +AUTH_URL = https://graph.qq.com/oauth2.0/authorize +TOKEN_URL = https://graph.qq.com/oauth2.0/token [oauth.weibo] ENABLED = false diff --git a/conf/locale/TRANSLATORS b/conf/locale/TRANSLATORS index a07e7d5e..9899ea4e 100644 --- a/conf/locale/TRANSLATORS +++ b/conf/locale/TRANSLATORS @@ -1,3 +1,5 @@ -# This file lists all individuals having contributed content to the translation. +# This file lists all PUBLIC individuals having contributed content to the translation. +# Order of name is meaningless. -Thomas Fanninger <gogs.thomas@fanninger.at>
\ No newline at end of file +Thomas Fanninger <gogs.thomas@fanninger.at> +Łukasz Jan Niemier <lukasz@niemier.pl>
\ No newline at end of file @@ -17,7 +17,7 @@ import ( "github.com/gogits/gogs/modules/setting" ) -const APP_VER = "0.5.8.1125 Beta" +const APP_VER = "0.5.8.1128 Beta" func init() { runtime.GOMAXPROCS(runtime.NumCPU()) diff --git a/modules/setting/setting.go b/modules/setting/setting.go index a775847c..9737fa7c 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -17,6 +17,7 @@ import ( "github.com/Unknwon/com" "github.com/Unknwon/goconfig" + "github.com/macaron-contrib/oauth2" "github.com/macaron-contrib/session" "github.com/gogits/gogs/modules/log" @@ -434,9 +435,8 @@ type Mailer struct { } type OauthInfo struct { - ClientId, ClientSecret string - Scopes string - AuthUrl, TokenUrl string + oauth2.Options + AuthUrl, TokenUrl string } // Oauther represents oauth service. diff --git a/modules/social/social.go b/modules/social/social.go index f4d85988..bdafae69 100644 --- a/modules/social/social.go +++ b/modules/social/social.go @@ -7,12 +7,12 @@ package social import ( "encoding/json" + "io/ioutil" "net/http" "net/url" "strconv" - "strings" - oauth "github.com/gogits/oauth2" + "github.com/macaron-contrib/oauth2" "github.com/gogits/gogs/models" "github.com/gogits/gogs/modules/log" @@ -27,16 +27,11 @@ type BasicUserInfo struct { type SocialConnector interface { Type() int - SetRedirectUrl(string) - UserInfo(*oauth.Token, *url.URL) (*BasicUserInfo, error) - - AuthCodeURL(string) string - Exchange(string) (*oauth.Token, error) + UserInfo(*oauth2.Token, *url.URL) (*BasicUserInfo, error) } var ( - SocialBaseUrl = "/user/login" - SocialMap = make(map[string]SocialConnector) + SocialMap = make(map[string]SocialConnector) ) func NewOauthService() { @@ -44,27 +39,34 @@ func NewOauthService() { return } + oauth2.AppSubUrl = setting.AppSubUrl + setting.OauthService = &setting.Oauther{} setting.OauthService.OauthInfos = make(map[string]*setting.OauthInfo) - socialConfigs := make(map[string]*oauth.Config) + socialConfigs := make(map[string]*oauth2.Options) allOauthes := []string{"github", "google", "qq", "twitter", "weibo"} // Load all OAuth config data. for _, name := range allOauthes { + if !setting.Cfg.MustBool("oauth."+name, "ENABLED") { + continue + } setting.OauthService.OauthInfos[name] = &setting.OauthInfo{ - ClientId: setting.Cfg.MustValue("oauth."+name, "CLIENT_ID"), - ClientSecret: setting.Cfg.MustValue("oauth."+name, "CLIENT_SECRET"), - Scopes: setting.Cfg.MustValue("oauth."+name, "SCOPES"), - AuthUrl: setting.Cfg.MustValue("oauth."+name, "AUTH_URL"), - TokenUrl: setting.Cfg.MustValue("oauth."+name, "TOKEN_URL"), + Options: oauth2.Options{ + ClientID: setting.Cfg.MustValue("oauth."+name, "CLIENT_ID"), + ClientSecret: setting.Cfg.MustValue("oauth."+name, "CLIENT_SECRET"), + Scopes: setting.Cfg.MustValueArray("oauth."+name, "SCOPES", " "), + PathLogin: "/user/login/oauth2/" + name, + PathCallback: setting.AppSubUrl + "/user/login/" + name, + RedirectURL: setting.AppUrl + "user/login/" + name, + }, + AuthUrl: setting.Cfg.MustValue("oauth."+name, "AUTH_URL"), + TokenUrl: setting.Cfg.MustValue("oauth."+name, "TOKEN_URL"), } - socialConfigs[name] = &oauth.Config{ - ClientId: setting.OauthService.OauthInfos[name].ClientId, + socialConfigs[name] = &oauth2.Options{ + ClientID: setting.OauthService.OauthInfos[name].ClientID, ClientSecret: setting.OauthService.OauthInfos[name].ClientSecret, - RedirectURL: strings.TrimSuffix(setting.AppUrl, "/") + SocialBaseUrl + name, - Scope: setting.OauthService.OauthInfos[name].Scopes, - AuthURL: setting.OauthService.OauthInfos[name].AuthUrl, - TokenURL: setting.OauthService.OauthInfos[name].TokenUrl, + Scopes: setting.OauthService.OauthInfos[name].Scopes, } } enabledOauths := make([]string, 0, 10) @@ -91,11 +93,11 @@ func NewOauthService() { } // Twitter. - if setting.Cfg.MustBool("oauth.twitter", "ENABLED") { - setting.OauthService.Twitter = true - newTwitterOauth(socialConfigs["twitter"]) - enabledOauths = append(enabledOauths, "Twitter") - } + // if setting.Cfg.MustBool("oauth.twitter", "ENABLED") { + // setting.OauthService.Twitter = true + // newTwitterOauth(socialConfigs["twitter"]) + // enabledOauths = append(enabledOauths, "Twitter") + // } // Weibo. if setting.Cfg.MustBool("oauth.weibo", "ENABLED") { @@ -115,38 +117,25 @@ func NewOauthService() { // \/ \/ \/ type SocialGithub struct { - Token *oauth.Token - *oauth.Transport -} - -func (s *SocialGithub) Type() int { - return int(models.GITHUB) + opts *oauth2.Options } -func newGitHubOauth(config *oauth.Config) { - SocialMap["github"] = &SocialGithub{ - Transport: &oauth.Transport{ - Config: config, - Transport: http.DefaultTransport, - }, - } +func newGitHubOauth(opts *oauth2.Options) { + SocialMap["github"] = &SocialGithub{opts} } -func (s *SocialGithub) SetRedirectUrl(url string) { - s.Transport.Config.RedirectURL = url +func (s *SocialGithub) Type() int { + return int(models.GITHUB) } -func (s *SocialGithub) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) { - transport := &oauth.Transport{ - Token: token, - } +func (s *SocialGithub) UserInfo(token *oauth2.Token, _ *url.URL) (*BasicUserInfo, error) { + transport := s.opts.NewTransportFromToken(token) var data struct { Id int `json:"id"` Name string `json:"login"` Email string `json:"email"` } - var err error - r, err := transport.Client().Get(s.Transport.Scope) + r, err := transport.Client().Get("https://api.github.com/user") if err != nil { return nil, err } @@ -169,38 +158,25 @@ func (s *SocialGithub) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, // \/ /_____/ \/ type SocialGoogle struct { - Token *oauth.Token - *oauth.Transport + opts *oauth2.Options } func (s *SocialGoogle) Type() int { return int(models.GOOGLE) } -func newGoogleOauth(config *oauth.Config) { - SocialMap["google"] = &SocialGoogle{ - Transport: &oauth.Transport{ - Config: config, - Transport: http.DefaultTransport, - }, - } -} - -func (s *SocialGoogle) SetRedirectUrl(url string) { - s.Transport.Config.RedirectURL = url +func newGoogleOauth(opts *oauth2.Options) { + SocialMap["google"] = &SocialGoogle{opts} } -func (s *SocialGoogle) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) { - transport := &oauth.Transport{Token: token} +func (s *SocialGoogle) UserInfo(token *oauth2.Token, _ *url.URL) (*BasicUserInfo, error) { + transport := s.opts.NewTransportFromToken(token) var data struct { Id string `json:"id"` Name string `json:"name"` Email string `json:"email"` } - var err error - - reqUrl := "https://www.googleapis.com/oauth2/v1/userinfo" - r, err := transport.Client().Get(reqUrl) + r, err := transport.Client().Get("https://www.googleapis.com/userinfo/v2/me") if err != nil { return nil, err } @@ -223,62 +199,35 @@ func (s *SocialGoogle) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, // \__> \__> type SocialTencent struct { - Token *oauth.Token - *oauth.Transport - reqUrl string + opts *oauth2.Options +} + +func newTencentOauth(opts *oauth2.Options) { + SocialMap["qq"] = &SocialTencent{opts} } func (s *SocialTencent) Type() int { return int(models.QQ) } -func newTencentOauth(config *oauth.Config) { - SocialMap["qq"] = &SocialTencent{ - reqUrl: "https://open.t.qq.com/api/user/info", - Transport: &oauth.Transport{ - Config: config, - Transport: http.DefaultTransport, - }, +func (s *SocialTencent) UserInfo(token *oauth2.Token, URL *url.URL) (*BasicUserInfo, error) { + r, err := http.Get("https://graph.z.qq.com/moc2/me?access_token=" + url.QueryEscape(token.AccessToken)) + if err != nil { + return nil, err } -} - -func (s *SocialTencent) SetRedirectUrl(url string) { - s.Transport.Config.RedirectURL = url -} + defer r.Body.Close() -func (s *SocialTencent) UserInfo(token *oauth.Token, URL *url.URL) (*BasicUserInfo, error) { - var data struct { - Data struct { - Id string `json:"openid"` - Name string `json:"name"` - Email string `json:"email"` - } `json:"data"` - } - var err error - // https://open.t.qq.com/api/user/info? - //oauth_consumer_key=APP_KEY& - //access_token=ACCESSTOKEN&openid=openid - //clientip=CLIENTIP&oauth_version=2.a - //scope=all - var urls = url.Values{ - "oauth_consumer_key": {s.Transport.Config.ClientId}, - "access_token": {token.AccessToken}, - "openid": URL.Query()["openid"], - "oauth_version": {"2.a"}, - "scope": {"all"}, - } - r, err := http.Get(s.reqUrl + "?" + urls.Encode()) + body, err := ioutil.ReadAll(r.Body) if err != nil { return nil, err } - defer r.Body.Close() - if err = json.NewDecoder(r.Body).Decode(&data); err != nil { + vals, err := url.ParseQuery(string(body)) + if err != nil { return nil, err } + return &BasicUserInfo{ - Identity: data.Data.Id, - Name: data.Data.Name, - Email: data.Data.Email, + Identity: vals.Get("openid"), }, nil } @@ -289,54 +238,54 @@ func (s *SocialTencent) UserInfo(token *oauth.Token, URL *url.URL) (*BasicUserIn // |____| \/\_/ |__||__| |__| \___ >__| // \/ -type SocialTwitter struct { - Token *oauth.Token - *oauth.Transport -} - -func (s *SocialTwitter) Type() int { - return int(models.TWITTER) -} - -func newTwitterOauth(config *oauth.Config) { - SocialMap["twitter"] = &SocialTwitter{ - Transport: &oauth.Transport{ - Config: config, - Transport: http.DefaultTransport, - }, - } -} - -func (s *SocialTwitter) SetRedirectUrl(url string) { - s.Transport.Config.RedirectURL = url -} - -//https://github.com/mrjones/oauth -func (s *SocialTwitter) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) { - // transport := &oauth.Transport{Token: token} - // var data struct { - // Id string `json:"id"` - // Name string `json:"name"` - // Email string `json:"email"` - // } - // var err error - - // reqUrl := "https://www.googleapis.com/oauth2/v1/userinfo" - // 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, - // Email: data.Email, - // }, nil - return nil, nil -} +// type SocialTwitter struct { +// Token *oauth2.Token +// *oauth2.Transport +// } + +// func (s *SocialTwitter) Type() int { +// return int(models.TWITTER) +// } + +// func newTwitterOauth(config *oauth2.Config) { +// SocialMap["twitter"] = &SocialTwitter{ +// Transport: &oauth.Transport{ +// Config: config, +// Transport: http.DefaultTransport, +// }, +// } +// } + +// func (s *SocialTwitter) SetRedirectUrl(url string) { +// s.Transport.Config.RedirectURL = url +// } + +// //https://github.com/mrjones/oauth +// func (s *SocialTwitter) UserInfo(token *oauth2.Token, _ *url.URL) (*BasicUserInfo, error) { +// // transport := &oauth.Transport{Token: token} +// // var data struct { +// // Id string `json:"id"` +// // Name string `json:"name"` +// // Email string `json:"email"` +// // } +// // var err error + +// // reqUrl := "https://www.googleapis.com/oauth2/v1/userinfo" +// // 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, +// // Email: data.Email, +// // }, nil +// return nil, nil +// } // __ __ ._____. // / \ / \ ____ |__\_ |__ ____ @@ -346,37 +295,25 @@ func (s *SocialTwitter) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo // \/ \/ \/ type SocialWeibo struct { - Token *oauth.Token - *oauth.Transport -} - -func (s *SocialWeibo) Type() int { - return int(models.WEIBO) + opts *oauth2.Options } -func newWeiboOauth(config *oauth.Config) { - SocialMap["weibo"] = &SocialWeibo{ - Transport: &oauth.Transport{ - Config: config, - Transport: http.DefaultTransport, - }, - } +func newWeiboOauth(opts *oauth2.Options) { + SocialMap["weibo"] = &SocialWeibo{opts} } -func (s *SocialWeibo) SetRedirectUrl(url string) { - s.Transport.Config.RedirectURL = url +func (s *SocialWeibo) Type() int { + return int(models.WEIBO) } -func (s *SocialWeibo) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) { - transport := &oauth.Transport{Token: token} +func (s *SocialWeibo) UserInfo(token *oauth2.Token, _ *url.URL) (*BasicUserInfo, error) { + transport := s.opts.NewTransportFromToken(token) var data struct { Name string `json:"name"` } - var err error - var urls = url.Values{ "access_token": {token.AccessToken}, - "uid": {token.Extra["id_token"]}, + "uid": {token.Extra("uid")}, } reqUrl := "https://api.weibo.com/2/users/show.json" r, err := transport.Client().Get(reqUrl + "?" + urls.Encode()) @@ -384,11 +321,12 @@ func (s *SocialWeibo) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, return nil, err } defer r.Body.Close() + if err = json.NewDecoder(r.Body).Decode(&data); err != nil { return nil, err } return &BasicUserInfo{ - Identity: token.Extra["id_token"], + Identity: token.Extra("uid"), Name: data.Name, }, nil } diff --git a/routers/user/social.go b/routers/user/social.go index 0bc1fa59..913fc094 100644 --- a/routers/user/social.go +++ b/routers/user/social.go @@ -8,10 +8,11 @@ import ( "encoding/json" "errors" "fmt" - "net/url" - "strings" + // "strings" "time" + "github.com/macaron-contrib/oauth2" + "github.com/gogits/gogs/models" "github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/middleware" @@ -19,52 +20,39 @@ import ( "github.com/gogits/gogs/modules/social" ) -func extractPath(next string) string { - n, err := url.Parse(next) - if err != nil { - return setting.AppSubUrl + "/" - } - return n.Path -} - func SocialSignIn(ctx *middleware.Context) { if setting.OauthService == nil { - ctx.Handle(404, "social.SocialSignIn(oauth service not enabled)", nil) + ctx.Handle(404, "OAuth2 service not enabled", nil) + return + } + + next := setting.AppSubUrl + "/user/login" + info := ctx.Session.Get(oauth2.KEY_TOKEN) + if info == nil { + ctx.Redirect(next) return } - next := extractPath(ctx.Query("next")) name := ctx.Params(":name") connect, ok := social.SocialMap[name] if !ok { - ctx.Handle(404, "social.SocialSignIn(social login not enabled)", errors.New(name)) + ctx.Handle(404, "social login not enabled", errors.New(name)) return } - appUrl := strings.TrimSuffix(setting.AppUrl, "/") - if name == "weibo" { - appUrl = strings.Replace(appUrl, "localhost", "127.0.0.1", 1) - } - code := ctx.Query("code") - if code == "" { - // redirect to social login page - connect.SetRedirectUrl(appUrl + ctx.Req.URL.Path) - ctx.Redirect(connect.AuthCodeURL(next)) + tk := new(oauth2.Token) + if err := json.Unmarshal(info.([]byte), tk); err != nil { + ctx.Handle(500, "Unmarshal token", err) return } - // handle call back - tk, err := connect.Exchange(code) + ui, err := connect.UserInfo(tk, ctx.Req.URL) if err != nil { - ctx.Handle(500, "social.SocialSignIn(Exchange)", err) + ctx.Handle(500, fmt.Sprintf("UserInfo(%s)", name), err) return } - next = extractPath(ctx.Query("state")) - log.Trace("social.SocialSignIn(Got token)") - - ui, err := connect.UserInfo(tk, ctx.Req.URL) - if err != nil { - ctx.Handle(500, fmt.Sprintf("social.SocialSignIn(get info from %s)", name), err) + if len(ui.Identity) == 0 { + ctx.Handle(404, "no identity is presented", errors.New(name)) return } log.Info("social.SocialSignIn(social login): %s", ui) diff --git a/templates/.VERSION b/templates/.VERSION index d244b039..c4127c31 100644 --- a/templates/.VERSION +++ b/templates/.VERSION @@ -1 +1 @@ -0.5.8.1125 Beta
\ No newline at end of file +0.5.8.1128 Beta
\ No newline at end of file diff --git a/templates/admin/repo/list.tmpl b/templates/admin/repo/list.tmpl index 276fdff8..3a201fea 100644 --- a/templates/admin/repo/list.tmpl +++ b/templates/admin/repo/list.tmpl @@ -35,8 +35,8 @@ <td><a href="{{AppSubUrl}}/{{.Owner.Name}}/{{.Name}}">{{.Name}}</a></td> <td><i class="fa fa{{if .IsPrivate}}-check{{end}}-square-o"></i></td> <td>{{.NumWatches}}</td> - <td>{{.NumIssues}}</td> <td>{{.NumStars}}</td> + <td>{{.NumIssues}}</td> <td>{{DateFormat .Created "M d, Y"}}</td> </tr> {{end}} @@ -57,4 +57,4 @@ </div> </div> </div> -{{template "ng/base/footer" .}}
\ No newline at end of file +{{template "ng/base/footer" .}} diff --git a/templates/ng/base/social.tmpl b/templates/ng/base/social.tmpl index 2d4acd28..277b54fc 100644 --- a/templates/ng/base/social.tmpl +++ b/templates/ng/base/social.tmpl @@ -1,4 +1,4 @@ -{{if .OauthService.GitHub}}<a class="btn github" href="{{AppSubUrl}}/user/login/github?next=/user/sign_up"><i class="fa fa-github"></i>GitHub</a>{{end}} -{{if .OauthService.Google}}<a class="btn google" href="{{AppSubUrl}}/user/login/google?next=/user/sign_up"><i class="fa fa-google"></i>Google +</a>{{end}} -{{if .OauthService.Weibo}}<a class="btn weibo" href="{{AppSubUrl}}/user/login/weibo?next=/user/sign_up"><i class="fa fa-weibo"></i>新浪微博</a>{{end}} -{{if .OauthService.Tencent}}<a class="btn qq" href="{{AppSubUrl}}/user/login/qq?next=/user/sign_up"><i class="fa fa-qq"></i>腾讯 QQ </a>{{end}}
\ No newline at end of file +{{if .OauthService.GitHub}}<a class="btn github" href="{{AppSubUrl}}/user/login/oauth2/github?next={{AppSubUrl}}/user/info/github"><i class="fa fa-github"></i>GitHub</a>{{end}} +{{if .OauthService.Google}}<a class="btn google" href="{{AppSubUrl}}/user/login/oauth2/google?next={{AppSubUrl}}/user/info/google"><i class="fa fa-google"></i>Google +</a>{{end}} +{{if .OauthService.Weibo}}<a class="btn weibo" href="{{AppSubUrl}}/user/login/oauth2/weibo?next={{AppSubUrl}}/user/info/weibo"><i class="fa fa-weibo"></i>新浪微博</a>{{end}} +{{if .OauthService.Tencent}}<a class="btn qq" href="{{AppSubUrl}}/user/login/oauth2/qq?next={{AppSubUrl}}/user/info/qq"><i class="fa fa-qq"></i>腾讯 QQ </a>{{end}}
\ No newline at end of file diff --git a/templates/repo/issue/list.tmpl b/templates/repo/issue/list.tmpl index 0f9daae9..db2d0752 100644 --- a/templates/repo/issue/list.tmpl +++ b/templates/repo/issue/list.tmpl @@ -85,7 +85,7 @@ </h5> <p class="info"> <span class="author"><img class="avatar" src="{{.Poster.AvatarLink}}" alt="" width="20"/> - <a href="{{AppSubUrl}}/user/{{.Poster.Name}}">{{.Poster.Name}}</a></span> + <a href="{{AppSubUrl}}/{{.Poster.Name}}">{{.Poster.Name}}</a></span> <span class="time">{{TimeSince .Created $.Lang}}</span> <span class="comment"><i class="fa fa-comments"></i> {{.NumComments}}</span> </p> diff --git a/templates/repo/issue/view.tmpl b/templates/repo/issue/view.tmpl index 68bc047b..738e0c34 100644 --- a/templates/repo/issue/view.tmpl +++ b/templates/repo/issue/view.tmpl @@ -8,7 +8,7 @@ <div class="issue-wrap col-md-10"> <div class="issue-head clearfix"> <div class="number pull-right">#{{.Issue.Index}}</div> - <a class="author pull-left" href="{{AppSubUrl}}/user/{{.Issue.Poster.Name}}"><img class="avatar" src="{{.Issue.Poster.AvatarLink}}" alt="" width="30"/></a> + <a class="author pull-left" href="{{AppSubUrl}}/{{.Issue.Poster.Name}}"><img class="avatar" src="{{.Issue.Poster.AvatarLink}}" alt="" width="30"/></a> <h1 class="title pull-left">{{.Issue.Name}}</h1> <input id="issue-edit-title" class="form-control input-lg pull-left hidden" type="text" value="{{.Issue.Name}}" data-ajax-rel="issue-edit-save" data-ajax-val="val" data-ajax-field="title"/> <input type="hidden" value="{{.Issue.Id}}" data-ajax-rel="issue-edit-save" data-ajax-val="val" data-ajax-field="issue_id"/> @@ -17,7 +17,7 @@ <a class="btn btn-danger pull-right issue-edit-cancel hidden" href="#">Cancel</a> <a class="btn btn-primary pull-right issue-edit-save hidden" href="#" data-ajax="{{.RepoLink}}/issues/{{.Issue.Index}}" data-ajax-name="issue-edit-save" data-ajax-method="post">Save</a>{{end}} <span class="status label label-{{if .Issue.IsClosed}}danger{{else}}success{{end}}">{{if .Issue.IsClosed}}Closed{{else}}Open{{end}}</span> - <a href="{{AppSubUrl}}/user/{{.Issue.Poster.Name}}" class="author"><strong>{{.Issue.Poster.Name}}</strong></a> opened this issue + <a href="{{AppSubUrl}}/{{.Issue.Poster.Name}}" class="author"><strong>{{.Issue.Poster.Name}}</strong></a> opened this issue <span class="time">{{TimeSince .Issue.Created $.Lang}}</span> · {{.Issue.NumComments}} comments </p> </div> @@ -63,10 +63,10 @@ {{/* 0 = COMMENT, 1 = REOPEN, 2 = CLOSE, 3 = ISSUE, 4 = COMMIT, 5 = PULL */}} {{if eq .Type 0}} <div class="issue-child" id="issue-comment-{{.Id}}"> - <a class="user pull-left" href="{{AppSubUrl}}/user/{{.Poster.Name}}"><img class="avatar" src="{{.Poster.AvatarLink}}" alt=""/></a> + <a class="user pull-left" href="{{AppSubUrl}}/{{.Poster.Name}}"><img class="avatar" src="{{.Poster.AvatarLink}}" alt=""/></a> <div class="issue-content panel panel-default"> <div class="panel-heading"> - <a href="{{AppSubUrl}}/user/{{.Poster.Name}}" class="user">{{.Poster.Name}}</a> commented <span class="time">{{TimeSince .Created $.Lang}}</span> + <a href="{{AppSubUrl}}/{{.Poster.Name}}" class="user">{{.Poster.Name}}</a> commented <span class="time">{{TimeSince .Created $.Lang}}</span> <!-- <a class="issue-comment-del pull-right issue-action" href="#" title="Edit Comment"><i class="fa fa-times-circle"></i></a> <a class="issue-comment-edit pull-right issue-action" href="#" title="Remove Comment" data-url="{remove-link}"><i class="fa fa-edit"></i></a> --> <span class="role label label-default pull-right">Owner</span> @@ -93,25 +93,25 @@ </div> {{else if eq .Type 1}} <div class="issue-child issue-opened"> - <a class="user pull-left" href="{{AppSubUrl}}/user/{{.Poster.Name}}"><img class="avatar" src="{{.Poster.AvatarLink}}" alt="" /></a> + <a class="user pull-left" href="{{AppSubUrl}}/{{.Poster.Name}}"><img class="avatar" src="{{.Poster.AvatarLink}}" alt="" /></a> <div class="issue-content"> - <a class="user pull-left" href="{{AppSubUrl}}/user/{{.Poster.Name}}">{{.Poster.Name}}</a> <span class="label label-success">Reopened</span> this issue <span class="time">{{TimeSince .Created $.Lang}}</span> + <a class="user pull-left" href="{{AppSubUrl}}/{{.Poster.Name}}">{{.Poster.Name}}</a> <span class="label label-success">Reopened</span> this issue <span class="time">{{TimeSince .Created $.Lang}}</span> </div> </div> {{else if eq .Type 2}} <div class="issue-child issue-closed"> - <a class="user pull-left" href="{{AppSubUrl}}/user/{{.Poster.Name}}"><img class="avatar" src="{{.Poster.AvatarLink}}" alt=""/></a> + <a class="user pull-left" href="{{AppSubUrl}}/{{.Poster.Name}}"><img class="avatar" src="{{.Poster.AvatarLink}}" alt=""/></a> <div class="issue-content"> - <a class="user pull-left" href="{{AppSubUrl}}/user/{{.Poster.Name}}">{{.Poster.Name}}</a> <span class="label label-danger">Closed</span> this issue <span class="time">{{TimeSince .Created $.Lang}}</span> + <a class="user pull-left" href="{{AppSubUrl}}/{{.Poster.Name}}">{{.Poster.Name}}</a> <span class="label label-danger">Closed</span> this issue <span class="time">{{TimeSince .Created $.Lang}}</span> </div> </div> {{else if eq .Type 4}} <div class="issue-child issue-reference issue-reference-commit"> - <a class="user pull-left" href="{{AppSubUrl}}/user/{{.Poster.Name}}"><img class="avatar" src="{{.Poster.AvatarLink}}" alt=""/></a> + <a class="user pull-left" href="{{AppSubUrl}}/{{.Poster.Name}}"><img class="avatar" src="{{.Poster.AvatarLink}}" alt=""/></a> <div class="issue-content"> - <a class="user pull-left" href="{{AppSubUrl}}/user/{{.Poster.Name}}">{{.Poster.Name}}</a> <span class="label label-primary">Referenced</span> this issue <span class="time">{{TimeSince .Created $.Lang}}</span> + <a class="user pull-left" href="{{AppSubUrl}}/{{.Poster.Name}}">{{.Poster.Name}}</a> <span class="label label-primary">Referenced</span> this issue <span class="time">{{TimeSince .Created $.Lang}}</span> <p> - <a class="user pull-left" href="{{AppSubUrl}}/user/{{.Poster.Name}}"><img class="avatar" src="{{.Poster.AvatarLink}}" alt=""/></a> + <a class="user pull-left" href="{{AppSubUrl}}/{{.Poster.Name}}"><img class="avatar" src="{{.Poster.AvatarLink}}" alt=""/></a> {{.ContentHtml}} </p> </div> @@ -120,7 +120,7 @@ {{end}} <hr class="issue-line"/> {{if .SignedUser}}<div class="issue-child issue-reply"> - <a class="user pull-left" href="{{AppSubUrl}}/user/{{.SignedUser.Name}}"><img class="avatar" src="{{.SignedUser.AvatarLink}}" alt=""/></a> + <a class="user pull-left" href="{{AppSubUrl}}/{{.SignedUser.Name}}"><img class="avatar" src="{{.SignedUser.AvatarLink}}" alt=""/></a> <form class="panel panel-default issue-content" action="{{.RepoLink}}/comment/new" method="post" enctype="multipart/form-data"> {{.CsrfTokenHtml}} <div class="panel-body"> diff --git a/templates/repo/release/list.tmpl b/templates/repo/release/list.tmpl index 1eb11fc5..b3e3db95 100644 --- a/templates/repo/release/list.tmpl +++ b/templates/repo/release/list.tmpl @@ -28,7 +28,7 @@ <h4 class="title"><a href="{{$.RepoLink}}/src/{{.TagName}}">{{.Title}}</a> <small>(<a href="{{$.RepoLink}}/releases/edit/{{.TagName}}" rel="nofollow">edit</a>)</small></h4> <p class="info"> <span class="author"><img class="avatar" src="{{.Publisher.AvatarLink}}" alt="" width="20"> - <a href="{{AppSubUrl}}/user/{{.Publisher.Name}}">{{.Publisher.Name}}</a></span> + <a href="{{AppSubUrl}}/{{.Publisher.Name}}">{{.Publisher.Name}}</a></span> {{if .Created}}<span class="time">{{TimeSince .Created $.Lang}}</span>{{end}} <span class="ahead"><strong>{{.NumCommitsBehind}}</strong> commits to {{.Target}} since this release</span> </p> diff --git a/templates/user/auth/signin.tmpl b/templates/user/auth/signin.tmpl index 54748077..78d6febb 100644 --- a/templates/user/auth/signin.tmpl +++ b/templates/user/auth/signin.tmpl @@ -26,18 +26,16 @@ <button class="btn btn-green btn-large btn-radius">{{.i18n.Tr "sign_in"}}</button> {{if not .IsSocialLogin}}<a href="{{AppSubUrl}}/user/forget_password">{{.i18n.Tr "auth.forget_password"}}</a>{{end}} </div> - {{if not .IsSocialLogin}} <div class="field"> <label></label> <a href="{{AppSubUrl}}/user/sign_up">{{.i18n.Tr "auth.sign_up_now" | Str2html}}</a> </div> - {{if .OauthEnabled}} + {{if and (not .IsSocialLogin) .OauthEnabled}} <hr/> <div id="sign-social" class="text-center social-buttons"> {{template "ng/base/social" .}} </div> {{end}} - {{end}} </div> </form> </div> diff --git a/templates/user/issues.tmpl b/templates/user/issues.tmpl index 45492039..bb81d4fa 100644 --- a/templates/user/issues.tmpl +++ b/templates/user/issues.tmpl @@ -40,7 +40,7 @@ <h5 class="title"><a href="{{AppSubUrl}}/{{.Repo.Owner.Name}}/{{.Repo.Name}}/issues/{{.Index}}">{{.Name}}</a></h5> <p class="info"> <span class="author"><img class="avatar" src="{{.Poster.AvatarLink}}" alt="" width="20"/> - <a href="{{AppSubUrl}}/user/{{.Poster.Name}}">{{.Poster.Name}}</a></span> + <a href="{{AppSubUrl}}/{{.Poster.Name}}">{{.Poster.Name}}</a></span> <span class="time">{{TimeSince .Created $.Lang}}</span> <span class="comment"><i class="fa fa-comments"></i> {{.NumComments}}</span> </p> diff --git a/templates/user/settings/profile.tmpl b/templates/user/settings/profile.tmpl index 827586fa..febf5237 100644 --- a/templates/user/settings/profile.tmpl +++ b/templates/user/settings/profile.tmpl @@ -47,7 +47,7 @@ <input class="ipt ipt-large ipt-radius {{if .Err_Location}}ipt-error{{end}}" id="location" name="location" type="text" value="{{.SignedUser.Location}}" /> </div> <div class="field"> - <label for="gravatar-email">Gravatar {{.i18n.Tr "email"}}</label> + <label class="req" for="gravatar-email">Gravatar {{.i18n.Tr "email"}}</label> <input class="ipt ipt-large ipt-radius {{if .Err_Avatar}}ipt-error{{end}}" id="gravatar-email" name="avatar" type="text" value="{{.SignedUser.AvatarEmail}}" /> </div> <div class="field"> |