"path" | "path" | ||||
"path/filepath" | "path/filepath" | ||||
"strings" | "strings" | ||||
"github.com/codegangsta/cli" | |||||
"time" | |||||
"github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
"github.com/codegangsta/cli" | |||||
"github.com/gogits/gogs/models" | "github.com/gogits/gogs/models" | ||||
"github.com/gogits/gogs/modules/log" | "github.com/gogits/gogs/modules/log" | ||||
if isWrite { | if isWrite { | ||||
tasks, err := models.GetUpdateTasksByUuid(uuid) | tasks, err := models.GetUpdateTasksByUuid(uuid) | ||||
if err != nil { | if err != nil { | ||||
log.GitLogger.Fatal(2, "Fail to get update task: %v", err) | |||||
log.GitLogger.Fatal(2, "GetUpdateTasksByUuid: %v", err) | |||||
} | } | ||||
for _, task := range tasks { | for _, task := range tasks { | ||||
err = models.Update(task.RefName, task.OldCommitId, task.NewCommitId, | err = models.Update(task.RefName, task.OldCommitId, task.NewCommitId, | ||||
user.Name, repoUserName, repoName, user.Id) | user.Name, repoUserName, repoName, user.Id) | ||||
if err != nil { | if err != nil { | ||||
log.GitLogger.Fatal(2, "Fail to update: %v", err) | |||||
log.GitLogger.Error(2, "Fail to update: %v", err) | |||||
} | } | ||||
} | } | ||||
if err = models.DelUpdateTasksByUuid(uuid); err != nil { | if err = models.DelUpdateTasksByUuid(uuid); err != nil { | ||||
log.GitLogger.Fatal(2, "Fail to del update task: %v", err) | |||||
log.GitLogger.Fatal(2, "DelUpdateTasksByUuid: %v", err) | |||||
} | } | ||||
} | } | ||||
// Update key activity. | |||||
key, err := models.GetPublicKeyById(keyId) | |||||
if err != nil { | |||||
log.GitLogger.Fatal(2, "GetPublicKeyById: %v", err) | |||||
} | |||||
key.Updated = time.Now() | |||||
if err = models.UpdatePublicKey(key); err != nil { | |||||
log.GitLogger.Fatal(2, "UpdatePublicKey: %v", err) | |||||
} | |||||
} | } |
m.Group("/settings", func(r *macaron.Router) { | m.Group("/settings", func(r *macaron.Router) { | ||||
r.Route("/collaboration", "GET,POST", repo.SettingsCollaboration) | r.Route("/collaboration", "GET,POST", repo.SettingsCollaboration) | ||||
r.Get("/hooks", repo.Webhooks) | r.Get("/hooks", repo.Webhooks) | ||||
r.Get("/hooks/new", repo.WebHooksAdd) | |||||
r.Post("/hooks/add", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksAddPost) | |||||
r.Get("/hooks/new", repo.WebHooksNew) | |||||
r.Post("/hooks/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost) | |||||
r.Get("/hooks/:id", repo.WebHooksEdit) | r.Get("/hooks/:id", repo.WebHooksEdit) | ||||
r.Post("/hooks/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost) | r.Post("/hooks/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost) | ||||
}) | }) |
Retype = Re-type password | Retype = Re-type password | ||||
SSHTitle = SSH key name | SSHTitle = SSH key name | ||||
HttpsUrl = HTTPS URL | HttpsUrl = HTTPS URL | ||||
PayloadUrl = Payload URL | |||||
require_error = ` cannot be empty.` | require_error = ` cannot be empty.` | ||||
alpha_dash_error = ` must be valid alpha or numeric or dash(-_) characters.` | alpha_dash_error = ` must be valid alpha or numeric or dash(-_) characters.` | ||||
settings.add_webhook = Add Webhook | settings.add_webhook = Add Webhook | ||||
settings.hooks_desc = Webhooks allow external services to be notified when certain events happen on Gogs. When the specified events happen, we'll send a POST request to each of the URLs you provide. Learn more in our <a target="_blank" href="http://gogs.io/docs/features/webhook.html">Webhooks Guide</a>. | settings.hooks_desc = Webhooks allow external services to be notified when certain events happen on Gogs. When the specified events happen, we'll send a POST request to each of the URLs you provide. Learn more in our <a target="_blank" href="http://gogs.io/docs/features/webhook.html">Webhooks Guide</a>. | ||||
settings.remove_hook_success = Webhook has been removed. | settings.remove_hook_success = Webhook has been removed. | ||||
settings.add_webhook_desc = We’ll send a <code>POST</code> request to the URL below with details of any subscribed events. You can also specify which data format you'd like to receive (JSON, <code>x-www-form-urlencoded</code>, <em>etc</em>). More information can be found in <a target="_blank" href="http://gogs.io/docs/features/webhook.html">Webhooks Guide</a>. | |||||
settings.payload_url = Payload URL | |||||
settings.content_type = Content Type | |||||
settings.secret = Secret | |||||
settings.event_desc = Which events would you like to trigger this webhook? | |||||
settings.event_push_only = Just the <code>push</code> event. | |||||
settings.active = Active | |||||
settings.active_helper = We will deliver event details when this hook is triggered. | |||||
settings.add_hook_success = New webhook has been added. | |||||
settings.update_webhook = Update Webhook | |||||
settings.update_hook_success = Webhook has been updated. | |||||
settings.delete_webhook = Delete Webhook | |||||
settings.recent_deliveries = Recent Deliveries | |||||
[org] | [org] | ||||
org_name_holder = Organization Name | org_name_holder = Organization Name |
Retype = 确认密码 | Retype = 确认密码 | ||||
SSHTitle = SSH 密钥名称 | SSHTitle = SSH 密钥名称 | ||||
HttpsUrl = HTTPS URL 地址 | HttpsUrl = HTTPS URL 地址 | ||||
PayloadUrl = 推送地址 | |||||
require_error = 不能为空。 | require_error = 不能为空。 | ||||
alpha_dash_error = 必须为英文字母、阿拉伯数字或横线(-_)。 | alpha_dash_error = 必须为英文字母、阿拉伯数字或横线(-_)。 | ||||
settings.add_webhook = 添加 Web 钩子 | settings.add_webhook = 添加 Web 钩子 | ||||
settings.hooks_desc = Web 钩子允许您设定在 Gogs 上发生指定事件时对指定 URL 发送 POST 通知。查看 <a target="_blank" href="http://gogs.io/docs/features/webhook.html">Webhooks 文档</a> 获取更多信息。 | settings.hooks_desc = Web 钩子允许您设定在 Gogs 上发生指定事件时对指定 URL 发送 POST 通知。查看 <a target="_blank" href="http://gogs.io/docs/features/webhook.html">Webhooks 文档</a> 获取更多信息。 | ||||
settings.remove_hook_success = Web 钩子删除成功! | settings.remove_hook_success = Web 钩子删除成功! | ||||
settings.add_webhook_desc = 我们会通过 <code>POST</code> 请求将订阅事件信息发送至向指定 URL 地址。您可以设置不同的数据接收方式(JSON 或 <code>x-www-form-urlencoded</code>)。 请查阅 <a target="_blank" href="http://gogs.io/docs/features/webhook.html">Webhooks 文档</a> 获取更多信息。 | |||||
settings.payload_url = 推送地址 | |||||
settings.content_type = 数据格式 | |||||
settings.secret = 密钥文本 | |||||
settings.event_desc = 请设置您希望触发 Web 钩子的事件: | |||||
settings.event_push_only = 只推送 <code>push</code> 事件。 | |||||
settings.active = 是否激活 | |||||
settings.active_helper = 当指定事件发生时我们将会触发此 Web 钩子。 | |||||
settings.add_hook_success = Web 钩子添加成功! | |||||
settings.update_webhook = 更新 Web 钩子 | |||||
settings.update_hook_success = Web 钩子更新成功! | |||||
settings.delete_webhook = 删除 Web 钩子 | |||||
settings.recent_deliveries = 最近推送记录 | |||||
[org] | [org] | ||||
org_name_holder = 组织名称 | org_name_holder = 组织名称 |
return nil | return nil | ||||
} | } | ||||
// GetPublicKeyById returns public key by given ID. | |||||
func GetPublicKeyById(keyId int64) (*PublicKey, error) { | |||||
key := new(PublicKey) | |||||
has, err := x.Id(keyId).Get(key) | |||||
if err != nil { | |||||
return nil, err | |||||
} else if !has { | |||||
return nil, ErrKeyNotExist | |||||
} | |||||
return key, nil | |||||
} | |||||
// ListPublicKey returns a list of all public keys that user has. | // ListPublicKey returns a list of all public keys that user has. | ||||
func ListPublicKey(uid int64) ([]*PublicKey, error) { | func ListPublicKey(uid int64) ([]*PublicKey, error) { | ||||
keys := make([]*PublicKey, 0, 5) | keys := make([]*PublicKey, 0, 5) | ||||
return nil | return nil | ||||
} | } | ||||
// UpdatePublicKey updates given public key. | |||||
func UpdatePublicKey(key *PublicKey) error { | |||||
_, err := x.Id(key.Id).AllCols().Update(key) | |||||
return err | |||||
} | |||||
// DeletePublicKey deletes SSH key information both in database and authorized_keys file. | // DeletePublicKey deletes SSH key information both in database and authorized_keys file. | ||||
func DeletePublicKey(key *PublicKey) error { | func DeletePublicKey(key *PublicKey) error { | ||||
has, err := x.Get(key) | has, err := x.Get(key) |
"github.com/gogits/gogs/modules/httplib" | "github.com/gogits/gogs/modules/httplib" | ||||
"github.com/gogits/gogs/modules/log" | "github.com/gogits/gogs/modules/log" | ||||
"github.com/gogits/gogs/modules/setting" | "github.com/gogits/gogs/modules/setting" | ||||
"github.com/gogits/gogs/modules/uuid" | |||||
) | ) | ||||
var ( | var ( | ||||
SERVICE | SERVICE | ||||
) | ) | ||||
type HookEventType string | |||||
const ( | |||||
PUSH HookEventType = "push" | |||||
) | |||||
type PayloadAuthor struct { | type PayloadAuthor struct { | ||||
Name string `json:"name"` | Name string `json:"name"` | ||||
Email string `json:"email"` | Email string `json:"email"` | ||||
// HookTask represents a hook task. | // HookTask represents a hook task. | ||||
type HookTask struct { | type HookTask struct { | ||||
Id int64 | Id int64 | ||||
Uuid string | |||||
Type HookTaskType | Type HookTaskType | ||||
Url string | Url string | ||||
*Payload `xorm:"-"` | *Payload `xorm:"-"` | ||||
PayloadContent string `xorm:"TEXT"` | PayloadContent string `xorm:"TEXT"` | ||||
ContentType HookContentType | ContentType HookContentType | ||||
EventType HookEventType | |||||
IsSsl bool | IsSsl bool | ||||
IsDeliveried bool | IsDeliveried bool | ||||
IsSucceed bool | |||||
} | } | ||||
// CreateHookTask creates a new hook task, | // CreateHookTask creates a new hook task, | ||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
} | } | ||||
t.Uuid = uuid.NewV4().String() | |||||
t.PayloadContent = string(data) | t.PayloadContent = string(data) | ||||
_, err = x.Insert(t) | _, err = x.Insert(t) | ||||
return err | return err | ||||
x.Where("is_deliveried=?", false).Iterate(new(HookTask), | x.Where("is_deliveried=?", false).Iterate(new(HookTask), | ||||
func(idx int, bean interface{}) error { | func(idx int, bean interface{}) error { | ||||
t := bean.(*HookTask) | t := bean.(*HookTask) | ||||
// Only support JSON now. | |||||
if _, err := httplib.Post(t.Url).SetTimeout(timeout, timeout). | |||||
Body([]byte(t.PayloadContent)).Response(); err != nil { | |||||
log.Error(4, "webhook.DeliverHooks(Delivery): %v", err) | |||||
return nil | |||||
req := httplib.Post(t.Url).SetTimeout(timeout, timeout). | |||||
Header("X-Gogs-Delivery", t.Uuid). | |||||
Header("X-Gogs-Event", string(t.EventType)) | |||||
switch t.ContentType { | |||||
case JSON: | |||||
req = req.Header("Content-Type", "application/json").Body(t.PayloadContent) | |||||
case FORM: | |||||
req.Param("payload", t.PayloadContent) | |||||
} | } | ||||
t.IsDeliveried = true | t.IsDeliveried = true | ||||
// TODO: record response. | |||||
if _, err := req.Response(); err != nil { | |||||
log.Error(4, "Delivery: %v", err) | |||||
} else { | |||||
t.IsSucceed = true | |||||
} | |||||
if err := UpdateHookTask(t); err != nil { | if err := UpdateHookTask(t); err != nil { | ||||
log.Error(4, "webhook.DeliverHooks(UpdateHookTask): %v", err) | |||||
log.Error(4, "UpdateHookTask: %v", err) | |||||
return nil | return nil | ||||
} | } | ||||
log.Trace("Hook delivered: %s", t.PayloadContent) | |||||
log.Trace("Hook delivered(%s): %s", t.Uuid, t.PayloadContent) | |||||
return nil | return nil | ||||
}) | }) | ||||
} | } |
// \/ \/ \/ \/ \/ \/ | // \/ \/ \/ \/ \/ \/ | ||||
type NewWebhookForm struct { | type NewWebhookForm struct { | ||||
Url string `form:"url" binding:"Required;Url"` | |||||
PayloadUrl string `form:"payload_url" binding:"Required;Url"` | |||||
ContentType string `form:"content_type" binding:"Required"` | ContentType string `form:"content_type" binding:"Required"` | ||||
Secret string `form:"secret"` | Secret string `form:"secret"` | ||||
PushOnly bool `form:"push_only"` | PushOnly bool `form:"push_only"` |
data, bytErr, err := com.ExecCmdDirBytes(repo.Path, "git", "cat-file", "-p", id.String()) | data, bytErr, err := com.ExecCmdDirBytes(repo.Path, "git", "cat-file", "-p", id.String()) | ||||
if err != nil { | if err != nil { | ||||
return nil, errors.New(string(bytErr)) | |||||
return nil, errors.New(err.Error() + ": " + string(bytErr)) | |||||
} | } | ||||
commit, err := parseCommitData(data) | commit, err := parseCommitData(data) |
# httplib | |||||
httplib is an libs help you to curl remote url. | |||||
# How to use? | |||||
## GET | |||||
you can use Get to crawl data. | |||||
import "httplib" | |||||
str, err := httplib.Get("http://beego.me/").String() | |||||
if err != nil { | |||||
t.Fatal(err) | |||||
} | |||||
fmt.Println(str) | |||||
## POST | |||||
POST data to remote url | |||||
b:=httplib.Post("http://beego.me/") | |||||
b.Param("username","astaxie") | |||||
b.Param("password","123456") | |||||
str, err := b.String() | |||||
if err != nil { | |||||
t.Fatal(err) | |||||
} | |||||
fmt.Println(str) | |||||
## set timeout | |||||
you can set timeout in request.default is 60 seconds. | |||||
set Get timeout: | |||||
httplib.Get("http://beego.me/").SetTimeout(100 * time.Second, 30 * time.Second) | |||||
set post timeout: | |||||
httplib.Post("http://beego.me/").SetTimeout(100 * time.Second, 30 * time.Second) | |||||
- first param is connectTimeout. | |||||
- second param is readWriteTimeout | |||||
## debug | |||||
if you want to debug the request info, set the debug on | |||||
httplib.Get("http://beego.me/").Debug(true) | |||||
## support HTTPS client | |||||
if request url is https. You can set the client support TSL: | |||||
httplib.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}) | |||||
more info about the tls.Config please visit http://golang.org/pkg/crypto/tls/#Config | |||||
## set cookie | |||||
some http request need setcookie. So set it like this: | |||||
cookie := &http.Cookie{} | |||||
cookie.Name = "username" | |||||
cookie.Value = "astaxie" | |||||
httplib.Get("http://beego.me/").SetCookie(cookie) | |||||
.text-red { | .text-red { | ||||
color: #DD4B39; | color: #DD4B39; | ||||
} | } | ||||
.text-grey { | |||||
color: #999999; | |||||
} | |||||
.markdown { | .markdown { | ||||
background-color: white; | background-color: white; | ||||
font-size: 16px; | font-size: 16px; | ||||
margin-bottom: 24px; | margin-bottom: 24px; | ||||
} | } | ||||
#repo-hooks-panel, | #repo-hooks-panel, | ||||
#repo-hooks-history-panel, | |||||
#user-ssh-panel { | #user-ssh-panel { | ||||
margin-bottom: 20px; | margin-bottom: 20px; | ||||
} | } | ||||
#repo-hooks-panel .setting-list, | #repo-hooks-panel .setting-list, | ||||
#repo-hooks-history-panel .setting-list, | |||||
#user-ssh-panel .setting-list { | #user-ssh-panel .setting-list { | ||||
background-color: #FFF; | background-color: #FFF; | ||||
} | } | ||||
#repo-hooks-panel .setting-list li, | #repo-hooks-panel .setting-list li, | ||||
#repo-hooks-history-panel .setting-list li, | |||||
#user-ssh-panel .setting-list li { | #user-ssh-panel .setting-list li { | ||||
padding: 8px 20px; | padding: 8px 20px; | ||||
border-bottom: 1px solid #eaeaea; | border-bottom: 1px solid #eaeaea; | ||||
} | } | ||||
#repo-hooks-panel .setting-list li.ssh:hover, | #repo-hooks-panel .setting-list li.ssh:hover, | ||||
#repo-hooks-history-panel .setting-list li.ssh:hover, | |||||
#user-ssh-panel .setting-list li.ssh:hover { | #user-ssh-panel .setting-list li.ssh:hover { | ||||
background-color: #ffffEE; | background-color: #ffffEE; | ||||
} | } | ||||
#repo-hooks-panel .setting-list li i, | #repo-hooks-panel .setting-list li i, | ||||
#repo-hooks-history-panel .setting-list li i, | |||||
#user-ssh-panel .setting-list li i { | #user-ssh-panel .setting-list li i { | ||||
padding-right: 5px; | padding-right: 5px; | ||||
} | } | ||||
#repo-hooks-panel .active-icon, | #repo-hooks-panel .active-icon, | ||||
#repo-hooks-history-panel .active-icon, | |||||
#user-ssh-panel .active-icon { | #user-ssh-panel .active-icon { | ||||
width: 10px; | width: 10px; | ||||
height: 10px; | height: 10px; | ||||
margin-top: 10px; | margin-top: 10px; | ||||
} | } | ||||
#repo-hooks-panel .ssh-content, | #repo-hooks-panel .ssh-content, | ||||
#repo-hooks-history-panel .ssh-content, | |||||
#user-ssh-panel .ssh-content { | #user-ssh-panel .ssh-content { | ||||
margin-left: 24px; | margin-left: 24px; | ||||
} | } | ||||
#repo-hooks-panel .ssh-content .octicon, | #repo-hooks-panel .ssh-content .octicon, | ||||
#repo-hooks-history-panel .ssh-content .octicon, | |||||
#user-ssh-panel .ssh-content .octicon { | #user-ssh-panel .ssh-content .octicon { | ||||
margin-right: 4px; | margin-right: 4px; | ||||
} | } | ||||
#repo-hooks-panel .ssh-content .print, | #repo-hooks-panel .ssh-content .print, | ||||
#repo-hooks-history-panel .ssh-content .print, | |||||
#user-ssh-panel .ssh-content .print, | #user-ssh-panel .ssh-content .print, | ||||
#repo-hooks-panel .ssh-content .activity, | #repo-hooks-panel .ssh-content .activity, | ||||
#repo-hooks-history-panel .ssh-content .activity, | |||||
#user-ssh-panel .ssh-content .activity { | #user-ssh-panel .ssh-content .activity { | ||||
color: #888; | color: #888; | ||||
} | } | ||||
#repo-hooks-panel .ssh-delete-btn, | #repo-hooks-panel .ssh-delete-btn, | ||||
#repo-hooks-history-panel .ssh-delete-btn, | |||||
#user-ssh-panel .ssh-delete-btn { | #user-ssh-panel .ssh-delete-btn { | ||||
margin-top: 6px; | margin-top: 6px; | ||||
} | } |
color: #FFF; | color: #FFF; | ||||
} | } | ||||
.btn-red { | .btn-red { | ||||
color: #FFF; | |||||
background-color: #d9453d; | background-color: #d9453d; | ||||
border: 1px solid #d9453d; | border: 1px solid #d9453d; | ||||
} | } | ||||
color: white; | color: white; | ||||
padding: 0 10px; | padding: 0 10px; | ||||
} | } | ||||
.btn-link { | |||||
overflow: visible; | |||||
padding: .6em 1.2em; | |||||
} | |||||
.btn-radius { | .btn-radius { | ||||
border-radius: .25em; | border-radius: .25em; | ||||
} | } | ||||
background-color: white; | background-color: white; | ||||
} | } | ||||
.panel .panel-body .panel-desc { | .panel .panel-body .panel-desc { | ||||
padding: 0 40px; | |||||
margin-bottom: 20px; | margin-bottom: 20px; | ||||
} | } | ||||
.panel .panel-content { | .panel .panel-content { |
} | } | ||||
.text-red { | .text-red { | ||||
color: #DD4B39; | color: #DD4B39; | ||||
} | |||||
.text-grey { | |||||
color: #999999; | |||||
} | } |
} | } | ||||
#repo-hooks-panel, | #repo-hooks-panel, | ||||
#repo-hooks-history-panel, | |||||
#user-ssh-panel { | #user-ssh-panel { | ||||
margin-bottom: 20px; | margin-bottom: 20px; | ||||
.setting-list { | .setting-list { |
color: #FFF; | color: #FFF; | ||||
} | } | ||||
} | } | ||||
.btn-red { | .btn-red { | ||||
background-color: @btnRedColor; | |||||
border: 1px solid @btnRedColor; | |||||
&:hover { | |||||
background-color: @btnHoverRedColor; | |||||
color: #FFF; | color: #FFF; | ||||
} | |||||
background-color: @btnRedColor; | |||||
border: 1px solid @btnRedColor; | |||||
&:hover { | |||||
background-color: @btnHoverRedColor; | |||||
color: #FFF; | |||||
} | |||||
} | } | ||||
.btn-orange { | .btn-orange { | ||||
background-color: @btnOrangeColor; | background-color: @btnOrangeColor; | ||||
border: 1px solid @btnOrangeColor; | border: 1px solid @btnOrangeColor; | ||||
// status buttons | // status buttons | ||||
.btn-active { | .btn-active { | ||||
box-shadow: 0 0 0 1px rgba(0, 0, 0, .1) inset, 0 0 4px rgba(0, 0, 0, .15) inset | |||||
box-shadow: 0 0 0 1px rgba(0, 0, 0, .1) inset, 0 0 4px rgba(0, 0, 0, .15) inset | |||||
} | } | ||||
.btn-header { | .btn-header { | ||||
margin-top: -1px; | margin-top: -1px; | ||||
color: white; | color: white; | ||||
padding: 0 10px; | padding: 0 10px; | ||||
} | } | ||||
.btn-link { | |||||
overflow: visible; | |||||
padding: .6em 1.2em; | |||||
} | |||||
.btn-radius { | .btn-radius { | ||||
border-radius: .25em; | |||||
border-radius: .25em; | |||||
} | } | ||||
.btn-left-radius { | .btn-left-radius { | ||||
border-top-left-radius: .25em; | |||||
border-bottom-left-radius: .25em; | |||||
border-top-left-radius: .25em; | |||||
border-bottom-left-radius: .25em; | |||||
} | } | ||||
.btn-right-radius { | .btn-right-radius { | ||||
border-top-right-radius: .25em; | |||||
border-bottom-right-radius: .25em; | |||||
border-top-right-radius: .25em; | |||||
border-bottom-right-radius: .25em; | |||||
} | } | ||||
.btn-block { | .btn-block { | ||||
display: block; | |||||
width: 100%; | |||||
box-sizing: content-box; | |||||
text-align: center; | |||||
display: block; | |||||
width: 100%; | |||||
box-sizing: content-box; | |||||
text-align: center; | |||||
} | } | ||||
.btn-disabled { | .btn-disabled { |
.panel-body { | .panel-body { | ||||
background-color: white; | background-color: white; | ||||
.panel-desc { | .panel-desc { | ||||
padding: 0 40px; | |||||
margin-bottom: 20px; | margin-bottom: 20px; | ||||
} | } | ||||
} | } |
SETTINGS_OPTIONS base.TplName = "repo/settings/options" | SETTINGS_OPTIONS base.TplName = "repo/settings/options" | ||||
COLLABORATION base.TplName = "repo/settings/collaboration" | COLLABORATION base.TplName = "repo/settings/collaboration" | ||||
HOOKS base.TplName = "repo/settings/hooks" | HOOKS base.TplName = "repo/settings/hooks" | ||||
HOOK_ADD base.TplName = "repo/hook_add" | |||||
HOOK_EDIT base.TplName = "repo/hook_edit" | |||||
HOOK_NEW base.TplName = "repo/settings/hook_new" | |||||
) | ) | ||||
func Settings(ctx *middleware.Context) { | func Settings(ctx *middleware.Context) { | ||||
ctx.HTML(200, HOOKS) | ctx.HTML(200, HOOKS) | ||||
} | } | ||||
func WebHooksAdd(ctx *middleware.Context) { | |||||
ctx.Data["IsRepoToolbarWebHooks"] = true | |||||
ctx.Data["Title"] = strings.TrimPrefix(ctx.Repo.RepoLink, "/") + " - Add Webhook" | |||||
ctx.HTML(200, HOOK_ADD) | |||||
func WebHooksNew(ctx *middleware.Context) { | |||||
ctx.Data["Title"] = ctx.Tr("repo.settings") | |||||
ctx.Data["PageIsSettingsHooks"] = true | |||||
ctx.Data["PageIsSettingsHooksNew"] = true | |||||
ctx.Data["Webhook"] = models.Webhook{HookEvent: &models.HookEvent{}} | |||||
ctx.HTML(200, HOOK_NEW) | |||||
} | } | ||||
func WebHooksAddPost(ctx *middleware.Context, form auth.NewWebhookForm) { | |||||
ctx.Data["IsRepoToolbarWebHooks"] = true | |||||
ctx.Data["Title"] = strings.TrimPrefix(ctx.Repo.RepoLink, "/") + " - Add Webhook" | |||||
func WebHooksNewPost(ctx *middleware.Context, form auth.NewWebhookForm) { | |||||
ctx.Data["Title"] = ctx.Tr("repo.settings") | |||||
ctx.Data["PageIsSettingsHooks"] = true | |||||
ctx.Data["PageIsSettingsHooksNew"] = true | |||||
ctx.Data["Webhook"] = models.Webhook{HookEvent: &models.HookEvent{}} | |||||
if ctx.HasError() { | if ctx.HasError() { | ||||
ctx.HTML(200, HOOK_ADD) | |||||
ctx.HTML(200, HOOK_NEW) | |||||
return | return | ||||
} | } | ||||
w := &models.Webhook{ | w := &models.Webhook{ | ||||
RepoId: ctx.Repo.Repository.Id, | RepoId: ctx.Repo.Repository.Id, | ||||
Url: form.Url, | |||||
Url: form.PayloadUrl, | |||||
ContentType: ct, | ContentType: ct, | ||||
Secret: form.Secret, | Secret: form.Secret, | ||||
HookEvent: &models.HookEvent{ | HookEvent: &models.HookEvent{ | ||||
IsActive: form.Active, | IsActive: form.Active, | ||||
} | } | ||||
if err := w.UpdateEvent(); err != nil { | if err := w.UpdateEvent(); err != nil { | ||||
ctx.Handle(500, "setting.WebHooksAddPost(UpdateEvent)", err) | |||||
ctx.Handle(500, "UpdateEvent", err) | |||||
return | return | ||||
} else if err := models.CreateWebhook(w); err != nil { | } else if err := models.CreateWebhook(w); err != nil { | ||||
ctx.Handle(500, "setting.WebHooksAddPost(CreateWebhook)", err) | |||||
ctx.Handle(500, "CreateWebhook", err) | |||||
return | return | ||||
} | } | ||||
ctx.Flash.Success("New webhook has been added.") | |||||
ctx.Flash.Success(ctx.Tr("repo.settings.add_hook_success")) | |||||
ctx.Redirect(ctx.Repo.RepoLink + "/settings/hooks") | ctx.Redirect(ctx.Repo.RepoLink + "/settings/hooks") | ||||
} | } | ||||
func WebHooksEdit(ctx *middleware.Context) { | func WebHooksEdit(ctx *middleware.Context) { | ||||
ctx.Data["IsRepoToolbarWebHooks"] = true | |||||
ctx.Data["Title"] = strings.TrimPrefix(ctx.Repo.RepoLink, "/") + " - Webhook" | |||||
ctx.Data["Title"] = ctx.Tr("repo.settings") | |||||
ctx.Data["PageIsSettingsHooks"] = true | |||||
ctx.Data["PageIsSettingsHooksEdit"] = true | |||||
hookId := com.StrTo(ctx.Params(":id")).MustInt64() | hookId := com.StrTo(ctx.Params(":id")).MustInt64() | ||||
if hookId == 0 { | if hookId == 0 { | ||||
w, err := models.GetWebhookById(hookId) | w, err := models.GetWebhookById(hookId) | ||||
if err != nil { | if err != nil { | ||||
if err == models.ErrWebhookNotExist { | if err == models.ErrWebhookNotExist { | ||||
ctx.Handle(404, "setting.WebHooksEdit(GetWebhookById)", nil) | |||||
ctx.Handle(404, "GetWebhookById", nil) | |||||
} else { | } else { | ||||
ctx.Handle(500, "setting.WebHooksEdit(GetWebhookById)", err) | |||||
ctx.Handle(500, "GetWebhookById", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
w.GetEvent() | w.GetEvent() | ||||
ctx.Data["Webhook"] = w | ctx.Data["Webhook"] = w | ||||
ctx.HTML(200, HOOK_EDIT) | |||||
ctx.HTML(200, HOOK_NEW) | |||||
} | } | ||||
func WebHooksEditPost(ctx *middleware.Context, form auth.NewWebhookForm) { | func WebHooksEditPost(ctx *middleware.Context, form auth.NewWebhookForm) { | ||||
ctx.Data["IsRepoToolbarWebHooks"] = true | |||||
ctx.Data["Title"] = strings.TrimPrefix(ctx.Repo.RepoLink, "/") + " - Webhook" | |||||
ctx.Data["Title"] = ctx.Tr("repo.settings") | |||||
ctx.Data["PageIsSettingsHooks"] = true | |||||
ctx.Data["PageIsSettingsHooksEdit"] = true | |||||
hookId := com.StrTo(ctx.Params(":id")).MustInt64() | hookId := com.StrTo(ctx.Params(":id")).MustInt64() | ||||
if hookId == 0 { | if hookId == 0 { | ||||
} | } | ||||
return | return | ||||
} | } | ||||
w.GetEvent() | |||||
ctx.Data["Webhook"] = w | |||||
if ctx.HasError() { | if ctx.HasError() { | ||||
ctx.HTML(200, HOOK_EDIT) | |||||
ctx.HTML(200, HOOK_NEW) | |||||
return | return | ||||
} | } | ||||
ct = models.FORM | ct = models.FORM | ||||
} | } | ||||
w.Url = form.Url | |||||
w.Url = form.PayloadUrl | |||||
w.ContentType = ct | w.ContentType = ct | ||||
w.Secret = form.Secret | w.Secret = form.Secret | ||||
w.HookEvent = &models.HookEvent{ | w.HookEvent = &models.HookEvent{ | ||||
return | return | ||||
} | } | ||||
ctx.Flash.Success("Webhook has been updated.") | |||||
ctx.Flash.Success(ctx.Tr("repo.settings.update_hook_success")) | |||||
ctx.Redirect(fmt.Sprintf("%s/settings/hooks/%d", ctx.Repo.RepoLink, hookId)) | ctx.Redirect(fmt.Sprintf("%s/settings/hooks/%d", ctx.Repo.RepoLink, hookId)) | ||||
} | } |
<strong>{{.i18n.Tr "repo.init_readme"}}</strong> | <strong>{{.i18n.Tr "repo.init_readme"}}</strong> | ||||
</div> | </div> | ||||
<div class="field"> | <div class="field"> | ||||
<label for="repo-create-submit"></label> | |||||
<button class="btn btn-large btn-blue btn-radius" id="repo-create-submit">{{.i18n.Tr "repo.create_repo"}}</button> | |||||
<label></label> | |||||
<button class="btn btn-large btn-blue btn-radius">{{.i18n.Tr "repo.create_repo"}}</button> | |||||
<a class="btn btn-small btn-gray btn-radius" id="repo-create-cancel" href="/"><strong>{{.i18n.Tr "cancel"}}</strong></a> | <a class="btn btn-small btn-gray btn-radius" id="repo-create-cancel" href="/"><strong>{{.i18n.Tr "cancel"}}</strong></a> | ||||
</div> | </div> | ||||
</div> | </div> |
{{template "base/head" .}} | |||||
{{template "base/navbar" .}} | |||||
{{template "repo/nav" .}} | |||||
{{template "repo/toolbar" .}} | |||||
<div id="body" class="container"> | |||||
{{template "repo/setting_nav" .}} | |||||
<div id="repo-setting-container" class="col-md-10"> | |||||
{{template "base/alert" .}} | |||||
<form id="repo-hooks-add-form" action="{{.RepoLink}}/settings/hooks/add" method="post"> | |||||
{{.CsrfTokenHtml}} | |||||
<div class="panel panel-default"> | |||||
<div class="panel-heading"> | |||||
Add Webhook | |||||
</div> | |||||
<div class="panel-body"> | |||||
<div class="col-md-7"> | |||||
<p>We’ll send a POST request to the URL below with details of any subscribed events.</p> | |||||
<hr/> | |||||
<div class="form-group"> | |||||
<label for="payload-url">Payload URL</label> | |||||
<input id="payload-url" name="url" class="form-control" type="url" required="required"/> | |||||
</div> | |||||
<div class="form-group"> | |||||
<label for="content-type">Content type</label> | |||||
<select id="content-type" name="content_type" class="form-control"> | |||||
<option value="1">application/json</option> | |||||
</select> | |||||
</div> | |||||
<div class="form-group"> | |||||
<label for="payload-secret">Secret</label> | |||||
<input id="payload-secret" name="secret" class="form-control" type="text"/> | |||||
</div> | |||||
<hr/> | |||||
<div class="form-group"> | |||||
<label>Which events would you like to trigger this webhook?</label> | |||||
<div class="radio"> | |||||
<label> | |||||
<input class="form-control" name="push_only" type="radio" checked name="trigger"/> Just the <i>push</i> event. | |||||
</label> | |||||
</div> | |||||
</div> | |||||
<hr/> | |||||
<div class="form-group"> | |||||
<label> | |||||
<input type="checkbox" name="active" checked/> Active | |||||
</label> | |||||
<p class="help-block">We will deliver event details when this hook is triggered.</p> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="panel-footer"> | |||||
<button class="btn btn-success">Add Webhook</button> | |||||
</div> | |||||
</div> | |||||
</form> | |||||
</div> | |||||
</div> | |||||
{{template "base/footer" .}} |
{{template "base/head" .}} | |||||
{{template "base/navbar" .}} | |||||
{{template "repo/nav" .}} | |||||
{{template "repo/toolbar" .}} | |||||
<div id="body" class="container"> | |||||
{{template "repo/setting_nav" .}} | |||||
<div id="repo-setting-container" class="col-md-10"> | |||||
{{template "base/alert" .}} | |||||
<form id="repo-hooks-edit-form" action="{{.RepoLink}}/settings/hooks/{{.Webhook.Id}}" method="post"> | |||||
{{.CsrfTokenHtml}} | |||||
<div class="panel panel-default"> | |||||
<div class="panel-heading"> | |||||
Manage Webhook | |||||
</div> | |||||
<div class="panel-body"> | |||||
<div class="col-md-7"> | |||||
<p>We’ll send a POST request to the URL below with details of any subscribed events.</p> | |||||
<hr/> | |||||
<div class="form-group"> | |||||
<label for="payload-url">Payload URL</label> | |||||
<input id="payload-url" name="url" class="form-control" type="url" required="required" value="{{.Webhook.Url}}" /> | |||||
</div> | |||||
<div class="form-group"> | |||||
<label for="payload-version">Content type</label> | |||||
<select id="content-type" name="content_type" class="form-control"> | |||||
<option value="1">application/json</option> | |||||
</select> | |||||
</div> | |||||
<div class="form-group"> | |||||
<label for="payload-secret">Secret</label> | |||||
<input id="payload-secret" name="secret" class="form-control" type="text" value="{{.Webhook.Secret}}" /> | |||||
</div> | |||||
<hr/> | |||||
<div class="form-group"> | |||||
<label>Which events would you like to trigger this webhook?</label> | |||||
<div class="radio"> | |||||
<label> | |||||
<input class="form-control" name="push_only" type="radio" {{if .Webhook.HookEvent.PushOnly}}checked {{end}}name="trigger"/> Just the <i>push</i> event. | |||||
</label> | |||||
</div> | |||||
</div> | |||||
<hr/> | |||||
<div class="form-group"> | |||||
<label> | |||||
<input type="checkbox" name="active" {{if .Webhook.IsActive}}checked{{end}}/> Active | |||||
</label> | |||||
<p class="help-block">We will deliver event details when this hook is triggered.</p> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="panel-footer"> | |||||
<button class="btn btn-primary">Update Webhook</button> | |||||
<a type="button" href="{{.RepoLink}}/settings/hooks?remove={{.Webhook.Id}}" class="btn btn-danger">Delete Webhook</a> | |||||
</div> | |||||
</div> | |||||
</form> | |||||
<div class="panel panel-default"> | |||||
<div class="panel-heading"> | |||||
<h3 class="panel-title">Recent Deliveries</h3> | |||||
</div> | |||||
<div class="panel-body"> | |||||
Coming soon | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
{{template "base/footer" .}} |
{{template "ng/base/head" .}} | |||||
{{template "ng/base/header" .}} | |||||
<div id="repo-wrapper"> | |||||
{{template "repo/header" .}} | |||||
<div id="setting-wrapper" class="main-wrapper"> | |||||
<div id="repo-setting" class="container clear"> | |||||
{{template "repo/settings/nav" .}} | |||||
<div class="grid-4-5 left"> | |||||
<div class="setting-content"> | |||||
{{template "ng/base/alert" .}} | |||||
<div id="setting-content"> | |||||
<div id="repo-hooks-panel" class="panel panel-radius"> | |||||
<div class="panel-header"> | |||||
<strong>{{if .PageIsSettingsHooksNew}}{{.i18n.Tr "repo.settings.add_webhook"}}{{else}}{{.i18n.Tr "repo.settings.update_webhook"}}{{end}}</strong> | |||||
</div> | |||||
<form class="form form-align panel-body" id="repo-setting-form" action="{{.RepoLink}}/settings/hooks/{{if .PageIsSettingsHooksNew}}new{{else}}{{.Webhook.Id}}{{end}}" method="post"> | |||||
{{.CsrfTokenHtml}} | |||||
<div class="text-center panel-desc">{{.i18n.Tr "repo.settings.add_webhook_desc" | Str2html}}</div> | |||||
<div class="field"> | |||||
<label class="req" for="payload-url">{{.i18n.Tr "repo.settings.payload_url"}}</label> | |||||
<input class="ipt ipt-large ipt-radius {{if .Err_UserName}}ipt-error{{end}}" id="payload-url" name="payload_url" type="url" value="{{.Webhook.Url}}" required /> | |||||
</div> | |||||
<div class="field"> | |||||
<label class="req">{{.i18n.Tr "repo.settings.content_type"}}</label> | |||||
<select name="content_type"> | |||||
<option value="1" {{if or .PageIsSettingsHooksNew (eq .Webhook.ContentType 1)}}selected{{end}}>application/json</option> | |||||
<option value="2" {{if eq .Webhook.ContentType 2}}selected{{end}}>application/x-www-form-urlencoded</option> | |||||
</select> | |||||
</div> | |||||
<div class="field"> | |||||
<label for="secret">{{.i18n.Tr "repo.settings.secret"}}</label> | |||||
<input class="ipt ipt-large ipt-radius {{if .Err_UserName}}ipt-error{{end}}" id="secret" name="secret" type="password" value="{{.Webhook.Secret}}" autocomplete="off" /> | |||||
</div> | |||||
<div class="field"> | |||||
<h4 class="text-center">{{.i18n.Tr "repo.settings.event_desc"}}</h4> | |||||
<label></label> | |||||
<input name="push_only" type="radio" {{if or .PageIsSettingsHooksNew .Webhook.PushOnly}}checked{{end}}> {{.i18n.Tr "repo.settings.event_push_only" | Str2html}} | |||||
</div> | |||||
<div class="field"> | |||||
<label for="active">{{.i18n.Tr "repo.settings.active"}}</label> | |||||
<input class="ipt-chk" id="active" name="active" type="checkbox" {{if or .PageIsSettingsHooksNew .Webhook.IsActive}}checked{{end}} /> | |||||
<span>{{.i18n.Tr "repo.settings.active_helper"}}</span> | |||||
</div> | |||||
<div class="field"> | |||||
<label></label> | |||||
<button class="btn btn-green btn-large btn-radius">{{if .PageIsSettingsHooksNew}}{{.i18n.Tr "repo.settings.add_webhook"}}{{else}}{{.i18n.Tr "repo.settings.update_webhook"}}{{end}}</button> | |||||
{{if .PageIsSettingsHooksEdit}}<a class="btn btn-red btn-large btn-link btn-radius" href="{{.RepoLink}}/settings/hooks?remove={{.Webhook.Id}}"><strong>{{.i18n.Tr "repo.settings.delete_webhook"}}</strong></a>{{end}} | |||||
</div> | |||||
</form> | |||||
</div> | |||||
</div> | |||||
<br> | |||||
<div id="setting-content"> | |||||
<div id="repo-hooks-history-panel" class="panel panel-radius"> | |||||
<div class="panel-header"> | |||||
<strong>{{.i18n.Tr "repo.settings.recent_deliveries"}}</strong> | |||||
</div> | |||||
<ul class="panel-body setting-list"> | |||||
<li>Coming soon!</li> | |||||
</ul> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
{{template "ng/base/footer" .}} |
<li>{{.i18n.Tr "repo.settings.hooks_desc" | Str2html}}</li> | <li>{{.i18n.Tr "repo.settings.hooks_desc" | Str2html}}</li> | ||||
{{range .Webhooks}} | {{range .Webhooks}} | ||||
<li> | <li> | ||||
{{if .IsActive}}<span class="left text-success"><i class="fa fa-check"></i></span>{{else}}<span class="pull-left status"><i class="fa fa-times"></i></span>{{end}} | |||||
{{if .IsActive}} | |||||
<span class="left text-success"><i class="octicon octicon-check"></i></span> | |||||
{{else}} | |||||
<span class="left text-grey"><i class="octicon octicon-primitive-dot"></i></span> | |||||
{{end}} | |||||
<a class="link" href="{{$.RepoLink}}/settings/hooks/{{.Id}}">{{.Url}}</a> | <a class="link" href="{{$.RepoLink}}/settings/hooks/{{.Id}}">{{.Url}}</a> | ||||
<a href="{{$.RepoLink}}/settings/hooks?remove={{.Id}}" class="text-red right"><i class="fa fa-times"></i></a> | <a href="{{$.RepoLink}}/settings/hooks?remove={{.Id}}" class="text-red right"><i class="fa fa-times"></i></a> | ||||
<a href="{{$.RepoLink}}/settings/hooks/{{.Id}}" class="text-blue right"><i class="fa fa-pencil"></i></a> | <a href="{{$.RepoLink}}/settings/hooks/{{.Id}}" class="text-blue right"><i class="fa fa-pencil"></i></a> |
<hr> | <hr> | ||||
<br> | <br> | ||||
<div class="field"> | <div class="field"> | ||||
<label for="lang">{{.i18n.Tr "repo.default_branch"}}</label> | |||||
<select id="lang" name="gitignore"> | |||||
<label>{{.i18n.Tr "repo.default_branch"}}</label> | |||||
<select name="branch"> | |||||
{{if .Repository.DefaultBranch}}<option value="{{.Repository.DefaultBranch}}">{{.Repository.DefaultBranch}}</option>{{end}} | {{if .Repository.DefaultBranch}}<option value="{{.Repository.DefaultBranch}}">{{.Repository.DefaultBranch}}</option>{{end}} | ||||
{{range .Branches}} | {{range .Branches}} | ||||
{{if not (eq . $.Repository.DefaultBranch)}}<option value="{{.}}">{{.}}</option>{{end}} | {{if not (eq . $.Repository.DefaultBranch)}}<option value="{{.}}">{{.}}</option>{{end}} |
<li>{{.i18n.Tr "settings.ssh_desc"}}</li> | <li>{{.i18n.Tr "settings.ssh_desc"}}</li> | ||||
{{range .Keys}} | {{range .Keys}} | ||||
<li class="ssh clear"> | <li class="ssh clear"> | ||||
<span class="active-icon left label {{if .HasRecentActivity}}label-green{{end}} label-radius"></span> | |||||
<span class="active-icon left label label-{{if .HasRecentActivity}}green{{else}}gray{{end}} label-radius"></span> | |||||
<i class="mega-octicon octicon-key left"></i> | <i class="mega-octicon octicon-key left"></i> | ||||
<div class="ssh-content left"> | <div class="ssh-content left"> | ||||
<p><strong>{{.Name}}</strong></p> | <p><strong>{{.Name}}</strong></p> |