aboutsummaryrefslogtreecommitdiff
path: root/models
diff options
context:
space:
mode:
authorAnthony Wang2023-03-12 23:17:11 +0000
committerAnthony Wang2023-03-12 23:19:57 +0000
commitdbc3eb7fa071307e623fde961bfdff0894856948 (patch)
tree8961dc6a935d9ee89f5adf680a142d36900aaebb /models
parentb4640101f3c8938ed689743606a79601201141ca (diff)
parente72290fd9aeb77a47311483d1d565e428ce40cd9 (diff)
Merge remote-tracking branch 'origin/main' into forgejo-federation
Diffstat (limited to 'models')
-rw-r--r--models/actions/run.go1
-rw-r--r--models/actions/task.go3
-rw-r--r--models/activities/action.go6
-rw-r--r--models/activities/action_test.go2
-rw-r--r--models/activities/user_heatmap.go4
-rw-r--r--models/auth/token_scope.go10
-rw-r--r--models/auth/token_scope_test.go4
-rw-r--r--models/db/common.go2
-rwxr-xr-xmodels/db/engine.go4
-rw-r--r--models/db/index.go2
-rw-r--r--models/db/iterate_test.go2
-rw-r--r--models/db/list_test.go4
-rw-r--r--models/db/sequence.go4
-rw-r--r--models/fixtures/repo_unit.yml6
-rw-r--r--models/fixtures/repository.yml15
-rw-r--r--models/fixtures/team.yml22
-rw-r--r--models/fixtures/user.yml6
-rw-r--r--models/fixtures/webhook.yml2
-rw-r--r--models/git/commit_status.go2
-rw-r--r--models/git/lfs_lock.go12
-rw-r--r--models/issues/label.go115
-rw-r--r--models/issues/label_test.go2
-rw-r--r--models/issues/pull_list.go16
-rw-r--r--models/issues/pull_test.go2
-rw-r--r--models/issues/stopwatch.go34
-rw-r--r--models/issues/stopwatch_test.go4
-rw-r--r--models/migrations/base/db.go28
-rw-r--r--models/migrations/migrations.go2
-rw-r--r--models/migrations/v1_12/v139.go4
-rw-r--r--models/migrations/v1_13/v140.go2
-rw-r--r--models/migrations/v1_13/v145.go8
-rw-r--r--models/migrations/v1_13/v151.go8
-rw-r--r--models/migrations/v1_14/v158.go10
-rw-r--r--models/migrations/v1_14/v175.go2
-rw-r--r--models/migrations/v1_15/v184.go4
-rw-r--r--models/migrations/v1_16/v191.go2
-rw-r--r--models/migrations/v1_17/v217.go2
-rw-r--r--models/migrations/v1_17/v218.go2
-rw-r--r--models/migrations/v1_17/v223.go4
-rw-r--r--models/migrations/v1_18/v225.go2
-rw-r--r--models/migrations/v1_19/v232.go2
-rw-r--r--models/migrations/v1_19/v242.go2
-rw-r--r--models/migrations/v1_20/v245.go74
-rw-r--r--models/organization/org.go26
-rw-r--r--models/project/project.go4
-rw-r--r--models/repo/repo_list.go2
-rw-r--r--models/unittest/testdb.go2
-rw-r--r--models/user/user.go5
-rw-r--r--models/webhook/webhook.go24
-rw-r--r--models/webhook/webhook_system.go10
-rw-r--r--models/webhook/webhook_test.go24
51 files changed, 347 insertions, 194 deletions
diff --git a/models/actions/run.go b/models/actions/run.go
index a8d991471..d5ab45a51 100644
--- a/models/actions/run.go
+++ b/models/actions/run.go
@@ -192,6 +192,7 @@ func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWork
if len(needs) > 0 || run.NeedApproval {
status = StatusBlocked
}
+ job.Name, _ = util.SplitStringAtByteN(job.Name, 255)
runJobs = append(runJobs, &ActionRunJob{
RunID: run.ID,
RepoID: run.RepoID,
diff --git a/models/actions/task.go b/models/actions/task.go
index 5b6206c34..ffec4c92a 100644
--- a/models/actions/task.go
+++ b/models/actions/task.go
@@ -298,8 +298,9 @@ func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask
if len(workflowJob.Steps) > 0 {
steps := make([]*ActionTaskStep, len(workflowJob.Steps))
for i, v := range workflowJob.Steps {
+ name, _ := util.SplitStringAtByteN(v.String(), 255)
steps[i] = &ActionTaskStep{
- Name: v.String(),
+ Name: name,
TaskID: task.ID,
Index: int64(i),
RepoID: task.RepoID,
diff --git a/models/activities/action.go b/models/activities/action.go
index 1412d2c05..c1d17517b 100644
--- a/models/activities/action.go
+++ b/models/activities/action.go
@@ -99,7 +99,7 @@ func (a *Action) TableIndices() []*schemas.Index {
actUserIndex.AddColumn("act_user_id", "repo_id", "created_unix", "user_id", "is_deleted")
indices := []*schemas.Index{actUserIndex, repoIndex}
- if setting.Database.UsePostgreSQL {
+ if setting.Database.Type.IsPostgreSQL() {
cudIndex := schemas.NewIndex("c_u_d", schemas.IndexType)
cudIndex.AddColumn("created_unix", "user_id", "is_deleted")
indices = append(indices, cudIndex)
@@ -640,7 +640,7 @@ func DeleteIssueActions(ctx context.Context, repoID, issueID int64) error {
// CountActionCreatedUnixString count actions where created_unix is an empty string
func CountActionCreatedUnixString(ctx context.Context) (int64, error) {
- if setting.Database.UseSQLite3 {
+ if setting.Database.Type.IsSQLite3() {
return db.GetEngine(ctx).Where(`created_unix = ""`).Count(new(Action))
}
return 0, nil
@@ -648,7 +648,7 @@ func CountActionCreatedUnixString(ctx context.Context) (int64, error) {
// FixActionCreatedUnixString set created_unix to zero if it is an empty string
func FixActionCreatedUnixString(ctx context.Context) (int64, error) {
- if setting.Database.UseSQLite3 {
+ if setting.Database.Type.IsSQLite3() {
res, err := db.GetEngine(ctx).Exec(`UPDATE action SET created_unix = 0 WHERE created_unix = ""`)
if err != nil {
return 0, err
diff --git a/models/activities/action_test.go b/models/activities/action_test.go
index 2fd86bb8f..7044bcc00 100644
--- a/models/activities/action_test.go
+++ b/models/activities/action_test.go
@@ -243,7 +243,7 @@ func TestGetFeedsCorrupted(t *testing.T) {
}
func TestConsistencyUpdateAction(t *testing.T) {
- if !setting.Database.UseSQLite3 {
+ if !setting.Database.Type.IsSQLite3() {
t.Skip("Test is only for SQLite database.")
}
assert.NoError(t, unittest.PrepareTestDatabase())
diff --git a/models/activities/user_heatmap.go b/models/activities/user_heatmap.go
index 3370103a5..d3f0f0db7 100644
--- a/models/activities/user_heatmap.go
+++ b/models/activities/user_heatmap.go
@@ -39,9 +39,9 @@ func getUserHeatmapData(user *user_model.User, team *organization.Team, doer *us
groupBy := "created_unix / 900 * 900"
groupByName := "timestamp" // We need this extra case because mssql doesn't allow grouping by alias
switch {
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
groupBy = "created_unix DIV 900 * 900"
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
groupByName = groupBy
}
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/db/common.go b/models/db/common.go
index 76c7c119f..af6130c9f 100644
--- a/models/db/common.go
+++ b/models/db/common.go
@@ -15,7 +15,7 @@ import (
// BuildCaseInsensitiveLike returns a condition to check if the given value is like the given key case-insensitively.
// Handles especially SQLite correctly as UPPER there only transforms ASCII letters.
func BuildCaseInsensitiveLike(key, value string) builder.Cond {
- if setting.Database.UseSQLite3 {
+ if setting.Database.Type.IsSQLite3() {
return builder.Like{"UPPER(" + key + ")", util.ToUpperASCII(value)}
}
return builder.Like{"UPPER(" + key + ")", strings.ToUpper(value)}
diff --git a/models/db/engine.go b/models/db/engine.go
index 5020101d4..56dd209fd 100755
--- a/models/db/engine.go
+++ b/models/db/engine.go
@@ -101,12 +101,12 @@ func newXORMEngine() (*xorm.Engine, error) {
var engine *xorm.Engine
- if setting.Database.UsePostgreSQL && len(setting.Database.Schema) > 0 {
+ if setting.Database.Type.IsPostgreSQL() && len(setting.Database.Schema) > 0 {
// OK whilst we sort out our schema issues - create a schema aware postgres
registerPostgresSchemaDriver()
engine, err = xorm.NewEngine("postgresschema", connStr)
} else {
- engine, err = xorm.NewEngine(setting.Database.Type, connStr)
+ engine, err = xorm.NewEngine(setting.Database.Type.String(), connStr)
}
if err != nil {
diff --git a/models/db/index.go b/models/db/index.go
index f840a62c8..7609d8fb6 100644
--- a/models/db/index.go
+++ b/models/db/index.go
@@ -73,7 +73,7 @@ func postgresGetNextResourceIndex(ctx context.Context, tableName string, groupID
// GetNextResourceIndex generates a resource index, it must run in the same transaction where the resource is created
func GetNextResourceIndex(ctx context.Context, tableName string, groupID int64) (int64, error) {
- if setting.Database.UsePostgreSQL {
+ if setting.Database.Type.IsPostgreSQL() {
return postgresGetNextResourceIndex(ctx, tableName, groupID)
}
diff --git a/models/db/iterate_test.go b/models/db/iterate_test.go
index a713fe0d8..6bcf740c2 100644
--- a/models/db/iterate_test.go
+++ b/models/db/iterate_test.go
@@ -25,7 +25,7 @@ func TestIterate(t *testing.T) {
return nil
})
assert.NoError(t, err)
- assert.EqualValues(t, 83, repoCnt)
+ assert.EqualValues(t, 84, repoCnt)
err = db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repoUnit *repo_model.RepoUnit) error {
reopUnit2 := repo_model.RepoUnit{ID: repoUnit.ID}
diff --git a/models/db/list_test.go b/models/db/list_test.go
index ffef1e494..1295692ce 100644
--- a/models/db/list_test.go
+++ b/models/db/list_test.go
@@ -35,11 +35,11 @@ func TestFind(t *testing.T) {
var repoUnits []repo_model.RepoUnit
err := db.Find(db.DefaultContext, &opts, &repoUnits)
assert.NoError(t, err)
- assert.EqualValues(t, 83, len(repoUnits))
+ assert.EqualValues(t, 84, len(repoUnits))
cnt, err := db.Count(db.DefaultContext, &opts, new(repo_model.RepoUnit))
assert.NoError(t, err)
- assert.EqualValues(t, 83, cnt)
+ assert.EqualValues(t, 84, cnt)
repoUnits = make([]repo_model.RepoUnit, 0, 10)
newCnt, err := db.FindAndCount(db.DefaultContext, &opts, &repoUnits)
diff --git a/models/db/sequence.go b/models/db/sequence.go
index 6d801d022..f49ad935d 100644
--- a/models/db/sequence.go
+++ b/models/db/sequence.go
@@ -13,7 +13,7 @@ import (
// CountBadSequences looks for broken sequences from recreate-table mistakes
func CountBadSequences(_ context.Context) (int64, error) {
- if !setting.Database.UsePostgreSQL {
+ if !setting.Database.Type.IsPostgreSQL() {
return 0, nil
}
@@ -34,7 +34,7 @@ func CountBadSequences(_ context.Context) (int64, error) {
// FixBadSequences fixes for broken sequences from recreate-table mistakes
func FixBadSequences(_ context.Context) error {
- if !setting.Database.UsePostgreSQL {
+ if !setting.Database.Type.IsPostgreSQL() {
return nil
}
diff --git a/models/fixtures/repo_unit.yml b/models/fixtures/repo_unit.yml
index 503b8c9dd..ef0b7c1a9 100644
--- a/models/fixtures/repo_unit.yml
+++ b/models/fixtures/repo_unit.yml
@@ -569,3 +569,9 @@
type: 3
config: "{\"IgnoreWhitespaceConflicts\":false,\"AllowMerge\":true,\"AllowRebase\":true,\"AllowRebaseMerge\":true,\"AllowSquash\":true}"
created_unix: 946684810
+
+-
+ id: 84
+ repo_id: 56
+ type: 1
+ created_unix: 946684810
diff --git a/models/fixtures/repository.yml b/models/fixtures/repository.yml
index 58f9b919a..32ba8744d 100644
--- a/models/fixtures/repository.yml
+++ b/models/fixtures/repository.yml
@@ -25,7 +25,7 @@
fork_id: 0
is_template: false
template_id: 0
- size: 6708
+ size: 7028
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false
@@ -1634,3 +1634,16 @@
is_private: true
num_issues: 1
status: 0
+
+-
+ id: 56
+ owner_id: 2
+ owner_name: user2
+ lower_name: readme-test
+ name: readme-test
+ default_branch: master
+ is_empty: false
+ is_archived: false
+ is_private: true
+ status: 0
+ num_issues: 0
diff --git a/models/fixtures/team.yml b/models/fixtures/team.yml
index dd434d78a..be988b8fc 100644
--- a/models/fixtures/team.yml
+++ b/models/fixtures/team.yml
@@ -151,3 +151,25 @@
num_members: 1
includes_all_repositories: false
can_create_org_repo: true
+
+-
+ id: 15
+ org_id: 22
+ lower_name: owners
+ name: Owners
+ authorize: 4 # owner
+ num_repos: 0
+ num_members: 0
+ includes_all_repositories: false
+ can_create_org_repo: true
+
+-
+ id: 16
+ org_id: 23
+ lower_name: owners
+ name: Owners
+ authorize: 4 # owner
+ num_repos: 0
+ num_members: 0
+ includes_all_repositories: false
+ can_create_org_repo: true \ No newline at end of file
diff --git a/models/fixtures/user.yml b/models/fixtures/user.yml
index b1c7fc003..ce54defac 100644
--- a/models/fixtures/user.yml
+++ b/models/fixtures/user.yml
@@ -66,7 +66,7 @@
num_followers: 2
num_following: 1
num_stars: 2
- num_repos: 11
+ num_repos: 12
num_teams: 0
num_members: 0
visibility: 0
@@ -807,7 +807,7 @@
num_following: 0
num_stars: 0
num_repos: 2
- num_teams: 0
+ num_teams: 1
num_members: 0
visibility: 1
repo_admin_change_team_access: false
@@ -844,7 +844,7 @@
num_following: 0
num_stars: 0
num_repos: 2
- num_teams: 0
+ num_teams: 1
num_members: 0
visibility: 2
repo_admin_change_team_access: false
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/git/commit_status.go b/models/git/commit_status.go
index 489507f71..82cbb2363 100644
--- a/models/git/commit_status.go
+++ b/models/git/commit_status.go
@@ -65,7 +65,7 @@ func postgresGetCommitStatusIndex(ctx context.Context, repoID int64, sha string)
// GetNextCommitStatusIndex retried 3 times to generate a resource index
func GetNextCommitStatusIndex(ctx context.Context, repoID int64, sha string) (int64, error) {
- if setting.Database.UsePostgreSQL {
+ if setting.Database.Type.IsPostgreSQL() {
return postgresGetCommitStatusIndex(ctx, repoID, sha)
}
diff --git a/models/git/lfs_lock.go b/models/git/lfs_lock.go
index 25480f3f9..178fa72f0 100644
--- a/models/git/lfs_lock.go
+++ b/models/git/lfs_lock.go
@@ -6,7 +6,6 @@ package git
import (
"context"
"fmt"
- "path"
"strings"
"time"
@@ -17,6 +16,7 @@ import (
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/util"
)
// LFSLock represents a git lfs lock of repository.
@@ -34,11 +34,7 @@ func init() {
// BeforeInsert is invoked from XORM before inserting an object of this type.
func (l *LFSLock) BeforeInsert() {
- l.Path = cleanPath(l.Path)
-}
-
-func cleanPath(p string) string {
- return path.Clean("/" + p)[1:]
+ l.Path = util.CleanPath(l.Path)
}
// CreateLFSLock creates a new lock.
@@ -53,7 +49,7 @@ func CreateLFSLock(ctx context.Context, repo *repo_model.Repository, lock *LFSLo
return nil, err
}
- lock.Path = cleanPath(lock.Path)
+ lock.Path = util.CleanPath(lock.Path)
lock.RepoID = repo.ID
l, err := GetLFSLock(dbCtx, repo, lock.Path)
@@ -73,7 +69,7 @@ func CreateLFSLock(ctx context.Context, repo *repo_model.Repository, lock *LFSLo
// GetLFSLock returns release by given path.
func GetLFSLock(ctx context.Context, repo *repo_model.Repository, path string) (*LFSLock, error) {
- path = cleanPath(path)
+ path = util.CleanPath(path)
rel := &LFSLock{RepoID: repo.ID}
has, err := db.GetEngine(ctx).Where("lower(path) = ?", strings.ToLower(path)).Get(rel)
if err != nil {
diff --git a/models/issues/label.go b/models/issues/label.go
index 90e4eb458..35c649e8f 100644
--- a/models/issues/label.go
+++ b/models/issues/label.go
@@ -7,12 +7,12 @@ package issues
import (
"context"
"fmt"
- "regexp"
"strconv"
"strings"
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/label"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
@@ -78,9 +78,6 @@ func (err ErrLabelNotExist) Unwrap() error {
return util.ErrNotExist
}
-// LabelColorPattern is a regexp witch can validate LabelColor
-var LabelColorPattern = regexp.MustCompile("^#?(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{3})$")
-
// Label represents a label of repository for issues.
type Label struct {
ID int64 `xorm:"pk autoincr"`
@@ -109,12 +106,12 @@ func init() {
}
// CalOpenIssues sets the number of open issues of a label based on the already stored number of closed issues.
-func (label *Label) CalOpenIssues() {
- label.NumOpenIssues = label.NumIssues - label.NumClosedIssues
+func (l *Label) CalOpenIssues() {
+ l.NumOpenIssues = l.NumIssues - l.NumClosedIssues
}
// CalOpenOrgIssues calculates the open issues of a label for a specific repo
-func (label *Label) CalOpenOrgIssues(ctx context.Context, repoID, labelID int64) {
+func (l *Label) CalOpenOrgIssues(ctx context.Context, repoID, labelID int64) {
counts, _ := CountIssuesByRepo(ctx, &IssuesOptions{
RepoID: repoID,
LabelIDs: []int64{labelID},
@@ -122,22 +119,22 @@ func (label *Label) CalOpenOrgIssues(ctx context.Context, repoID, labelID int64)
})
for _, count := range counts {
- label.NumOpenRepoIssues += count
+ l.NumOpenRepoIssues += count
}
}
// LoadSelectedLabelsAfterClick calculates the set of selected labels when a label is clicked
-func (label *Label) LoadSelectedLabelsAfterClick(currentSelectedLabels []int64, currentSelectedExclusiveScopes []string) {
+func (l *Label) LoadSelectedLabelsAfterClick(currentSelectedLabels []int64, currentSelectedExclusiveScopes []string) {
var labelQuerySlice []string
labelSelected := false
- labelID := strconv.FormatInt(label.ID, 10)
- labelScope := label.ExclusiveScope()
+ labelID := strconv.FormatInt(l.ID, 10)
+ labelScope := l.ExclusiveScope()
for i, s := range currentSelectedLabels {
- if s == label.ID {
+ if s == l.ID {
labelSelected = true
- } else if -s == label.ID {
+ } else if -s == l.ID {
labelSelected = true
- label.IsExcluded = true
+ l.IsExcluded = true
} else if s != 0 {
// Exclude other labels in the same scope from selection
if s < 0 || labelScope == "" || labelScope != currentSelectedExclusiveScopes[i] {
@@ -148,23 +145,23 @@ func (label *Label) LoadSelectedLabelsAfterClick(currentSelectedLabels []int64,
if !labelSelected {
labelQuerySlice = append(labelQuerySlice, labelID)
}
- label.IsSelected = labelSelected
- label.QueryString = strings.Join(labelQuerySlice, ",")
+ l.IsSelected = labelSelected
+ l.QueryString = strings.Join(labelQuerySlice, ",")
}
// BelongsToOrg returns true if label is an organization label
-func (label *Label) BelongsToOrg() bool {
- return label.OrgID > 0
+func (l *Label) BelongsToOrg() bool {
+ return l.OrgID > 0
}
// BelongsToRepo returns true if label is a repository label
-func (label *Label) BelongsToRepo() bool {
- return label.RepoID > 0
+func (l *Label) BelongsToRepo() bool {
+ return l.RepoID > 0
}
// Get color as RGB values in 0..255 range
-func (label *Label) ColorRGB() (float64, float64, float64, error) {
- color, err := strconv.ParseUint(label.Color[1:], 16, 64)
+func (l *Label) ColorRGB() (float64, float64, float64, error) {
+ color, err := strconv.ParseUint(l.Color[1:], 16, 64)
if err != nil {
return 0, 0, 0, err
}
@@ -176,9 +173,9 @@ func (label *Label) ColorRGB() (float64, float64, float64, error) {
}
// Determine if label text should be light or dark to be readable on background color
-func (label *Label) UseLightTextColor() bool {
- if strings.HasPrefix(label.Color, "#") {
- if r, g, b, err := label.ColorRGB(); err == nil {
+func (l *Label) UseLightTextColor() bool {
+ if strings.HasPrefix(l.Color, "#") {
+ if r, g, b, err := l.ColorRGB(); err == nil {
// Perceived brightness from: https://www.w3.org/TR/AERT/#color-contrast
// In the future WCAG 3 APCA may be a better solution
brightness := (0.299*r + 0.587*g + 0.114*b) / 255
@@ -190,40 +187,26 @@ func (label *Label) UseLightTextColor() bool {
}
// Return scope substring of label name, or empty string if none exists
-func (label *Label) ExclusiveScope() string {
- if !label.Exclusive {
+func (l *Label) ExclusiveScope() string {
+ if !l.Exclusive {
return ""
}
- lastIndex := strings.LastIndex(label.Name, "/")
- if lastIndex == -1 || lastIndex == 0 || lastIndex == len(label.Name)-1 {
+ lastIndex := strings.LastIndex(l.Name, "/")
+ if lastIndex == -1 || lastIndex == 0 || lastIndex == len(l.Name)-1 {
return ""
}
- return label.Name[:lastIndex]
+ return l.Name[:lastIndex]
}
// NewLabel creates a new label
-func NewLabel(ctx context.Context, label *Label) error {
- if !LabelColorPattern.MatchString(label.Color) {
- return fmt.Errorf("bad color code: %s", label.Color)
- }
-
- // normalize case
- label.Color = strings.ToLower(label.Color)
-
- // add leading hash
- if label.Color[0] != '#' {
- label.Color = "#" + label.Color
- }
-
- // convert 3-character shorthand into 6-character version
- if len(label.Color) == 4 {
- r := label.Color[1]
- g := label.Color[2]
- b := label.Color[3]
- label.Color = fmt.Sprintf("#%c%c%c%c%c%c", r, r, g, g, b, b)
+func NewLabel(ctx context.Context, l *Label) error {
+ color, err := label.NormalizeColor(l.Color)
+ if err != nil {
+ return err
}
+ l.Color = color
- return db.Insert(ctx, label)
+ return db.Insert(ctx, l)
}
// NewLabels creates new labels
@@ -234,11 +217,14 @@ func NewLabels(labels ...*Label) error {
}
defer committer.Close()
- for _, label := range labels {
- if !LabelColorPattern.MatchString(label.Color) {
- return fmt.Errorf("bad color code: %s", label.Color)
+ for _, l := range labels {
+ color, err := label.NormalizeColor(l.Color)
+ if err != nil {
+ return err
}
- if err := db.Insert(ctx, label); err != nil {
+ l.Color = color
+
+ if err := db.Insert(ctx, l); err != nil {
return err
}
}
@@ -247,15 +233,18 @@ func NewLabels(labels ...*Label) error {
// UpdateLabel updates label information.
func UpdateLabel(l *Label) error {
- if !LabelColorPattern.MatchString(l.Color) {
- return fmt.Errorf("bad color code: %s", l.Color)
+ color, err := label.NormalizeColor(l.Color)
+ if err != nil {
+ return err
}
+ l.Color = color
+
return updateLabelCols(db.DefaultContext, l, "name", "description", "color", "exclusive")
}
// DeleteLabel delete a label
func DeleteLabel(id, labelID int64) error {
- label, err := GetLabelByID(db.DefaultContext, labelID)
+ l, err := GetLabelByID(db.DefaultContext, labelID)
if err != nil {
if IsErrLabelNotExist(err) {
return nil
@@ -271,10 +260,10 @@ func DeleteLabel(id, labelID int64) error {
sess := db.GetEngine(ctx)
- if label.BelongsToOrg() && label.OrgID != id {
+ if l.BelongsToOrg() && l.OrgID != id {
return nil
}
- if label.BelongsToRepo() && label.RepoID != id {
+ if l.BelongsToRepo() && l.RepoID != id {
return nil
}
@@ -682,14 +671,14 @@ func newIssueLabels(ctx context.Context, issue *Issue, labels []*Label, doer *us
if err = issue.LoadRepo(ctx); err != nil {
return err
}
- for _, label := range labels {
+ for _, l := range labels {
// Don't add already present labels and invalid labels
- if HasIssueLabel(ctx, issue.ID, label.ID) ||
- (label.RepoID != issue.RepoID && label.OrgID != issue.Repo.OwnerID) {
+ if HasIssueLabel(ctx, issue.ID, l.ID) ||
+ (l.RepoID != issue.RepoID && l.OrgID != issue.Repo.OwnerID) {
continue
}
- if err = newIssueLabel(ctx, issue, label, doer); err != nil {
+ if err = newIssueLabel(ctx, issue, l, doer); err != nil {
return fmt.Errorf("newIssueLabel: %w", err)
}
}
diff --git a/models/issues/label_test.go b/models/issues/label_test.go
index 0e45e0db0..1f6ce4f42 100644
--- a/models/issues/label_test.go
+++ b/models/issues/label_test.go
@@ -15,8 +15,6 @@ import (
"github.com/stretchr/testify/assert"
)
-// TODO TestGetLabelTemplateFile
-
func TestLabel_CalOpenIssues(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
label := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
diff --git a/models/issues/pull_list.go b/models/issues/pull_list.go
index f4efd916c..9d361c5c5 100644
--- a/models/issues/pull_list.go
+++ b/models/issues/pull_list.go
@@ -52,13 +52,16 @@ func listPullRequestStatement(baseRepoID int64, opts *PullRequestsOptions) (*xor
// GetUnmergedPullRequestsByHeadInfo returns all pull requests that are open and has not been merged
// by given head information (repo and branch).
-func GetUnmergedPullRequestsByHeadInfo(repoID int64, branch string) ([]*PullRequest, error) {
+// arg `includeClosed` controls whether the SQL returns closed PRs
+func GetUnmergedPullRequestsByHeadInfo(repoID int64, branch string, includeClosed bool) ([]*PullRequest, error) {
prs := make([]*PullRequest, 0, 2)
- return prs, db.GetEngine(db.DefaultContext).
- Where("head_repo_id = ? AND head_branch = ? AND has_merged = ? AND issue.is_closed = ? AND flow = ?",
- repoID, branch, false, false, PullRequestFlowGithub).
+ sess := db.GetEngine(db.DefaultContext).
Join("INNER", "issue", "issue.id = pull_request.issue_id").
- Find(&prs)
+ Where("head_repo_id = ? AND head_branch = ? AND has_merged = ? AND flow = ?", repoID, branch, false, PullRequestFlowGithub)
+ if !includeClosed {
+ sess.Where("issue.is_closed = ?", false)
+ }
+ return prs, sess.Find(&prs)
}
// CanMaintainerWriteToBranch check whether user is a maintainer and could write to the branch
@@ -71,7 +74,7 @@ func CanMaintainerWriteToBranch(p access_model.Permission, branch string, user *
return false
}
- prs, err := GetUnmergedPullRequestsByHeadInfo(p.Units[0].RepoID, branch)
+ prs, err := GetUnmergedPullRequestsByHeadInfo(p.Units[0].RepoID, branch, false)
if err != nil {
return false
}
@@ -111,6 +114,7 @@ func GetUnmergedPullRequestsByBaseInfo(repoID int64, branch string) ([]*PullRequ
return prs, db.GetEngine(db.DefaultContext).
Where("base_repo_id=? AND base_branch=? AND has_merged=? AND issue.is_closed=?",
repoID, branch, false, false).
+ OrderBy("issue.updated_unix DESC").
Join("INNER", "issue", "issue.id=pull_request.issue_id").
Find(&prs)
}
diff --git a/models/issues/pull_test.go b/models/issues/pull_test.go
index 8ce8eecc4..bcd33329e 100644
--- a/models/issues/pull_test.go
+++ b/models/issues/pull_test.go
@@ -118,7 +118,7 @@ func TestHasUnmergedPullRequestsByHeadInfo(t *testing.T) {
func TestGetUnmergedPullRequestsByHeadInfo(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(1, "branch2")
+ prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(1, "branch2", false)
assert.NoError(t, err)
assert.Len(t, prs, 1)
for _, pr := range prs {
diff --git a/models/issues/stopwatch.go b/models/issues/stopwatch.go
index 6bf936c5d..c8cd5ad33 100644
--- a/models/issues/stopwatch.go
+++ b/models/issues/stopwatch.go
@@ -9,6 +9,7 @@ import (
"time"
"code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
@@ -132,12 +133,26 @@ func StopwatchExists(userID, issueID int64) bool {
}
// HasUserStopwatch returns true if the user has a stopwatch
-func HasUserStopwatch(ctx context.Context, userID int64) (exists bool, sw *Stopwatch, err error) {
- sw = new(Stopwatch)
+func HasUserStopwatch(ctx context.Context, userID int64) (exists bool, sw *Stopwatch, issue *Issue, err error) {
+ type stopwatchIssueRepo struct {
+ Stopwatch `xorm:"extends"`
+ Issue `xorm:"extends"`
+ repo.Repository `xorm:"extends"`
+ }
+
+ swIR := new(stopwatchIssueRepo)
exists, err = db.GetEngine(ctx).
+ Table("stopwatch").
Where("user_id = ?", userID).
- Get(sw)
- return exists, sw, err
+ Join("INNER", "issue", "issue.id = stopwatch.issue_id").
+ Join("INNER", "repository", "repository.id = issue.repo_id").
+ Get(swIR)
+ if exists {
+ sw = &swIR.Stopwatch
+ issue = &swIR.Issue
+ issue.Repo = &swIR.Repository
+ }
+ return exists, sw, issue, err
}
// FinishIssueStopwatchIfPossible if stopwatch exist then finish it otherwise ignore
@@ -217,23 +232,18 @@ func CreateIssueStopwatch(ctx context.Context, user *user_model.User, issue *Iss
}
// if another stopwatch is running: stop it
- exists, sw, err := HasUserStopwatch(ctx, user.ID)
+ exists, _, otherIssue, err := HasUserStopwatch(ctx, user.ID)
if err != nil {
return err
}
if exists {
- issue, err := GetIssueByID(ctx, sw.IssueID)
- if err != nil {
- return err
- }
-
- if err := FinishIssueStopwatch(ctx, user, issue); err != nil {
+ if err := FinishIssueStopwatch(ctx, user, otherIssue); err != nil {
return err
}
}
// Create stopwatch
- sw = &Stopwatch{
+ sw := &Stopwatch{
UserID: user.ID,
IssueID: issue.ID,
}
diff --git a/models/issues/stopwatch_test.go b/models/issues/stopwatch_test.go
index ec2778aa8..ea3827a1f 100644
--- a/models/issues/stopwatch_test.go
+++ b/models/issues/stopwatch_test.go
@@ -45,12 +45,12 @@ func TestStopwatchExists(t *testing.T) {
func TestHasUserStopwatch(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- exists, sw, err := issues_model.HasUserStopwatch(db.DefaultContext, 1)
+ exists, sw, _, err := issues_model.HasUserStopwatch(db.DefaultContext, 1)
assert.NoError(t, err)
assert.True(t, exists)
assert.Equal(t, int64(1), sw.ID)
- exists, _, err = issues_model.HasUserStopwatch(db.DefaultContext, 3)
+ exists, _, _, err = issues_model.HasUserStopwatch(db.DefaultContext, 3)
assert.NoError(t, err)
assert.False(t, exists)
}
diff --git a/models/migrations/base/db.go b/models/migrations/base/db.go
index dcf99c96a..b038ad733 100644
--- a/models/migrations/base/db.go
+++ b/models/migrations/base/db.go
@@ -89,7 +89,7 @@ func RecreateTable(sess *xorm.Session, bean interface{}) error {
hasID = hasID || (column.IsPrimaryKey && column.IsAutoIncrement)
}
- if hasID && setting.Database.UseMSSQL {
+ if hasID && setting.Database.Type.IsMSSQL() {
if _, err := sess.Exec(fmt.Sprintf("SET IDENTITY_INSERT `%s` ON", tempTableName)); err != nil {
log.Error("Unable to set identity insert for table %s. Error: %v", tempTableName, err)
return err
@@ -143,7 +143,7 @@ func RecreateTable(sess *xorm.Session, bean interface{}) error {
return err
}
- if hasID && setting.Database.UseMSSQL {
+ if hasID && setting.Database.Type.IsMSSQL() {
if _, err := sess.Exec(fmt.Sprintf("SET IDENTITY_INSERT `%s` OFF", tempTableName)); err != nil {
log.Error("Unable to switch off identity insert for table %s. Error: %v", tempTableName, err)
return err
@@ -151,7 +151,7 @@ func RecreateTable(sess *xorm.Session, bean interface{}) error {
}
switch {
- case setting.Database.UseSQLite3:
+ case setting.Database.Type.IsSQLite3():
// SQLite will drop all the constraints on the old table
if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil {
log.Error("Unable to drop old table %s. Error: %v", tableName, err)
@@ -178,7 +178,7 @@ func RecreateTable(sess *xorm.Session, bean interface{}) error {
return err
}
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
// MySQL will drop all the constraints on the old table
if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil {
log.Error("Unable to drop old table %s. Error: %v", tableName, err)
@@ -205,7 +205,7 @@ func RecreateTable(sess *xorm.Session, bean interface{}) error {
log.Error("Unable to recreate uniques on table %s. Error: %v", tableName, err)
return err
}
- case setting.Database.UsePostgreSQL:
+ case setting.Database.Type.IsPostgreSQL():
var originalSequences []string
type sequenceData struct {
LastValue int `xorm:"'last_value'"`
@@ -296,7 +296,7 @@ func RecreateTable(sess *xorm.Session, bean interface{}) error {
}
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
// MSSQL will drop all the constraints on the old table
if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil {
log.Error("Unable to drop old table %s. Error: %v", tableName, err)
@@ -323,7 +323,7 @@ func DropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
// TODO: This will not work if there are foreign keys
switch {
- case setting.Database.UseSQLite3:
+ case setting.Database.Type.IsSQLite3():
// First drop the indexes on the columns
res, errIndex := sess.Query(fmt.Sprintf("PRAGMA index_list(`%s`)", tableName))
if errIndex != nil {
@@ -405,7 +405,7 @@ func DropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
return err
}
- case setting.Database.UsePostgreSQL:
+ case setting.Database.Type.IsPostgreSQL():
cols := ""
for _, col := range columnNames {
if cols != "" {
@@ -416,7 +416,7 @@ func DropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil {
return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err)
}
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
// Drop indexes on columns first
sql := fmt.Sprintf("SHOW INDEX FROM %s WHERE column_name IN ('%s')", tableName, strings.Join(columnNames, "','"))
res, err := sess.Query(sql)
@@ -444,7 +444,7 @@ func DropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil {
return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err)
}
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
cols := ""
for _, col := range columnNames {
if cols != "" {
@@ -543,13 +543,13 @@ func newXORMEngine() (*xorm.Engine, error) {
func deleteDB() error {
switch {
- case setting.Database.UseSQLite3:
+ case setting.Database.Type.IsSQLite3():
if err := util.Remove(setting.Database.Path); err != nil {
return err
}
return os.MkdirAll(path.Dir(setting.Database.Path), os.ModePerm)
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/",
setting.Database.User, setting.Database.Passwd, setting.Database.Host))
if err != nil {
@@ -565,7 +565,7 @@ func deleteDB() error {
return err
}
return nil
- case setting.Database.UsePostgreSQL:
+ case setting.Database.Type.IsPostgreSQL():
db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/?sslmode=%s",
setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.SSLMode))
if err != nil {
@@ -612,7 +612,7 @@ func deleteDB() error {
}
return nil
}
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
host, port := setting.ParseMSSQLHostPort(setting.Database.Host)
db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;",
host, port, "master", setting.Database.User, setting.Database.Passwd))
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_12/v139.go b/models/migrations/v1_12/v139.go
index 725b8fa30..279aa7df8 100644
--- a/models/migrations/v1_12/v139.go
+++ b/models/migrations/v1_12/v139.go
@@ -13,9 +13,9 @@ func PrependRefsHeadsToIssueRefs(x *xorm.Engine) error {
var query string
switch {
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
query = "UPDATE `issue` SET `ref` = 'refs/heads/' + `ref` WHERE `ref` IS NOT NULL AND `ref` <> '' AND `ref` NOT LIKE 'refs/%'"
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
query = "UPDATE `issue` SET `ref` = CONCAT('refs/heads/', `ref`) WHERE `ref` IS NOT NULL AND `ref` <> '' AND `ref` NOT LIKE 'refs/%';"
default:
query = "UPDATE `issue` SET `ref` = 'refs/heads/' || `ref` WHERE `ref` IS NOT NULL AND `ref` <> '' AND `ref` NOT LIKE 'refs/%'"
diff --git a/models/migrations/v1_13/v140.go b/models/migrations/v1_13/v140.go
index 3de9eaaf7..4d87b955f 100644
--- a/models/migrations/v1_13/v140.go
+++ b/models/migrations/v1_13/v140.go
@@ -41,7 +41,7 @@ func FixLanguageStatsToSaveSize(x *xorm.Engine) error {
// Delete language stat statuses
truncExpr := "TRUNCATE TABLE"
- if setting.Database.UseSQLite3 {
+ if setting.Database.Type.IsSQLite3() {
truncExpr = "DELETE FROM"
}
diff --git a/models/migrations/v1_13/v145.go b/models/migrations/v1_13/v145.go
index c96e79f8a..ee40bfc77 100644
--- a/models/migrations/v1_13/v145.go
+++ b/models/migrations/v1_13/v145.go
@@ -21,7 +21,7 @@ func IncreaseLanguageField(x *xorm.Engine) error {
return err
}
- if setting.Database.UseSQLite3 {
+ if setting.Database.Type.IsSQLite3() {
// SQLite maps VARCHAR to TEXT without size so we're done
return nil
}
@@ -41,11 +41,11 @@ func IncreaseLanguageField(x *xorm.Engine) error {
}
switch {
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE language_stat MODIFY COLUMN language %s", sqlType)); err != nil {
return err
}
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
// Yet again MSSQL just has to be awkward.
// Here we have to drop the constraints first and then rebuild them
constraints := make([]string, 0)
@@ -71,7 +71,7 @@ func IncreaseLanguageField(x *xorm.Engine) error {
if err := sess.CreateUniques(new(LanguageStat)); err != nil {
return err
}
- case setting.Database.UsePostgreSQL:
+ case setting.Database.Type.IsPostgreSQL():
if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE language_stat ALTER COLUMN language TYPE %s", sqlType)); err != nil {
return err
}
diff --git a/models/migrations/v1_13/v151.go b/models/migrations/v1_13/v151.go
index 9490c1778..9aa71ec29 100644
--- a/models/migrations/v1_13/v151.go
+++ b/models/migrations/v1_13/v151.go
@@ -17,13 +17,13 @@ import (
func SetDefaultPasswordToArgon2(x *xorm.Engine) error {
switch {
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
_, err := x.Exec("ALTER TABLE `user` ALTER passwd_hash_algo SET DEFAULT 'argon2';")
return err
- case setting.Database.UsePostgreSQL:
+ case setting.Database.Type.IsPostgreSQL():
_, err := x.Exec("ALTER TABLE `user` ALTER COLUMN passwd_hash_algo SET DEFAULT 'argon2';")
return err
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
// need to find the constraint and drop it, then recreate it.
sess := x.NewSession()
defer sess.Close()
@@ -53,7 +53,7 @@ func SetDefaultPasswordToArgon2(x *xorm.Engine) error {
}
return sess.Commit()
- case setting.Database.UseSQLite3:
+ case setting.Database.Type.IsSQLite3():
// drop through
default:
log.Fatal("Unrecognized DB")
diff --git a/models/migrations/v1_14/v158.go b/models/migrations/v1_14/v158.go
index 7ea80a659..2029829ff 100644
--- a/models/migrations/v1_14/v158.go
+++ b/models/migrations/v1_14/v158.go
@@ -62,7 +62,7 @@ func UpdateCodeCommentReplies(x *xorm.Engine) error {
return err
}
- if setting.Database.UseMSSQL {
+ if setting.Database.Type.IsMSSQL() {
if _, err := sess.Exec(sqlSelect + " INTO #temp_comments" + sqlTail); err != nil {
log.Error("unable to create temporary table")
return err
@@ -72,13 +72,13 @@ func UpdateCodeCommentReplies(x *xorm.Engine) error {
comments := make([]*Comment, 0, batchSize)
switch {
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
sqlCmd = sqlSelect + sqlTail + " LIMIT " + strconv.Itoa(batchSize) + ", " + strconv.Itoa(start)
- case setting.Database.UsePostgreSQL:
+ case setting.Database.Type.IsPostgreSQL():
fallthrough
- case setting.Database.UseSQLite3:
+ case setting.Database.Type.IsSQLite3():
sqlCmd = sqlSelect + sqlTail + " LIMIT " + strconv.Itoa(batchSize) + " OFFSET " + strconv.Itoa(start)
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
sqlCmd = "SELECT TOP " + strconv.Itoa(batchSize) + " * FROM #temp_comments WHERE " +
"(id NOT IN ( SELECT TOP " + strconv.Itoa(start) + " id FROM #temp_comments ORDER BY id )) ORDER BY id"
default:
diff --git a/models/migrations/v1_14/v175.go b/models/migrations/v1_14/v175.go
index f1b9b974c..70d72b260 100644
--- a/models/migrations/v1_14/v175.go
+++ b/models/migrations/v1_14/v175.go
@@ -14,7 +14,7 @@ import (
)
func FixPostgresIDSequences(x *xorm.Engine) error {
- if !setting.Database.UsePostgreSQL {
+ if !setting.Database.Type.IsPostgreSQL() {
return nil
}
diff --git a/models/migrations/v1_15/v184.go b/models/migrations/v1_15/v184.go
index 48f8b6216..caf41b604 100644
--- a/models/migrations/v1_15/v184.go
+++ b/models/migrations/v1_15/v184.go
@@ -54,11 +54,11 @@ func RenameTaskErrorsToMessage(x *xorm.Engine) error {
}
switch {
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
if _, err := sess.Exec("ALTER TABLE `task` CHANGE errors message text"); err != nil {
return err
}
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
if _, err := sess.Exec("sp_rename 'task.errors', 'message', 'COLUMN'"); err != nil {
return err
}
diff --git a/models/migrations/v1_16/v191.go b/models/migrations/v1_16/v191.go
index 2d2c3d1a5..c618783c0 100644
--- a/models/migrations/v1_16/v191.go
+++ b/models/migrations/v1_16/v191.go
@@ -16,7 +16,7 @@ func AlterIssueAndCommentTextFieldsToLongText(x *xorm.Engine) error {
return err
}
- if setting.Database.UseMySQL {
+ if setting.Database.Type.IsMySQL() {
if _, err := sess.Exec("ALTER TABLE `issue` CHANGE `content` `content` LONGTEXT"); err != nil {
return err
}
diff --git a/models/migrations/v1_17/v217.go b/models/migrations/v1_17/v217.go
index 3ca9215f0..3f970b68a 100644
--- a/models/migrations/v1_17/v217.go
+++ b/models/migrations/v1_17/v217.go
@@ -16,7 +16,7 @@ func AlterHookTaskTextFieldsToLongText(x *xorm.Engine) error {
return err
}
- if setting.Database.UseMySQL {
+ if setting.Database.Type.IsMySQL() {
if _, err := sess.Exec("ALTER TABLE `hook_task` CHANGE `payload_content` `payload_content` LONGTEXT, CHANGE `request_content` `request_content` LONGTEXT, change `response_content` `response_content` LONGTEXT"); err != nil {
return err
}
diff --git a/models/migrations/v1_17/v218.go b/models/migrations/v1_17/v218.go
index 675fd1df9..ae91ba0c4 100644
--- a/models/migrations/v1_17/v218.go
+++ b/models/migrations/v1_17/v218.go
@@ -38,7 +38,7 @@ func (*improveActionTableIndicesAction) TableIndices() []*schemas.Index {
actUserIndex := schemas.NewIndex("au_r_c_u_d", schemas.IndexType)
actUserIndex.AddColumn("act_user_id", "repo_id", "created_unix", "user_id", "is_deleted")
indices := []*schemas.Index{actUserIndex, repoIndex}
- if setting.Database.UsePostgreSQL {
+ if setting.Database.Type.IsPostgreSQL() {
cudIndex := schemas.NewIndex("c_u_d", schemas.IndexType)
cudIndex.AddColumn("created_unix", "user_id", "is_deleted")
indices = append(indices, cudIndex)
diff --git a/models/migrations/v1_17/v223.go b/models/migrations/v1_17/v223.go
index a23d9916b..6c61dbc53 100644
--- a/models/migrations/v1_17/v223.go
+++ b/models/migrations/v1_17/v223.go
@@ -65,11 +65,11 @@ func RenameCredentialIDBytes(x *xorm.Engine) error {
}
switch {
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
if _, err := sess.Exec("ALTER TABLE `webauthn_credential` CHANGE credential_id_bytes credential_id VARBINARY(1024)"); err != nil {
return err
}
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
if _, err := sess.Exec("sp_rename 'webauthn_credential.credential_id_bytes', 'credential_id', 'COLUMN'"); err != nil {
return err
}
diff --git a/models/migrations/v1_18/v225.go b/models/migrations/v1_18/v225.go
index 786772c14..b0ac3777f 100644
--- a/models/migrations/v1_18/v225.go
+++ b/models/migrations/v1_18/v225.go
@@ -16,7 +16,7 @@ func AlterPublicGPGKeyContentFieldsToMediumText(x *xorm.Engine) error {
return err
}
- if setting.Database.UseMySQL {
+ if setting.Database.Type.IsMySQL() {
if _, err := sess.Exec("ALTER TABLE `gpg_key` CHANGE `content` `content` MEDIUMTEXT"); err != nil {
return err
}
diff --git a/models/migrations/v1_19/v232.go b/models/migrations/v1_19/v232.go
index 89b595c54..9caf587c1 100644
--- a/models/migrations/v1_19/v232.go
+++ b/models/migrations/v1_19/v232.go
@@ -16,7 +16,7 @@ func AlterPackageVersionMetadataToLongText(x *xorm.Engine) error {
return err
}
- if setting.Database.UseMySQL {
+ if setting.Database.Type.IsMySQL() {
if _, err := sess.Exec("ALTER TABLE `package_version` MODIFY COLUMN `metadata_json` LONGTEXT"); err != nil {
return err
}
diff --git a/models/migrations/v1_19/v242.go b/models/migrations/v1_19/v242.go
index 517c7767b..447083521 100644
--- a/models/migrations/v1_19/v242.go
+++ b/models/migrations/v1_19/v242.go
@@ -17,7 +17,7 @@ func AlterPublicGPGKeyImportContentFieldToMediumText(x *xorm.Engine) error {
return err
}
- if setting.Database.UseMySQL {
+ if setting.Database.Type.IsMySQL() {
if _, err := sess.Exec("ALTER TABLE `gpg_key_import` CHANGE `content` `content` MEDIUMTEXT"); err != nil {
return err
}
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/organization/org.go b/models/organization/org.go
index f05027be7..269b3e832 100644
--- a/models/organization/org.go
+++ b/models/organization/org.go
@@ -239,6 +239,32 @@ func (org *Organization) CustomAvatarRelativePath() string {
return org.Avatar
}
+// UnitPermission returns unit permission
+func (org *Organization) UnitPermission(ctx context.Context, doer *user_model.User, unitType unit.Type) perm.AccessMode {
+ if doer != nil {
+ teams, err := GetUserOrgTeams(ctx, org.ID, doer.ID)
+ if err != nil {
+ log.Error("GetUserOrgTeams: %v", err)
+ return perm.AccessModeNone
+ }
+
+ if err := teams.LoadUnits(ctx); err != nil {
+ log.Error("LoadUnits: %v", err)
+ return perm.AccessModeNone
+ }
+
+ if len(teams) > 0 {
+ return teams.UnitMaxAccess(unitType)
+ }
+ }
+
+ if org.Visibility.IsPublic() {
+ return perm.AccessModeRead
+ }
+
+ return perm.AccessModeNone
+}
+
// CreateOrganization creates record of a new organization.
func CreateOrganization(org *Organization, owner *user_model.User) (err error) {
if !owner.CanCreateOrganization() {
diff --git a/models/project/project.go b/models/project/project.go
index 46b5c07c4..f3ed72303 100644
--- a/models/project/project.go
+++ b/models/project/project.go
@@ -409,7 +409,7 @@ func DeleteProjectByID(ctx context.Context, id int64) error {
func DeleteProjectByRepoID(ctx context.Context, repoID int64) error {
switch {
- case setting.Database.UseSQLite3:
+ case setting.Database.Type.IsSQLite3():
if _, err := db.GetEngine(ctx).Exec("DELETE FROM project_issue WHERE project_issue.id IN (SELECT project_issue.id FROM project_issue INNER JOIN project WHERE project.id = project_issue.project_id AND project.repo_id = ?)", repoID); err != nil {
return err
}
@@ -419,7 +419,7 @@ func DeleteProjectByRepoID(ctx context.Context, repoID int64) error {
if _, err := db.GetEngine(ctx).Table("project").Where("repo_id = ? ", repoID).Delete(&Project{}); err != nil {
return err
}
- case setting.Database.UsePostgreSQL:
+ case setting.Database.Type.IsPostgreSQL():
if _, err := db.GetEngine(ctx).Exec("DELETE FROM project_issue USING project WHERE project.id = project_issue.project_id AND project.repo_id = ? ", repoID); err != nil {
return err
}
diff --git a/models/repo/repo_list.go b/models/repo/repo_list.go
index d64368daa..d9cd905a1 100644
--- a/models/repo/repo_list.go
+++ b/models/repo/repo_list.go
@@ -498,7 +498,7 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
subQueryCond := builder.NewCond()
// Topic checking. Topics are present.
- if setting.Database.UsePostgreSQL { // postgres stores the topics as json and not as text
+ if setting.Database.Type.IsPostgreSQL() { // postgres stores the topics as json and not as text
subQueryCond = subQueryCond.Or(builder.And(builder.NotNull{"topics"}, builder.Neq{"(topics)::text": "[]"}))
} else {
subQueryCond = subQueryCond.Or(builder.And(builder.Neq{"topics": "null"}, builder.Neq{"topics": "[]"}))
diff --git a/models/unittest/testdb.go b/models/unittest/testdb.go
index 2bc41084b..cff1489a7 100644
--- a/models/unittest/testdb.go
+++ b/models/unittest/testdb.go
@@ -76,7 +76,7 @@ func MainTest(m *testing.M, testOpts *TestOptions) {
setting.SSH.BuiltinServerUser = "builtinuser"
setting.SSH.Port = 3000
setting.SSH.Domain = "try.gitea.io"
- setting.Database.UseSQLite3 = true
+ setting.Database.Type = "sqlite3"
setting.Repository.DefaultBranch = "master" // many test code still assume that default branch is called "master"
repoRootPath, err := os.MkdirTemp(os.TempDir(), "repos")
if err != nil {
diff --git a/models/user/user.go b/models/user/user.go
index 3a2e4f19b..7bc88e773 100644
--- a/models/user/user.go
+++ b/models/user/user.go
@@ -394,6 +394,11 @@ func (u *User) IsOrganization() bool {
return u.Type == UserTypeOrganization
}
+// IsIndividual returns true if user is actually a individual user.
+func (u *User) IsIndividual() bool {
+ return u.Type == UserTypeIndividual
+}
+
// DisplayName returns full name if it's not empty,
// returns username otherwise.
func (u *User) DisplayName() string {
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))
}