Add weibo oauth
This commit is contained in:
		
							parent
							
								
									4b9b8024ba
								
							
						
					
					
						commit
						d2b53dd43b
					
				
					 20 changed files with 198 additions and 21 deletions
				
			
		|  | @ -5,7 +5,7 @@ Gogs(Go Git Service) is a Self Hosted Git Service in the Go Programming Language | |||
| 
 | ||||
|  | ||||
| 
 | ||||
| ##### 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 | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ Gogs(Go Git Service) 是一个由 Go 语言编写的自助 Git 托管服务。 | |||
| 
 | ||||
|  | ||||
| 
 | ||||
| ##### 当前版本:0.2.8 Alpha | ||||
| ##### 当前版本:0.2.9 Alpha | ||||
| 
 | ||||
| ## 开发目的 | ||||
| 
 | ||||
|  | @ -31,6 +31,7 @@ Gogs 完全使用 Go 语言来实现对 Git 数据的操作,实现 **零** 依 | |||
| - 邮件服务(注册、Issue) | ||||
| - 管理员面板 | ||||
| - 支持 MySQL、PostgreSQL 以及 SQLite3 | ||||
| - 社交帐号登录(GitHub、Google、QQ、微博) | ||||
| 
 | ||||
| ## 安装部署 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
							
								
								
									
										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.
 | ||||
| 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 | ||||
|  |  | |||
|  | @ -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 | ||||
| 	} | ||||
|  |  | |||
|  | @ -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 | ||||
| } | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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 | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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   = `<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>` | ||||
| 	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 { | ||||
|  | @ -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 "" | ||||
| } | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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 | ||||
| } | ||||
|  |  | |||
|  | @ -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 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -88,12 +88,34 @@ | |||
|                 <dl class="dl-horizontal admin-dl-horizontal"> | ||||
|                     <dt>Enabled</dt> | ||||
|                     <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> | ||||
|                     <dt>Host</dt> | ||||
|                     <dd>{{.Mailer.Host}}</dd> | ||||
|                     <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> | ||||
|             </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> | ||||
|                     </a>{{end}}</li> | ||||
|                     {{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}} | ||||
|                     <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}} | ||||
|  |  | |||
|  | @ -4,8 +4,8 @@ | |||
|     {{template "user/setting_nav" .}} | ||||
|     <div id="user-setting-container" class="col-md-9"> | ||||
|         <div id="ssh-keys"> | ||||
|             <h4>SSH Keys</h4>{{if .AddSSHKeySuccess}} | ||||
|             <p class="alert alert-success">New SSH Key has been added !</p>{{else if .HasError}}<p class="alert alert-danger">{{.ErrorMsg}}</p>{{end}} | ||||
|             <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}} | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ | |||
|     <h4>Account Setting</h4> | ||||
|     <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 .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 .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> | ||||
|  |  | |||
|  | @ -61,8 +61,9 @@ | |||
|             </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.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.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.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>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> | ||||
|         {{end}}{{end}} | ||||
|     </form> | ||||
|  |  | |||
							
								
								
									
										17
									
								
								templates/user/social.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								templates/user/social.tmpl
									
									
									
									
									
										Normal file
									
								
							|  | @ -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" .}} | ||||
							
								
								
									
										3
									
								
								web.go
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								web.go
									
									
									
									
									
								
							|  | @ -63,7 +63,7 @@ func runWeb(*cli.Context) { | |||
| 		SignInRequire: base.Service.RequireSignInView, | ||||
| 		DisableCsrf:   true, | ||||
| 	}) | ||||
| 
 | ||||
| 	 | ||||
| 	reqSignOut := middleware.Toggle(&middleware.ToggleOptions{SignOutRequire: true}) | ||||
| 
 | ||||
| 	bindIgnErr := middleware.BindIgnErr | ||||
|  | @ -108,6 +108,7 @@ func runWeb(*cli.Context) { | |||
| 		r.Post("/forget_password", user.ForgotPasswdPost) | ||||
| 	}) | ||||
| 	m.Group("/user/setting", func(r martini.Router) { | ||||
| 		r.Get("/social", user.SettingSocial) | ||||
| 		r.Get("/password", user.SettingPassword) | ||||
| 		r.Post("/password", bindIgnErr(auth.UpdatePasswdForm{}), user.SettingPasswordPost) | ||||
| 		r.Any("/ssh", bindIgnErr(auth.AddSSHKeyForm{}), user.SettingSSHKeys) | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue