Add weibo oauth
This commit is contained in:
Родитель
4b9b8024ba
Коммит
d2b53dd43b
|
@ -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)
|
![Demo](http://gowalker.org/public/gogs_demo.gif)
|
||||||
|
|
||||||
##### Current version: 0.2.8 Alpha
|
##### Current version: 0.2.9 Alpha
|
||||||
|
|
||||||
### NOTICES
|
### NOTICES
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ More importantly, Gogs only needs one binary to setup your own project hosting o
|
||||||
- Mail service(register, issue).
|
- Mail service(register, issue).
|
||||||
- Administration panel.
|
- Administration panel.
|
||||||
- Supports MySQL, PostgreSQL and SQLite3.
|
- Supports MySQL, PostgreSQL and SQLite3.
|
||||||
|
- Social account login(GitHub, Google, QQ, Weibo)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ Gogs(Go Git Service) 是一个由 Go 语言编写的自助 Git 托管服务。
|
||||||
|
|
||||||
![Demo](http://gowalker.org/public/gogs_demo.gif)
|
![Demo](http://gowalker.org/public/gogs_demo.gif)
|
||||||
|
|
||||||
##### 当前版本:0.2.8 Alpha
|
##### 当前版本:0.2.9 Alpha
|
||||||
|
|
||||||
## 开发目的
|
## 开发目的
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ Gogs 完全使用 Go 语言来实现对 Git 数据的操作,实现 **零** 依
|
||||||
- 邮件服务(注册、Issue)
|
- 邮件服务(注册、Issue)
|
||||||
- 管理员面板
|
- 管理员面板
|
||||||
- 支持 MySQL、PostgreSQL 以及 SQLite3
|
- 支持 MySQL、PostgreSQL 以及 SQLite3
|
||||||
|
- 社交帐号登录(GitHub、Google、QQ、微博)
|
||||||
|
|
||||||
## 安装部署
|
## 安装部署
|
||||||
|
|
||||||
|
|
|
@ -109,6 +109,14 @@ SCOPES = all
|
||||||
AUTH_URL = https://api.twitter.com/oauth/authorize
|
AUTH_URL = https://api.twitter.com/oauth/authorize
|
||||||
TOKEN_URL = https://api.twitter.com/oauth/access_token
|
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]
|
[cache]
|
||||||
; Either "memory", "redis", or "memcache", default is "memory"
|
; Either "memory", "redis", or "memcache", default is "memory"
|
||||||
ADAPTER = memory
|
ADAPTER = memory
|
||||||
|
|
2
gogs.go
2
gogs.go
|
@ -19,7 +19,7 @@ import (
|
||||||
// Test that go1.2 tag above is included in builds. main.go refers to this definition.
|
// Test that go1.2 tag above is included in builds. main.go refers to this definition.
|
||||||
const go12tag = true
|
const go12tag = true
|
||||||
|
|
||||||
const APP_VER = "0.2.8.0413 Alpha"
|
const APP_VER = "0.2.9.0413 Alpha"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
base.AppVer = APP_VER
|
base.AppVer = APP_VER
|
||||||
|
|
|
@ -8,6 +8,8 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
// "github.com/gogits/git"
|
||||||
|
|
||||||
"github.com/gogits/gogs/modules/base"
|
"github.com/gogits/gogs/modules/base"
|
||||||
"github.com/gogits/gogs/modules/log"
|
"github.com/gogits/gogs/modules/log"
|
||||||
)
|
)
|
||||||
|
@ -22,6 +24,7 @@ const (
|
||||||
OP_CREATE_ISSUE
|
OP_CREATE_ISSUE
|
||||||
OP_PULL_REQUEST
|
OP_PULL_REQUEST
|
||||||
OP_TRANSFER_REPO
|
OP_TRANSFER_REPO
|
||||||
|
OP_PUSH_TAG
|
||||||
)
|
)
|
||||||
|
|
||||||
// Action represents user operation type and other information to repository.,
|
// 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.
|
// CommitRepoAction adds new action for committing repository.
|
||||||
func CommitRepoAction(userId int64, userName, actEmail string,
|
func CommitRepoAction(userId int64, userName, actEmail string,
|
||||||
repoId int64, repoName string, refName string, commit *base.PushCommits) error {
|
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)
|
bs, err := json.Marshal(commit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -76,7 +86,7 @@ func CommitRepoAction(userId int64, userName, actEmail string,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = NotifyWatchers(&Action{ActUserId: userId, ActUserName: userName, ActEmail: actEmail,
|
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)
|
log.Error("action.CommitRepoAction(notify watchers): %d/%s", userId, repoName)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,3 +68,9 @@ func GetOauth2ById(id int64) (oa *Oauth2, err error) {
|
||||||
}
|
}
|
||||||
return oa, nil
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -75,9 +75,9 @@ type Repository struct {
|
||||||
NumStars int
|
NumStars int
|
||||||
NumForks int
|
NumForks int
|
||||||
NumIssues int
|
NumIssues int
|
||||||
NumReleases int `xorm:"NOT NULL"`
|
|
||||||
NumClosedIssues int
|
NumClosedIssues int
|
||||||
NumOpenIssues int `xorm:"-"`
|
NumOpenIssues int `xorm:"-"`
|
||||||
|
NumTags int `xorm:"-"`
|
||||||
IsPrivate bool
|
IsPrivate bool
|
||||||
IsMirror bool
|
IsMirror bool
|
||||||
IsBare bool
|
IsBare bool
|
||||||
|
|
|
@ -38,7 +38,7 @@ type OauthInfo struct {
|
||||||
// Oauther represents oauth service.
|
// Oauther represents oauth service.
|
||||||
type Oauther struct {
|
type Oauther struct {
|
||||||
GitHub, Google, Tencent bool
|
GitHub, Google, Tencent bool
|
||||||
Twitter bool
|
Twitter, Weibo bool
|
||||||
OauthInfos map[string]*OauthInfo
|
OauthInfos map[string]*OauthInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,7 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{
|
||||||
"DiffTypeToStr": DiffTypeToStr,
|
"DiffTypeToStr": DiffTypeToStr,
|
||||||
"DiffLineTypeToStr": DiffLineTypeToStr,
|
"DiffLineTypeToStr": DiffLineTypeToStr,
|
||||||
"ShortSha": ShortSha,
|
"ShortSha": ShortSha,
|
||||||
|
"Oauth2Icon": Oauth2Icon,
|
||||||
}
|
}
|
||||||
|
|
||||||
type Actioner interface {
|
type Actioner interface {
|
||||||
|
@ -109,7 +110,7 @@ func ActionIcon(opType int) string {
|
||||||
switch opType {
|
switch opType {
|
||||||
case 1: // Create repository.
|
case 1: // Create repository.
|
||||||
return "plus-circle"
|
return "plus-circle"
|
||||||
case 5: // Commit repository.
|
case 5, 9: // Commit repository.
|
||||||
return "arrow-circle-o-right"
|
return "arrow-circle-o-right"
|
||||||
case 6: // Create issue.
|
case 6: // Create issue.
|
||||||
return "exclamation-circle"
|
return "exclamation-circle"
|
||||||
|
@ -127,6 +128,7 @@ const (
|
||||||
TPL_CREATE_ISSUE = `<a href="/user/%s">%s</a> opened issue <a href="/%s/issues/%s">%s#%s</a>
|
TPL_CREATE_ISSUE = `<a href="/user/%s">%s</a> opened issue <a href="/%s/issues/%s">%s#%s</a>
|
||||||
<div><img src="%s?s=16" alt="user-avatar"/> %s</div>`
|
<div><img src="%s?s=16" alt="user-avatar"/> %s</div>`
|
||||||
TPL_TRANSFER_REPO = `<a href="/user/%s">%s</a> transfered repository <code>%s</code> to <a href="/%s">%s</a>`
|
TPL_TRANSFER_REPO = `<a href="/user/%s">%s</a> transfered repository <code>%s</code> to <a href="/%s">%s</a>`
|
||||||
|
TPL_PUSH_TAG = `<a href="/user/%s">%s</a> pushed tag <a href="/%s/src/%s">%s</a> at <a href="/%s">%s</a>`
|
||||||
)
|
)
|
||||||
|
|
||||||
type PushCommit struct {
|
type PushCommit struct {
|
||||||
|
@ -174,6 +176,8 @@ func ActionDesc(act Actioner) string {
|
||||||
case 8: // Transfer repository.
|
case 8: // Transfer repository.
|
||||||
newRepoLink := content + "/" + repoName
|
newRepoLink := content + "/" + repoName
|
||||||
return fmt.Sprintf(TPL_TRANSFER_REPO, actUserName, actUserName, repoLink, newRepoLink, newRepoLink)
|
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:
|
default:
|
||||||
return "invalid type"
|
return "invalid type"
|
||||||
}
|
}
|
||||||
|
@ -197,3 +201,19 @@ func DiffLineTypeToStr(diffType int) string {
|
||||||
}
|
}
|
||||||
return "same"
|
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 ""
|
||||||
|
}
|
||||||
|
|
|
@ -123,6 +123,13 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler {
|
||||||
ctx.Repo.GitRepo = gitRepo
|
ctx.Repo.GitRepo = gitRepo
|
||||||
ctx.Repo.RepoLink = "/" + user.Name + "/" + repo.Name
|
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["Title"] = user.Name + "/" + repo.Name
|
||||||
ctx.Data["Repository"] = repo
|
ctx.Data["Repository"] = repo
|
||||||
ctx.Data["Owner"] = user
|
ctx.Data["Owner"] = user
|
||||||
|
|
|
@ -48,7 +48,7 @@ func NewOauthService() {
|
||||||
base.OauthService.OauthInfos = make(map[string]*base.OauthInfo)
|
base.OauthService.OauthInfos = make(map[string]*base.OauthInfo)
|
||||||
|
|
||||||
socialConfigs := make(map[string]*oauth.Config)
|
socialConfigs := make(map[string]*oauth.Config)
|
||||||
allOauthes := []string{"github", "google", "qq", "twitter"}
|
allOauthes := []string{"github", "google", "qq", "twitter", "weibo"}
|
||||||
// Load all OAuth config data.
|
// Load all OAuth config data.
|
||||||
for _, name := range allOauthes {
|
for _, name := range allOauthes {
|
||||||
base.OauthService.OauthInfos[name] = &base.OauthInfo{
|
base.OauthService.OauthInfos[name] = &base.OauthInfo{
|
||||||
|
@ -98,6 +98,13 @@ func NewOauthService() {
|
||||||
enabledOauths = append(enabledOauths, "Twitter")
|
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)
|
log.Info("Oauth Service Enabled %s", enabledOauths)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,3 +338,56 @@ func (s *SocialTwitter) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo
|
||||||
// }, nil
|
// }, nil
|
||||||
return nil, 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
|
||||||
|
}
|
||||||
|
|
|
@ -153,6 +153,12 @@ func Config(ctx *middleware.Context) {
|
||||||
ctx.Data["Mailer"] = base.MailService
|
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["CacheAdapter"] = base.CacheAdapter
|
||||||
ctx.Data["CacheConfig"] = base.CacheConfig
|
ctx.Data["CacheConfig"] = base.CacheConfig
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,20 @@ func SettingPost(ctx *middleware.Context, form auth.UpdateProfileForm) {
|
||||||
ctx.Redirect("/user/setting")
|
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) {
|
func SettingPassword(ctx *middleware.Context) {
|
||||||
ctx.Data["Title"] = "Password"
|
ctx.Data["Title"] = "Password"
|
||||||
ctx.Data["PageIsUserSetting"] = true
|
ctx.Data["PageIsUserSetting"] = true
|
||||||
|
@ -147,7 +161,7 @@ func SettingSSHKeys(ctx *middleware.Context, form auth.AddSSHKeyForm) {
|
||||||
|
|
||||||
// Add new SSH key.
|
// Add new SSH key.
|
||||||
if ctx.Req.Method == "POST" {
|
if ctx.Req.Method == "POST" {
|
||||||
if hasErr, ok := ctx.Data["HasError"]; ok && hasErr.(bool) {
|
if ctx.HasError() {
|
||||||
ctx.HTML(200, "user/publickey")
|
ctx.HTML(200, "user/publickey")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -162,11 +176,13 @@ func SettingSSHKeys(ctx *middleware.Context, form auth.AddSSHKeyForm) {
|
||||||
ctx.RenderWithErr("Public key name has been used", "user/publickey", &form)
|
ctx.RenderWithErr("Public key name has been used", "user/publickey", &form)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Handle(200, "ssh.AddPublicKey", err)
|
ctx.Handle(500, "ssh.AddPublicKey", err)
|
||||||
log.Trace("%s User SSH key added: %s", ctx.Req.RequestURI, ctx.User.LowerName)
|
|
||||||
return
|
return
|
||||||
} else {
|
} 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,12 +88,34 @@
|
||||||
<dl class="dl-horizontal admin-dl-horizontal">
|
<dl class="dl-horizontal admin-dl-horizontal">
|
||||||
<dt>Enabled</dt>
|
<dt>Enabled</dt>
|
||||||
<dd><i class="fa fa{{if .MailerEnabled}}-check{{end}}-square-o"></i></dd>
|
<dd><i class="fa fa{{if .MailerEnabled}}-check{{end}}-square-o"></i></dd>
|
||||||
<dt>Name</dt>
|
{{if .MailerEnabled}}<dt>Name</dt>
|
||||||
<dd>{{.Mailer.Name}}</dd>
|
<dd>{{.Mailer.Name}}</dd>
|
||||||
<dt>Host</dt>
|
<dt>Host</dt>
|
||||||
<dd>{{.Mailer.Host}}</dd>
|
<dd>{{.Mailer.Host}}</dd>
|
||||||
<dt>User</dt>
|
<dt>User</dt>
|
||||||
<dd>{{.Mailer.User}}</dd>
|
<dd>{{.Mailer.User}}</dd>{{end}}
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
OAuth Configuration
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel-body">
|
||||||
|
<dl class="dl-horizontal admin-dl-horizontal">
|
||||||
|
<dt>Enabled</dt>
|
||||||
|
<dd><i class="fa fa{{if .OauthEnabled}}-check{{end}}-square-o"></i></dd>
|
||||||
|
{{if .OauthEnabled}}<dt>GitHub</dt>
|
||||||
|
<dd><i class="fa fa{{if .Oauther.GitHub}}-check{{end}}-square-o"></i></dd>
|
||||||
|
<dt>Google</dt>
|
||||||
|
<dd><i class="fa fa{{if .Oauther.Google}}-check{{end}}-square-o"></i></dd>
|
||||||
|
<dt>Tencent QQ</dt>
|
||||||
|
<dd><i class="fa fa{{if .Oauther.Tencent}}-check{{end}}-square-o"></i></dd>
|
||||||
|
<dt>Weibo</dt>
|
||||||
|
<dd><i class="fa fa{{if .Oauther.Weibo}}-check{{end}}-square-o"></i></dd>
|
||||||
|
<dd>{{.Mailer.User}}</dd>{{end}}
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<li class="tmp">{{if .IsRepoToolbarIssuesList}}<a href="{{.RepoLink}}/issues/new"><button class="btn btn-primary btn-sm">New Issue</button>
|
<li class="tmp">{{if .IsRepoToolbarIssuesList}}<a href="{{.RepoLink}}/issues/new"><button class="btn btn-primary btn-sm">New Issue</button>
|
||||||
</a>{{end}}</li>
|
</a>{{end}}</li>
|
||||||
{{end}}
|
{{end}}
|
||||||
<li class="{{if .IsRepoToolbarReleases}}active{{end}}"><a href="{{.RepoLink}}/releases">{{if .Repository.NumReleases}}<span class="badge">{{.Repository.NumReleases}}</span> {{end}}Releases</a></li>
|
<li class="{{if .IsRepoToolbarReleases}}active{{end}}"><a href="{{.RepoLink}}/releases">{{if .Repository.NumTags}}<span class="badge">{{.Repository.NumTags}}</span> {{end}}Releases</a></li>
|
||||||
{{if .IsRepoToolbarReleases}}
|
{{if .IsRepoToolbarReleases}}
|
||||||
<li class="tmp">{{if not .IsRepoReleaseNew}}<a href="{{.RepoLink}}/releases/new"><button class="btn btn-primary btn-sm">New Release</button></a>{{end}}</li>
|
<li class="tmp">{{if not .IsRepoReleaseNew}}<a href="{{.RepoLink}}/releases/new"><button class="btn btn-primary btn-sm">New Release</button></a>{{end}}</li>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
{{template "user/setting_nav" .}}
|
{{template "user/setting_nav" .}}
|
||||||
<div id="user-setting-container" class="col-md-9">
|
<div id="user-setting-container" class="col-md-9">
|
||||||
<div id="ssh-keys">
|
<div id="ssh-keys">
|
||||||
<h4>SSH Keys</h4>{{if .AddSSHKeySuccess}}
|
<h4>SSH Keys</h4>
|
||||||
<p class="alert alert-success">New SSH Key has been added !</p>{{else if .HasError}}<p class="alert alert-danger">{{.ErrorMsg}}</p>{{end}}
|
{{template "base/alert" .}}
|
||||||
<ul id="ssh-keys-list" class="list-group">
|
<ul id="ssh-keys-list" class="list-group">
|
||||||
<li class="list-group-item"><span class="name">SSH Key's name</span></li>
|
<li class="list-group-item"><span class="name">SSH Key's name</span></li>
|
||||||
{{range .Keys}}
|
{{range .Keys}}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
<h4>Account Setting</h4>
|
<h4>Account Setting</h4>
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item{{if .IsUserPageSetting}} list-group-item-success{{end}}"><a href="/user/setting">Account Profile</a></li>
|
<li class="list-group-item{{if .IsUserPageSetting}} list-group-item-success{{end}}"><a href="/user/setting">Account Profile</a></li>
|
||||||
|
<li class="list-group-item{{if .IsUserPageSettingSocial}} list-group-item-success{{end}}"><a href="/user/setting/social">Social Account</a></li>
|
||||||
<li class="list-group-item{{if .IsUserPageSettingPasswd}} list-group-item-success{{end}}"><a href="/user/setting/password">Password</a></li>
|
<li class="list-group-item{{if .IsUserPageSettingPasswd}} list-group-item-success{{end}}"><a href="/user/setting/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 .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/setting/ssh/">SSH Keys</a></li>
|
<li class="list-group-item{{if .IsUserPageSettingSSH}} list-group-item-success{{end}}"><a href="/user/setting/ssh/">SSH Keys</a></li>
|
||||||
|
|
|
@ -61,8 +61,9 @@
|
||||||
</a>-->
|
</a>-->
|
||||||
{{if .OauthService.GitHub}}<a href="/user/login/github?next=/user/sign_up" class="btn btn-default"><i class="fa fa-github-square fa-2x"></i><span>GitHub</span></a>{{end}}
|
{{if .OauthService.GitHub}}<a href="/user/login/github?next=/user/sign_up" class="btn btn-default"><i class="fa fa-github-square fa-2x"></i><span>GitHub</span></a>{{end}}
|
||||||
{{if .OauthService.Google}}<a href="/user/login/google?next=/user/sign_up" class="btn btn-default"><i class="fa fa-google-plus-square fa-2x"></i><span>Google</span></a>{{end}}
|
{{if .OauthService.Google}}<a href="/user/login/google?next=/user/sign_up" class="btn btn-default"><i class="fa fa-google-plus-square fa-2x"></i><span>Google</span></a>{{end}}
|
||||||
{{if .OauthService.Tencent}}<a href="/user/login/twitter?next=/user/sign_up" class="btn btn-default"><i class="fa fa-twitter-square fa-2x"></i><span>Twitter</span></a>{{end}}
|
{{if .OauthService.Twitter}}<a href="/user/login/twitter?next=/user/sign_up" class="btn btn-default"><i class="fa fa-twitter-square fa-2x"></i><span>Twitter</span></a>{{end}}
|
||||||
{{if .OauthService.Tencent}}<a href="/user/login/qq?next=/user/sign_up" class="btn btn-default"><i class="fa fa-linux fa-2x"></i><span>QQ</span></a>{{end}}
|
{{if .OauthService.Tencent}}<a href="/user/login/qq?next=/user/sign_up" class="btn btn-default"><i class="fa fa-linux fa-2x"></i><span>Tencent QQ</span></a>{{end}}
|
||||||
|
{{if .OauthService.Weibo}}<a href="/user/login/weibo?next=/user/sign_up" class="btn btn-default"><i class="fa fa-weibo fa-2x"></i><span>Weibo</span></a>{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}{{end}}
|
{{end}}{{end}}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
{{template "base/head" .}}
|
||||||
|
{{template "base/navbar" .}}
|
||||||
|
<div id="body" class="container" data-page="user">
|
||||||
|
{{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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{template "base/footer" .}}
|
1
web.go
1
web.go
|
@ -108,6 +108,7 @@ func runWeb(*cli.Context) {
|
||||||
r.Post("/forget_password", user.ForgotPasswdPost)
|
r.Post("/forget_password", user.ForgotPasswdPost)
|
||||||
})
|
})
|
||||||
m.Group("/user/setting", func(r martini.Router) {
|
m.Group("/user/setting", func(r martini.Router) {
|
||||||
|
r.Get("/social", user.SettingSocial)
|
||||||
r.Get("/password", user.SettingPassword)
|
r.Get("/password", user.SettingPassword)
|
||||||
r.Post("/password", bindIgnErr(auth.UpdatePasswdForm{}), user.SettingPasswordPost)
|
r.Post("/password", bindIgnErr(auth.UpdatePasswdForm{}), user.SettingPasswordPost)
|
||||||
r.Any("/ssh", bindIgnErr(auth.AddSSHKeyForm{}), user.SettingSSHKeys)
|
r.Any("/ssh", bindIgnErr(auth.AddSSHKeyForm{}), user.SettingSSHKeys)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче