commit
94c7278194
@ -0,0 +1,13 @@ |
|||||||
|
{ |
||||||
|
"paths": ["."], |
||||||
|
"depth": 2, |
||||||
|
"exclude": [], |
||||||
|
"include": ["\\.go$"], |
||||||
|
"command": [ |
||||||
|
"bash", "-c", "go build && ./gogs web" |
||||||
|
], |
||||||
|
"env": { |
||||||
|
"POWERED_BY": "github.com/shxsun/fswatch" |
||||||
|
}, |
||||||
|
"enable-restart": true |
||||||
|
} |
@ -1,28 +1,26 @@ |
|||||||
[target] |
[target] |
||||||
path=github.com/gogits/gogs |
path = github.com/gogits/gogs |
||||||
|
|
||||||
[deps] |
[deps] |
||||||
github.com/codegangsta/cli= |
github.com/codegangsta/cli = |
||||||
github.com/go-martini/martini= |
github.com/go-martini/martini = |
||||||
github.com/Unknwon/com= |
github.com/Unknwon/com = |
||||||
github.com/Unknwon/cae= |
github.com/Unknwon/cae = |
||||||
github.com/Unknwon/goconfig= |
github.com/Unknwon/goconfig = |
||||||
github.com/dchest/scrypt= |
github.com/nfnt/resize = |
||||||
github.com/nfnt/resize= |
github.com/lunny/xorm = |
||||||
github.com/lunny/xorm= |
github.com/go-sql-driver/mysql = |
||||||
github.com/go-sql-driver/mysql= |
github.com/lib/pq = |
||||||
github.com/lib/pq= |
github.com/qiniu/log = |
||||||
github.com/gogits/logs= |
code.google.com/p/goauth2 = |
||||||
github.com/gogits/binding= |
github.com/gogits/logs = |
||||||
github.com/gogits/git= |
github.com/gogits/binding = |
||||||
github.com/gogits/gfm= |
github.com/gogits/git = |
||||||
github.com/gogits/cache= |
github.com/gogits/gfm = |
||||||
github.com/gogits/session= |
github.com/gogits/cache = |
||||||
github.com/gogits/webdav= |
github.com/gogits/session = |
||||||
github.com/martini-contrib/oauth2= |
github.com/gogits/webdav = |
||||||
github.com/martini-contrib/sessions= |
|
||||||
code.google.com/p/goauth2= |
|
||||||
|
|
||||||
[res] |
[res] |
||||||
include=templates|public|conf |
include = templates|public|conf |
||||||
|
|
||||||
|
@ -1,49 +1,122 @@ |
|||||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package user |
package user |
||||||
|
|
||||||
import ( |
import ( |
||||||
"encoding/json" |
"encoding/json" |
||||||
|
"strconv" |
||||||
|
|
||||||
"code.google.com/p/goauth2/oauth" |
"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/log" |
||||||
|
"github.com/gogits/gogs/modules/middleware" |
||||||
"github.com/gogits/gogs/modules/oauth2" |
"github.com/gogits/gogs/modules/oauth2" |
||||||
) |
) |
||||||
|
|
||||||
// github && google && ...
|
type SocialConnector interface { |
||||||
func SocialSignIn(tokens oauth2.Tokens) { |
Identity() string |
||||||
transport := &oauth.Transport{} |
Type() int |
||||||
transport.Token = &oauth.Token{ |
Name() string |
||||||
AccessToken: tokens.Access(), |
Email() string |
||||||
RefreshToken: tokens.Refresh(), |
Token() string |
||||||
Expiry: tokens.ExpiryTime(), |
} |
||||||
Extra: tokens.ExtraData(), |
|
||||||
} |
|
||||||
|
|
||||||
// Github API refer: https://developer.github.com/v3/users/
|
type SocialGithub struct { |
||||||
// FIXME: need to judge url
|
data struct { |
||||||
type GithubUser struct { |
|
||||||
Id int `json:"id"` |
Id int `json:"id"` |
||||||
Name string `json:"login"` |
Name string `json:"login"` |
||||||
Email string `json:"email"` |
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" |
scope := "https://api.github.com/user" |
||||||
|
transport := &oauth.Transport{ |
||||||
|
Token: s.WebToken, |
||||||
|
} |
||||||
|
log.Debug("update github info") |
||||||
r, err := transport.Client().Get(scope) |
r, err := transport.Client().Get(scope) |
||||||
if err != nil { |
if err != nil { |
||||||
log.Error("connect with github error: %s", err) |
return err |
||||||
// FIXME: handle error page
|
|
||||||
return |
|
||||||
} |
} |
||||||
defer r.Body.Close() |
defer r.Body.Close() |
||||||
|
return json.NewDecoder(r.Body).Decode(&s.data) |
||||||
|
} |
||||||
|
|
||||||
user := &GithubUser{} |
// github && google && ...
|
||||||
err = json.NewDecoder(r.Body).Decode(user) |
func SocialSignIn(ctx *middleware.Context, tokens oauth2.Tokens) { |
||||||
if err != nil { |
gh := &SocialGithub{ |
||||||
log.Error("Get: %s", err) |
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
|
// 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("/") |
||||||
} |
} |
||||||
|
@ -1,6 +1,15 @@ |
|||||||
#!/bin/bash - |
#!/bin/sh - |
||||||
|
# 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. |
||||||
# |
# |
||||||
# start gogs web |
# start gogs web |
||||||
# |
# |
||||||
cd "$(dirname $0)" |
IFS=' |
||||||
./gogs web |
' |
||||||
|
PATH=/bin:/usr/bin:/usr/local/bin |
||||||
|
HOME=${HOME:?"need \$HOME variable"} |
||||||
|
USER=$(whoami) |
||||||
|
export USER HOME PATH |
||||||
|
|
||||||
|
cd "$(dirname $0)" && exec ./gogs web |
||||||
|
@ -0,0 +1,33 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
||||||
|
<title>{{.User.Name}}, please reset your password</title> |
||||||
|
</head> |
||||||
|
<body style="background:#eee;"> |
||||||
|
<div style="color:#333; font:12px/1.5 Tahoma,Arial,sans-serif;; text-shadow:1px 1px #fff; padding:0; margin:0;"> |
||||||
|
<div style="width:600px;margin:0 auto; padding:40px 0 20px;"> |
||||||
|
<div style="border:1px solid #d9d9d9;border-radius:3px; background:#fff; box-shadow: 0px 2px 5px rgba(0, 0, 0,.05); -webkit-box-shadow: 0px 2px 5px rgba(0, 0, 0,.05);"> |
||||||
|
<div style="padding: 20px 15px;"> |
||||||
|
<h1 style="font-size:20px; padding:10px 0 20px; margin:0; border-bottom:1px solid #ddd;"><img src="{{.AppUrl}}/{{.AppLogo}}" style="height: 32px; margin-bottom: -10px;"> <a style="color:#333;text-decoration:none;" target="_blank" href="{{.AppUrl}}">{{.AppName}}</a></h1> |
||||||
|
<div style="padding:40px 15px;"> |
||||||
|
<div style="font-size:16px; padding-bottom:30px; font-weight:bold;"> |
||||||
|
Hi <span style="color: #00BFFF;">{{.User.Name}}</span>, |
||||||
|
</div> |
||||||
|
<div style="font-size:14px; padding:0 15px;"> |
||||||
|
<p style="margin:0;padding:0 0 9px 0;">Please click following link to reset your password within <b>{{.ActiveCodeLives}} hours</b>.</p> |
||||||
|
<p style="margin:0;padding:0 0 9px 0;"> |
||||||
|
<a href="{{.AppUrl}}user/reset_password?code={{.Code}}">{{.AppUrl}}user/reset_password?code={{.Code}}</a> |
||||||
|
</p> |
||||||
|
<p style="margin:0;padding:0 0 9px 0;">Copy and paste it to your browser if the link is not working.</p> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div style="color:#aaa;padding:10px;text-align:center;"> |
||||||
|
© 2014 <a style="color:#888;text-decoration:none;" target="_blank" href="http://gogits.org">Gogs: Go Git Service</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</body> |
||||||
|
</html> |
@ -1,25 +0,0 @@ |
|||||||
{{template "mail/base.html" .}} |
|
||||||
{{define "title"}} |
|
||||||
{{if eq .Lang "zh-CN"}} |
|
||||||
{{.User.NickName}},重置账户密码 |
|
||||||
{{end}} |
|
||||||
{{if eq .Lang "en-US"}} |
|
||||||
{{.User.NickName}}, reset your password |
|
||||||
{{end}} |
|
||||||
{{end}} |
|
||||||
{{define "body"}} |
|
||||||
{{if eq .Lang "zh-CN"}} |
|
||||||
<p style="margin:0;padding:0 0 9px 0;">点击链接重置密码,{{.ResetPwdCodeLives}} 分钟内有效</p> |
|
||||||
<p style="margin:0;padding:0 0 9px 0;"> |
|
||||||
<a href="{{.AppUrl}}reset/{{.Code}}">{{.AppUrl}}reset/{{.Code}}</a> |
|
||||||
</p> |
|
||||||
<p style="margin:0;padding:0 0 9px 0;">如果链接点击无反应,请复制到浏览器打开。</p> |
|
||||||
{{end}} |
|
||||||
{{if eq .Lang "en-US"}} |
|
||||||
<p style="margin:0;padding:0 0 9px 0;">Please click following link to reset your password in {{.ResetPwdCodeLives}} hours</p> |
|
||||||
<p style="margin:0;padding:0 0 9px 0;"> |
|
||||||
<a href="{{.AppUrl}}reset/{{.Code}}">{{.AppUrl}}reset/{{.Code}}</a> |
|
||||||
</p> |
|
||||||
<p style="margin:0;padding:0 0 9px 0;">Copy and paste it to your browser if it's not working.</p> |
|
||||||
{{end}} |
|
||||||
{{end}} |
|
@ -0,0 +1,66 @@ |
|||||||
|
{{template "base/head" .}} |
||||||
|
{{template "base/navbar" .}} |
||||||
|
{{template "repo/nav" .}} |
||||||
|
{{template "repo/toolbar" .}} |
||||||
|
<div id="body" class="container"> |
||||||
|
<div id="release"> |
||||||
|
<h4 id="release-head">New Release</h4> |
||||||
|
<form id="release-new-form" action="" class="form form-inline"> |
||||||
|
<div class="form-group"> |
||||||
|
<input id="release-tag-name" type="text" class="form-control" placeholder="tag name"/> |
||||||
|
<span class="target-at">@</span> |
||||||
|
<div class="btn-group" id="release-new-target-select"> |
||||||
|
<button type="button" class="btn btn-default"><i class="fa fa-code-fork fa-lg fa-m"></i> |
||||||
|
<span class="target-text">Target : </span> |
||||||
|
<strong id="release-new-target-name"> master</strong> |
||||||
|
</button> |
||||||
|
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> |
||||||
|
<span class="caret"></span> |
||||||
|
</button> |
||||||
|
<div class="dropdown-menu clone-group-btn" id="release-new-target-branch-list"> |
||||||
|
<ul class="list-group"> |
||||||
|
<li class="list-group-item"> |
||||||
|
<a href="#" rel="master"><i class="fa fa-code-fork"></i>master</a> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<p class="help-block">Choose an existing tag without release notes</p> |
||||||
|
</div> |
||||||
|
<div class="form-group" style="display: block"> |
||||||
|
<input class="form-control input-lg" id="release-new-title" name="title" type="text" placeholder="release title"/> |
||||||
|
</div> |
||||||
|
<div class="form-group col-md-8" style="display: block" id="release-new-content-div"> |
||||||
|
<div class="md-help pull-right"> |
||||||
|
Content with <a href="https://help.github.com/articles/markdown-basics">Markdown</a> |
||||||
|
</div> |
||||||
|
<ul class="nav nav-tabs" data-init="tabs"> |
||||||
|
<li class="release-write active"><a href="#release-textarea" data-toggle="tab">Write</a></li> |
||||||
|
<li class="release-preview"><a href="#release-preview" data-toggle="tab" data-ajax="/api/v1/markdown?repo=repo_id&release=new" data-ajax-name="release-preview" data-ajax-method="post" data-preview="#release-preview">Preview</a></li> |
||||||
|
</ul> |
||||||
|
<div class="tab-content"> |
||||||
|
<div class="tab-pane active" id="release-textarea"> |
||||||
|
<div class="form-group"> |
||||||
|
<textarea class="form-control" name="content" id="release-new-content" rows="10" placeholder="Write some content" data-ajax-rel="release-preview" data-ajax-val="val" data-ajax-field="content"></textarea> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="tab-pane release-preview-content" id="release-preview">loading...</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="text-right form-group col-md-8" style="display: block"> |
||||||
|
<hr/> |
||||||
|
<label for="release-new-pre-release"> |
||||||
|
<input id="release-new-pre-release" type="checkbox" name="is-pre-release" value="true"/> |
||||||
|
<strong>This is a pre-release</strong> |
||||||
|
</label> |
||||||
|
<p class="help-block">We’ll point out that this release is identified as non-production ready.</p> |
||||||
|
</div> |
||||||
|
<div class="text-right form-group col-md-8" style="display: block"> |
||||||
|
<input type="hidden" value="id" name="repo-id"> |
||||||
|
<button class="btn-success btn">Publish release</button> |
||||||
|
<input class="btn btn-default" type="submit" name="is-draft" value="Save Draft"/> |
||||||
|
</div> |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{{template "base/footer" .}} |
@ -0,0 +1,30 @@ |
|||||||
|
{{template "base/head" .}} |
||||||
|
{{template "base/navbar" .}} |
||||||
|
<div id="body" class="container"> |
||||||
|
<form action="/user/forget_password" method="post" class="form-horizontal card" id="login-card"> |
||||||
|
{{.CsrfTokenHtml}} |
||||||
|
<h3>Reset Your Password</h3> |
||||||
|
<div class="alert alert-danger form-error{{if .HasError}}{{else}} hidden{{end}}">{{.ErrorMsg}}</div> |
||||||
|
{{if .IsResetSent}} |
||||||
|
<p>A confirmation e-mail has been sent to <b>{{.Email}}</b>, please check your inbox within {{.Hours}} hours.</p> |
||||||
|
<hr/> |
||||||
|
<a href="http://{{Mail2Domain .Email}}" class="btn btn-lg btn-success">Sign in to your e-mail</a> |
||||||
|
{{else if .IsResetRequest}} |
||||||
|
<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> |
||||||
|
<label class="col-md-3 control-label">Email: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<input name="email" class="form-control" placeholder="Type your e-mail address" required="required"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<hr/> |
||||||
|
<div class="form-group"> |
||||||
|
<div class="col-md-offset-4 col-md-6"> |
||||||
|
<button type="submit" class="btn btn-lg btn-primary">Click here to send reset confirmation e-mail</button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{{else if .IsResetDisable}} |
||||||
|
<p>Sorry, mail service is not enabled.</p> |
||||||
|
{{end}} |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
{{template "base/footer" .}} |
@ -0,0 +1,26 @@ |
|||||||
|
{{template "base/head" .}} |
||||||
|
{{template "base/navbar" .}} |
||||||
|
<div id="body" class="container"> |
||||||
|
<form action="/user/reset_password?code={{.Code}}" method="post" class="form-horizontal card" id="login-card"> |
||||||
|
{{.CsrfTokenHtml}} |
||||||
|
<h3>Reset Your Pasword</h3> |
||||||
|
<div class="alert alert-danger form-error{{if .HasError}}{{else}} hidden{{end}}">{{.ErrorMsg}}</div> |
||||||
|
{{if .IsResetForm}} |
||||||
|
<div class="form-group"> |
||||||
|
<label class="col-md-4 control-label">Password: </label> |
||||||
|
<div class="col-md-6"> |
||||||
|
<input name="passwd" type="password" class="form-control" placeholder="Type your password" required="required"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<hr/> |
||||||
|
<div class="form-group"> |
||||||
|
<div class="col-md-offset-4 col-md-6"> |
||||||
|
<button type="submit" class="btn btn-lg btn-primary">Click here to reset your password</button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{{else}} |
||||||
|
<p>Sorry, your confirmation code has been exipired or not valid.</p> |
||||||
|
{{end}} |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
{{template "base/footer" .}} |
Loading…
Reference in new issue