_This is a different approach to #20267, I took the liberty of adapting
some parts, see below_
## Context
In some cases, a weebhook endpoint requires some kind of authentication.
The usual way is by sending a static `Authorization` header, with a
given token. For instance:
- Matrix expects a `Bearer <token>` (already implemented, by storing the
header cleartext in the metadata - which is buggy on retry #19872)
- TeamCity #18667
- Gitea instances #20267
- SourceHut https://man.sr.ht/graphql.md#authentication-strategies (this
is my actual personal need :)
## Proposed solution
Add a dedicated encrypt column to the webhook table (instead of storing
it as meta as proposed in #20267), so that it gets available for all
present and future hook types (especially the custom ones #19307).
This would also solve the buggy matrix retry #19872.
As a first step, I would recommend focusing on the backend logic and
improve the frontend at a later stage. For now the UI is a simple
`Authorization` field (which could be later customized with `Bearer` and
`Basic` switches):
![2022-08-23-142911](https://user-images.githubusercontent.com/3864879/186162483-5b721504-eef5-4932-812e-eb96a68494cc.png)
The header name is hard-coded, since I couldn't fine any usecase
justifying otherwise.
## Questions
- What do you think of this approach? @justusbunsi @Gusted @silverwind
- ~~How are the migrations generated? Do I have to manually create a new
file, or is there a command for that?~~
- ~~I started adding it to the API: should I complete it or should I
drop it? (I don't know how much the API is actually used)~~
## Done as well:
- add a migration for the existing matrix webhooks and remove the
`Authorization` logic there
_Closes #19872_
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Gusted <williamzijl7@hotmail.com>
Co-authored-by: delvh <dev.lh@web.de>
@ -188,3 +188,7 @@ if (json_last_error() !== JSON_ERROR_NONE) {
```
There is a Test Delivery button in the webhook settings that allows to test the configuration as well as a list of the most Recent Deliveries.
### Authorization header
**With 1.19**, Gitea hooks can be configured to send an [authorization header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization) to the webhook target.
settings.event_package_desc=Package created or deleted in a repository.
settings.branch_filter=Branch filter
settings.branch_filter_desc=Branch whitelist for push, branch creation and branch deletion events, specified as glob pattern. If empty or <code>*</code>, events for all branches are reported. See <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> documentation for syntax. Examples: <code>master</code>, <code>{master,release*}</code>.
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo):[test](http://localhost:3000/test/repo/src/branch/test)] branch created by user1",pl.(*MatrixPayloadUnsafe).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>:<a href="http://localhost:3000/test/repo/src/branch/test">test</a>] branch created by user1`,pl.(*MatrixPayloadUnsafe).FormattedBody)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo):[test](http://localhost:3000/test/repo/src/branch/test)] branch created by user1",pl.(*MatrixPayload).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>:<a href="http://localhost:3000/test/repo/src/branch/test">test</a>] branch created by user1`,pl.(*MatrixPayload).FormattedBody)
})
t.Run("Delete",func(t*testing.T){
p:=deleteTestPayload()
d:=new(MatrixPayloadUnsafe)
d:=new(MatrixPayload)
pl,err:=d.Delete(p)
require.NoError(t,err)
require.NotNil(t,pl)
require.IsType(t,&MatrixPayloadUnsafe{},pl)
require.IsType(t,&MatrixPayload{},pl)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo):test] branch deleted by user1",pl.(*MatrixPayloadUnsafe).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>:test] branch deleted by user1`,pl.(*MatrixPayloadUnsafe).FormattedBody)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo):test] branch deleted by user1",pl.(*MatrixPayload).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>:test] branch deleted by user1`,pl.(*MatrixPayload).FormattedBody)
})
t.Run("Fork",func(t*testing.T){
p:=forkTestPayload()
d:=new(MatrixPayloadUnsafe)
d:=new(MatrixPayload)
pl,err:=d.Fork(p)
require.NoError(t,err)
require.NotNil(t,pl)
require.IsType(t,&MatrixPayloadUnsafe{},pl)
require.IsType(t,&MatrixPayload{},pl)
assert.Equal(t,"[test/repo2](http://localhost:3000/test/repo2) is forked to [test/repo](http://localhost:3000/test/repo)",pl.(*MatrixPayloadUnsafe).Body)
assert.Equal(t,`<a href="http://localhost:3000/test/repo2">test/repo2</a> is forked to <a href="http://localhost:3000/test/repo">test/repo</a>`,pl.(*MatrixPayloadUnsafe).FormattedBody)
assert.Equal(t,"[test/repo2](http://localhost:3000/test/repo2) is forked to [test/repo](http://localhost:3000/test/repo)",pl.(*MatrixPayload).Body)
assert.Equal(t,`<a href="http://localhost:3000/test/repo2">test/repo2</a> is forked to <a href="http://localhost:3000/test/repo">test/repo</a>`,pl.(*MatrixPayload).FormattedBody)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo)] Issue opened: [#2 crash](http://localhost:3000/test/repo/issues/2) by [user1](https://try.gitea.io/user1)",pl.(*MatrixPayloadUnsafe).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>] Issue opened: <a href="http://localhost:3000/test/repo/issues/2">#2 crash</a> by <a href="https://try.gitea.io/user1">user1</a>`,pl.(*MatrixPayloadUnsafe).FormattedBody)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo)] Issue opened: [#2 crash](http://localhost:3000/test/repo/issues/2) by [user1](https://try.gitea.io/user1)",pl.(*MatrixPayload).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>] Issue opened: <a href="http://localhost:3000/test/repo/issues/2">#2 crash</a> by <a href="https://try.gitea.io/user1">user1</a>`,pl.(*MatrixPayload).FormattedBody)
p.Action=api.HookIssueClosed
pl,err=d.Issue(p)
require.NoError(t,err)
require.NotNil(t,pl)
require.IsType(t,&MatrixPayloadUnsafe{},pl)
require.IsType(t,&MatrixPayload{},pl)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo)] Issue closed: [#2 crash](http://localhost:3000/test/repo/issues/2) by [user1](https://try.gitea.io/user1)",pl.(*MatrixPayloadUnsafe).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>] Issue closed: <a href="http://localhost:3000/test/repo/issues/2">#2 crash</a> by <a href="https://try.gitea.io/user1">user1</a>`,pl.(*MatrixPayloadUnsafe).FormattedBody)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo)] Issue closed: [#2 crash](http://localhost:3000/test/repo/issues/2) by [user1](https://try.gitea.io/user1)",pl.(*MatrixPayload).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>] Issue closed: <a href="http://localhost:3000/test/repo/issues/2">#2 crash</a> by <a href="https://try.gitea.io/user1">user1</a>`,pl.(*MatrixPayload).FormattedBody)
})
t.Run("IssueComment",func(t*testing.T){
p:=issueCommentTestPayload()
d:=new(MatrixPayloadUnsafe)
d:=new(MatrixPayload)
pl,err:=d.IssueComment(p)
require.NoError(t,err)
require.NotNil(t,pl)
require.IsType(t,&MatrixPayloadUnsafe{},pl)
require.IsType(t,&MatrixPayload{},pl)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo)] New comment on issue [#2 crash](http://localhost:3000/test/repo/issues/2) by [user1](https://try.gitea.io/user1)",pl.(*MatrixPayloadUnsafe).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>] New comment on issue <a href="http://localhost:3000/test/repo/issues/2">#2 crash</a> by <a href="https://try.gitea.io/user1">user1</a>`,pl.(*MatrixPayloadUnsafe).FormattedBody)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo)] New comment on issue [#2 crash](http://localhost:3000/test/repo/issues/2) by [user1](https://try.gitea.io/user1)",pl.(*MatrixPayload).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>] New comment on issue <a href="http://localhost:3000/test/repo/issues/2">#2 crash</a> by <a href="https://try.gitea.io/user1">user1</a>`,pl.(*MatrixPayload).FormattedBody)
})
t.Run("PullRequest",func(t*testing.T){
p:=pullRequestTestPayload()
d:=new(MatrixPayloadUnsafe)
d:=new(MatrixPayload)
pl,err:=d.PullRequest(p)
require.NoError(t,err)
require.NotNil(t,pl)
require.IsType(t,&MatrixPayloadUnsafe{},pl)
require.IsType(t,&MatrixPayload{},pl)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo)] Pull request opened: [#12 Fix bug](http://localhost:3000/test/repo/pulls/12) by [user1](https://try.gitea.io/user1)",pl.(*MatrixPayloadUnsafe).Body)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo)] New comment on pull request [#12 Fix bug](http://localhost:3000/test/repo/pulls/12) by [user1](https://try.gitea.io/user1)",pl.(*MatrixPayloadUnsafe).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>] New comment on pull request <a href="http://localhost:3000/test/repo/pulls/12">#12 Fix bug</a> by <a href="https://try.gitea.io/user1">user1</a>`,pl.(*MatrixPayloadUnsafe).FormattedBody)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo)] New comment on pull request [#12 Fix bug](http://localhost:3000/test/repo/pulls/12) by [user1](https://try.gitea.io/user1)",pl.(*MatrixPayload).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>] New comment on pull request <a href="http://localhost:3000/test/repo/pulls/12">#12 Fix bug</a> by <a href="https://try.gitea.io/user1">user1</a>`,pl.(*MatrixPayload).FormattedBody)
assert.Equal(t,`[[test/repo](http://localhost:3000/test/repo)] Repository created by [user1](https://try.gitea.io/user1)`,pl.(*MatrixPayloadUnsafe).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>] Repository created by <a href="https://try.gitea.io/user1">user1</a>`,pl.(*MatrixPayloadUnsafe).FormattedBody)
assert.Equal(t,`[[test/repo](http://localhost:3000/test/repo)] Repository created by [user1](https://try.gitea.io/user1)`,pl.(*MatrixPayload).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>] Repository created by <a href="https://try.gitea.io/user1">user1</a>`,pl.(*MatrixPayload).FormattedBody)
})
t.Run("Wiki",func(t*testing.T){
p:=wikiTestPayload()
d:=new(MatrixPayloadUnsafe)
d:=new(MatrixPayload)
p.Action=api.HookWikiCreated
pl,err:=d.Wiki(p)
require.NoError(t,err)
require.NotNil(t,pl)
require.IsType(t,&MatrixPayloadUnsafe{},pl)
require.IsType(t,&MatrixPayload{},pl)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo)] New wiki page '[index](http://localhost:3000/test/repo/wiki/index)' (Wiki change comment) by [user1](https://try.gitea.io/user1)",pl.(*MatrixPayloadUnsafe).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>] New wiki page '<a href="http://localhost:3000/test/repo/wiki/index">index</a>' (Wiki change comment) by <a href="https://try.gitea.io/user1">user1</a>`,pl.(*MatrixPayloadUnsafe).FormattedBody)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo)] New wiki page '[index](http://localhost:3000/test/repo/wiki/index)' (Wiki change comment) by [user1](https://try.gitea.io/user1)",pl.(*MatrixPayload).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>] New wiki page '<a href="http://localhost:3000/test/repo/wiki/index">index</a>' (Wiki change comment) by <a href="https://try.gitea.io/user1">user1</a>`,pl.(*MatrixPayload).FormattedBody)
p.Action=api.HookWikiEdited
pl,err=d.Wiki(p)
require.NoError(t,err)
require.NotNil(t,pl)
require.IsType(t,&MatrixPayloadUnsafe{},pl)
require.IsType(t,&MatrixPayload{},pl)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo)] Wiki page '[index](http://localhost:3000/test/repo/wiki/index)' edited (Wiki change comment) by [user1](https://try.gitea.io/user1)",pl.(*MatrixPayloadUnsafe).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>] Wiki page '<a href="http://localhost:3000/test/repo/wiki/index">index</a>' edited (Wiki change comment) by <a href="https://try.gitea.io/user1">user1</a>`,pl.(*MatrixPayloadUnsafe).FormattedBody)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo)] Wiki page '[index](http://localhost:3000/test/repo/wiki/index)' edited (Wiki change comment) by [user1](https://try.gitea.io/user1)",pl.(*MatrixPayload).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>] Wiki page '<a href="http://localhost:3000/test/repo/wiki/index">index</a>' edited (Wiki change comment) by <a href="https://try.gitea.io/user1">user1</a>`,pl.(*MatrixPayload).FormattedBody)
p.Action=api.HookWikiDeleted
pl,err=d.Wiki(p)
require.NoError(t,err)
require.NotNil(t,pl)
require.IsType(t,&MatrixPayloadUnsafe{},pl)
require.IsType(t,&MatrixPayload{},pl)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo)] Wiki page '[index](http://localhost:3000/test/repo/wiki/index)' deleted by [user1](https://try.gitea.io/user1)",pl.(*MatrixPayloadUnsafe).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>] Wiki page '<a href="http://localhost:3000/test/repo/wiki/index">index</a>' deleted by <a href="https://try.gitea.io/user1">user1</a>`,pl.(*MatrixPayloadUnsafe).FormattedBody)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo)] Wiki page '[index](http://localhost:3000/test/repo/wiki/index)' deleted by [user1](https://try.gitea.io/user1)",pl.(*MatrixPayload).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>] Wiki page '<a href="http://localhost:3000/test/repo/wiki/index">index</a>' deleted by <a href="https://try.gitea.io/user1">user1</a>`,pl.(*MatrixPayload).FormattedBody)
})
t.Run("Release",func(t*testing.T){
p:=pullReleaseTestPayload()
d:=new(MatrixPayloadUnsafe)
d:=new(MatrixPayload)
pl,err:=d.Release(p)
require.NoError(t,err)
require.NotNil(t,pl)
require.IsType(t,&MatrixPayloadUnsafe{},pl)
require.IsType(t,&MatrixPayload{},pl)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo)] Release created: [v1.0](http://localhost:3000/test/repo/releases/tag/v1.0) by [user1](https://try.gitea.io/user1)",pl.(*MatrixPayloadUnsafe).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>] Release created: <a href="http://localhost:3000/test/repo/releases/tag/v1.0">v1.0</a> by <a href="https://try.gitea.io/user1">user1</a>`,pl.(*MatrixPayloadUnsafe).FormattedBody)
assert.Equal(t,"[[test/repo](http://localhost:3000/test/repo)] Release created: [v1.0](http://localhost:3000/test/repo/releases/tag/v1.0) by [user1](https://try.gitea.io/user1)",pl.(*MatrixPayload).Body)
assert.Equal(t,`[<a href="http://localhost:3000/test/repo">test/repo</a>] Release created: <a href="http://localhost:3000/test/repo/releases/tag/v1.0">v1.0</a> by <a href="https://try.gitea.io/user1">user1</a>`,pl.(*MatrixPayload).FormattedBody)
})
}
funcTestMatrixJSONPayload(t*testing.T){
p:=pushTestPayload()
pl,err:=new(MatrixPayloadUnsafe).Push(p)
pl,err:=new(MatrixPayload).Push(p)
require.NoError(t,err)
require.NotNil(t,pl)
require.IsType(t,&MatrixPayloadUnsafe{},pl)
require.IsType(t,&MatrixPayload{},pl)
json,err:=pl.JSONPayload()
require.NoError(t,err)
assert.NotEmpty(t,json)
}
funcTestMatrixHookRequest(t*testing.T){
w:=&webhook_model.Webhook{}
h:=&webhook_model.HookTask{
PayloadContent:`{
"body":"[[user1/test](http://localhost:3000/user1/test)] user1 pushed 1 commit to [master](http://localhost:3000/user1/test/src/branch/master):\n[5175ef2](http://localhost:3000/user1/test/commit/5175ef26201c58b035a3404b3fe02b4e8d436eee): Merge pull request 'Change readme.md' (#2) from add-matrix-webhook into master\n\nReviewed-on: http://localhost:3000/user1/test/pulls/2\n - user1",
"msgtype":"m.notice",
"format":"org.matrix.custom.html",
"formatted_body":"[\u003ca href=\"http://localhost:3000/user1/test\"\u003euser1/test\u003c/a\u003e] user1 pushed 1 commit to \u003ca href=\"http://localhost:3000/user1/test/src/branch/master\"\u003emaster\u003c/a\u003e:\u003cbr\u003e\u003ca href=\"http://localhost:3000/user1/test/commit/5175ef26201c58b035a3404b3fe02b4e8d436eee\"\u003e5175ef2\u003c/a\u003e: Merge pull request 'Change readme.md' (#2) from add-matrix-webhook into master\n\nReviewed-on: http://localhost:3000/user1/test/pulls/2\n - user1",
"io.gitea.commits":[
{
"id":"5175ef26201c58b035a3404b3fe02b4e8d436eee",
"message":"Merge pull request 'Change readme.md' (#2) from add-matrix-webhook into master\n\nReviewed-on: http://localhost:3000/user1/test/pulls/2\n",