aboutsummaryrefslogtreecommitdiff
path: root/models
diff options
context:
space:
mode:
authorKN4CK3R2023-03-10 15:28:32 +0100
committerGitHub2023-03-10 08:28:32 -0600
commit2173f14708ff3b35d7821fc9b6dcb5fcd06b8494 (patch)
tree5dcb735cc960095f9f8e114a1d896bb80df66ba9 /models
parentdad057b6393548ad389ead07c2cce5b3ac2811e0 (diff)
Add user webhooks (#21563)
Currently we can add webhooks for organizations but not for users. This PR adds the latter. You can access it from the current users settings. ![grafik](https://user-images.githubusercontent.com/1666336/197391408-15dfdc23-b476-4d0c-82f7-9bc9b065988f.png)
Diffstat (limited to 'models')
-rw-r--r--models/auth/token_scope.go10
-rw-r--r--models/auth/token_scope_test.go4
-rw-r--r--models/fixtures/webhook.yml2
-rw-r--r--models/migrations/migrations.go2
-rw-r--r--models/migrations/v1_20/v245.go74
-rw-r--r--models/webhook/webhook.go24
-rw-r--r--models/webhook/webhook_system.go10
-rw-r--r--models/webhook/webhook_test.go24
8 files changed, 116 insertions, 34 deletions
diff --git a/models/auth/token_scope.go b/models/auth/token_scope.go
index 38733a1c8..06c89fecc 100644
--- a/models/auth/token_scope.go
+++ b/models/auth/token_scope.go
@@ -32,6 +32,8 @@ const (
AccessTokenScopeAdminOrgHook AccessTokenScope = "admin:org_hook"
+ AccessTokenScopeAdminUserHook AccessTokenScope = "admin:user_hook"
+
AccessTokenScopeNotification AccessTokenScope = "notification"
AccessTokenScopeUser AccessTokenScope = "user"
@@ -64,7 +66,7 @@ type AccessTokenScopeBitmap uint64
const (
// AccessTokenScopeAllBits is the bitmap of all access token scopes, except `sudo`.
AccessTokenScopeAllBits AccessTokenScopeBitmap = AccessTokenScopeRepoBits |
- AccessTokenScopeAdminOrgBits | AccessTokenScopeAdminPublicKeyBits | AccessTokenScopeAdminOrgHookBits |
+ AccessTokenScopeAdminOrgBits | AccessTokenScopeAdminPublicKeyBits | AccessTokenScopeAdminOrgHookBits | AccessTokenScopeAdminUserHookBits |
AccessTokenScopeNotificationBits | AccessTokenScopeUserBits | AccessTokenScopeDeleteRepoBits |
AccessTokenScopePackageBits | AccessTokenScopeAdminGPGKeyBits | AccessTokenScopeAdminApplicationBits
@@ -86,6 +88,8 @@ const (
AccessTokenScopeAdminOrgHookBits AccessTokenScopeBitmap = 1 << iota
+ AccessTokenScopeAdminUserHookBits AccessTokenScopeBitmap = 1 << iota
+
AccessTokenScopeNotificationBits AccessTokenScopeBitmap = 1 << iota
AccessTokenScopeUserBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeReadUserBits | AccessTokenScopeUserEmailBits | AccessTokenScopeUserFollowBits
@@ -123,6 +127,7 @@ var allAccessTokenScopes = []AccessTokenScope{
AccessTokenScopeAdminPublicKey, AccessTokenScopeWritePublicKey, AccessTokenScopeReadPublicKey,
AccessTokenScopeAdminRepoHook, AccessTokenScopeWriteRepoHook, AccessTokenScopeReadRepoHook,
AccessTokenScopeAdminOrgHook,
+ AccessTokenScopeAdminUserHook,
AccessTokenScopeNotification,
AccessTokenScopeUser, AccessTokenScopeReadUser, AccessTokenScopeUserEmail, AccessTokenScopeUserFollow,
AccessTokenScopeDeleteRepo,
@@ -147,6 +152,7 @@ var allAccessTokenScopeBits = map[AccessTokenScope]AccessTokenScopeBitmap{
AccessTokenScopeWriteRepoHook: AccessTokenScopeWriteRepoHookBits,
AccessTokenScopeReadRepoHook: AccessTokenScopeReadRepoHookBits,
AccessTokenScopeAdminOrgHook: AccessTokenScopeAdminOrgHookBits,
+ AccessTokenScopeAdminUserHook: AccessTokenScopeAdminUserHookBits,
AccessTokenScopeNotification: AccessTokenScopeNotificationBits,
AccessTokenScopeUser: AccessTokenScopeUserBits,
AccessTokenScopeReadUser: AccessTokenScopeReadUserBits,
@@ -263,7 +269,7 @@ func (bitmap AccessTokenScopeBitmap) ToScope() AccessTokenScope {
scope := AccessTokenScope(strings.Join(scopes, ","))
scope = AccessTokenScope(strings.ReplaceAll(
string(scope),
- "repo,admin:org,admin:public_key,admin:org_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application",
+ "repo,admin:org,admin:public_key,admin:org_hook,admin:user_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application",
"all",
))
return scope
diff --git a/models/auth/token_scope_test.go b/models/auth/token_scope_test.go
index 1d7f4794a..b96a5fd46 100644
--- a/models/auth/token_scope_test.go
+++ b/models/auth/token_scope_test.go
@@ -40,8 +40,8 @@ func TestAccessTokenScope_Normalize(t *testing.T) {
{"admin:gpg_key,write:gpg_key,user", "user,admin:gpg_key", nil},
{"admin:application,write:application,user", "user,admin:application", nil},
{"all", "all", nil},
- {"repo,admin:org,admin:public_key,admin:repo_hook,admin:org_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application", "all", nil},
- {"repo,admin:org,admin:public_key,admin:repo_hook,admin:org_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application,sudo", "all,sudo", nil},
+ {"repo,admin:org,admin:public_key,admin:repo_hook,admin:org_hook,admin:user_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application", "all", nil},
+ {"repo,admin:org,admin:public_key,admin:repo_hook,admin:org_hook,admin:user_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application,sudo", "all,sudo", nil},
}
for _, test := range tests {
diff --git a/models/fixtures/webhook.yml b/models/fixtures/webhook.yml
index 5563dcada..f62bae1f3 100644
--- a/models/fixtures/webhook.yml
+++ b/models/fixtures/webhook.yml
@@ -16,7 +16,7 @@
-
id: 3
- org_id: 3
+ owner_id: 3
repo_id: 3
url: www.example.com/url3
content_type: 1 # json
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index 585457e47..4cbcd95d2 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -467,6 +467,8 @@ var migrations = []Migration{
// v244 -> v245
NewMigration("Add NeedApproval to actions tables", v1_20.AddNeedApprovalToActionRun),
+ // v245 -> v246
+ NewMigration("Rename Webhook org_id to owner_id", v1_20.RenameWebhookOrgToOwner),
}
// GetCurrentDBVersion returns the current db version
diff --git a/models/migrations/v1_20/v245.go b/models/migrations/v1_20/v245.go
new file mode 100644
index 000000000..466f21c23
--- /dev/null
+++ b/models/migrations/v1_20/v245.go
@@ -0,0 +1,74 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_20 //nolint
+
+import (
+ "context"
+ "fmt"
+
+ "code.gitea.io/gitea/models/migrations/base"
+ "code.gitea.io/gitea/modules/setting"
+
+ "xorm.io/xorm"
+)
+
+func RenameWebhookOrgToOwner(x *xorm.Engine) error {
+ type Webhook struct {
+ OrgID int64 `xorm:"INDEX"`
+ }
+
+ // This migration maybe rerun so that we should check if it has been run
+ ownerExist, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "webhook", "owner_id")
+ if err != nil {
+ return err
+ }
+
+ if ownerExist {
+ orgExist, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "webhook", "org_id")
+ if err != nil {
+ return err
+ }
+ if !orgExist {
+ return nil
+ }
+ }
+
+ sess := x.NewSession()
+ defer sess.Close()
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+
+ if err := sess.Sync2(new(Webhook)); err != nil {
+ return err
+ }
+
+ if ownerExist {
+ if err := base.DropTableColumns(sess, "webhook", "owner_id"); err != nil {
+ return err
+ }
+ }
+
+ switch {
+ case setting.Database.Type.IsMySQL():
+ inferredTable, err := x.TableInfo(new(Webhook))
+ if err != nil {
+ return err
+ }
+ sqlType := x.Dialect().SQLType(inferredTable.GetColumn("org_id"))
+ if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `webhook` CHANGE org_id owner_id %s", sqlType)); err != nil {
+ return err
+ }
+ case setting.Database.Type.IsMSSQL():
+ if _, err := sess.Exec("sp_rename 'webhook.org_id', 'owner_id', 'COLUMN'"); err != nil {
+ return err
+ }
+ default:
+ if _, err := sess.Exec("ALTER TABLE `webhook` RENAME COLUMN org_id TO owner_id"); err != nil {
+ return err
+ }
+ }
+
+ return sess.Commit()
+}
diff --git a/models/webhook/webhook.go b/models/webhook/webhook.go
index 64119f149..e3f6b593d 100644
--- a/models/webhook/webhook.go
+++ b/models/webhook/webhook.go
@@ -122,7 +122,7 @@ func IsValidHookContentType(name string) bool {
type Webhook struct {
ID int64 `xorm:"pk autoincr"`
RepoID int64 `xorm:"INDEX"` // An ID of 0 indicates either a default or system webhook
- OrgID int64 `xorm:"INDEX"`
+ OwnerID int64 `xorm:"INDEX"`
IsSystemWebhook bool
URL string `xorm:"url TEXT"`
HTTPMethod string `xorm:"http_method"`
@@ -412,11 +412,11 @@ func GetWebhookByRepoID(repoID, id int64) (*Webhook, error) {
})
}
-// GetWebhookByOrgID returns webhook of organization by given ID.
-func GetWebhookByOrgID(orgID, id int64) (*Webhook, error) {
+// GetWebhookByOwnerID returns webhook of a user or organization by given ID.
+func GetWebhookByOwnerID(ownerID, id int64) (*Webhook, error) {
return getWebhook(&Webhook{
- ID: id,
- OrgID: orgID,
+ ID: id,
+ OwnerID: ownerID,
})
}
@@ -424,7 +424,7 @@ func GetWebhookByOrgID(orgID, id int64) (*Webhook, error) {
type ListWebhookOptions struct {
db.ListOptions
RepoID int64
- OrgID int64
+ OwnerID int64
IsActive util.OptionalBool
}
@@ -433,8 +433,8 @@ func (opts *ListWebhookOptions) toCond() builder.Cond {
if opts.RepoID != 0 {
cond = cond.And(builder.Eq{"webhook.repo_id": opts.RepoID})
}
- if opts.OrgID != 0 {
- cond = cond.And(builder.Eq{"webhook.org_id": opts.OrgID})
+ if opts.OwnerID != 0 {
+ cond = cond.And(builder.Eq{"webhook.owner_id": opts.OwnerID})
}
if !opts.IsActive.IsNone() {
cond = cond.And(builder.Eq{"webhook.is_active": opts.IsActive.IsTrue()})
@@ -503,10 +503,10 @@ func DeleteWebhookByRepoID(repoID, id int64) error {
})
}
-// DeleteWebhookByOrgID deletes webhook of organization by given ID.
-func DeleteWebhookByOrgID(orgID, id int64) error {
+// DeleteWebhookByOwnerID deletes webhook of a user or organization by given ID.
+func DeleteWebhookByOwnerID(ownerID, id int64) error {
return deleteWebhook(&Webhook{
- ID: id,
- OrgID: orgID,
+ ID: id,
+ OwnerID: ownerID,
})
}
diff --git a/models/webhook/webhook_system.go b/models/webhook/webhook_system.go
index 21dc0406a..2e89f9547 100644
--- a/models/webhook/webhook_system.go
+++ b/models/webhook/webhook_system.go
@@ -15,7 +15,7 @@ import (
func GetDefaultWebhooks(ctx context.Context) ([]*Webhook, error) {
webhooks := make([]*Webhook, 0, 5)
return webhooks, db.GetEngine(ctx).
- Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, false).
+ Where("repo_id=? AND owner_id=? AND is_system_webhook=?", 0, 0, false).
Find(&webhooks)
}
@@ -23,7 +23,7 @@ func GetDefaultWebhooks(ctx context.Context) ([]*Webhook, error) {
func GetSystemOrDefaultWebhook(ctx context.Context, id int64) (*Webhook, error) {
webhook := &Webhook{ID: id}
has, err := db.GetEngine(ctx).
- Where("repo_id=? AND org_id=?", 0, 0).
+ Where("repo_id=? AND owner_id=?", 0, 0).
Get(webhook)
if err != nil {
return nil, err
@@ -38,11 +38,11 @@ func GetSystemWebhooks(ctx context.Context, isActive util.OptionalBool) ([]*Webh
webhooks := make([]*Webhook, 0, 5)
if isActive.IsNone() {
return webhooks, db.GetEngine(ctx).
- Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, true).
+ Where("repo_id=? AND owner_id=? AND is_system_webhook=?", 0, 0, true).
Find(&webhooks)
}
return webhooks, db.GetEngine(ctx).
- Where("repo_id=? AND org_id=? AND is_system_webhook=? AND is_active = ?", 0, 0, true, isActive.IsTrue()).
+ Where("repo_id=? AND owner_id=? AND is_system_webhook=? AND is_active = ?", 0, 0, true, isActive.IsTrue()).
Find(&webhooks)
}
@@ -50,7 +50,7 @@ func GetSystemWebhooks(ctx context.Context, isActive util.OptionalBool) ([]*Webh
func DeleteDefaultSystemWebhook(ctx context.Context, id int64) error {
return db.WithTx(ctx, func(ctx context.Context) error {
count, err := db.GetEngine(ctx).
- Where("repo_id=? AND org_id=?", 0, 0).
+ Where("repo_id=? AND owner_id=?", 0, 0).
Delete(&Webhook{ID: id})
if err != nil {
return err
diff --git a/models/webhook/webhook_test.go b/models/webhook/webhook_test.go
index c368fc620..74f7aeaa0 100644
--- a/models/webhook/webhook_test.go
+++ b/models/webhook/webhook_test.go
@@ -109,13 +109,13 @@ func TestGetWebhookByRepoID(t *testing.T) {
assert.True(t, IsErrWebhookNotExist(err))
}
-func TestGetWebhookByOrgID(t *testing.T) {
+func TestGetWebhookByOwnerID(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- hook, err := GetWebhookByOrgID(3, 3)
+ hook, err := GetWebhookByOwnerID(3, 3)
assert.NoError(t, err)
assert.Equal(t, int64(3), hook.ID)
- _, err = GetWebhookByOrgID(unittest.NonexistentID, unittest.NonexistentID)
+ _, err = GetWebhookByOwnerID(unittest.NonexistentID, unittest.NonexistentID)
assert.Error(t, err)
assert.True(t, IsErrWebhookNotExist(err))
}
@@ -140,9 +140,9 @@ func TestGetWebhooksByRepoID(t *testing.T) {
}
}
-func TestGetActiveWebhooksByOrgID(t *testing.T) {
+func TestGetActiveWebhooksByOwnerID(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- hooks, err := ListWebhooksByOpts(db.DefaultContext, &ListWebhookOptions{OrgID: 3, IsActive: util.OptionalBoolTrue})
+ hooks, err := ListWebhooksByOpts(db.DefaultContext, &ListWebhookOptions{OwnerID: 3, IsActive: util.OptionalBoolTrue})
assert.NoError(t, err)
if assert.Len(t, hooks, 1) {
assert.Equal(t, int64(3), hooks[0].ID)
@@ -150,9 +150,9 @@ func TestGetActiveWebhooksByOrgID(t *testing.T) {
}
}
-func TestGetWebhooksByOrgID(t *testing.T) {
+func TestGetWebhooksByOwnerID(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- hooks, err := ListWebhooksByOpts(db.DefaultContext, &ListWebhookOptions{OrgID: 3})
+ hooks, err := ListWebhooksByOpts(db.DefaultContext, &ListWebhookOptions{OwnerID: 3})
assert.NoError(t, err)
if assert.Len(t, hooks, 1) {
assert.Equal(t, int64(3), hooks[0].ID)
@@ -181,13 +181,13 @@ func TestDeleteWebhookByRepoID(t *testing.T) {
assert.True(t, IsErrWebhookNotExist(err))
}
-func TestDeleteWebhookByOrgID(t *testing.T) {
+func TestDeleteWebhookByOwnerID(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- unittest.AssertExistsAndLoadBean(t, &Webhook{ID: 3, OrgID: 3})
- assert.NoError(t, DeleteWebhookByOrgID(3, 3))
- unittest.AssertNotExistsBean(t, &Webhook{ID: 3, OrgID: 3})
+ unittest.AssertExistsAndLoadBean(t, &Webhook{ID: 3, OwnerID: 3})
+ assert.NoError(t, DeleteWebhookByOwnerID(3, 3))
+ unittest.AssertNotExistsBean(t, &Webhook{ID: 3, OwnerID: 3})
- err := DeleteWebhookByOrgID(unittest.NonexistentID, unittest.NonexistentID)
+ err := DeleteWebhookByOwnerID(unittest.NonexistentID, unittest.NonexistentID)
assert.Error(t, err)
assert.True(t, IsErrWebhookNotExist(err))
}