From 72b3ac7192266cf20e9f08149a2f1e864a4eac5f Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 16 Nov 2023 11:14:24 +0800 Subject: [PATCH 01/21] Use db.Find instead of writing methods for every object --- models/actions/run.go | 4 +- models/actions/run_job_list.go | 11 ++--- models/actions/run_list.go | 16 ++----- models/actions/runner.go | 23 ++-------- models/db/list.go | 65 ++++++++++++++++++++++----- models/project/project.go | 15 +++---- routers/api/actions/runner/utils.go | 3 +- routers/web/org/projects.go | 8 +++- routers/web/repo/actions/actions.go | 9 ++-- routers/web/repo/issue.go | 16 +++++-- routers/web/repo/projects.go | 6 ++- routers/web/shared/actions/runners.go | 9 +--- services/actions/clear_tasks.go | 2 +- services/actions/job_emitter.go | 2 +- services/actions/notifier_helper.go | 5 ++- services/pull/review.go | 6 +-- 16 files changed, 109 insertions(+), 91 deletions(-) diff --git a/models/actions/run.go b/models/actions/run.go index 8078613fb8f5..9ffc551cf08b 100644 --- a/models/actions/run.go +++ b/models/actions/run.go @@ -170,7 +170,7 @@ func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) err // CancelRunningJobs cancels all running and waiting jobs associated with a specific workflow. func CancelRunningJobs(ctx context.Context, repoID int64, ref, workflowID string) error { // Find all runs in the specified repository, reference, and workflow with statuses 'Running' or 'Waiting'. - runs, total, err := FindRuns(ctx, FindRunOptions{ + runs, total, err := db.FindAndCount[*ActionRun](ctx, &FindRunOptions{ RepoID: repoID, Ref: ref, WorkflowID: workflowID, @@ -188,7 +188,7 @@ func CancelRunningJobs(ctx context.Context, repoID int64, ref, workflowID string // Iterate over each found run and cancel its associated jobs. for _, run := range runs { // Find all jobs associated with the current run. - jobs, _, err := FindRunJobs(ctx, FindRunJobOptions{ + jobs, _, err := db.FindAndCount[*ActionRunJob](ctx, &FindRunJobOptions{ RunID: run.ID, }) if err != nil { diff --git a/models/actions/run_job_list.go b/models/actions/run_job_list.go index a166396694d1..166291df1525 100644 --- a/models/actions/run_job_list.go +++ b/models/actions/run_job_list.go @@ -61,7 +61,7 @@ type FindRunJobOptions struct { UpdatedBefore timeutil.TimeStamp } -func (opts FindRunJobOptions) toConds() builder.Cond { +func (opts FindRunJobOptions) ToConds() builder.Cond { cond := builder.NewCond() if opts.RunID > 0 { cond = cond.And(builder.Eq{"run_id": opts.RunID}) @@ -84,16 +84,13 @@ func (opts FindRunJobOptions) toConds() builder.Cond { return cond } +/* func FindRunJobs(ctx context.Context, opts FindRunJobOptions) (ActionJobList, int64, error) { - e := db.GetEngine(ctx).Where(opts.toConds()) + e := db.GetEngine(ctx).Where(opts.ToConds()) if opts.PageSize > 0 && opts.Page >= 1 { e.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) } var tasks ActionJobList total, err := e.FindAndCount(&tasks) return tasks, total, err -} - -func CountRunJobs(ctx context.Context, opts FindRunJobOptions) (int64, error) { - return db.GetEngine(ctx).Where(opts.toConds()).Count(new(ActionRunJob)) -} +}*/ diff --git a/models/actions/run_list.go b/models/actions/run_list.go index cd053ea7b544..375c46221b04 100644 --- a/models/actions/run_list.go +++ b/models/actions/run_list.go @@ -75,7 +75,7 @@ type FindRunOptions struct { Status []Status } -func (opts FindRunOptions) toConds() builder.Cond { +func (opts FindRunOptions) ToConds() builder.Cond { cond := builder.NewCond() if opts.RepoID > 0 { cond = cond.And(builder.Eq{"repo_id": opts.RepoID}) @@ -101,18 +101,8 @@ func (opts FindRunOptions) toConds() builder.Cond { return cond } -func FindRuns(ctx context.Context, opts FindRunOptions) (RunList, int64, error) { - e := db.GetEngine(ctx).Where(opts.toConds()) - if opts.PageSize > 0 && opts.Page >= 1 { - e.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) - } - var runs RunList - total, err := e.Desc("id").FindAndCount(&runs) - return runs, total, err -} - -func CountRuns(ctx context.Context, opts FindRunOptions) (int64, error) { - return db.GetEngine(ctx).Where(opts.toConds()).Count(new(ActionRun)) +func (opts FindRunOptions) ToOrders() string { + return "`id` DESC" } type StatusInfo struct { diff --git a/models/actions/runner.go b/models/actions/runner.go index 2c092c2b4a36..717b770800dc 100644 --- a/models/actions/runner.go +++ b/models/actions/runner.go @@ -156,7 +156,7 @@ type FindRunnerOptions struct { WithAvailable bool // not only runners belong to, but also runners can be used } -func (opts FindRunnerOptions) toCond() builder.Cond { +func (opts FindRunnerOptions) ToConds() builder.Cond { cond := builder.NewCond() if opts.RepoID > 0 { @@ -181,7 +181,7 @@ func (opts FindRunnerOptions) toCond() builder.Cond { return cond } -func (opts FindRunnerOptions) toOrder() string { +func (opts FindRunnerOptions) ToOrders() string { switch opts.Sort { case "online": return "last_online DESC" @@ -199,22 +199,6 @@ func (opts FindRunnerOptions) toOrder() string { return "last_online DESC" } -func CountRunners(ctx context.Context, opts FindRunnerOptions) (int64, error) { - return db.GetEngine(ctx). - Where(opts.toCond()). - Count(ActionRunner{}) -} - -func FindRunners(ctx context.Context, opts FindRunnerOptions) (runners RunnerList, err error) { - sess := db.GetEngine(ctx). - Where(opts.toCond()). - OrderBy(opts.toOrder()) - if opts.Page > 0 { - sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) - } - return runners, sess.Find(&runners) -} - // GetRunnerByUUID returns a runner via uuid func GetRunnerByUUID(ctx context.Context, uuid string) (*ActionRunner, error) { var runner ActionRunner @@ -263,8 +247,7 @@ func DeleteRunner(ctx context.Context, id int64) error { // CreateRunner creates new runner. func CreateRunner(ctx context.Context, t *ActionRunner) error { - _, err := db.GetEngine(ctx).Insert(t) - return err + return db.Insert(ctx, t) } func CountRunnersWithoutBelongingOwner(ctx context.Context) (int64, error) { diff --git a/models/db/list.go b/models/db/list.go index 9fb4d0741fde..194717d86650 100644 --- a/models/db/list.go +++ b/models/db/list.go @@ -52,7 +52,10 @@ type ListOptions struct { ListAll bool // if true, then PageSize and Page will not be taken } -var _ Paginator = &ListOptions{} +var ( + _ Paginator = &ListOptions{} + _ FindOptions = &ListOptions{} +) // GetSkipTake returns the skip and take values func (opts *ListOptions) GetSkipTake() (skip, take int) { @@ -67,6 +70,14 @@ func (opts *ListOptions) GetStartEnd() (start, end int) { return start, end } +func (opts *ListOptions) GetPage() int { + return opts.Page +} + +func (opts *ListOptions) GetPageSize() int { + return opts.PageSize +} + // IsListAll indicates PageSize and Page will be ignored func (opts *ListOptions) IsListAll() bool { return opts.ListAll @@ -85,6 +96,10 @@ func (opts *ListOptions) SetDefaultValues() { } } +func (opts *ListOptions) ToConds() builder.Cond { + return builder.NewCond() +} + // AbsoluteListOptions absolute options to paginate results type AbsoluteListOptions struct { skip int @@ -124,29 +139,55 @@ func (opts *AbsoluteListOptions) GetStartEnd() (start, end int) { // FindOptions represents a find options type FindOptions interface { - Paginator + GetPage() int + GetPageSize() int + IsListAll() bool ToConds() builder.Cond } +type FindOptionsOrder interface { + ToOrders() string +} + // Find represents a common find function which accept an options interface -func Find[T any](ctx context.Context, opts FindOptions, objects *[]T) error { +func Find[T any](ctx context.Context, opts FindOptions) ([]T, error) { sess := GetEngine(ctx).Where(opts.ToConds()) - if !opts.IsListAll() { - sess.Limit(opts.GetSkipTake()) + page, pageSize := opts.GetPage(), opts.GetPageSize() + if !opts.IsListAll() && pageSize > 0 && page >= 1 { + sess.Limit(pageSize, (page-1)*pageSize) + } + if newOpt, ok := opts.(FindOptionsOrder); ok { + sess.OrderBy(newOpt.ToOrders()) + } + + var objects []T + if err := sess.Find(objects); err != nil { + return nil, err } - return sess.Find(objects) + return objects, nil } // Count represents a common count function which accept an options interface -func Count[T any](ctx context.Context, opts FindOptions, object T) (int64, error) { - return GetEngine(ctx).Where(opts.ToConds()).Count(object) +func Count[T any](ctx context.Context, opts FindOptions) (int64, error) { + var object T + return GetEngine(ctx).Where(opts.ToConds()).Count(&object) } // FindAndCount represents a common findandcount function which accept an options interface -func FindAndCount[T any](ctx context.Context, opts FindOptions, objects *[]T) (int64, error) { +func FindAndCount[T any](ctx context.Context, opts FindOptions) ([]T, int64, error) { sess := GetEngine(ctx).Where(opts.ToConds()) - if !opts.IsListAll() { - sess.Limit(opts.GetSkipTake()) + page, pageSize := opts.GetPage(), opts.GetPageSize() + if !opts.IsListAll() && pageSize > 0 && page >= 1 { + sess.Limit(pageSize, (page-1)*pageSize) + } + if newOpt, ok := opts.(FindOptionsOrder); ok { + sess.OrderBy(newOpt.ToOrders()) + } + + var objects []T + cnt, err := sess.FindAndCount(&objects) + if err != nil { + return nil, 0, err } - return sess.FindAndCount(objects) + return objects, cnt, nil } diff --git a/models/project/project.go b/models/project/project.go index 3a1bfe1dbd3f..b7fcef0d24c6 100644 --- a/models/project/project.go +++ b/models/project/project.go @@ -192,16 +192,16 @@ func IsTypeValid(p Type) bool { // SearchOptions are options for GetProjects type SearchOptions struct { + db.ListOptions OwnerID int64 RepoID int64 - Page int IsClosed util.OptionalBool OrderBy db.SearchOrderBy Type Type Title string } -func (opts *SearchOptions) toConds() builder.Cond { +func (opts *SearchOptions) ToConds() builder.Cond { cond := builder.NewCond() if opts.RepoID > 0 { cond = cond.And(builder.Eq{"repo_id": opts.RepoID}) @@ -226,11 +226,6 @@ func (opts *SearchOptions) toConds() builder.Cond { return cond } -// CountProjects counts projects -func CountProjects(ctx context.Context, opts SearchOptions) (int64, error) { - return db.GetEngine(ctx).Where(opts.toConds()).Count(new(Project)) -} - func GetSearchOrderByBySortType(sortType string) db.SearchOrderBy { switch sortType { case "oldest": @@ -246,14 +241,14 @@ func GetSearchOrderByBySortType(sortType string) db.SearchOrderBy { // FindProjects returns a list of all projects that have been created in the repository func FindProjects(ctx context.Context, opts SearchOptions) ([]*Project, int64, error) { - e := db.GetEngine(ctx).Where(opts.toConds()) + e := db.GetEngine(ctx).Where(opts.ToConds()) if opts.OrderBy.String() != "" { e = e.OrderBy(opts.OrderBy.String()) } projects := make([]*Project, 0, setting.UI.IssuePagingNum) - if opts.Page > 0 { - e = e.Limit(setting.UI.IssuePagingNum, (opts.Page-1)*setting.UI.IssuePagingNum) + if opts.Page > 0 && !opts.ListAll { + e = e.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) } count, err := e.FindAndCount(&projects) diff --git a/routers/api/actions/runner/utils.go b/routers/api/actions/runner/utils.go index 24432ab6b202..901888ed5522 100644 --- a/routers/api/actions/runner/utils.go +++ b/routers/api/actions/runner/utils.go @@ -8,6 +8,7 @@ import ( "fmt" actions_model "code.gitea.io/gitea/models/actions" + "code.gitea.io/gitea/models/db" secret_model "code.gitea.io/gitea/models/secret" actions_module "code.gitea.io/gitea/modules/actions" "code.gitea.io/gitea/modules/container" @@ -200,7 +201,7 @@ func findTaskNeeds(ctx context.Context, task *actions_model.ActionTask) (map[str } needs := container.SetOf(task.Job.Needs...) - jobs, _, err := actions_model.FindRunJobs(ctx, actions_model.FindRunJobOptions{RunID: task.Job.RunID}) + jobs, err := db.Find[*actions_model.ActionRunJob](ctx, &actions_model.FindRunJobOptions{RunID: task.Job.RunID}) if err != nil { return nil, fmt.Errorf("FindRunJobs: %w", err) } diff --git a/routers/web/org/projects.go b/routers/web/org/projects.go index 439fdf644bb6..ecd989733cce 100644 --- a/routers/web/org/projects.go +++ b/routers/web/org/projects.go @@ -11,6 +11,7 @@ import ( "strconv" "strings" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" project_model "code.gitea.io/gitea/models/project" attachment_model "code.gitea.io/gitea/models/repo" @@ -60,8 +61,11 @@ func Projects(ctx *context.Context) { projectType = project_model.TypeIndividual } projects, total, err := project_model.FindProjects(ctx, project_model.SearchOptions{ + ListOptions: db.ListOptions{ + Page: page, + PageSize: setting.UI.IssuePagingNum, + }, OwnerID: ctx.ContextUser.ID, - Page: page, IsClosed: util.OptionalBoolOf(isShowClosed), OrderBy: project_model.GetSearchOrderByBySortType(sortType), Type: projectType, @@ -72,7 +76,7 @@ func Projects(ctx *context.Context) { return } - opTotal, err := project_model.CountProjects(ctx, project_model.SearchOptions{ + opTotal, err := db.Count[project_model.Project](ctx, &project_model.SearchOptions{ OwnerID: ctx.ContextUser.ID, IsClosed: util.OptionalBoolOf(!isShowClosed), Type: projectType, diff --git a/routers/web/repo/actions/actions.go b/routers/web/repo/actions/actions.go index 6284d21463f3..47ea9441531e 100644 --- a/routers/web/repo/actions/actions.go +++ b/routers/web/repo/actions/actions.go @@ -75,11 +75,10 @@ func List(ctx *context.Context) { } // Get all runner labels - opts := actions_model.FindRunnerOptions{ + runners, err := db.Find[*actions_model.ActionRunner](ctx, &actions_model.FindRunnerOptions{ RepoID: ctx.Repo.Repository.ID, WithAvailable: true, - } - runners, err := actions_model.FindRunners(ctx, opts) + }) if err != nil { ctx.ServerError("FindRunners", err) return @@ -169,7 +168,7 @@ func List(ctx *context.Context) { opts.Status = []actions_model.Status{actions_model.Status(status)} } - runs, total, err := actions_model.FindRuns(ctx, opts) + runs, total, err := db.FindAndCount[*actions_model.ActionRun](ctx, &opts) if err != nil { ctx.Error(http.StatusInternalServerError, err.Error()) return @@ -179,7 +178,7 @@ func List(ctx *context.Context) { run.Repo = ctx.Repo.Repository } - if err := runs.LoadTriggerUser(ctx); err != nil { + if err := actions_model.RunList(runs).LoadTriggerUser(ctx); err != nil { ctx.Error(http.StatusInternalServerError, err.Error()) return } diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 94300da86833..395dfcafb43d 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -570,8 +570,10 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) { } var err error projects, _, err := project_model.FindProjects(ctx, project_model.SearchOptions{ + ListOptions: db.ListOptions{ + ListAll: true, + }, RepoID: repo.ID, - Page: -1, IsClosed: util.OptionalBoolFalse, Type: project_model.TypeRepository, }) @@ -580,8 +582,10 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) { return } projects2, _, err := project_model.FindProjects(ctx, project_model.SearchOptions{ + ListOptions: db.ListOptions{ + ListAll: true, + }, OwnerID: repo.OwnerID, - Page: -1, IsClosed: util.OptionalBoolFalse, Type: repoOwnerType, }) @@ -593,8 +597,10 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) { ctx.Data["OpenProjects"] = append(projects, projects2...) projects, _, err = project_model.FindProjects(ctx, project_model.SearchOptions{ + ListOptions: db.ListOptions{ + ListAll: true, + }, RepoID: repo.ID, - Page: -1, IsClosed: util.OptionalBoolTrue, Type: project_model.TypeRepository, }) @@ -603,8 +609,10 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) { return } projects2, _, err = project_model.FindProjects(ctx, project_model.SearchOptions{ + ListOptions: db.ListOptions{ + ListAll: true, + }, OwnerID: repo.OwnerID, - Page: -1, IsClosed: util.OptionalBoolTrue, Type: repoOwnerType, }) diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go index 6417024f8ba3..1aa4bab9677a 100644 --- a/routers/web/repo/projects.go +++ b/routers/web/repo/projects.go @@ -10,6 +10,7 @@ import ( "net/url" "strings" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/perm" project_model "code.gitea.io/gitea/models/project" @@ -72,8 +73,11 @@ func Projects(ctx *context.Context) { } projects, count, err := project_model.FindProjects(ctx, project_model.SearchOptions{ + ListOptions: db.ListOptions{ + PageSize: setting.UI.IssuePagingNum, + Page: page, + }, RepoID: repo.ID, - Page: page, IsClosed: util.OptionalBoolOf(isShowClosed), OrderBy: project_model.GetSearchOrderByBySortType(sortType), Type: project_model.TypeRepository, diff --git a/routers/web/shared/actions/runners.go b/routers/web/shared/actions/runners.go index 1da4ddf14fc2..4e203d8f8a2c 100644 --- a/routers/web/shared/actions/runners.go +++ b/routers/web/shared/actions/runners.go @@ -17,18 +17,13 @@ import ( // RunnersList prepares data for runners list func RunnersList(ctx *context.Context, opts actions_model.FindRunnerOptions) { - count, err := actions_model.CountRunners(ctx, opts) + runners, count, err := db.FindAndCount[*actions_model.ActionRunner](ctx, &opts) if err != nil { ctx.ServerError("CountRunners", err) return } - runners, err := actions_model.FindRunners(ctx, opts) - if err != nil { - ctx.ServerError("FindRunners", err) - return - } - if err := runners.LoadAttributes(ctx); err != nil { + if err := actions_model.RunnerList(runners).LoadAttributes(ctx); err != nil { ctx.ServerError("LoadAttributes", err) return } diff --git a/services/actions/clear_tasks.go b/services/actions/clear_tasks.go index 7c7043c42f4b..128cb881f6f0 100644 --- a/services/actions/clear_tasks.go +++ b/services/actions/clear_tasks.go @@ -74,7 +74,7 @@ func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error { // CancelAbandonedJobs cancels the jobs which have waiting status, but haven't been picked by a runner for a long time func CancelAbandonedJobs(ctx context.Context) error { - jobs, _, err := actions_model.FindRunJobs(ctx, actions_model.FindRunJobOptions{ + jobs, err := db.Find[*actions_model.ActionRunJob](ctx, &actions_model.FindRunJobOptions{ Statuses: []actions_model.Status{actions_model.StatusWaiting, actions_model.StatusBlocked}, UpdatedBefore: timeutil.TimeStamp(time.Now().Add(-setting.Actions.AbandonedJobTimeout).Unix()), }) diff --git a/services/actions/job_emitter.go b/services/actions/job_emitter.go index f7ec615364a6..8b89d6aae60a 100644 --- a/services/actions/job_emitter.go +++ b/services/actions/job_emitter.go @@ -44,7 +44,7 @@ func jobEmitterQueueHandler(items ...*jobUpdate) []*jobUpdate { } func checkJobsOfRun(ctx context.Context, runID int64) error { - jobs, _, err := actions_model.FindRunJobs(ctx, actions_model.FindRunJobOptions{RunID: runID}) + jobs, err := db.Find[*actions_model.ActionRunJob](ctx, &actions_model.FindRunJobOptions{RunID: runID}) if err != nil { return err } diff --git a/services/actions/notifier_helper.go b/services/actions/notifier_helper.go index 7d5f6c6c0a3c..35aa9e6f690d 100644 --- a/services/actions/notifier_helper.go +++ b/services/actions/notifier_helper.go @@ -10,6 +10,7 @@ import ( "strings" actions_model "code.gitea.io/gitea/models/actions" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" packages_model "code.gitea.io/gitea/models/packages" access_model "code.gitea.io/gitea/models/perm/access" @@ -273,7 +274,7 @@ func handleWorkflows( continue } - alljobs, _, err := actions_model.FindRunJobs(ctx, actions_model.FindRunJobOptions{RunID: run.ID}) + alljobs, err := db.Find[*actions_model.ActionRunJob](ctx, &actions_model.FindRunJobOptions{RunID: run.ID}) if err != nil { log.Error("FindRunJobs: %v", err) continue @@ -352,7 +353,7 @@ func ifNeedApproval(ctx context.Context, run *actions_model.ActionRun, repo *rep } // don't need approval if the user has been approved before - if count, err := actions_model.CountRuns(ctx, actions_model.FindRunOptions{ + if count, err := db.Count[actions_model.ActionRun](ctx, &actions_model.FindRunOptions{ RepoID: repo.ID, TriggerUserID: user.ID, Approved: true, diff --git a/services/pull/review.go b/services/pull/review.go index 3f5644b0cd4f..65d5f4816d01 100644 --- a/services/pull/review.go +++ b/services/pull/review.go @@ -49,16 +49,16 @@ func InvalidateCodeComments(ctx context.Context, prs issues_model.PullRequestLis return nil } issueIDs := prs.GetIssueIDs() - var codeComments []*issues_model.Comment - if err := db.Find(ctx, &issues_model.FindCommentsOptions{ + codeComments, err := db.Find[*issues_model.Comment](ctx, &issues_model.FindCommentsOptions{ ListOptions: db.ListOptions{ ListAll: true, }, Type: issues_model.CommentTypeCode, Invalidated: util.OptionalBoolFalse, IssueIDs: issueIDs, - }, &codeComments); err != nil { + }) + if err != nil { return fmt.Errorf("find code comments: %v", err) } for _, comment := range codeComments { From 4e5b90d0be342e599f318bceab6f3664f98ab78f Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 16 Nov 2023 11:17:23 +0800 Subject: [PATCH 02/21] remove comment code --- models/actions/run_job_list.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/models/actions/run_job_list.go b/models/actions/run_job_list.go index 166291df1525..6ea6cb9d3b30 100644 --- a/models/actions/run_job_list.go +++ b/models/actions/run_job_list.go @@ -83,14 +83,3 @@ func (opts FindRunJobOptions) ToConds() builder.Cond { } return cond } - -/* -func FindRunJobs(ctx context.Context, opts FindRunJobOptions) (ActionJobList, int64, error) { - e := db.GetEngine(ctx).Where(opts.ToConds()) - if opts.PageSize > 0 && opts.Page >= 1 { - e.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) - } - var tasks ActionJobList - total, err := e.FindAndCount(&tasks) - return tasks, total, err -}*/ From e4ab82ff3125973708607c3dae701917be724557 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 16 Nov 2023 11:25:28 +0800 Subject: [PATCH 03/21] Move FindProjects --- models/db/list.go | 6 +++-- models/project/project.go | 20 +++------------ routers/web/org/projects.go | 2 +- routers/web/repo/issue.go | 48 +++++++++++++++--------------------- routers/web/repo/projects.go | 2 +- 5 files changed, 30 insertions(+), 48 deletions(-) diff --git a/models/db/list.go b/models/db/list.go index 194717d86650..39dbc337b0f9 100644 --- a/models/db/list.go +++ b/models/db/list.go @@ -52,6 +52,8 @@ type ListOptions struct { ListAll bool // if true, then PageSize and Page will not be taken } +var ListOptionsAll = ListOptions{ListAll: true} + var ( _ Paginator = &ListOptions{} _ FindOptions = &ListOptions{} @@ -156,7 +158,7 @@ func Find[T any](ctx context.Context, opts FindOptions) ([]T, error) { if !opts.IsListAll() && pageSize > 0 && page >= 1 { sess.Limit(pageSize, (page-1)*pageSize) } - if newOpt, ok := opts.(FindOptionsOrder); ok { + if newOpt, ok := opts.(FindOptionsOrder); ok && newOpt.ToOrders() != "" { sess.OrderBy(newOpt.ToOrders()) } @@ -180,7 +182,7 @@ func FindAndCount[T any](ctx context.Context, opts FindOptions) ([]T, int64, err if !opts.IsListAll() && pageSize > 0 && page >= 1 { sess.Limit(pageSize, (page-1)*pageSize) } - if newOpt, ok := opts.(FindOptionsOrder); ok { + if newOpt, ok := opts.(FindOptionsOrder); ok && newOpt.ToOrders() != "" { sess.OrderBy(newOpt.ToOrders()) } diff --git a/models/project/project.go b/models/project/project.go index b7fcef0d24c6..24434a6c3907 100644 --- a/models/project/project.go +++ b/models/project/project.go @@ -226,6 +226,10 @@ func (opts *SearchOptions) ToConds() builder.Cond { return cond } +func (opts *SearchOptions) ToOrders() string { + return opts.OrderBy.String() +} + func GetSearchOrderByBySortType(sortType string) db.SearchOrderBy { switch sortType { case "oldest": @@ -239,22 +243,6 @@ func GetSearchOrderByBySortType(sortType string) db.SearchOrderBy { } } -// FindProjects returns a list of all projects that have been created in the repository -func FindProjects(ctx context.Context, opts SearchOptions) ([]*Project, int64, error) { - e := db.GetEngine(ctx).Where(opts.ToConds()) - if opts.OrderBy.String() != "" { - e = e.OrderBy(opts.OrderBy.String()) - } - projects := make([]*Project, 0, setting.UI.IssuePagingNum) - - if opts.Page > 0 && !opts.ListAll { - e = e.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) - } - - count, err := e.FindAndCount(&projects) - return projects, count, err -} - // NewProject creates a new Project func NewProject(ctx context.Context, p *Project) error { if !IsBoardTypeValid(p.BoardType) { diff --git a/routers/web/org/projects.go b/routers/web/org/projects.go index ecd989733cce..29794f82310e 100644 --- a/routers/web/org/projects.go +++ b/routers/web/org/projects.go @@ -60,7 +60,7 @@ func Projects(ctx *context.Context) { } else { projectType = project_model.TypeIndividual } - projects, total, err := project_model.FindProjects(ctx, project_model.SearchOptions{ + projects, total, err := db.FindAndCount[*project_model.Project](ctx, &project_model.SearchOptions{ ListOptions: db.ListOptions{ Page: page, PageSize: setting.UI.IssuePagingNum, diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 395dfcafb43d..42e35855ed03 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -569,25 +569,21 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) { repoOwnerType = project_model.TypeOrganization } var err error - projects, _, err := project_model.FindProjects(ctx, project_model.SearchOptions{ - ListOptions: db.ListOptions{ - ListAll: true, - }, - RepoID: repo.ID, - IsClosed: util.OptionalBoolFalse, - Type: project_model.TypeRepository, + projects, err := db.Find[*project_model.Project](ctx, &project_model.SearchOptions{ + ListOptions: db.ListOptionsAll, + RepoID: repo.ID, + IsClosed: util.OptionalBoolFalse, + Type: project_model.TypeRepository, }) if err != nil { ctx.ServerError("GetProjects", err) return } - projects2, _, err := project_model.FindProjects(ctx, project_model.SearchOptions{ - ListOptions: db.ListOptions{ - ListAll: true, - }, - OwnerID: repo.OwnerID, - IsClosed: util.OptionalBoolFalse, - Type: repoOwnerType, + projects2, err := db.Find[*project_model.Project](ctx, &project_model.SearchOptions{ + ListOptions: db.ListOptionsAll, + OwnerID: repo.OwnerID, + IsClosed: util.OptionalBoolFalse, + Type: repoOwnerType, }) if err != nil { ctx.ServerError("GetProjects", err) @@ -596,25 +592,21 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) { ctx.Data["OpenProjects"] = append(projects, projects2...) - projects, _, err = project_model.FindProjects(ctx, project_model.SearchOptions{ - ListOptions: db.ListOptions{ - ListAll: true, - }, - RepoID: repo.ID, - IsClosed: util.OptionalBoolTrue, - Type: project_model.TypeRepository, + projects, err = db.Find[*project_model.Project](ctx, &project_model.SearchOptions{ + ListOptions: db.ListOptionsAll, + RepoID: repo.ID, + IsClosed: util.OptionalBoolTrue, + Type: project_model.TypeRepository, }) if err != nil { ctx.ServerError("GetProjects", err) return } - projects2, _, err = project_model.FindProjects(ctx, project_model.SearchOptions{ - ListOptions: db.ListOptions{ - ListAll: true, - }, - OwnerID: repo.OwnerID, - IsClosed: util.OptionalBoolTrue, - Type: repoOwnerType, + projects2, err = db.Find[*project_model.Project](ctx, &project_model.SearchOptions{ + ListOptions: db.ListOptionsAll, + OwnerID: repo.OwnerID, + IsClosed: util.OptionalBoolTrue, + Type: repoOwnerType, }) if err != nil { ctx.ServerError("GetProjects", err) diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go index 1aa4bab9677a..1e104341942e 100644 --- a/routers/web/repo/projects.go +++ b/routers/web/repo/projects.go @@ -72,7 +72,7 @@ func Projects(ctx *context.Context) { total = repo.NumClosedProjects } - projects, count, err := project_model.FindProjects(ctx, project_model.SearchOptions{ + projects, count, err := db.FindAndCount[*project_model.Project](ctx, &project_model.SearchOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.IssuePagingNum, Page: page, From 172181c1a7af3a637d646b44d8a014777243d098 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 16 Nov 2023 11:46:56 +0800 Subject: [PATCH 04/21] Fix lint --- models/db/list.go | 15 ++++++++++++--- models/db/list_test.go | 9 ++++----- models/project/project_test.go | 6 +++--- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/models/db/list.go b/models/db/list.go index 39dbc337b0f9..79c2f69f6371 100644 --- a/models/db/list.go +++ b/models/db/list.go @@ -14,7 +14,8 @@ import ( const ( // DefaultMaxInSize represents default variables number on IN () in SQL - DefaultMaxInSize = 50 + DefaultMaxInSize = 50 + defaultFindSliceSize = 10 ) // Paginator is the base for different ListOptions types @@ -162,7 +163,11 @@ func Find[T any](ctx context.Context, opts FindOptions) ([]T, error) { sess.OrderBy(newOpt.ToOrders()) } - var objects []T + findPageSize := defaultFindSliceSize + if pageSize > 0 { + findPageSize = pageSize + } + objects := make([]T, 0, findPageSize) if err := sess.Find(objects); err != nil { return nil, err } @@ -186,7 +191,11 @@ func FindAndCount[T any](ctx context.Context, opts FindOptions) ([]T, int64, err sess.OrderBy(newOpt.ToOrders()) } - var objects []T + findPageSize := defaultFindSliceSize + if pageSize > 0 { + findPageSize = pageSize + } + objects := make([]T, 0, findPageSize) cnt, err := sess.FindAndCount(&objects) if err != nil { return nil, 0, err diff --git a/models/db/list_test.go b/models/db/list_test.go index b923dc9c22da..1035af9ea0d7 100644 --- a/models/db/list_test.go +++ b/models/db/list_test.go @@ -37,17 +37,16 @@ func TestFind(t *testing.T) { assert.NotEmpty(t, repoUnitCount) opts := mockListOptions{} - var repoUnits []repo_model.RepoUnit - err = db.Find(db.DefaultContext, &opts, &repoUnits) + repoUnits, err := db.Find[repo_model.RepoUnit](db.DefaultContext, &opts) assert.NoError(t, err) assert.Len(t, repoUnits, repoUnitCount) - cnt, err := db.Count(db.DefaultContext, &opts, new(repo_model.RepoUnit)) + cnt, err := db.Count[repo_model.RepoUnit](db.DefaultContext, &opts) assert.NoError(t, err) assert.EqualValues(t, repoUnitCount, cnt) - repoUnits = make([]repo_model.RepoUnit, 0, 10) - newCnt, err := db.FindAndCount(db.DefaultContext, &opts, &repoUnits) + repoUnits, newCnt, err := db.FindAndCount[repo_model.RepoUnit](db.DefaultContext, &opts) assert.NoError(t, err) assert.EqualValues(t, cnt, newCnt) + assert.Len(t, repoUnits, repoUnitCount) } diff --git a/models/project/project_test.go b/models/project/project_test.go index 6b5bd5b371dd..253c8b476079 100644 --- a/models/project/project_test.go +++ b/models/project/project_test.go @@ -34,13 +34,13 @@ func TestIsProjectTypeValid(t *testing.T) { func TestGetProjects(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - projects, _, err := FindProjects(db.DefaultContext, SearchOptions{RepoID: 1}) + projects, err := db.Find[Project](db.DefaultContext, &SearchOptions{RepoID: 1}) assert.NoError(t, err) // 1 value for this repo exists in the fixtures assert.Len(t, projects, 1) - projects, _, err = FindProjects(db.DefaultContext, SearchOptions{RepoID: 3}) + projects, err = db.Find[Project](db.DefaultContext, &SearchOptions{RepoID: 3}) assert.NoError(t, err) // 1 value for this repo exists in the fixtures @@ -109,7 +109,7 @@ func TestProjectsSort(t *testing.T) { } for _, tt := range tests { - projects, count, err := FindProjects(db.DefaultContext, SearchOptions{ + projects, count, err := db.FindAndCount[Project](db.DefaultContext, &SearchOptions{ OrderBy: GetSearchOrderByBySortType(tt.sortType), }) assert.NoError(t, err) From 42b06acb452630af18fab88c62d95bb7ad39f2a6 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 16 Nov 2023 11:54:15 +0800 Subject: [PATCH 05/21] Fix bug --- models/db/list.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/db/list.go b/models/db/list.go index 79c2f69f6371..1d029d53e25b 100644 --- a/models/db/list.go +++ b/models/db/list.go @@ -168,7 +168,7 @@ func Find[T any](ctx context.Context, opts FindOptions) ([]T, error) { findPageSize = pageSize } objects := make([]T, 0, findPageSize) - if err := sess.Find(objects); err != nil { + if err := sess.Find(&objects); err != nil { return nil, err } return objects, nil From 95a8eefa5606b7bca28c559a6af088ca712a1234 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 17 Nov 2023 10:30:18 +0800 Subject: [PATCH 06/21] refactor more find/count functions --- models/actions/schedule_list.go | 16 +++------------- models/actions/schedule_spec_list.go | 19 +++++++------------ models/actions/task_list.go | 17 ++++------------- models/activities/notification.go | 19 ++++++------------- routers/api/v1/notify/repo.go | 9 +++++---- routers/api/v1/notify/user.go | 9 +++++---- routers/web/shared/actions/runners.go | 6 +++--- services/actions/clear_tasks.go | 2 +- services/actions/notifier_helper.go | 2 +- services/repository/delete.go | 2 +- 10 files changed, 36 insertions(+), 65 deletions(-) diff --git a/models/actions/schedule_list.go b/models/actions/schedule_list.go index ddd9a1321e54..b806550b87d8 100644 --- a/models/actions/schedule_list.go +++ b/models/actions/schedule_list.go @@ -67,7 +67,7 @@ type FindScheduleOptions struct { OwnerID int64 } -func (opts FindScheduleOptions) toConds() builder.Cond { +func (opts FindScheduleOptions) ToConds() builder.Cond { cond := builder.NewCond() if opts.RepoID > 0 { cond = cond.And(builder.Eq{"repo_id": opts.RepoID}) @@ -79,16 +79,6 @@ func (opts FindScheduleOptions) toConds() builder.Cond { return cond } -func FindSchedules(ctx context.Context, opts FindScheduleOptions) (ScheduleList, int64, error) { - e := db.GetEngine(ctx).Where(opts.toConds()) - if !opts.ListAll && opts.PageSize > 0 && opts.Page >= 1 { - e.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) - } - var schedules ScheduleList - total, err := e.Desc("id").FindAndCount(&schedules) - return schedules, total, err -} - -func CountSchedules(ctx context.Context, opts FindScheduleOptions) (int64, error) { - return db.GetEngine(ctx).Where(opts.toConds()).Count(new(ActionSchedule)) +func (opts FindScheduleOptions) ToOrders() string { + return "`id` DESC" } diff --git a/models/actions/schedule_spec_list.go b/models/actions/schedule_spec_list.go index 6bf91cf8196f..c04ac01eae21 100644 --- a/models/actions/schedule_spec_list.go +++ b/models/actions/schedule_spec_list.go @@ -71,7 +71,7 @@ type FindSpecOptions struct { Next int64 } -func (opts FindSpecOptions) toConds() builder.Cond { +func (opts FindSpecOptions) ToConds() builder.Cond { cond := builder.NewCond() if opts.RepoID > 0 { cond = cond.And(builder.Eq{"repo_id": opts.RepoID}) @@ -84,23 +84,18 @@ func (opts FindSpecOptions) toConds() builder.Cond { return cond } +func (opts FindSpecOptions) ToOrders() string { + return "`id` DESC" +} + func FindSpecs(ctx context.Context, opts FindSpecOptions) (SpecList, int64, error) { - e := db.GetEngine(ctx).Where(opts.toConds()) - if opts.PageSize > 0 && opts.Page >= 1 { - e.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) - } - var specs SpecList - total, err := e.Desc("id").FindAndCount(&specs) + specs, total, err := db.FindAndCount[*ActionScheduleSpec](ctx, &opts) if err != nil { return nil, 0, err } - if err := specs.LoadSchedules(ctx); err != nil { + if err := SpecList(specs).LoadSchedules(ctx); err != nil { return nil, 0, err } return specs, total, nil } - -func CountSpecs(ctx context.Context, opts FindSpecOptions) (int64, error) { - return db.GetEngine(ctx).Where(opts.toConds()).Count(new(ActionScheduleSpec)) -} diff --git a/models/actions/task_list.go b/models/actions/task_list.go index 1f6b16772b8f..b07d00b8dbd6 100644 --- a/models/actions/task_list.go +++ b/models/actions/task_list.go @@ -62,7 +62,7 @@ type FindTaskOptions struct { IDOrderDesc bool } -func (opts FindTaskOptions) toConds() builder.Cond { +func (opts FindTaskOptions) ToConds() builder.Cond { cond := builder.NewCond() if opts.RepoID > 0 { cond = cond.And(builder.Eq{"repo_id": opts.RepoID}) @@ -88,18 +88,9 @@ func (opts FindTaskOptions) toConds() builder.Cond { return cond } -func FindTasks(ctx context.Context, opts FindTaskOptions) (TaskList, error) { - e := db.GetEngine(ctx).Where(opts.toConds()) - if opts.PageSize > 0 && opts.Page >= 1 { - e.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) - } +func (opts FindTaskOptions) ToOrders() string { if opts.IDOrderDesc { - e.OrderBy("id DESC") + return "`id` DESC" } - var tasks TaskList - return tasks, e.Find(&tasks) -} - -func CountTasks(ctx context.Context, opts FindTaskOptions) (int64, error) { - return db.GetEngine(ctx).Where(opts.toConds()).Count(new(ActionTask)) + return "" } diff --git a/models/activities/notification.go b/models/activities/notification.go index 7c794564b673..fd48e1f0f8a9 100644 --- a/models/activities/notification.go +++ b/models/activities/notification.go @@ -93,7 +93,7 @@ type FindNotificationOptions struct { } // ToCond will convert each condition into a xorm-Cond -func (opts *FindNotificationOptions) ToCond() builder.Cond { +func (opts *FindNotificationOptions) ToConds() builder.Cond { cond := builder.NewCond() if opts.UserID != 0 { cond = cond.And(builder.Eq{"notification.user_id": opts.UserID}) @@ -119,26 +119,19 @@ func (opts *FindNotificationOptions) ToCond() builder.Cond { return cond } +func (opts *FindNotificationOptions) ToOrders() string { + return "notification.updated_unix DESC" +} + // ToSession will convert the given options to a xorm Session by using the conditions from ToCond and joining with issue table if required func (opts *FindNotificationOptions) ToSession(ctx context.Context) *xorm.Session { - sess := db.GetEngine(ctx).Where(opts.ToCond()) + sess := db.GetEngine(ctx).Where(opts.ToConds()) if opts.Page != 0 { sess = db.SetSessionPagination(sess, opts) } return sess } -// GetNotifications returns all notifications that fit to the given options. -func GetNotifications(ctx context.Context, options *FindNotificationOptions) (nl NotificationList, err error) { - err = options.ToSession(ctx).OrderBy("notification.updated_unix DESC").Find(&nl) - return nl, err -} - -// CountNotifications count all notifications that fit to the given options and ignore pagination. -func CountNotifications(ctx context.Context, opts *FindNotificationOptions) (int64, error) { - return db.GetEngine(ctx).Where(opts.ToCond()).Count(&Notification{}) -} - // CreateRepoTransferNotification creates notification for the user a repository was transferred to func CreateRepoTransferNotification(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) error { return db.WithTx(ctx, func(ctx context.Context) error { diff --git a/routers/api/v1/notify/repo.go b/routers/api/v1/notify/repo.go index 0e4efcc640f4..6a2ba7e76c90 100644 --- a/routers/api/v1/notify/repo.go +++ b/routers/api/v1/notify/repo.go @@ -9,6 +9,7 @@ import ( "time" activities_model "code.gitea.io/gitea/models/activities" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/structs" @@ -108,18 +109,18 @@ func ListRepoNotifications(ctx *context.APIContext) { } opts.RepoID = ctx.Repo.Repository.ID - totalCount, err := activities_model.CountNotifications(ctx, opts) + totalCount, err := db.Count[activities_model.Notification](ctx, opts) if err != nil { ctx.InternalServerError(err) return } - nl, err := activities_model.GetNotifications(ctx, opts) + nl, err := db.Find[*activities_model.Notification](ctx, opts) if err != nil { ctx.InternalServerError(err) return } - err = nl.LoadAttributes(ctx) + err = activities_model.NotificationList(nl).LoadAttributes(ctx) if err != nil { ctx.InternalServerError(err) return @@ -202,7 +203,7 @@ func ReadRepoNotifications(ctx *context.APIContext) { opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread"}) log.Error("%v", opts.Status) } - nl, err := activities_model.GetNotifications(ctx, opts) + nl, err := db.Find[*activities_model.Notification](ctx, opts) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/notify/user.go b/routers/api/v1/notify/user.go index 267b7d8ea8c5..8f38b36921ec 100644 --- a/routers/api/v1/notify/user.go +++ b/routers/api/v1/notify/user.go @@ -8,6 +8,7 @@ import ( "time" activities_model "code.gitea.io/gitea/models/activities" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/services/convert" @@ -68,18 +69,18 @@ func ListNotifications(ctx *context.APIContext) { return } - totalCount, err := activities_model.CountNotifications(ctx, opts) + totalCount, err := db.Count[activities_model.Notification](ctx, opts) if err != nil { ctx.InternalServerError(err) return } - nl, err := activities_model.GetNotifications(ctx, opts) + nl, err := db.Find[*activities_model.Notification](ctx, opts) if err != nil { ctx.InternalServerError(err) return } - err = nl.LoadAttributes(ctx) + err = activities_model.NotificationList(nl).LoadAttributes(ctx) if err != nil { ctx.InternalServerError(err) return @@ -147,7 +148,7 @@ func ReadNotifications(ctx *context.APIContext) { statuses := ctx.FormStrings("status-types") opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread"}) } - nl, err := activities_model.GetNotifications(ctx, opts) + nl, err := db.Find[activities_model.Notification](ctx, opts) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/web/shared/actions/runners.go b/routers/web/shared/actions/runners.go index 4e203d8f8a2c..c9e4ecaf1b8b 100644 --- a/routers/web/shared/actions/runners.go +++ b/routers/web/shared/actions/runners.go @@ -84,18 +84,18 @@ func RunnerDetails(ctx *context.Context, page int, runnerID, ownerID, repoID int RunnerID: runner.ID, } - count, err := actions_model.CountTasks(ctx, opts) + count, err := db.Count[actions_model.ActionTask](ctx, &opts) if err != nil { ctx.ServerError("CountTasks", err) return } - tasks, err := actions_model.FindTasks(ctx, opts) + tasks, err := db.Find[*actions_model.ActionTask](ctx, &opts) if err != nil { ctx.ServerError("FindTasks", err) return } - if err = tasks.LoadAttributes(ctx); err != nil { + if err = actions_model.TaskList(tasks).LoadAttributes(ctx); err != nil { ctx.ServerError("TasksLoadAttributes", err) return } diff --git a/services/actions/clear_tasks.go b/services/actions/clear_tasks.go index 128cb881f6f0..be2dec4a3313 100644 --- a/services/actions/clear_tasks.go +++ b/services/actions/clear_tasks.go @@ -33,7 +33,7 @@ func StopEndlessTasks(ctx context.Context) error { } func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error { - tasks, err := actions_model.FindTasks(ctx, opts) + tasks, err := db.Find[*actions_model.ActionTask](ctx, &opts) if err != nil { return fmt.Errorf("find tasks: %w", err) } diff --git a/services/actions/notifier_helper.go b/services/actions/notifier_helper.go index 35aa9e6f690d..825780cc6a7e 100644 --- a/services/actions/notifier_helper.go +++ b/services/actions/notifier_helper.go @@ -384,7 +384,7 @@ func handleSchedules( return nil } - if count, err := actions_model.CountSchedules(ctx, actions_model.FindScheduleOptions{RepoID: input.Repo.ID}); err != nil { + if count, err := db.Count[actions_model.ActionSchedule](ctx, &actions_model.FindScheduleOptions{RepoID: input.Repo.ID}); err != nil { log.Error("CountSchedules: %v", err) return err } else if count > 0 { diff --git a/services/repository/delete.go b/services/repository/delete.go index 861dfa2dcd0a..46e95a8eeb6d 100644 --- a/services/repository/delete.go +++ b/services/repository/delete.go @@ -54,7 +54,7 @@ func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID } // Query the action tasks of this repo, they will be needed after they have been deleted to remove the logs - tasks, err := actions_model.FindTasks(ctx, actions_model.FindTaskOptions{RepoID: repoID}) + tasks, err := db.Find[actions_model.ActionTask](ctx, &actions_model.FindTaskOptions{RepoID: repoID}) if err != nil { return fmt.Errorf("find actions tasks of repo %v: %w", repoID, err) } From 990cfcf2e762c93331e117ec0f2d460181aa4457 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 17 Nov 2023 11:20:48 +0800 Subject: [PATCH 07/21] more refactor --- cmd/admin_auth.go | 3 +- models/activities/notification.go | 360 ----------------- models/activities/notification_list.go | 361 ++++++++++++++++++ models/activities/notification_test.go | 12 - models/activities/statistic.go | 4 +- models/auth/source.go | 15 +- models/db/list.go | 8 +- models/organization/org.go | 21 +- models/organization/org_test.go | 8 +- routers/api/v1/notify/notifications.go | 13 +- routers/api/v1/org/org.go | 4 +- routers/web/admin/auths.go | 6 +- routers/web/admin/users.go | 8 +- routers/web/shared/user/header.go | 2 +- routers/web/user/notification.go | 22 +- routers/web/user/setting/profile.go | 8 +- routers/web/user/setting/security/security.go | 3 +- services/auth/signin.go | 2 +- services/auth/source/oauth2/init.go | 3 +- services/auth/source/oauth2/providers.go | 3 +- services/auth/sspi.go | 3 +- services/auth/sync.go | 2 +- services/user/user.go | 2 +- tests/integration/auth_ldap_test.go | 2 +- tests/integration/org_count_test.go | 2 +- 25 files changed, 434 insertions(+), 443 deletions(-) create mode 100644 models/activities/notification_list.go diff --git a/cmd/admin_auth.go b/cmd/admin_auth.go index 014ddf329f94..ec92e342d4d4 100644 --- a/cmd/admin_auth.go +++ b/cmd/admin_auth.go @@ -9,6 +9,7 @@ import ( "text/tabwriter" auth_model "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/models/db" auth_service "code.gitea.io/gitea/services/auth" "github.com/urfave/cli/v2" @@ -62,7 +63,7 @@ func runListAuth(c *cli.Context) error { return err } - authSources, err := auth_model.FindSources(ctx, auth_model.FindSourcesOptions{}) + authSources, err := db.Find[auth_model.Source](ctx, auth_model.FindSourcesOptions{}) if err != nil { return err } diff --git a/models/activities/notification.go b/models/activities/notification.go index fd48e1f0f8a9..c7ebc07e49d7 100644 --- a/models/activities/notification.go +++ b/models/activities/notification.go @@ -17,12 +17,10 @@ import ( "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/container" - "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" "xorm.io/builder" - "xorm.io/xorm" ) type ( @@ -80,58 +78,6 @@ func init() { db.RegisterModel(new(Notification)) } -// FindNotificationOptions represent the filters for notifications. If an ID is 0 it will be ignored. -type FindNotificationOptions struct { - db.ListOptions - UserID int64 - RepoID int64 - IssueID int64 - Status []NotificationStatus - Source []NotificationSource - UpdatedAfterUnix int64 - UpdatedBeforeUnix int64 -} - -// ToCond will convert each condition into a xorm-Cond -func (opts *FindNotificationOptions) ToConds() builder.Cond { - cond := builder.NewCond() - if opts.UserID != 0 { - cond = cond.And(builder.Eq{"notification.user_id": opts.UserID}) - } - if opts.RepoID != 0 { - cond = cond.And(builder.Eq{"notification.repo_id": opts.RepoID}) - } - if opts.IssueID != 0 { - cond = cond.And(builder.Eq{"notification.issue_id": opts.IssueID}) - } - if len(opts.Status) > 0 { - cond = cond.And(builder.In("notification.status", opts.Status)) - } - if len(opts.Source) > 0 { - cond = cond.And(builder.In("notification.source", opts.Source)) - } - if opts.UpdatedAfterUnix != 0 { - cond = cond.And(builder.Gte{"notification.updated_unix": opts.UpdatedAfterUnix}) - } - if opts.UpdatedBeforeUnix != 0 { - cond = cond.And(builder.Lte{"notification.updated_unix": opts.UpdatedBeforeUnix}) - } - return cond -} - -func (opts *FindNotificationOptions) ToOrders() string { - return "notification.updated_unix DESC" -} - -// ToSession will convert the given options to a xorm Session by using the conditions from ToCond and joining with issue table if required -func (opts *FindNotificationOptions) ToSession(ctx context.Context) *xorm.Session { - sess := db.GetEngine(ctx).Where(opts.ToConds()) - if opts.Page != 0 { - sess = db.SetSessionPagination(sess, opts) - } - return sess -} - // CreateRepoTransferNotification creates notification for the user a repository was transferred to func CreateRepoTransferNotification(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) error { return db.WithTx(ctx, func(ctx context.Context) error { @@ -266,23 +212,6 @@ func createOrUpdateIssueNotifications(ctx context.Context, issueID, commentID, n return nil } -func getNotificationsByIssueID(ctx context.Context, issueID int64) (notifications []*Notification, err error) { - err = db.GetEngine(ctx). - Where("issue_id = ?", issueID). - Find(¬ifications) - return notifications, err -} - -func notificationExists(notifications []*Notification, issueID, userID int64) bool { - for _, notification := range notifications { - if notification.IssueID == issueID && notification.UserID == userID { - return true - } - } - - return false -} - func createIssueNotification(ctx context.Context, userID int64, issue *issues_model.Issue, commentID, updatedByID int64) error { notification := &Notification{ UserID: userID, @@ -334,35 +263,6 @@ func GetIssueNotification(ctx context.Context, userID, issueID int64) (*Notifica return notification, err } -// NotificationsForUser returns notifications for a given user and status -func NotificationsForUser(ctx context.Context, user *user_model.User, statuses []NotificationStatus, page, perPage int) (notifications NotificationList, err error) { - if len(statuses) == 0 { - return nil, nil - } - - sess := db.GetEngine(ctx). - Where("user_id = ?", user.ID). - In("status", statuses). - OrderBy("updated_unix DESC") - - if page > 0 && perPage > 0 { - sess.Limit(perPage, (page-1)*perPage) - } - - err = sess.Find(¬ifications) - return notifications, err -} - -// CountUnread count unread notifications for a user -func CountUnread(ctx context.Context, userID int64) int64 { - exist, err := db.GetEngine(ctx).Where("user_id = ?", userID).And("status = ?", NotificationStatusUnread).Count(new(Notification)) - if err != nil { - log.Error("countUnread", err) - return 0 - } - return exist -} - // LoadAttributes load Repo Issue User and Comment if not loaded func (n *Notification) LoadAttributes(ctx context.Context) (err error) { if err = n.loadRepo(ctx); err != nil { @@ -474,266 +374,6 @@ func (n *Notification) APIURL() string { return setting.AppURL + "api/v1/notifications/threads/" + strconv.FormatInt(n.ID, 10) } -// NotificationList contains a list of notifications -type NotificationList []*Notification - -// LoadAttributes load Repo Issue User and Comment if not loaded -func (nl NotificationList) LoadAttributes(ctx context.Context) error { - var err error - for i := 0; i < len(nl); i++ { - err = nl[i].LoadAttributes(ctx) - if err != nil && !issues_model.IsErrCommentNotExist(err) { - return err - } - } - return nil -} - -func (nl NotificationList) getPendingRepoIDs() []int64 { - ids := make(container.Set[int64], len(nl)) - for _, notification := range nl { - if notification.Repository != nil { - continue - } - ids.Add(notification.RepoID) - } - return ids.Values() -} - -// LoadRepos loads repositories from database -func (nl NotificationList) LoadRepos(ctx context.Context) (repo_model.RepositoryList, []int, error) { - if len(nl) == 0 { - return repo_model.RepositoryList{}, []int{}, nil - } - - repoIDs := nl.getPendingRepoIDs() - repos := make(map[int64]*repo_model.Repository, len(repoIDs)) - left := len(repoIDs) - for left > 0 { - limit := db.DefaultMaxInSize - if left < limit { - limit = left - } - rows, err := db.GetEngine(ctx). - In("id", repoIDs[:limit]). - Rows(new(repo_model.Repository)) - if err != nil { - return nil, nil, err - } - - for rows.Next() { - var repo repo_model.Repository - err = rows.Scan(&repo) - if err != nil { - rows.Close() - return nil, nil, err - } - - repos[repo.ID] = &repo - } - _ = rows.Close() - - left -= limit - repoIDs = repoIDs[limit:] - } - - failed := []int{} - - reposList := make(repo_model.RepositoryList, 0, len(repoIDs)) - for i, notification := range nl { - if notification.Repository == nil { - notification.Repository = repos[notification.RepoID] - } - if notification.Repository == nil { - log.Error("Notification[%d]: RepoID: %d not found", notification.ID, notification.RepoID) - failed = append(failed, i) - continue - } - var found bool - for _, r := range reposList { - if r.ID == notification.RepoID { - found = true - break - } - } - if !found { - reposList = append(reposList, notification.Repository) - } - } - return reposList, failed, nil -} - -func (nl NotificationList) getPendingIssueIDs() []int64 { - ids := make(container.Set[int64], len(nl)) - for _, notification := range nl { - if notification.Issue != nil { - continue - } - ids.Add(notification.IssueID) - } - return ids.Values() -} - -// LoadIssues loads issues from database -func (nl NotificationList) LoadIssues(ctx context.Context) ([]int, error) { - if len(nl) == 0 { - return []int{}, nil - } - - issueIDs := nl.getPendingIssueIDs() - issues := make(map[int64]*issues_model.Issue, len(issueIDs)) - left := len(issueIDs) - for left > 0 { - limit := db.DefaultMaxInSize - if left < limit { - limit = left - } - rows, err := db.GetEngine(ctx). - In("id", issueIDs[:limit]). - Rows(new(issues_model.Issue)) - if err != nil { - return nil, err - } - - for rows.Next() { - var issue issues_model.Issue - err = rows.Scan(&issue) - if err != nil { - rows.Close() - return nil, err - } - - issues[issue.ID] = &issue - } - _ = rows.Close() - - left -= limit - issueIDs = issueIDs[limit:] - } - - failures := []int{} - - for i, notification := range nl { - if notification.Issue == nil { - notification.Issue = issues[notification.IssueID] - if notification.Issue == nil { - if notification.IssueID != 0 { - log.Error("Notification[%d]: IssueID: %d Not Found", notification.ID, notification.IssueID) - failures = append(failures, i) - } - continue - } - notification.Issue.Repo = notification.Repository - } - } - return failures, nil -} - -// Without returns the notification list without the failures -func (nl NotificationList) Without(failures []int) NotificationList { - if len(failures) == 0 { - return nl - } - remaining := make([]*Notification, 0, len(nl)) - last := -1 - var i int - for _, i = range failures { - remaining = append(remaining, nl[last+1:i]...) - last = i - } - if len(nl) > i { - remaining = append(remaining, nl[i+1:]...) - } - return remaining -} - -func (nl NotificationList) getPendingCommentIDs() []int64 { - ids := make(container.Set[int64], len(nl)) - for _, notification := range nl { - if notification.CommentID == 0 || notification.Comment != nil { - continue - } - ids.Add(notification.CommentID) - } - return ids.Values() -} - -// LoadComments loads comments from database -func (nl NotificationList) LoadComments(ctx context.Context) ([]int, error) { - if len(nl) == 0 { - return []int{}, nil - } - - commentIDs := nl.getPendingCommentIDs() - comments := make(map[int64]*issues_model.Comment, len(commentIDs)) - left := len(commentIDs) - for left > 0 { - limit := db.DefaultMaxInSize - if left < limit { - limit = left - } - rows, err := db.GetEngine(ctx). - In("id", commentIDs[:limit]). - Rows(new(issues_model.Comment)) - if err != nil { - return nil, err - } - - for rows.Next() { - var comment issues_model.Comment - err = rows.Scan(&comment) - if err != nil { - rows.Close() - return nil, err - } - - comments[comment.ID] = &comment - } - _ = rows.Close() - - left -= limit - commentIDs = commentIDs[limit:] - } - - failures := []int{} - for i, notification := range nl { - if notification.CommentID > 0 && notification.Comment == nil && comments[notification.CommentID] != nil { - notification.Comment = comments[notification.CommentID] - if notification.Comment == nil { - log.Error("Notification[%d]: CommentID[%d] failed to load", notification.ID, notification.CommentID) - failures = append(failures, i) - continue - } - notification.Comment.Issue = notification.Issue - } - } - return failures, nil -} - -// GetNotificationCount returns the notification count for user -func GetNotificationCount(ctx context.Context, user *user_model.User, status NotificationStatus) (count int64, err error) { - count, err = db.GetEngine(ctx). - Where("user_id = ?", user.ID). - And("status = ?", status). - Count(&Notification{}) - return count, err -} - -// UserIDCount is a simple coalition of UserID and Count -type UserIDCount struct { - UserID int64 - Count int64 -} - -// GetUIDsAndNotificationCounts between the two provided times -func GetUIDsAndNotificationCounts(ctx context.Context, since, until timeutil.TimeStamp) ([]UserIDCount, error) { - sql := `SELECT user_id, count(*) AS count FROM notification ` + - `WHERE user_id IN (SELECT user_id FROM notification WHERE updated_unix >= ? AND ` + - `updated_unix < ?) AND status = ? GROUP BY user_id` - var res []UserIDCount - return res, db.GetEngine(ctx).SQL(sql, since, until, NotificationStatusUnread).Find(&res) -} - // SetIssueReadBy sets issue to be read by given user. func SetIssueReadBy(ctx context.Context, issueID, userID int64) error { if err := issues_model.UpdateIssueUserByRead(ctx, userID, issueID); err != nil { diff --git a/models/activities/notification_list.go b/models/activities/notification_list.go new file mode 100644 index 000000000000..f2f03541f4e6 --- /dev/null +++ b/models/activities/notification_list.go @@ -0,0 +1,361 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package activities + +import ( + "context" + + "code.gitea.io/gitea/models/db" + issues_model "code.gitea.io/gitea/models/issues" + repo_model "code.gitea.io/gitea/models/repo" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/container" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/timeutil" + "xorm.io/builder" + "xorm.io/xorm" +) + +// FindNotificationOptions represent the filters for notifications. If an ID is 0 it will be ignored. +type FindNotificationOptions struct { + db.ListOptions + UserID int64 + RepoID int64 + IssueID int64 + Status []NotificationStatus + Source []NotificationSource + UpdatedAfterUnix int64 + UpdatedBeforeUnix int64 +} + +// ToCond will convert each condition into a xorm-Cond +func (opts *FindNotificationOptions) ToConds() builder.Cond { + cond := builder.NewCond() + if opts.UserID != 0 { + cond = cond.And(builder.Eq{"notification.user_id": opts.UserID}) + } + if opts.RepoID != 0 { + cond = cond.And(builder.Eq{"notification.repo_id": opts.RepoID}) + } + if opts.IssueID != 0 { + cond = cond.And(builder.Eq{"notification.issue_id": opts.IssueID}) + } + if len(opts.Status) > 0 { + if len(opts.Status) == 1 { + cond = cond.And(builder.Eq{"notification.status": opts.Status[0]}) + } else { + cond = cond.And(builder.In("notification.status", opts.Status)) + } + } + if len(opts.Source) > 0 { + cond = cond.And(builder.In("notification.source", opts.Source)) + } + if opts.UpdatedAfterUnix != 0 { + cond = cond.And(builder.Gte{"notification.updated_unix": opts.UpdatedAfterUnix}) + } + if opts.UpdatedBeforeUnix != 0 { + cond = cond.And(builder.Lte{"notification.updated_unix": opts.UpdatedBeforeUnix}) + } + return cond +} + +func (opts *FindNotificationOptions) ToOrders() string { + return "notification.updated_unix DESC" +} + +// ToSession will convert the given options to a xorm Session by using the conditions from ToCond and joining with issue table if required +func (opts *FindNotificationOptions) ToSession(ctx context.Context) *xorm.Session { + sess := db.GetEngine(ctx).Where(opts.ToConds()) + if opts.Page != 0 { + sess = db.SetSessionPagination(sess, opts) + } + return sess +} + +func getNotificationsByIssueID(ctx context.Context, issueID int64) (notifications []*Notification, err error) { + err = db.GetEngine(ctx). + Where("issue_id = ?", issueID). + Find(¬ifications) + return notifications, err +} + +func notificationExists(notifications []*Notification, issueID, userID int64) bool { + for _, notification := range notifications { + if notification.IssueID == issueID && notification.UserID == userID { + return true + } + } + + return false +} + +// NotificationsForUser returns notifications for a given user and status +func NotificationsForUser(ctx context.Context, user *user_model.User, statuses []NotificationStatus, page, perPage int) (notifications NotificationList, err error) { + if len(statuses) == 0 { + return nil, nil + } + + sess := db.GetEngine(ctx). + Where("user_id = ?", user.ID). + In("status", statuses). + OrderBy("updated_unix DESC") + + if page > 0 && perPage > 0 { + sess.Limit(perPage, (page-1)*perPage) + } + + err = sess.Find(¬ifications) + return notifications, err +} + +// UserIDCount is a simple coalition of UserID and Count +type UserIDCount struct { + UserID int64 + Count int64 +} + +// GetUIDsAndNotificationCounts between the two provided times +func GetUIDsAndNotificationCounts(ctx context.Context, since, until timeutil.TimeStamp) ([]UserIDCount, error) { + sql := `SELECT user_id, count(*) AS count FROM notification ` + + `WHERE user_id IN (SELECT user_id FROM notification WHERE updated_unix >= ? AND ` + + `updated_unix < ?) AND status = ? GROUP BY user_id` + var res []UserIDCount + return res, db.GetEngine(ctx).SQL(sql, since, until, NotificationStatusUnread).Find(&res) +} + +// NotificationList contains a list of notifications +type NotificationList []*Notification + +// LoadAttributes load Repo Issue User and Comment if not loaded +func (nl NotificationList) LoadAttributes(ctx context.Context) error { + var err error + for i := 0; i < len(nl); i++ { + err = nl[i].LoadAttributes(ctx) + if err != nil && !issues_model.IsErrCommentNotExist(err) { + return err + } + } + return nil +} + +func (nl NotificationList) getPendingRepoIDs() []int64 { + ids := make(container.Set[int64], len(nl)) + for _, notification := range nl { + if notification.Repository != nil { + continue + } + ids.Add(notification.RepoID) + } + return ids.Values() +} + +// LoadRepos loads repositories from database +func (nl NotificationList) LoadRepos(ctx context.Context) (repo_model.RepositoryList, []int, error) { + if len(nl) == 0 { + return repo_model.RepositoryList{}, []int{}, nil + } + + repoIDs := nl.getPendingRepoIDs() + repos := make(map[int64]*repo_model.Repository, len(repoIDs)) + left := len(repoIDs) + for left > 0 { + limit := db.DefaultMaxInSize + if left < limit { + limit = left + } + rows, err := db.GetEngine(ctx). + In("id", repoIDs[:limit]). + Rows(new(repo_model.Repository)) + if err != nil { + return nil, nil, err + } + + for rows.Next() { + var repo repo_model.Repository + err = rows.Scan(&repo) + if err != nil { + rows.Close() + return nil, nil, err + } + + repos[repo.ID] = &repo + } + _ = rows.Close() + + left -= limit + repoIDs = repoIDs[limit:] + } + + failed := []int{} + + reposList := make(repo_model.RepositoryList, 0, len(repoIDs)) + for i, notification := range nl { + if notification.Repository == nil { + notification.Repository = repos[notification.RepoID] + } + if notification.Repository == nil { + log.Error("Notification[%d]: RepoID: %d not found", notification.ID, notification.RepoID) + failed = append(failed, i) + continue + } + var found bool + for _, r := range reposList { + if r.ID == notification.RepoID { + found = true + break + } + } + if !found { + reposList = append(reposList, notification.Repository) + } + } + return reposList, failed, nil +} + +func (nl NotificationList) getPendingIssueIDs() []int64 { + ids := make(container.Set[int64], len(nl)) + for _, notification := range nl { + if notification.Issue != nil { + continue + } + ids.Add(notification.IssueID) + } + return ids.Values() +} + +// LoadIssues loads issues from database +func (nl NotificationList) LoadIssues(ctx context.Context) ([]int, error) { + if len(nl) == 0 { + return []int{}, nil + } + + issueIDs := nl.getPendingIssueIDs() + issues := make(map[int64]*issues_model.Issue, len(issueIDs)) + left := len(issueIDs) + for left > 0 { + limit := db.DefaultMaxInSize + if left < limit { + limit = left + } + rows, err := db.GetEngine(ctx). + In("id", issueIDs[:limit]). + Rows(new(issues_model.Issue)) + if err != nil { + return nil, err + } + + for rows.Next() { + var issue issues_model.Issue + err = rows.Scan(&issue) + if err != nil { + rows.Close() + return nil, err + } + + issues[issue.ID] = &issue + } + _ = rows.Close() + + left -= limit + issueIDs = issueIDs[limit:] + } + + failures := []int{} + + for i, notification := range nl { + if notification.Issue == nil { + notification.Issue = issues[notification.IssueID] + if notification.Issue == nil { + if notification.IssueID != 0 { + log.Error("Notification[%d]: IssueID: %d Not Found", notification.ID, notification.IssueID) + failures = append(failures, i) + } + continue + } + notification.Issue.Repo = notification.Repository + } + } + return failures, nil +} + +// Without returns the notification list without the failures +func (nl NotificationList) Without(failures []int) NotificationList { + if len(failures) == 0 { + return nl + } + remaining := make([]*Notification, 0, len(nl)) + last := -1 + var i int + for _, i = range failures { + remaining = append(remaining, nl[last+1:i]...) + last = i + } + if len(nl) > i { + remaining = append(remaining, nl[i+1:]...) + } + return remaining +} + +func (nl NotificationList) getPendingCommentIDs() []int64 { + ids := make(container.Set[int64], len(nl)) + for _, notification := range nl { + if notification.CommentID == 0 || notification.Comment != nil { + continue + } + ids.Add(notification.CommentID) + } + return ids.Values() +} + +// LoadComments loads comments from database +func (nl NotificationList) LoadComments(ctx context.Context) ([]int, error) { + if len(nl) == 0 { + return []int{}, nil + } + + commentIDs := nl.getPendingCommentIDs() + comments := make(map[int64]*issues_model.Comment, len(commentIDs)) + left := len(commentIDs) + for left > 0 { + limit := db.DefaultMaxInSize + if left < limit { + limit = left + } + rows, err := db.GetEngine(ctx). + In("id", commentIDs[:limit]). + Rows(new(issues_model.Comment)) + if err != nil { + return nil, err + } + + for rows.Next() { + var comment issues_model.Comment + err = rows.Scan(&comment) + if err != nil { + rows.Close() + return nil, err + } + + comments[comment.ID] = &comment + } + _ = rows.Close() + + left -= limit + commentIDs = commentIDs[limit:] + } + + failures := []int{} + for i, notification := range nl { + if notification.CommentID > 0 && notification.Comment == nil && comments[notification.CommentID] != nil { + notification.Comment = comments[notification.CommentID] + if notification.Comment == nil { + log.Error("Notification[%d]: CommentID[%d] failed to load", notification.ID, notification.CommentID) + failures = append(failures, i) + continue + } + notification.Comment.Issue = notification.Issue + } + } + return failures, nil +} diff --git a/models/activities/notification_test.go b/models/activities/notification_test.go index b90ce70536f8..cdb4d6b1aac8 100644 --- a/models/activities/notification_test.go +++ b/models/activities/notification_test.go @@ -65,18 +65,6 @@ func TestNotification_GetIssue(t *testing.T) { assert.EqualValues(t, notf.IssueID, issue.ID) } -func TestGetNotificationCount(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) - cnt, err := activities_model.GetNotificationCount(db.DefaultContext, user, activities_model.NotificationStatusRead) - assert.NoError(t, err) - assert.EqualValues(t, 0, cnt) - - cnt, err = activities_model.GetNotificationCount(db.DefaultContext, user, activities_model.NotificationStatusUnread) - assert.NoError(t, err) - assert.EqualValues(t, 1, cnt) -} - func TestSetNotificationStatus(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) diff --git a/models/activities/statistic.go b/models/activities/statistic.go index e9dab6fc10b6..4044f249b266 100644 --- a/models/activities/statistic.go +++ b/models/activities/statistic.go @@ -52,7 +52,7 @@ type IssueByRepositoryCount struct { func GetStatistic(ctx context.Context) (stats Statistic) { e := db.GetEngine(ctx) stats.Counter.User = user_model.CountUsers(ctx, nil) - stats.Counter.Org, _ = organization.CountOrgs(ctx, organization.FindOrgOptions{IncludePrivate: true}) + stats.Counter.Org, _ = db.Count[organization.Organization](ctx, &organization.FindOrgOptions{IncludePrivate: true}) stats.Counter.PublicKey, _ = e.Count(new(asymkey_model.PublicKey)) stats.Counter.Repo, _ = repo_model.CountRepositories(ctx, repo_model.CountRepositoryOptions{}) stats.Counter.Watch, _ = e.Count(new(repo_model.Watch)) @@ -102,7 +102,7 @@ func GetStatistic(ctx context.Context) (stats Statistic) { stats.Counter.Follow, _ = e.Count(new(user_model.Follow)) stats.Counter.Mirror, _ = e.Count(new(repo_model.Mirror)) stats.Counter.Release, _ = e.Count(new(repo_model.Release)) - stats.Counter.AuthSource = auth.CountSources(ctx, auth.FindSourcesOptions{}) + stats.Counter.AuthSource, _ = db.Count[auth.Source](ctx, auth.FindSourcesOptions{}) stats.Counter.Webhook, _ = e.Count(new(webhook.Webhook)) stats.Counter.Milestone, _ = e.Count(new(issues_model.Milestone)) stats.Counter.Label, _ = e.Count(new(issues_model.Label)) diff --git a/models/auth/source.go b/models/auth/source.go index 5f2781c808f2..0e2914a8be74 100644 --- a/models/auth/source.go +++ b/models/auth/source.go @@ -242,6 +242,7 @@ func CreateSource(ctx context.Context, source *Source) error { } type FindSourcesOptions struct { + db.ListOptions IsActive util.OptionalBool LoginType Type } @@ -257,19 +258,13 @@ func (opts FindSourcesOptions) ToConds() builder.Cond { return conds } -// FindSources returns a slice of login sources found in DB according to given conditions. -func FindSources(ctx context.Context, opts FindSourcesOptions) ([]*Source, error) { - auths := make([]*Source, 0, 6) - return auths, db.GetEngine(ctx).Where(opts.ToConds()).Find(&auths) -} - // IsSSPIEnabled returns true if there is at least one activated login // source of type LoginSSPI func IsSSPIEnabled(ctx context.Context) bool { if !db.HasEngine { return false } - sources, err := FindSources(ctx, FindSourcesOptions{ + sources, err := db.Find[Source](ctx, &FindSourcesOptions{ IsActive: util.OptionalBoolTrue, LoginType: SSPI, }) @@ -346,12 +341,6 @@ func UpdateSource(ctx context.Context, source *Source) error { return err } -// CountSources returns number of login sources. -func CountSources(ctx context.Context, opts FindSourcesOptions) int64 { - count, _ := db.GetEngine(ctx).Where(opts.ToConds()).Count(new(Source)) - return count -} - // ErrSourceNotExist represents a "SourceNotExist" kind of error. type ErrSourceNotExist struct { ID int64 diff --git a/models/db/list.go b/models/db/list.go index 1d029d53e25b..df3323301d32 100644 --- a/models/db/list.go +++ b/models/db/list.go @@ -73,16 +73,16 @@ func (opts *ListOptions) GetStartEnd() (start, end int) { return start, end } -func (opts *ListOptions) GetPage() int { +func (opts ListOptions) GetPage() int { return opts.Page } -func (opts *ListOptions) GetPageSize() int { +func (opts ListOptions) GetPageSize() int { return opts.PageSize } // IsListAll indicates PageSize and Page will be ignored -func (opts *ListOptions) IsListAll() bool { +func (opts ListOptions) IsListAll() bool { return opts.ListAll } @@ -99,7 +99,7 @@ func (opts *ListOptions) SetDefaultValues() { } } -func (opts *ListOptions) ToConds() builder.Cond { +func (opts ListOptions) ToConds() builder.Cond { return builder.NewCond() } diff --git a/models/organization/org.go b/models/organization/org.go index 07091194ebcc..23a4e2f96a50 100644 --- a/models/organization/org.go +++ b/models/organization/org.go @@ -456,7 +456,7 @@ func queryUserOrgIDs(userID int64, includePrivate bool) *builder.Builder { return builder.Select("org_id").From("org_user").Where(cond) } -func (opts FindOrgOptions) toConds() builder.Cond { +func (opts FindOrgOptions) ToConds() builder.Cond { var cond builder.Cond = builder.Eq{"`user`.`type`": user_model.UserTypeOrganization} if opts.UserID > 0 { cond = cond.And(builder.In("`user`.`id`", queryUserOrgIDs(opts.UserID, opts.IncludePrivate))) @@ -467,23 +467,8 @@ func (opts FindOrgOptions) toConds() builder.Cond { return cond } -// FindOrgs returns a list of organizations according given conditions -func FindOrgs(ctx context.Context, opts FindOrgOptions) ([]*Organization, error) { - orgs := make([]*Organization, 0, 10) - sess := db.GetEngine(ctx). - Where(opts.toConds()). - Asc("`user`.name") - if opts.Page > 0 && opts.PageSize > 0 { - sess.Limit(opts.PageSize, opts.PageSize*(opts.Page-1)) - } - return orgs, sess.Find(&orgs) -} - -// CountOrgs returns total count organizations according options -func CountOrgs(ctx context.Context, opts FindOrgOptions) (int64, error) { - return db.GetEngine(ctx). - Where(opts.toConds()). - Count(new(Organization)) +func (opts FindOrgOptions) ToOrders() string { + return "`user`.name ASC" } // HasOrgOrUserVisible tells if the given user can see the given org or user diff --git a/models/organization/org_test.go b/models/organization/org_test.go index aa72fc467ea7..5e40dd41907b 100644 --- a/models/organization/org_test.go +++ b/models/organization/org_test.go @@ -131,7 +131,7 @@ func TestCountOrganizations(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) expected, err := db.GetEngine(db.DefaultContext).Where("type=?", user_model.UserTypeOrganization).Count(&organization.Organization{}) assert.NoError(t, err) - cnt, err := organization.CountOrgs(db.DefaultContext, organization.FindOrgOptions{IncludePrivate: true}) + cnt, err := db.Count[organization.Organization](db.DefaultContext, organization.FindOrgOptions{IncludePrivate: true}) assert.NoError(t, err) assert.Equal(t, expected, cnt) } @@ -183,7 +183,7 @@ func TestIsPublicMembership(t *testing.T) { func TestFindOrgs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - orgs, err := organization.FindOrgs(db.DefaultContext, organization.FindOrgOptions{ + orgs, err := db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{ UserID: 4, IncludePrivate: true, }) @@ -192,14 +192,14 @@ func TestFindOrgs(t *testing.T) { assert.EqualValues(t, 3, orgs[0].ID) } - orgs, err = organization.FindOrgs(db.DefaultContext, organization.FindOrgOptions{ + orgs, err = db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{ UserID: 4, IncludePrivate: false, }) assert.NoError(t, err) assert.Len(t, orgs, 0) - total, err := organization.CountOrgs(db.DefaultContext, organization.FindOrgOptions{ + total, err := db.Count[organization.Organization](db.DefaultContext, organization.FindOrgOptions{ UserID: 4, IncludePrivate: true, }) diff --git a/routers/api/v1/notify/notifications.go b/routers/api/v1/notify/notifications.go index b22ea8a77157..74ee76b5e5a7 100644 --- a/routers/api/v1/notify/notifications.go +++ b/routers/api/v1/notify/notifications.go @@ -8,6 +8,7 @@ import ( "strings" activities_model "code.gitea.io/gitea/models/activities" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/context" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/routers/api/v1/utils" @@ -21,7 +22,17 @@ func NewAvailable(ctx *context.APIContext) { // responses: // "200": // "$ref": "#/responses/NotificationCount" - ctx.JSON(http.StatusOK, api.NotificationCount{New: activities_model.CountUnread(ctx, ctx.Doer.ID)}) + + total, err := db.Count[activities_model.Notification](ctx, &activities_model.FindNotificationOptions{ + UserID: ctx.Doer.ID, + Status: []activities_model.NotificationStatus{activities_model.NotificationStatusUnread}, + }) + if err != nil { + ctx.Error(http.StatusUnprocessableEntity, "db.Count[activities_model.Notification]", err) + return + } + + ctx.JSON(http.StatusOK, api.NotificationCount{New: total}) } func getFindNotificationOptions(ctx *context.APIContext) *activities_model.FindNotificationOptions { diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index 6fb8ecd403a0..f2d183f567bc 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -30,12 +30,12 @@ func listUserOrgs(ctx *context.APIContext, u *user_model.User) { UserID: u.ID, IncludePrivate: showPrivate, } - orgs, err := organization.FindOrgs(ctx, opts) + orgs, err := db.Find[*organization.Organization](ctx, &opts) if err != nil { ctx.Error(http.StatusInternalServerError, "FindOrgs", err) return } - maxResults, err := organization.CountOrgs(ctx, opts) + maxResults, err := db.Count[organization.Organization](ctx, &opts) if err != nil { ctx.Error(http.StatusInternalServerError, "CountOrgs", err) return diff --git a/routers/web/admin/auths.go b/routers/web/admin/auths.go index 23946d64afa3..2cf63c646d3d 100644 --- a/routers/web/admin/auths.go +++ b/routers/web/admin/auths.go @@ -13,6 +13,7 @@ import ( "strings" "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/auth/pam" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" @@ -48,13 +49,12 @@ func Authentications(ctx *context.Context) { ctx.Data["PageIsAdminAuthentications"] = true var err error - ctx.Data["Sources"], err = auth.FindSources(ctx, auth.FindSourcesOptions{}) + ctx.Data["Sources"], ctx.Data["Total"], err = db.FindAndCount[auth.Source](ctx, auth.FindSourcesOptions{}) if err != nil { ctx.ServerError("auth.Sources", err) return } - ctx.Data["Total"] = auth.CountSources(ctx, auth.FindSourcesOptions{}) ctx.HTML(http.StatusOK, tplAuths) } @@ -284,7 +284,7 @@ func NewAuthSourcePost(ctx *context.Context) { ctx.RenderWithErr(err.Error(), tplAuthNew, form) return } - existing, err := auth.FindSources(ctx, auth.FindSourcesOptions{LoginType: auth.SSPI}) + existing, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{LoginType: auth.SSPI}) if err != nil || len(existing) > 0 { ctx.Data["Err_Type"] = true ctx.RenderWithErr(ctx.Tr("admin.auths.login_source_of_type_exist"), tplAuthNew, form) diff --git a/routers/web/admin/users.go b/routers/web/admin/users.go index 58120818b0bc..44c4fa751254 100644 --- a/routers/web/admin/users.go +++ b/routers/web/admin/users.go @@ -93,7 +93,7 @@ func NewUser(ctx *context.Context) { ctx.Data["login_type"] = "0-0" - sources, err := auth.FindSources(ctx, auth.FindSourcesOptions{ + sources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ IsActive: util.OptionalBoolTrue, }) if err != nil { @@ -114,7 +114,7 @@ func NewUserPost(ctx *context.Context) { ctx.Data["DefaultUserVisibilityMode"] = setting.Service.DefaultUserVisibilityMode ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice() - sources, err := auth.FindSources(ctx, auth.FindSourcesOptions{ + sources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ IsActive: util.OptionalBoolTrue, }) if err != nil { @@ -237,7 +237,7 @@ func prepareUserInfo(ctx *context.Context) *user_model.User { ctx.Data["LoginSource"] = &auth.Source{} } - sources, err := auth.FindSources(ctx, auth.FindSourcesOptions{}) + sources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{}) if err != nil { ctx.ServerError("auth.Sources", err) return nil @@ -296,7 +296,7 @@ func ViewUser(ctx *context.Context) { ctx.Data["Emails"] = emails ctx.Data["EmailsTotal"] = len(emails) - orgs, err := org_model.FindOrgs(ctx, org_model.FindOrgOptions{ + orgs, err := db.Find[org_model.Organization](ctx, org_model.FindOrgOptions{ ListOptions: db.ListOptions{ ListAll: true, }, diff --git a/routers/web/shared/user/header.go b/routers/web/shared/user/header.go index 3a83722ef767..b49ff62f4814 100644 --- a/routers/web/shared/user/header.go +++ b/routers/web/shared/user/header.go @@ -59,7 +59,7 @@ func PrepareContextForProfileBigAvatar(ctx *context.Context) { } showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID) - orgs, err := organization.FindOrgs(ctx, organization.FindOrgOptions{ + orgs, err := db.Find[*organization.Organization](ctx, &organization.FindOrgOptions{ UserID: ctx.ContextUser.ID, IncludePrivate: showPrivate, }) diff --git a/routers/web/user/notification.go b/routers/web/user/notification.go index 579287ffac65..283b53212c2f 100644 --- a/routers/web/user/notification.go +++ b/routers/web/user/notification.go @@ -42,7 +42,10 @@ func GetNotificationCount(ctx *context.Context) { } ctx.Data["NotificationUnreadCount"] = func() int64 { - count, err := activities_model.GetNotificationCount(ctx, ctx.Doer, activities_model.NotificationStatusUnread) + count, err := db.Count[activities_model.Notification](ctx, &activities_model.FindNotificationOptions{ + UserID: ctx.Doer.ID, + Status: []activities_model.NotificationStatus{activities_model.NotificationStatusUnread}, + }) if err != nil { if err != goctx.Canceled { log.Error("Unable to GetNotificationCount for user:%-v: %v", ctx.Doer, err) @@ -89,7 +92,10 @@ func getNotifications(ctx *context.Context) { status = activities_model.NotificationStatusUnread } - total, err := activities_model.GetNotificationCount(ctx, ctx.Doer, status) + total, err := db.Count[activities_model.Notification](ctx, &activities_model.FindNotificationOptions{ + UserID: ctx.Doer.ID, + Status: []activities_model.NotificationStatus{status}, + }) if err != nil { ctx.ServerError("ErrGetNotificationCount", err) return @@ -409,5 +415,15 @@ func NotificationWatching(ctx *context.Context) { // NewAvailable returns the notification counts func NewAvailable(ctx *context.Context) { - ctx.JSON(http.StatusOK, structs.NotificationCount{New: activities_model.CountUnread(ctx, ctx.Doer.ID)}) + total, err := db.Count[activities_model.Notification](ctx, &activities_model.FindNotificationOptions{ + UserID: ctx.Doer.ID, + Status: []activities_model.NotificationStatus{activities_model.NotificationStatusUnread}, + }) + if err != nil { + log.Error("db.Count[activities_model.Notification]", err) + ctx.JSON(http.StatusOK, structs.NotificationCount{New: 0}) + return + } + + ctx.JSON(http.StatusOK, structs.NotificationCount{New: total}) } diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index 2390b0746c1a..df8ed174f70c 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -214,16 +214,12 @@ func Organization(ctx *context.Context) { opts.Page = 1 } - orgs, err := organization.FindOrgs(ctx, opts) + orgs, total, err := db.FindAndCount[organization.Organization](ctx, &opts) if err != nil { ctx.ServerError("FindOrgs", err) return } - total, err := organization.CountOrgs(ctx, opts) - if err != nil { - ctx.ServerError("CountOrgs", err) - return - } + ctx.Data["Orgs"] = orgs pager := context.NewPagination(int(total), opts.PageSize, opts.Page, 5) pager.SetDefaultParams(ctx) diff --git a/routers/web/user/setting/security/security.go b/routers/web/user/setting/security/security.go index ec269776e2b6..153322dc3f1a 100644 --- a/routers/web/user/setting/security/security.go +++ b/routers/web/user/setting/security/security.go @@ -9,6 +9,7 @@ import ( "sort" auth_model "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/models/db" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" @@ -107,7 +108,7 @@ func loadSecurityData(ctx *context.Context) { } ctx.Data["AccountLinks"] = sources - authSources, err := auth_model.FindSources(ctx, auth_model.FindSourcesOptions{ + authSources, err := db.Find[*auth_model.Source](ctx, auth_model.FindSourcesOptions{ IsActive: util.OptionalBoolNone, LoginType: auth_model.OAuth2, }) diff --git a/services/auth/signin.go b/services/auth/signin.go index 2e534536817e..023f05000f69 100644 --- a/services/auth/signin.go +++ b/services/auth/signin.go @@ -86,7 +86,7 @@ func UserSignIn(ctx context.Context, username, password string) (*user_model.Use } } - sources, err := auth.FindSources(ctx, auth.FindSourcesOptions{ + sources, err := db.Find[*auth.Source](ctx, auth.FindSourcesOptions{ IsActive: util.OptionalBoolTrue, }) if err != nil { diff --git a/services/auth/source/oauth2/init.go b/services/auth/source/oauth2/init.go index 0ebbdaebd411..3ad6e307f106 100644 --- a/services/auth/source/oauth2/init.go +++ b/services/auth/source/oauth2/init.go @@ -10,6 +10,7 @@ import ( "sync" "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" @@ -64,7 +65,7 @@ func ResetOAuth2(ctx context.Context) error { // initOAuth2Sources is used to load and register all active OAuth2 providers func initOAuth2Sources(ctx context.Context) error { - authSources, err := auth.FindSources(ctx, auth.FindSourcesOptions{ + authSources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ IsActive: util.OptionalBoolTrue, LoginType: auth.OAuth2, }) diff --git a/services/auth/source/oauth2/providers.go b/services/auth/source/oauth2/providers.go index 3b45b252f709..ac2f2dc6c1b0 100644 --- a/services/auth/source/oauth2/providers.go +++ b/services/auth/source/oauth2/providers.go @@ -13,6 +13,7 @@ import ( "sort" "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" @@ -107,7 +108,7 @@ func CreateProviderFromSource(source *auth.Source) (Provider, error) { // GetOAuth2Providers returns the list of configured OAuth2 providers func GetOAuth2Providers(ctx context.Context, isActive util.OptionalBool) ([]Provider, error) { - authSources, err := auth.FindSources(ctx, auth.FindSourcesOptions{ + authSources, err := db.Find[*auth.Source](ctx, auth.FindSourcesOptions{ IsActive: isActive, LoginType: auth.OAuth2, }) diff --git a/services/auth/sspi.go b/services/auth/sspi.go index bc8ec948f29c..57ba0462c573 100644 --- a/services/auth/sspi.go +++ b/services/auth/sspi.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/models/avatars" + "code.gitea.io/gitea/models/db" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/base" gitea_context "code.gitea.io/gitea/modules/context" @@ -130,7 +131,7 @@ func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore, // getConfig retrieves the SSPI configuration from login sources func (s *SSPI) getConfig(ctx context.Context) (*sspi.Source, error) { - sources, err := auth.FindSources(ctx, auth.FindSourcesOptions{ + sources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ IsActive: util.OptionalBoolTrue, LoginType: auth.SSPI, }) diff --git a/services/auth/sync.go b/services/auth/sync.go index 11a59d41ae1b..7562ac812bd3 100644 --- a/services/auth/sync.go +++ b/services/auth/sync.go @@ -15,7 +15,7 @@ import ( func SyncExternalUsers(ctx context.Context, updateExisting bool) error { log.Trace("Doing: SyncExternalUsers") - ls, err := auth.FindSources(ctx, auth.FindSourcesOptions{}) + ls, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{}) if err != nil { log.Error("SyncExternalUsers: %v", err) return err diff --git a/services/user/user.go b/services/user/user.go index 4a4908fe8e52..ba49e0194d11 100644 --- a/services/user/user.go +++ b/services/user/user.go @@ -172,7 +172,7 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) error { // An alternative option here would be write a function which would delete all organizations but it seems // but such a function would likely get out of date for { - orgs, err := organization.FindOrgs(ctx, organization.FindOrgOptions{ + orgs, err := db.Find[*organization.Organization](ctx, &organization.FindOrgOptions{ ListOptions: db.ListOptions{ PageSize: repo_model.RepositoryListDefaultPageSize, Page: 1, diff --git a/tests/integration/auth_ldap_test.go b/tests/integration/auth_ldap_test.go index 9bb9e7b3c7eb..1148b3ad3993 100644 --- a/tests/integration/auth_ldap_test.go +++ b/tests/integration/auth_ldap_test.go @@ -414,7 +414,7 @@ func TestLDAPGroupTeamSyncAddMember(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ Name: gitLDAPUser.UserName, }) - usersOrgs, err := organization.FindOrgs(db.DefaultContext, organization.FindOrgOptions{ + usersOrgs, err := db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{ UserID: user.ID, IncludePrivate: true, }) diff --git a/tests/integration/org_count_test.go b/tests/integration/org_count_test.go index d1aa41963eb8..6386f53f0599 100644 --- a/tests/integration/org_count_test.go +++ b/tests/integration/org_count_test.go @@ -118,7 +118,7 @@ func doCheckOrgCounts(username string, orgCounts map[string]int, strict bool, ca Name: username, }) - orgs, err := organization.FindOrgs(db.DefaultContext, organization.FindOrgOptions{ + orgs, err := db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{ UserID: user.ID, IncludePrivate: true, }) From d98c24d48e7cb7041b3025692dab281f50234eeb Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 17 Nov 2023 12:12:38 +0800 Subject: [PATCH 08/21] more refactor --- models/actions/run.go | 4 ++-- models/actions/schedule_spec_list.go | 2 +- models/activities/notification_list.go | 4 ++-- models/activities/statistic.go | 2 +- models/auth/source.go | 2 +- models/db/list.go | 2 +- models/db/list_test.go | 10 +++++----- models/issues/comment.go | 2 +- models/project/project.go | 4 ++-- models/project/project_test.go | 6 +++--- routers/api/actions/runner/utils.go | 2 +- routers/api/v1/notify/notifications.go | 2 +- routers/api/v1/org/org.go | 4 ++-- routers/web/org/projects.go | 4 ++-- routers/web/repo/actions/actions.go | 4 ++-- routers/web/repo/issue.go | 8 ++++---- routers/web/repo/projects.go | 2 +- routers/web/shared/actions/runners.go | 6 +++--- routers/web/shared/user/header.go | 2 +- routers/web/user/notification.go | 6 +++--- routers/web/user/setting/profile.go | 2 +- services/actions/clear_tasks.go | 4 ++-- services/actions/job_emitter.go | 2 +- services/actions/notifier_helper.go | 6 +++--- services/pull/review.go | 2 +- services/repository/delete.go | 2 +- services/user/user.go | 2 +- 27 files changed, 49 insertions(+), 49 deletions(-) diff --git a/models/actions/run.go b/models/actions/run.go index 9ffc551cf08b..24461e3587a2 100644 --- a/models/actions/run.go +++ b/models/actions/run.go @@ -170,7 +170,7 @@ func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) err // CancelRunningJobs cancels all running and waiting jobs associated with a specific workflow. func CancelRunningJobs(ctx context.Context, repoID int64, ref, workflowID string) error { // Find all runs in the specified repository, reference, and workflow with statuses 'Running' or 'Waiting'. - runs, total, err := db.FindAndCount[*ActionRun](ctx, &FindRunOptions{ + runs, total, err := db.FindAndCount[*ActionRun](ctx, FindRunOptions{ RepoID: repoID, Ref: ref, WorkflowID: workflowID, @@ -188,7 +188,7 @@ func CancelRunningJobs(ctx context.Context, repoID int64, ref, workflowID string // Iterate over each found run and cancel its associated jobs. for _, run := range runs { // Find all jobs associated with the current run. - jobs, _, err := db.FindAndCount[*ActionRunJob](ctx, &FindRunJobOptions{ + jobs, _, err := db.FindAndCount[*ActionRunJob](ctx, FindRunJobOptions{ RunID: run.ID, }) if err != nil { diff --git a/models/actions/schedule_spec_list.go b/models/actions/schedule_spec_list.go index c04ac01eae21..5aedc8364271 100644 --- a/models/actions/schedule_spec_list.go +++ b/models/actions/schedule_spec_list.go @@ -89,7 +89,7 @@ func (opts FindSpecOptions) ToOrders() string { } func FindSpecs(ctx context.Context, opts FindSpecOptions) (SpecList, int64, error) { - specs, total, err := db.FindAndCount[*ActionScheduleSpec](ctx, &opts) + specs, total, err := db.FindAndCount[*ActionScheduleSpec](ctx, opts) if err != nil { return nil, 0, err } diff --git a/models/activities/notification_list.go b/models/activities/notification_list.go index f2f03541f4e6..bd54a7f1b7a8 100644 --- a/models/activities/notification_list.go +++ b/models/activities/notification_list.go @@ -30,7 +30,7 @@ type FindNotificationOptions struct { } // ToCond will convert each condition into a xorm-Cond -func (opts *FindNotificationOptions) ToConds() builder.Cond { +func (opts FindNotificationOptions) ToConds() builder.Cond { cond := builder.NewCond() if opts.UserID != 0 { cond = cond.And(builder.Eq{"notification.user_id": opts.UserID}) @@ -60,7 +60,7 @@ func (opts *FindNotificationOptions) ToConds() builder.Cond { return cond } -func (opts *FindNotificationOptions) ToOrders() string { +func (opts FindNotificationOptions) ToOrders() string { return "notification.updated_unix DESC" } diff --git a/models/activities/statistic.go b/models/activities/statistic.go index 4044f249b266..fe5f7d087253 100644 --- a/models/activities/statistic.go +++ b/models/activities/statistic.go @@ -52,7 +52,7 @@ type IssueByRepositoryCount struct { func GetStatistic(ctx context.Context) (stats Statistic) { e := db.GetEngine(ctx) stats.Counter.User = user_model.CountUsers(ctx, nil) - stats.Counter.Org, _ = db.Count[organization.Organization](ctx, &organization.FindOrgOptions{IncludePrivate: true}) + stats.Counter.Org, _ = db.Count[organization.Organization](ctx, organization.FindOrgOptions{IncludePrivate: true}) stats.Counter.PublicKey, _ = e.Count(new(asymkey_model.PublicKey)) stats.Counter.Repo, _ = repo_model.CountRepositories(ctx, repo_model.CountRepositoryOptions{}) stats.Counter.Watch, _ = e.Count(new(repo_model.Watch)) diff --git a/models/auth/source.go b/models/auth/source.go index 0e2914a8be74..2607c5bb7b79 100644 --- a/models/auth/source.go +++ b/models/auth/source.go @@ -264,7 +264,7 @@ func IsSSPIEnabled(ctx context.Context) bool { if !db.HasEngine { return false } - sources, err := db.Find[Source](ctx, &FindSourcesOptions{ + sources, err := db.Find[Source](ctx, FindSourcesOptions{ IsActive: util.OptionalBoolTrue, LoginType: SSPI, }) diff --git a/models/db/list.go b/models/db/list.go index df3323301d32..a9c1e53cac67 100644 --- a/models/db/list.go +++ b/models/db/list.go @@ -57,7 +57,7 @@ var ListOptionsAll = ListOptions{ListAll: true} var ( _ Paginator = &ListOptions{} - _ FindOptions = &ListOptions{} + _ FindOptions = ListOptions{} ) // GetSkipTake returns the skip and take values diff --git a/models/db/list_test.go b/models/db/list_test.go index 1035af9ea0d7..45194611f8a4 100644 --- a/models/db/list_test.go +++ b/models/db/list_test.go @@ -18,11 +18,11 @@ type mockListOptions struct { db.ListOptions } -func (opts *mockListOptions) IsListAll() bool { +func (opts mockListOptions) IsListAll() bool { return true } -func (opts *mockListOptions) ToConds() builder.Cond { +func (opts mockListOptions) ToConds() builder.Cond { return builder.NewCond() } @@ -37,15 +37,15 @@ func TestFind(t *testing.T) { assert.NotEmpty(t, repoUnitCount) opts := mockListOptions{} - repoUnits, err := db.Find[repo_model.RepoUnit](db.DefaultContext, &opts) + repoUnits, err := db.Find[repo_model.RepoUnit](db.DefaultContext, opts) assert.NoError(t, err) assert.Len(t, repoUnits, repoUnitCount) - cnt, err := db.Count[repo_model.RepoUnit](db.DefaultContext, &opts) + cnt, err := db.Count[repo_model.RepoUnit](db.DefaultContext, opts) assert.NoError(t, err) assert.EqualValues(t, repoUnitCount, cnt) - repoUnits, newCnt, err := db.FindAndCount[repo_model.RepoUnit](db.DefaultContext, &opts) + repoUnits, newCnt, err := db.FindAndCount[repo_model.RepoUnit](db.DefaultContext, opts) assert.NoError(t, err) assert.EqualValues(t, cnt, newCnt) assert.Len(t, repoUnits, repoUnitCount) diff --git a/models/issues/comment.go b/models/issues/comment.go index 7fd07867dfe7..a59fa570af95 100644 --- a/models/issues/comment.go +++ b/models/issues/comment.go @@ -1027,7 +1027,7 @@ type FindCommentsOptions struct { } // ToConds implements FindOptions interface -func (opts *FindCommentsOptions) ToConds() builder.Cond { +func (opts FindCommentsOptions) ToConds() builder.Cond { cond := builder.NewCond() if opts.RepoID > 0 { cond = cond.And(builder.Eq{"issue.repo_id": opts.RepoID}) diff --git a/models/project/project.go b/models/project/project.go index 24434a6c3907..becfcbea1e68 100644 --- a/models/project/project.go +++ b/models/project/project.go @@ -201,7 +201,7 @@ type SearchOptions struct { Title string } -func (opts *SearchOptions) ToConds() builder.Cond { +func (opts SearchOptions) ToConds() builder.Cond { cond := builder.NewCond() if opts.RepoID > 0 { cond = cond.And(builder.Eq{"repo_id": opts.RepoID}) @@ -226,7 +226,7 @@ func (opts *SearchOptions) ToConds() builder.Cond { return cond } -func (opts *SearchOptions) ToOrders() string { +func (opts SearchOptions) ToOrders() string { return opts.OrderBy.String() } diff --git a/models/project/project_test.go b/models/project/project_test.go index 253c8b476079..7a37c1faf290 100644 --- a/models/project/project_test.go +++ b/models/project/project_test.go @@ -34,13 +34,13 @@ func TestIsProjectTypeValid(t *testing.T) { func TestGetProjects(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - projects, err := db.Find[Project](db.DefaultContext, &SearchOptions{RepoID: 1}) + projects, err := db.Find[Project](db.DefaultContext, SearchOptions{RepoID: 1}) assert.NoError(t, err) // 1 value for this repo exists in the fixtures assert.Len(t, projects, 1) - projects, err = db.Find[Project](db.DefaultContext, &SearchOptions{RepoID: 3}) + projects, err = db.Find[Project](db.DefaultContext, SearchOptions{RepoID: 3}) assert.NoError(t, err) // 1 value for this repo exists in the fixtures @@ -109,7 +109,7 @@ func TestProjectsSort(t *testing.T) { } for _, tt := range tests { - projects, count, err := db.FindAndCount[Project](db.DefaultContext, &SearchOptions{ + projects, count, err := db.FindAndCount[Project](db.DefaultContext, SearchOptions{ OrderBy: GetSearchOrderByBySortType(tt.sortType), }) assert.NoError(t, err) diff --git a/routers/api/actions/runner/utils.go b/routers/api/actions/runner/utils.go index 901888ed5522..7435ed272c74 100644 --- a/routers/api/actions/runner/utils.go +++ b/routers/api/actions/runner/utils.go @@ -201,7 +201,7 @@ func findTaskNeeds(ctx context.Context, task *actions_model.ActionTask) (map[str } needs := container.SetOf(task.Job.Needs...) - jobs, err := db.Find[*actions_model.ActionRunJob](ctx, &actions_model.FindRunJobOptions{RunID: task.Job.RunID}) + jobs, err := db.Find[*actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: task.Job.RunID}) if err != nil { return nil, fmt.Errorf("FindRunJobs: %w", err) } diff --git a/routers/api/v1/notify/notifications.go b/routers/api/v1/notify/notifications.go index 74ee76b5e5a7..c87da9399f05 100644 --- a/routers/api/v1/notify/notifications.go +++ b/routers/api/v1/notify/notifications.go @@ -23,7 +23,7 @@ func NewAvailable(ctx *context.APIContext) { // "200": // "$ref": "#/responses/NotificationCount" - total, err := db.Count[activities_model.Notification](ctx, &activities_model.FindNotificationOptions{ + total, err := db.Count[activities_model.Notification](ctx, activities_model.FindNotificationOptions{ UserID: ctx.Doer.ID, Status: []activities_model.NotificationStatus{activities_model.NotificationStatusUnread}, }) diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index f2d183f567bc..28f71d0bf046 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -30,12 +30,12 @@ func listUserOrgs(ctx *context.APIContext, u *user_model.User) { UserID: u.ID, IncludePrivate: showPrivate, } - orgs, err := db.Find[*organization.Organization](ctx, &opts) + orgs, err := db.Find[*organization.Organization](ctx, opts) if err != nil { ctx.Error(http.StatusInternalServerError, "FindOrgs", err) return } - maxResults, err := db.Count[organization.Organization](ctx, &opts) + maxResults, err := db.Count[organization.Organization](ctx, opts) if err != nil { ctx.Error(http.StatusInternalServerError, "CountOrgs", err) return diff --git a/routers/web/org/projects.go b/routers/web/org/projects.go index 29794f82310e..45bbf0fb9b2c 100644 --- a/routers/web/org/projects.go +++ b/routers/web/org/projects.go @@ -60,7 +60,7 @@ func Projects(ctx *context.Context) { } else { projectType = project_model.TypeIndividual } - projects, total, err := db.FindAndCount[*project_model.Project](ctx, &project_model.SearchOptions{ + projects, total, err := db.FindAndCount[*project_model.Project](ctx, project_model.SearchOptions{ ListOptions: db.ListOptions{ Page: page, PageSize: setting.UI.IssuePagingNum, @@ -76,7 +76,7 @@ func Projects(ctx *context.Context) { return } - opTotal, err := db.Count[project_model.Project](ctx, &project_model.SearchOptions{ + opTotal, err := db.Count[project_model.Project](ctx, project_model.SearchOptions{ OwnerID: ctx.ContextUser.ID, IsClosed: util.OptionalBoolOf(!isShowClosed), Type: projectType, diff --git a/routers/web/repo/actions/actions.go b/routers/web/repo/actions/actions.go index 47ea9441531e..cd039de6cdd1 100644 --- a/routers/web/repo/actions/actions.go +++ b/routers/web/repo/actions/actions.go @@ -75,7 +75,7 @@ func List(ctx *context.Context) { } // Get all runner labels - runners, err := db.Find[*actions_model.ActionRunner](ctx, &actions_model.FindRunnerOptions{ + runners, err := db.Find[*actions_model.ActionRunner](ctx, actions_model.FindRunnerOptions{ RepoID: ctx.Repo.Repository.ID, WithAvailable: true, }) @@ -168,7 +168,7 @@ func List(ctx *context.Context) { opts.Status = []actions_model.Status{actions_model.Status(status)} } - runs, total, err := db.FindAndCount[*actions_model.ActionRun](ctx, &opts) + runs, total, err := db.FindAndCount[*actions_model.ActionRun](ctx, opts) if err != nil { ctx.Error(http.StatusInternalServerError, err.Error()) return diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 42e35855ed03..1693b0135e8c 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -569,7 +569,7 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) { repoOwnerType = project_model.TypeOrganization } var err error - projects, err := db.Find[*project_model.Project](ctx, &project_model.SearchOptions{ + projects, err := db.Find[*project_model.Project](ctx, project_model.SearchOptions{ ListOptions: db.ListOptionsAll, RepoID: repo.ID, IsClosed: util.OptionalBoolFalse, @@ -579,7 +579,7 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) { ctx.ServerError("GetProjects", err) return } - projects2, err := db.Find[*project_model.Project](ctx, &project_model.SearchOptions{ + projects2, err := db.Find[*project_model.Project](ctx, project_model.SearchOptions{ ListOptions: db.ListOptionsAll, OwnerID: repo.OwnerID, IsClosed: util.OptionalBoolFalse, @@ -592,7 +592,7 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) { ctx.Data["OpenProjects"] = append(projects, projects2...) - projects, err = db.Find[*project_model.Project](ctx, &project_model.SearchOptions{ + projects, err = db.Find[*project_model.Project](ctx, project_model.SearchOptions{ ListOptions: db.ListOptionsAll, RepoID: repo.ID, IsClosed: util.OptionalBoolTrue, @@ -602,7 +602,7 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) { ctx.ServerError("GetProjects", err) return } - projects2, err = db.Find[*project_model.Project](ctx, &project_model.SearchOptions{ + projects2, err = db.Find[*project_model.Project](ctx, project_model.SearchOptions{ ListOptions: db.ListOptionsAll, OwnerID: repo.OwnerID, IsClosed: util.OptionalBoolTrue, diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go index 1e104341942e..098a95744beb 100644 --- a/routers/web/repo/projects.go +++ b/routers/web/repo/projects.go @@ -72,7 +72,7 @@ func Projects(ctx *context.Context) { total = repo.NumClosedProjects } - projects, count, err := db.FindAndCount[*project_model.Project](ctx, &project_model.SearchOptions{ + projects, count, err := db.FindAndCount[*project_model.Project](ctx, project_model.SearchOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.IssuePagingNum, Page: page, diff --git a/routers/web/shared/actions/runners.go b/routers/web/shared/actions/runners.go index c9e4ecaf1b8b..74d59eda346d 100644 --- a/routers/web/shared/actions/runners.go +++ b/routers/web/shared/actions/runners.go @@ -17,7 +17,7 @@ import ( // RunnersList prepares data for runners list func RunnersList(ctx *context.Context, opts actions_model.FindRunnerOptions) { - runners, count, err := db.FindAndCount[*actions_model.ActionRunner](ctx, &opts) + runners, count, err := db.FindAndCount[*actions_model.ActionRunner](ctx, opts) if err != nil { ctx.ServerError("CountRunners", err) return @@ -84,13 +84,13 @@ func RunnerDetails(ctx *context.Context, page int, runnerID, ownerID, repoID int RunnerID: runner.ID, } - count, err := db.Count[actions_model.ActionTask](ctx, &opts) + count, err := db.Count[actions_model.ActionTask](ctx, opts) if err != nil { ctx.ServerError("CountTasks", err) return } - tasks, err := db.Find[*actions_model.ActionTask](ctx, &opts) + tasks, err := db.Find[*actions_model.ActionTask](ctx, opts) if err != nil { ctx.ServerError("FindTasks", err) return diff --git a/routers/web/shared/user/header.go b/routers/web/shared/user/header.go index b49ff62f4814..797ff6f6f3d0 100644 --- a/routers/web/shared/user/header.go +++ b/routers/web/shared/user/header.go @@ -59,7 +59,7 @@ func PrepareContextForProfileBigAvatar(ctx *context.Context) { } showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID) - orgs, err := db.Find[*organization.Organization](ctx, &organization.FindOrgOptions{ + orgs, err := db.Find[*organization.Organization](ctx, organization.FindOrgOptions{ UserID: ctx.ContextUser.ID, IncludePrivate: showPrivate, }) diff --git a/routers/web/user/notification.go b/routers/web/user/notification.go index 283b53212c2f..47755117de58 100644 --- a/routers/web/user/notification.go +++ b/routers/web/user/notification.go @@ -42,7 +42,7 @@ func GetNotificationCount(ctx *context.Context) { } ctx.Data["NotificationUnreadCount"] = func() int64 { - count, err := db.Count[activities_model.Notification](ctx, &activities_model.FindNotificationOptions{ + count, err := db.Count[activities_model.Notification](ctx, activities_model.FindNotificationOptions{ UserID: ctx.Doer.ID, Status: []activities_model.NotificationStatus{activities_model.NotificationStatusUnread}, }) @@ -92,7 +92,7 @@ func getNotifications(ctx *context.Context) { status = activities_model.NotificationStatusUnread } - total, err := db.Count[activities_model.Notification](ctx, &activities_model.FindNotificationOptions{ + total, err := db.Count[activities_model.Notification](ctx, activities_model.FindNotificationOptions{ UserID: ctx.Doer.ID, Status: []activities_model.NotificationStatus{status}, }) @@ -415,7 +415,7 @@ func NotificationWatching(ctx *context.Context) { // NewAvailable returns the notification counts func NewAvailable(ctx *context.Context) { - total, err := db.Count[activities_model.Notification](ctx, &activities_model.FindNotificationOptions{ + total, err := db.Count[activities_model.Notification](ctx, activities_model.FindNotificationOptions{ UserID: ctx.Doer.ID, Status: []activities_model.NotificationStatus{activities_model.NotificationStatusUnread}, }) diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index df8ed174f70c..d8331fef43f5 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -214,7 +214,7 @@ func Organization(ctx *context.Context) { opts.Page = 1 } - orgs, total, err := db.FindAndCount[organization.Organization](ctx, &opts) + orgs, total, err := db.FindAndCount[organization.Organization](ctx, opts) if err != nil { ctx.ServerError("FindOrgs", err) return diff --git a/services/actions/clear_tasks.go b/services/actions/clear_tasks.go index be2dec4a3313..a108dcdf1f6a 100644 --- a/services/actions/clear_tasks.go +++ b/services/actions/clear_tasks.go @@ -33,7 +33,7 @@ func StopEndlessTasks(ctx context.Context) error { } func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error { - tasks, err := db.Find[*actions_model.ActionTask](ctx, &opts) + tasks, err := db.Find[*actions_model.ActionTask](ctx, opts) if err != nil { return fmt.Errorf("find tasks: %w", err) } @@ -74,7 +74,7 @@ func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error { // CancelAbandonedJobs cancels the jobs which have waiting status, but haven't been picked by a runner for a long time func CancelAbandonedJobs(ctx context.Context) error { - jobs, err := db.Find[*actions_model.ActionRunJob](ctx, &actions_model.FindRunJobOptions{ + jobs, err := db.Find[*actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{ Statuses: []actions_model.Status{actions_model.StatusWaiting, actions_model.StatusBlocked}, UpdatedBefore: timeutil.TimeStamp(time.Now().Add(-setting.Actions.AbandonedJobTimeout).Unix()), }) diff --git a/services/actions/job_emitter.go b/services/actions/job_emitter.go index 8b89d6aae60a..fd3825f75ed1 100644 --- a/services/actions/job_emitter.go +++ b/services/actions/job_emitter.go @@ -44,7 +44,7 @@ func jobEmitterQueueHandler(items ...*jobUpdate) []*jobUpdate { } func checkJobsOfRun(ctx context.Context, runID int64) error { - jobs, err := db.Find[*actions_model.ActionRunJob](ctx, &actions_model.FindRunJobOptions{RunID: runID}) + jobs, err := db.Find[*actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: runID}) if err != nil { return err } diff --git a/services/actions/notifier_helper.go b/services/actions/notifier_helper.go index 825780cc6a7e..e8fc1fbcbeed 100644 --- a/services/actions/notifier_helper.go +++ b/services/actions/notifier_helper.go @@ -274,7 +274,7 @@ func handleWorkflows( continue } - alljobs, err := db.Find[*actions_model.ActionRunJob](ctx, &actions_model.FindRunJobOptions{RunID: run.ID}) + alljobs, err := db.Find[*actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID}) if err != nil { log.Error("FindRunJobs: %v", err) continue @@ -353,7 +353,7 @@ func ifNeedApproval(ctx context.Context, run *actions_model.ActionRun, repo *rep } // don't need approval if the user has been approved before - if count, err := db.Count[actions_model.ActionRun](ctx, &actions_model.FindRunOptions{ + if count, err := db.Count[actions_model.ActionRun](ctx, actions_model.FindRunOptions{ RepoID: repo.ID, TriggerUserID: user.ID, Approved: true, @@ -384,7 +384,7 @@ func handleSchedules( return nil } - if count, err := db.Count[actions_model.ActionSchedule](ctx, &actions_model.FindScheduleOptions{RepoID: input.Repo.ID}); err != nil { + if count, err := db.Count[actions_model.ActionSchedule](ctx, actions_model.FindScheduleOptions{RepoID: input.Repo.ID}); err != nil { log.Error("CountSchedules: %v", err) return err } else if count > 0 { diff --git a/services/pull/review.go b/services/pull/review.go index 65d5f4816d01..1d3a8003f73d 100644 --- a/services/pull/review.go +++ b/services/pull/review.go @@ -50,7 +50,7 @@ func InvalidateCodeComments(ctx context.Context, prs issues_model.PullRequestLis } issueIDs := prs.GetIssueIDs() - codeComments, err := db.Find[*issues_model.Comment](ctx, &issues_model.FindCommentsOptions{ + codeComments, err := db.Find[*issues_model.Comment](ctx, issues_model.FindCommentsOptions{ ListOptions: db.ListOptions{ ListAll: true, }, diff --git a/services/repository/delete.go b/services/repository/delete.go index 46e95a8eeb6d..f306e117619f 100644 --- a/services/repository/delete.go +++ b/services/repository/delete.go @@ -54,7 +54,7 @@ func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID } // Query the action tasks of this repo, they will be needed after they have been deleted to remove the logs - tasks, err := db.Find[actions_model.ActionTask](ctx, &actions_model.FindTaskOptions{RepoID: repoID}) + tasks, err := db.Find[actions_model.ActionTask](ctx, actions_model.FindTaskOptions{RepoID: repoID}) if err != nil { return fmt.Errorf("find actions tasks of repo %v: %w", repoID, err) } diff --git a/services/user/user.go b/services/user/user.go index ba49e0194d11..667559f793a8 100644 --- a/services/user/user.go +++ b/services/user/user.go @@ -172,7 +172,7 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) error { // An alternative option here would be write a function which would delete all organizations but it seems // but such a function would likely get out of date for { - orgs, err := db.Find[*organization.Organization](ctx, &organization.FindOrgOptions{ + orgs, err := db.Find[*organization.Organization](ctx, organization.FindOrgOptions{ ListOptions: db.ListOptions{ PageSize: repo_model.RepositoryListDefaultPageSize, Page: 1, From 1228312bb5d2d770777374fbe299cb7d99319467 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 17 Nov 2023 21:31:38 +0800 Subject: [PATCH 09/21] Fix check --- models/activities/notification_list.go | 1 + 1 file changed, 1 insertion(+) diff --git a/models/activities/notification_list.go b/models/activities/notification_list.go index bd54a7f1b7a8..50440d542976 100644 --- a/models/activities/notification_list.go +++ b/models/activities/notification_list.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/timeutil" + "xorm.io/builder" "xorm.io/xorm" ) From b29cb74678bfc7a61b4f3197164c6458eee79d0e Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 18 Nov 2023 11:29:42 +0800 Subject: [PATCH 10/21] Follow @delvh suggestion --- models/actions/run.go | 2 +- models/activities/notification.go | 4 +- models/activities/notification_list.go | 115 ++++++++++++++++--------- models/activities/notification_test.go | 16 ---- models/auth/source.go | 7 +- models/db/context.go | 5 ++ routers/api/v1/org/org.go | 9 +- routers/web/shared/actions/runners.go | 7 +- routers/web/user/notification.go | 13 ++- 9 files changed, 100 insertions(+), 78 deletions(-) diff --git a/models/actions/run.go b/models/actions/run.go index 24461e3587a2..4367f603667c 100644 --- a/models/actions/run.go +++ b/models/actions/run.go @@ -188,7 +188,7 @@ func CancelRunningJobs(ctx context.Context, repoID int64, ref, workflowID string // Iterate over each found run and cancel its associated jobs. for _, run := range runs { // Find all jobs associated with the current run. - jobs, _, err := db.FindAndCount[*ActionRunJob](ctx, FindRunJobOptions{ + jobs, err := db.Find[*ActionRunJob](ctx, FindRunJobOptions{ RunID: run.ID, }) if err != nil { diff --git a/models/activities/notification.go b/models/activities/notification.go index c7ebc07e49d7..f2abe7bdce26 100644 --- a/models/activities/notification.go +++ b/models/activities/notification.go @@ -131,7 +131,9 @@ func CreateOrUpdateIssueNotifications(ctx context.Context, issueID, commentID, n func createOrUpdateIssueNotifications(ctx context.Context, issueID, commentID, notificationAuthorID, receiverID int64) error { // init var toNotify container.Set[int64] - notifications, err := getNotificationsByIssueID(ctx, issueID) + notifications, err := db.Find[*Notification](ctx, FindNotificationOptions{ + IssueID: issueID, + }) if err != nil { return err } diff --git a/models/activities/notification_list.go b/models/activities/notification_list.go index 50440d542976..23dacae4595c 100644 --- a/models/activities/notification_list.go +++ b/models/activities/notification_list.go @@ -15,7 +15,6 @@ import ( "code.gitea.io/gitea/modules/timeutil" "xorm.io/builder" - "xorm.io/xorm" ) // FindNotificationOptions represent the filters for notifications. If an ID is 0 it will be ignored. @@ -65,22 +64,6 @@ func (opts FindNotificationOptions) ToOrders() string { return "notification.updated_unix DESC" } -// ToSession will convert the given options to a xorm Session by using the conditions from ToCond and joining with issue table if required -func (opts *FindNotificationOptions) ToSession(ctx context.Context) *xorm.Session { - sess := db.GetEngine(ctx).Where(opts.ToConds()) - if opts.Page != 0 { - sess = db.SetSessionPagination(sess, opts) - } - return sess -} - -func getNotificationsByIssueID(ctx context.Context, issueID int64) (notifications []*Notification, err error) { - err = db.GetEngine(ctx). - Where("issue_id = ?", issueID). - Find(¬ifications) - return notifications, err -} - func notificationExists(notifications []*Notification, issueID, userID int64) bool { for _, notification := range notifications { if notification.IssueID == issueID && notification.UserID == userID { @@ -91,25 +74,6 @@ func notificationExists(notifications []*Notification, issueID, userID int64) bo return false } -// NotificationsForUser returns notifications for a given user and status -func NotificationsForUser(ctx context.Context, user *user_model.User, statuses []NotificationStatus, page, perPage int) (notifications NotificationList, err error) { - if len(statuses) == 0 { - return nil, nil - } - - sess := db.GetEngine(ctx). - Where("user_id = ?", user.ID). - In("status", statuses). - OrderBy("updated_unix DESC") - - if page > 0 && perPage > 0 { - sess.Limit(perPage, (page-1)*perPage) - } - - err = sess.Find(¬ifications) - return notifications, err -} - // UserIDCount is a simple coalition of UserID and Count type UserIDCount struct { UserID int64 @@ -130,12 +94,17 @@ type NotificationList []*Notification // LoadAttributes load Repo Issue User and Comment if not loaded func (nl NotificationList) LoadAttributes(ctx context.Context) error { - var err error - for i := 0; i < len(nl); i++ { - err = nl[i].LoadAttributes(ctx) - if err != nil && !issues_model.IsErrCommentNotExist(err) { - return err - } + if _, _, err := nl.LoadRepos(ctx); err != nil { + return err + } + if _, err := nl.LoadIssues(ctx); err != nil { + return err + } + if _, err := nl.LoadUsers(ctx); err != nil { + return err + } + if _, err := nl.LoadComments(ctx); err != nil { + return err } return nil } @@ -309,6 +278,68 @@ func (nl NotificationList) getPendingCommentIDs() []int64 { return ids.Values() } +func (nl NotificationList) getUserIDs() []int64 { + ids := make(container.Set[int64], len(nl)) + for _, notification := range nl { + if notification.UserID == 0 || notification.User != nil { + continue + } + ids.Add(notification.UserID) + } + return ids.Values() +} + +// LoadUsers loads users from database +func (nl NotificationList) LoadUsers(ctx context.Context) ([]int, error) { + if len(nl) == 0 { + return []int{}, nil + } + + userIDs := nl.getUserIDs() + users := make(map[int64]*user_model.User, len(userIDs)) + left := len(userIDs) + for left > 0 { + limit := db.DefaultMaxInSize + if left < limit { + limit = left + } + rows, err := db.GetEngine(ctx). + In("id", userIDs[:limit]). + Rows(new(user_model.User)) + if err != nil { + return nil, err + } + + for rows.Next() { + var user user_model.User + err = rows.Scan(&user) + if err != nil { + rows.Close() + return nil, err + } + + users[user.ID] = &user + } + _ = rows.Close() + + left -= limit + userIDs = userIDs[limit:] + } + + failures := []int{} + for i, notification := range nl { + if notification.UserID > 0 && notification.User == nil && users[notification.UserID] != nil { + notification.User = users[notification.UserID] + if notification.User == nil { + log.Error("Notification[%d]: UserID[%d] failed to load", notification.ID, notification.UserID) + failures = append(failures, i) + continue + } + } + } + return failures, nil +} + // LoadComments loads comments from database func (nl NotificationList) LoadComments(ctx context.Context) ([]int, error) { if len(nl) == 0 { diff --git a/models/activities/notification_test.go b/models/activities/notification_test.go index cdb4d6b1aac8..d46debfecc1a 100644 --- a/models/activities/notification_test.go +++ b/models/activities/notification_test.go @@ -31,22 +31,6 @@ func TestCreateOrUpdateIssueNotifications(t *testing.T) { assert.Equal(t, activities_model.NotificationStatusUnread, notf.Status) } -func TestNotificationsForUser(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - statuses := []activities_model.NotificationStatus{activities_model.NotificationStatusRead, activities_model.NotificationStatusUnread} - notfs, err := activities_model.NotificationsForUser(db.DefaultContext, user, statuses, 1, 10) - assert.NoError(t, err) - if assert.Len(t, notfs, 3) { - assert.EqualValues(t, 5, notfs[0].ID) - assert.EqualValues(t, user.ID, notfs[0].UserID) - assert.EqualValues(t, 4, notfs[1].ID) - assert.EqualValues(t, user.ID, notfs[1].UserID) - assert.EqualValues(t, 2, notfs[2].ID) - assert.EqualValues(t, user.ID, notfs[2].UserID) - } -} - func TestNotification_GetRepo(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{RepoID: 1}) diff --git a/models/auth/source.go b/models/auth/source.go index 2607c5bb7b79..98ce5968d3ec 100644 --- a/models/auth/source.go +++ b/models/auth/source.go @@ -264,15 +264,16 @@ func IsSSPIEnabled(ctx context.Context) bool { if !db.HasEngine { return false } - sources, err := db.Find[Source](ctx, FindSourcesOptions{ + + exist, err := db.Exits[Source](ctx, FindSourcesOptions{ IsActive: util.OptionalBoolTrue, LoginType: SSPI, }) if err != nil { - log.Error("ActiveSources: %v", err) + log.Error("Active SSPI Sources: %v", err) return false } - return len(sources) > 0 + return exist } // GetSourceByID returns login source by given ID. diff --git a/models/db/context.go b/models/db/context.go index 521857fae836..e0ac0c8aefe6 100644 --- a/models/db/context.go +++ b/models/db/context.go @@ -264,3 +264,8 @@ func inTransaction(ctx context.Context) (*xorm.Session, bool) { return nil, false } } + +func Exits[T any](ctx context.Context, opts FindOptions) (bool, error) { + var bean T + return GetEngine(ctx).Where(opts.ToConds()).Exist(&bean) +} diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index 28f71d0bf046..8b66bc94bfda 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -30,14 +30,9 @@ func listUserOrgs(ctx *context.APIContext, u *user_model.User) { UserID: u.ID, IncludePrivate: showPrivate, } - orgs, err := db.Find[*organization.Organization](ctx, opts) + orgs, maxResults, err := db.FindAndCount[*organization.Organization](ctx, opts) if err != nil { - ctx.Error(http.StatusInternalServerError, "FindOrgs", err) - return - } - maxResults, err := db.Count[organization.Organization](ctx, opts) - if err != nil { - ctx.Error(http.StatusInternalServerError, "CountOrgs", err) + ctx.Error(http.StatusInternalServerError, "db.FindAndCount[*organization.Organization]", err) return } diff --git a/routers/web/shared/actions/runners.go b/routers/web/shared/actions/runners.go index 74d59eda346d..042393ed721d 100644 --- a/routers/web/shared/actions/runners.go +++ b/routers/web/shared/actions/runners.go @@ -84,17 +84,12 @@ func RunnerDetails(ctx *context.Context, page int, runnerID, ownerID, repoID int RunnerID: runner.ID, } - count, err := db.Count[actions_model.ActionTask](ctx, opts) + tasks, count, err := db.FindAndCount[*actions_model.ActionTask](ctx, opts) if err != nil { ctx.ServerError("CountTasks", err) return } - tasks, err := db.Find[*actions_model.ActionTask](ctx, opts) - if err != nil { - ctx.ServerError("FindTasks", err) - return - } if err = actions_model.TaskList(tasks).LoadAttributes(ctx); err != nil { ctx.ServerError("TasksLoadAttributes", err) return diff --git a/routers/web/user/notification.go b/routers/web/user/notification.go index 47755117de58..50f500a8dcbd 100644 --- a/routers/web/user/notification.go +++ b/routers/web/user/notification.go @@ -109,12 +109,21 @@ func getNotifications(ctx *context.Context) { } statuses := []activities_model.NotificationStatus{status, activities_model.NotificationStatusPinned} - notifications, err := activities_model.NotificationsForUser(ctx, ctx.Doer, statuses, page, perPage) + nls, err := db.Find[*activities_model.Notification](ctx, activities_model.FindNotificationOptions{ + ListOptions: db.ListOptions{ + PageSize: perPage, + Page: page, + }, + UserID: ctx.Doer.ID, + Status: statuses, + }) if err != nil { - ctx.ServerError("ErrNotificationsForUser", err) + ctx.ServerError("db.Find[*activities_model.Notification]", err) return } + notifications := activities_model.NotificationList(nls) + failCount := 0 repos, failures, err := notifications.LoadRepos(ctx) From a32c00dbcaf8a960fae324b420cf10f7713ad956 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 18 Nov 2023 15:02:20 +0800 Subject: [PATCH 11/21] Fix lint --- routers/web/shared/user/header.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/web/shared/user/header.go b/routers/web/shared/user/header.go index 5fb492de6022..10c3146ecc62 100644 --- a/routers/web/shared/user/header.go +++ b/routers/web/shared/user/header.go @@ -141,7 +141,7 @@ func LoadHeaderCount(ctx *context.Context) error { } else { projectType = project_model.TypeIndividual } - projectCount, err := project_model.CountProjects(ctx, project_model.SearchOptions{ + projectCount, err := db.Count[project_model.Project](ctx, project_model.SearchOptions{ OwnerID: ctx.ContextUser.ID, IsClosed: util.OptionalBoolOf(false), Type: projectType, From 90a4937d5a05b518c6f8a0927022b84ea5836570 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 18 Nov 2023 22:28:32 +0800 Subject: [PATCH 12/21] Fix typo --- models/auth/source.go | 2 +- models/db/context.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/models/auth/source.go b/models/auth/source.go index 98ce5968d3ec..5e77afddc369 100644 --- a/models/auth/source.go +++ b/models/auth/source.go @@ -265,7 +265,7 @@ func IsSSPIEnabled(ctx context.Context) bool { return false } - exist, err := db.Exits[Source](ctx, FindSourcesOptions{ + exist, err := db.Exists[Source](ctx, FindSourcesOptions{ IsActive: util.OptionalBoolTrue, LoginType: SSPI, }) diff --git a/models/db/context.go b/models/db/context.go index e0ac0c8aefe6..45765ef7d38c 100644 --- a/models/db/context.go +++ b/models/db/context.go @@ -265,7 +265,7 @@ func inTransaction(ctx context.Context) (*xorm.Session, bool) { } } -func Exits[T any](ctx context.Context, opts FindOptions) (bool, error) { +func Exists[T any](ctx context.Context, opts FindOptions) (bool, error) { var bean T return GetEngine(ctx).Where(opts.ToConds()).Exist(&bean) } From 108c087d9dc6dd18b66cc4b472d910136f44a5c9 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 19 Nov 2023 10:40:06 +0800 Subject: [PATCH 13/21] more refactors --- models/actions/artifact.go | 50 ++++++++++++------------- models/actions/variable.go | 11 +----- models/secret/secret.go | 18 +-------- models/webhook/webhook.go | 23 +----------- models/webhook/webhook_test.go | 8 ++-- routers/api/actions/artifacts.go | 8 +++- routers/api/actions/artifacts_chunks.go | 6 ++- routers/api/actions/runner/utils.go | 8 ++-- routers/api/v1/org/action.go | 9 +---- routers/api/v1/repo/hook.go | 9 +---- routers/api/v1/utils/hook.go | 9 +---- routers/web/org/setting.go | 2 +- routers/web/repo/actions/view.go | 7 +++- routers/web/repo/setting/webhook.go | 3 +- routers/web/shared/actions/variables.go | 2 +- routers/web/shared/secrets/secrets.go | 3 +- routers/web/user/setting/webhooks.go | 3 +- services/repository/delete.go | 2 +- services/repository/hooks.go | 2 +- services/secrets/secrets.go | 6 +-- services/webhook/webhook.go | 5 ++- 21 files changed, 73 insertions(+), 121 deletions(-) diff --git a/models/actions/artifact.go b/models/actions/artifact.go index 849a90fd10a4..42bd9c23cb48 100644 --- a/models/actions/artifact.go +++ b/models/actions/artifact.go @@ -14,6 +14,8 @@ import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" + + "xorm.io/builder" ) // ArtifactStatus is the status of an artifact, uploading, expired or need-delete @@ -108,29 +110,37 @@ func UpdateArtifactByID(ctx context.Context, id int64, art *ActionArtifact) erro return err } -// ListArtifactsByRunID returns all artifacts of a run -func ListArtifactsByRunID(ctx context.Context, runID int64) ([]*ActionArtifact, error) { - arts := make([]*ActionArtifact, 0, 10) - return arts, db.GetEngine(ctx).Where("run_id=?", runID).Find(&arts) +type FindArtifactsOptions struct { + db.ListOptions + RepoID int64 + RunID int64 + ArtifactName string + Status int } -// ListArtifactsByRunIDAndArtifactName returns an artifacts of a run by artifact name -func ListArtifactsByRunIDAndArtifactName(ctx context.Context, runID int64, artifactName string) ([]*ActionArtifact, error) { - arts := make([]*ActionArtifact, 0, 10) - return arts, db.GetEngine(ctx).Where("run_id=? AND artifact_name=?", runID, artifactName).Find(&arts) -} +func (opts FindArtifactsOptions) ToConds() builder.Cond { + cond := builder.NewCond() + if opts.RepoID > 0 { + cond = cond.And(builder.Eq{"repo_id": opts.RepoID}) + } + if opts.RunID > 0 { + cond = cond.And(builder.Eq{"run_id": opts.RunID}) + } + if opts.ArtifactName != "" { + cond = cond.And(builder.Eq{"artifact_name": opts.ArtifactName}) + } + if opts.Status > 0 { + cond = cond.And(builder.Eq{"status": opts.Status}) + } -// ListUploadedArtifactsByRunID returns all uploaded artifacts of a run -func ListUploadedArtifactsByRunID(ctx context.Context, runID int64) ([]*ActionArtifact, error) { - arts := make([]*ActionArtifact, 0, 10) - return arts, db.GetEngine(ctx).Where("run_id=? AND status=?", runID, ArtifactStatusUploadConfirmed).Find(&arts) + return cond } // ActionArtifactMeta is the meta data of an artifact type ActionArtifactMeta struct { ArtifactName string FileSize int64 - Status int64 + Status ArtifactStatus } // ListUploadedArtifactsMeta returns all uploaded artifacts meta of a run @@ -143,18 +153,6 @@ func ListUploadedArtifactsMeta(ctx context.Context, runID int64) ([]*ActionArtif Find(&arts) } -// ListArtifactsByRepoID returns all artifacts of a repo -func ListArtifactsByRepoID(ctx context.Context, repoID int64) ([]*ActionArtifact, error) { - arts := make([]*ActionArtifact, 0, 10) - return arts, db.GetEngine(ctx).Where("repo_id=?", repoID).Find(&arts) -} - -// ListArtifactsByRunIDAndName returns artifacts by name of a run -func ListArtifactsByRunIDAndName(ctx context.Context, runID int64, name string) ([]*ActionArtifact, error) { - arts := make([]*ActionArtifact, 0, 10) - return arts, db.GetEngine(ctx).Where("run_id=? AND artifact_name=?", runID, name).Find(&arts) -} - // ListNeedExpiredArtifacts returns all need expired artifacts but not deleted func ListNeedExpiredArtifacts(ctx context.Context) ([]*ActionArtifact, error) { arts := make([]*ActionArtifact, 0, 10) diff --git a/models/actions/variable.go b/models/actions/variable.go index e0bb59ccbe6e..030b7bae92ae 100644 --- a/models/actions/variable.go +++ b/models/actions/variable.go @@ -56,7 +56,7 @@ type FindVariablesOpts struct { RepoID int64 } -func (opts *FindVariablesOpts) toConds() builder.Cond { +func (opts FindVariablesOpts) ToConds() builder.Cond { cond := builder.NewCond() if opts.OwnerID > 0 { cond = cond.And(builder.Eq{"owner_id": opts.OwnerID}) @@ -67,15 +67,6 @@ func (opts *FindVariablesOpts) toConds() builder.Cond { return cond } -func FindVariables(ctx context.Context, opts FindVariablesOpts) ([]*ActionVariable, error) { - var variables []*ActionVariable - sess := db.GetEngine(ctx) - if opts.PageSize != 0 { - sess = db.SetSessionPagination(sess, &opts.ListOptions) - } - return variables, sess.Where(opts.toConds()).Find(&variables) -} - func GetVariableByID(ctx context.Context, variableID int64) (*ActionVariable, error) { var variable ActionVariable has, err := db.GetEngine(ctx).Where("id=?", variableID).Get(&variable) diff --git a/models/secret/secret.go b/models/secret/secret.go index 8df46b6c38ec..41e860d7f664 100644 --- a/models/secret/secret.go +++ b/models/secret/secret.go @@ -78,7 +78,7 @@ type FindSecretsOptions struct { Name string } -func (opts *FindSecretsOptions) toConds() builder.Cond { +func (opts FindSecretsOptions) ToConds() builder.Cond { cond := builder.NewCond() if opts.OwnerID > 0 { cond = cond.And(builder.Eq{"owner_id": opts.OwnerID}) @@ -96,22 +96,6 @@ func (opts *FindSecretsOptions) toConds() builder.Cond { return cond } -func FindSecrets(ctx context.Context, opts FindSecretsOptions) ([]*Secret, error) { - var secrets []*Secret - sess := db.GetEngine(ctx) - if opts.PageSize != 0 { - sess = db.SetSessionPagination(sess, &opts.ListOptions) - } - return secrets, sess. - Where(opts.toConds()). - Find(&secrets) -} - -// CountSecrets counts the secrets -func CountSecrets(ctx context.Context, opts *FindSecretsOptions) (int64, error) { - return db.GetEngine(ctx).Where(opts.toConds()).Count(new(Secret)) -} - // UpdateSecret changes org or user reop secret. func UpdateSecret(ctx context.Context, secretID int64, data string) error { encrypted, err := secret_module.EncryptSecret(setting.SecretKey, data) diff --git a/models/webhook/webhook.go b/models/webhook/webhook.go index b28cea6a9cc9..408023507a5f 100644 --- a/models/webhook/webhook.go +++ b/models/webhook/webhook.go @@ -435,7 +435,7 @@ type ListWebhookOptions struct { IsActive util.OptionalBool } -func (opts *ListWebhookOptions) toCond() builder.Cond { +func (opts ListWebhookOptions) ToConds() builder.Cond { cond := builder.NewCond() if opts.RepoID != 0 { cond = cond.And(builder.Eq{"webhook.repo_id": opts.RepoID}) @@ -449,27 +449,6 @@ func (opts *ListWebhookOptions) toCond() builder.Cond { return cond } -// ListWebhooksByOpts return webhooks based on options -func ListWebhooksByOpts(ctx context.Context, opts *ListWebhookOptions) ([]*Webhook, error) { - sess := db.GetEngine(ctx).Where(opts.toCond()) - - if opts.Page != 0 { - sess = db.SetSessionPagination(sess, opts) - webhooks := make([]*Webhook, 0, opts.PageSize) - err := sess.Find(&webhooks) - return webhooks, err - } - - webhooks := make([]*Webhook, 0, 10) - err := sess.Find(&webhooks) - return webhooks, err -} - -// CountWebhooksByOpts count webhooks based on options and ignore pagination -func CountWebhooksByOpts(ctx context.Context, opts *ListWebhookOptions) (int64, error) { - return db.GetEngine(ctx).Where(opts.toCond()).Count(&Webhook{}) -} - // UpdateWebhook updates information of webhook. func UpdateWebhook(ctx context.Context, w *Webhook) error { _, err := db.GetEngine(ctx).ID(w.ID).AllCols().Update(w) diff --git a/models/webhook/webhook_test.go b/models/webhook/webhook_test.go index 6a01fdd75f56..694fd7a873f3 100644 --- a/models/webhook/webhook_test.go +++ b/models/webhook/webhook_test.go @@ -123,7 +123,7 @@ func TestGetWebhookByOwnerID(t *testing.T) { func TestGetActiveWebhooksByRepoID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hooks, err := ListWebhooksByOpts(db.DefaultContext, &ListWebhookOptions{RepoID: 1, IsActive: util.OptionalBoolTrue}) + hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{RepoID: 1, IsActive: util.OptionalBoolTrue}) assert.NoError(t, err) if assert.Len(t, hooks, 1) { assert.Equal(t, int64(1), hooks[0].ID) @@ -133,7 +133,7 @@ func TestGetActiveWebhooksByRepoID(t *testing.T) { func TestGetWebhooksByRepoID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hooks, err := ListWebhooksByOpts(db.DefaultContext, &ListWebhookOptions{RepoID: 1}) + hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{RepoID: 1}) assert.NoError(t, err) if assert.Len(t, hooks, 2) { assert.Equal(t, int64(1), hooks[0].ID) @@ -143,7 +143,7 @@ func TestGetWebhooksByRepoID(t *testing.T) { func TestGetActiveWebhooksByOwnerID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hooks, err := ListWebhooksByOpts(db.DefaultContext, &ListWebhookOptions{OwnerID: 3, IsActive: util.OptionalBoolTrue}) + hooks, err := db.Find[Webhook](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) @@ -153,7 +153,7 @@ func TestGetActiveWebhooksByOwnerID(t *testing.T) { func TestGetWebhooksByOwnerID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hooks, err := ListWebhooksByOpts(db.DefaultContext, &ListWebhookOptions{OwnerID: 3}) + hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{OwnerID: 3}) assert.NoError(t, err) if assert.Len(t, hooks, 1) { assert.Equal(t, int64(3), hooks[0].ID) diff --git a/routers/api/actions/artifacts.go b/routers/api/actions/artifacts.go index c45dc667afcd..5411237103a0 100644 --- a/routers/api/actions/artifacts.go +++ b/routers/api/actions/artifacts.go @@ -70,6 +70,7 @@ import ( "strings" "code.gitea.io/gitea/models/actions" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" @@ -314,7 +315,7 @@ func (ar artifactRoutes) listArtifacts(ctx *ArtifactContext) { return } - artifacts, err := actions.ListArtifactsByRunID(ctx, runID) + artifacts, err := db.Find[actions.ActionArtifact](ctx, actions.FindArtifactsOptions{RunID: runID}) if err != nil { log.Error("Error getting artifacts: %v", err) ctx.Error(http.StatusInternalServerError, err.Error()) @@ -376,7 +377,10 @@ func (ar artifactRoutes) getDownloadArtifactURL(ctx *ArtifactContext) { return } - artifacts, err := actions.ListArtifactsByRunIDAndArtifactName(ctx, runID, itemPath) + artifacts, err := db.Find[actions.ActionArtifact](ctx, actions.FindArtifactsOptions{ + RunID: runID, + ArtifactName: itemPath, + }) if err != nil { log.Error("Error getting artifacts: %v", err) ctx.Error(http.StatusInternalServerError, err.Error()) diff --git a/routers/api/actions/artifacts_chunks.go b/routers/api/actions/artifacts_chunks.go index 458d671cff6d..0cbcbb383685 100644 --- a/routers/api/actions/artifacts_chunks.go +++ b/routers/api/actions/artifacts_chunks.go @@ -13,6 +13,7 @@ import ( "time" "code.gitea.io/gitea/models/actions" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/storage" ) @@ -86,7 +87,10 @@ func listChunksByRunID(st storage.ObjectStorage, runID int64) (map[int64][]*chun func mergeChunksForRun(ctx *ArtifactContext, st storage.ObjectStorage, runID int64, artifactName string) error { // read all db artifacts by name - artifacts, err := actions.ListArtifactsByRunIDAndName(ctx, runID, artifactName) + artifacts, err := db.Find[*actions.ActionArtifact](ctx, actions.FindArtifactsOptions{ + RunID: runID, + ArtifactName: artifactName, + }) if err != nil { return err } diff --git a/routers/api/actions/runner/utils.go b/routers/api/actions/runner/utils.go index 7435ed272c74..d7ee3d8d4a38 100644 --- a/routers/api/actions/runner/utils.go +++ b/routers/api/actions/runner/utils.go @@ -68,12 +68,12 @@ func getSecretsOfTask(ctx context.Context, task *actions_model.ActionTask) map[s return secrets } - ownerSecrets, err := secret_model.FindSecrets(ctx, secret_model.FindSecretsOptions{OwnerID: task.Job.Run.Repo.OwnerID}) + ownerSecrets, err := db.Find[secret_model.Secret](ctx, secret_model.FindSecretsOptions{OwnerID: task.Job.Run.Repo.OwnerID}) if err != nil { log.Error("find secrets of owner %v: %v", task.Job.Run.Repo.OwnerID, err) // go on } - repoSecrets, err := secret_model.FindSecrets(ctx, secret_model.FindSecretsOptions{RepoID: task.Job.Run.RepoID}) + repoSecrets, err := db.Find[secret_model.Secret](ctx, secret_model.FindSecretsOptions{RepoID: task.Job.Run.RepoID}) if err != nil { log.Error("find secrets of repo %v: %v", task.Job.Run.RepoID, err) // go on @@ -95,13 +95,13 @@ func getVariablesOfTask(ctx context.Context, task *actions_model.ActionTask) map variables := map[string]string{} // Org / User level - ownerVariables, err := actions_model.FindVariables(ctx, actions_model.FindVariablesOpts{OwnerID: task.Job.Run.Repo.OwnerID}) + ownerVariables, err := db.Find[actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{OwnerID: task.Job.Run.Repo.OwnerID}) if err != nil { log.Error("find variables of org: %d, error: %v", task.Job.Run.Repo.OwnerID, err) } // Repo level - repoVariables, err := actions_model.FindVariables(ctx, actions_model.FindVariablesOpts{RepoID: task.Job.Run.RepoID}) + repoVariables, err := db.Find[actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{RepoID: task.Job.Run.RepoID}) if err != nil { log.Error("find variables of repo: %d, error: %v", task.Job.Run.RepoID, err) } diff --git a/routers/api/v1/org/action.go b/routers/api/v1/org/action.go index 5af61257735c..ddc74d865b18 100644 --- a/routers/api/v1/org/action.go +++ b/routers/api/v1/org/action.go @@ -7,6 +7,7 @@ import ( "errors" "net/http" + "code.gitea.io/gitea/models/db" secret_model "code.gitea.io/gitea/models/secret" "code.gitea.io/gitea/modules/context" api "code.gitea.io/gitea/modules/structs" @@ -48,13 +49,7 @@ func ListActionsSecrets(ctx *context.APIContext) { ListOptions: utils.GetListOptions(ctx), } - count, err := secret_model.CountSecrets(ctx, opts) - if err != nil { - ctx.InternalServerError(err) - return - } - - secrets, err := secret_model.FindSecrets(ctx, *opts) + secrets, count, err := db.FindAndCount[secret_model.Secret](ctx, opts) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/repo/hook.go b/routers/api/v1/repo/hook.go index 7d0142748ac0..1e4072056223 100644 --- a/routers/api/v1/repo/hook.go +++ b/routers/api/v1/repo/hook.go @@ -7,6 +7,7 @@ package repo import ( "net/http" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/perm" access_model "code.gitea.io/gitea/models/perm/access" "code.gitea.io/gitea/models/webhook" @@ -58,13 +59,7 @@ func ListHooks(ctx *context.APIContext) { RepoID: ctx.Repo.Repository.ID, } - count, err := webhook.CountWebhooksByOpts(ctx, opts) - if err != nil { - ctx.InternalServerError(err) - return - } - - hooks, err := webhook.ListWebhooksByOpts(ctx, opts) + hooks, count, err := db.FindAndCount[*webhook.Webhook](ctx, opts) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/utils/hook.go b/routers/api/v1/utils/hook.go index 362f4bfc4d3f..a25a922197d1 100644 --- a/routers/api/v1/utils/hook.go +++ b/routers/api/v1/utils/hook.go @@ -8,6 +8,7 @@ import ( "net/http" "strings" + "code.gitea.io/gitea/models/db" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/context" @@ -26,13 +27,7 @@ func ListOwnerHooks(ctx *context.APIContext, owner *user_model.User) { OwnerID: owner.ID, } - count, err := webhook.CountWebhooksByOpts(ctx, opts) - if err != nil { - ctx.InternalServerError(err) - return - } - - hooks, err := webhook.ListWebhooksByOpts(ctx, opts) + hooks, count, err := db.FindAndCount[*webhook.Webhook](ctx, opts) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/web/org/setting.go b/routers/web/org/setting.go index fac83b361285..f0d9259d3fe4 100644 --- a/routers/web/org/setting.go +++ b/routers/web/org/setting.go @@ -215,7 +215,7 @@ func Webhooks(ctx *context.Context) { ctx.Data["BaseLinkNew"] = ctx.Org.OrgLink + "/settings/hooks" ctx.Data["Description"] = ctx.Tr("org.settings.hooks_desc") - ws, err := webhook.ListWebhooksByOpts(ctx, &webhook.ListWebhookOptions{OwnerID: ctx.Org.Organization.ID}) + ws, err := db.Find[webhook.Webhook](ctx, webhook.ListWebhookOptions{OwnerID: ctx.Org.Organization.ID}) if err != nil { ctx.ServerError("ListWebhooksByOpts", err) return diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go index 2c69b1361614..1cdae32a32fe 100644 --- a/routers/web/repo/actions/view.go +++ b/routers/web/repo/actions/view.go @@ -512,7 +512,7 @@ func ArtifactsView(ctx *context_module.Context) { } for _, art := range artifacts { status := "completed" - if art.Status == int64(actions_model.ArtifactStatusExpired) { + if art.Status == actions_model.ArtifactStatusExpired { status = "expired" } artifactsResponse.Artifacts = append(artifactsResponse.Artifacts, &ArtifactsViewItem{ @@ -538,7 +538,10 @@ func ArtifactsDownloadView(ctx *context_module.Context) { return } - artifacts, err := actions_model.ListArtifactsByRunIDAndName(ctx, run.ID, artifactName) + artifacts, err := db.Find[actions_model.ActionArtifact](ctx, actions_model.FindArtifactsOptions{ + RunID: run.ID, + ArtifactName: artifactName, + }) if err != nil { ctx.Error(http.StatusInternalServerError, err.Error()) return diff --git a/routers/web/repo/setting/webhook.go b/routers/web/repo/setting/webhook.go index ea5abb057920..5100bf782f06 100644 --- a/routers/web/repo/setting/webhook.go +++ b/routers/web/repo/setting/webhook.go @@ -12,6 +12,7 @@ import ( "path" "strings" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/perm" access_model "code.gitea.io/gitea/models/perm/access" user_model "code.gitea.io/gitea/models/user" @@ -46,7 +47,7 @@ func Webhooks(ctx *context.Context) { ctx.Data["BaseLinkNew"] = ctx.Repo.RepoLink + "/settings/hooks" ctx.Data["Description"] = ctx.Tr("repo.settings.hooks_desc", "https://docs.gitea.com/usage/webhooks") - ws, err := webhook.ListWebhooksByOpts(ctx, &webhook.ListWebhookOptions{RepoID: ctx.Repo.Repository.ID}) + ws, err := db.Find[webhook.Webhook](ctx, webhook.ListWebhookOptions{RepoID: ctx.Repo.Repository.ID}) if err != nil { ctx.ServerError("GetWebhooksByRepoID", err) return diff --git a/routers/web/shared/actions/variables.go b/routers/web/shared/actions/variables.go index 341c18f589c5..07a057520781 100644 --- a/routers/web/shared/actions/variables.go +++ b/routers/web/shared/actions/variables.go @@ -18,7 +18,7 @@ import ( ) func SetVariablesContext(ctx *context.Context, ownerID, repoID int64) { - variables, err := actions_model.FindVariables(ctx, actions_model.FindVariablesOpts{ + variables, err := db.Find[actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{ OwnerID: ownerID, RepoID: repoID, }) diff --git a/routers/web/shared/secrets/secrets.go b/routers/web/shared/secrets/secrets.go index 875cb0cfec74..c805da734ac0 100644 --- a/routers/web/shared/secrets/secrets.go +++ b/routers/web/shared/secrets/secrets.go @@ -4,6 +4,7 @@ package secrets import ( + "code.gitea.io/gitea/models/db" secret_model "code.gitea.io/gitea/models/secret" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" @@ -14,7 +15,7 @@ import ( ) func SetSecretsContext(ctx *context.Context, ownerID, repoID int64) { - secrets, err := secret_model.FindSecrets(ctx, secret_model.FindSecretsOptions{OwnerID: ownerID, RepoID: repoID}) + secrets, err := db.Find[secret_model.Secret](ctx, secret_model.FindSecretsOptions{OwnerID: ownerID, RepoID: repoID}) if err != nil { ctx.ServerError("FindSecrets", err) return diff --git a/routers/web/user/setting/webhooks.go b/routers/web/user/setting/webhooks.go index 50cebc2a3de0..679b72e50119 100644 --- a/routers/web/user/setting/webhooks.go +++ b/routers/web/user/setting/webhooks.go @@ -6,6 +6,7 @@ package setting import ( "net/http" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" @@ -24,7 +25,7 @@ func Webhooks(ctx *context.Context) { ctx.Data["BaseLinkNew"] = setting.AppSubURL + "/user/settings/hooks" ctx.Data["Description"] = ctx.Tr("settings.hooks.desc") - ws, err := webhook.ListWebhooksByOpts(ctx, &webhook.ListWebhookOptions{OwnerID: ctx.Doer.ID}) + ws, err := db.Find[webhook.Webhook](ctx, webhook.ListWebhookOptions{OwnerID: ctx.Doer.ID}) if err != nil { ctx.ServerError("ListWebhooksByOpts", err) return diff --git a/services/repository/delete.go b/services/repository/delete.go index f306e117619f..ae91d3df9fa1 100644 --- a/services/repository/delete.go +++ b/services/repository/delete.go @@ -60,7 +60,7 @@ func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID } // Query the artifacts of this repo, they will be needed after they have been deleted to remove artifacts files in ObjectStorage - artifacts, err := actions_model.ListArtifactsByRepoID(ctx, repoID) + artifacts, err := db.Find[actions_model.ActionArtifact](ctx, actions_model.FindArtifactsOptions{RepoID: repoID}) if err != nil { return fmt.Errorf("list actions artifacts of repo %v: %w", repoID, err) } diff --git a/services/repository/hooks.go b/services/repository/hooks.go index 8506fa341369..7b82f36b43fd 100644 --- a/services/repository/hooks.go +++ b/services/repository/hooks.go @@ -85,7 +85,7 @@ func GenerateGitHooks(ctx context.Context, templateRepo, generateRepo *repo_mode // GenerateWebhooks generates webhooks from a template repository func GenerateWebhooks(ctx context.Context, templateRepo, generateRepo *repo_model.Repository) error { - templateWebhooks, err := webhook.ListWebhooksByOpts(ctx, &webhook.ListWebhookOptions{RepoID: templateRepo.ID}) + templateWebhooks, err := db.Find[webhook.Webhook](ctx, webhook.ListWebhookOptions{RepoID: templateRepo.ID}) if err != nil { return err } diff --git a/services/secrets/secrets.go b/services/secrets/secrets.go index 1c4772d6bf9b..e1e5da64e50d 100644 --- a/services/secrets/secrets.go +++ b/services/secrets/secrets.go @@ -15,7 +15,7 @@ func CreateOrUpdateSecret(ctx context.Context, ownerID, repoID int64, name, data return nil, false, err } - s, err := secret_model.FindSecrets(ctx, secret_model.FindSecretsOptions{ + s, err := db.Find[*secret_model.Secret](ctx, secret_model.FindSecretsOptions{ OwnerID: ownerID, RepoID: repoID, Name: name, @@ -40,7 +40,7 @@ func CreateOrUpdateSecret(ctx context.Context, ownerID, repoID int64, name, data } func DeleteSecretByID(ctx context.Context, ownerID, repoID, secretID int64) error { - s, err := secret_model.FindSecrets(ctx, secret_model.FindSecretsOptions{ + s, err := db.Find[*secret_model.Secret](ctx, secret_model.FindSecretsOptions{ OwnerID: ownerID, RepoID: repoID, SecretID: secretID, @@ -60,7 +60,7 @@ func DeleteSecretByName(ctx context.Context, ownerID, repoID int64, name string) return err } - s, err := secret_model.FindSecrets(ctx, secret_model.FindSecretsOptions{ + s, err := db.Find[*secret_model.Secret](ctx, secret_model.FindSecretsOptions{ OwnerID: ownerID, RepoID: repoID, Name: name, diff --git a/services/webhook/webhook.go b/services/webhook/webhook.go index 9d5dab85f797..96c1779e053f 100644 --- a/services/webhook/webhook.go +++ b/services/webhook/webhook.go @@ -9,6 +9,7 @@ import ( "fmt" "strings" + "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" webhook_model "code.gitea.io/gitea/models/webhook" @@ -222,7 +223,7 @@ func PrepareWebhooks(ctx context.Context, source EventSource, event webhook_modu var ws []*webhook_model.Webhook if source.Repository != nil { - repoHooks, err := webhook_model.ListWebhooksByOpts(ctx, &webhook_model.ListWebhookOptions{ + repoHooks, err := db.Find[*webhook_model.Webhook](ctx, webhook_model.ListWebhookOptions{ RepoID: source.Repository.ID, IsActive: util.OptionalBoolTrue, }) @@ -236,7 +237,7 @@ func PrepareWebhooks(ctx context.Context, source EventSource, event webhook_modu // append additional webhooks of a user or organization if owner != nil { - ownerHooks, err := webhook_model.ListWebhooksByOpts(ctx, &webhook_model.ListWebhookOptions{ + ownerHooks, err := db.Find[*webhook_model.Webhook](ctx, webhook_model.ListWebhookOptions{ OwnerID: owner.ID, IsActive: util.OptionalBoolTrue, }) From 8108df9db05d770b11a02cf1f1c1c7c7027316d0 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 21 Nov 2023 11:32:00 +0800 Subject: [PATCH 14/21] refactor for keys --- models/asymkey/ssh_key.go | 63 ++++++++----------- models/asymkey/ssh_key_commit_verification.go | 5 +- models/asymkey/ssh_key_deploy.go | 22 +------ models/user/external_login_user.go | 31 ++++----- routers/api/v1/repo/key.go | 10 +-- routers/api/v1/user/key.go | 22 +++++-- routers/web/repo/setting/deploy_key.go | 4 +- routers/web/user/home.go | 4 +- routers/web/user/setting/keys.go | 5 +- routers/web/user/setting/security/security.go | 5 +- services/asymkey/ssh_key_test.go | 5 +- services/auth/httpsign.go | 5 +- services/migrations/update.go | 13 ++-- services/repository/delete.go | 2 +- 14 files changed, 92 insertions(+), 104 deletions(-) diff --git a/models/asymkey/ssh_key.go b/models/asymkey/ssh_key.go index f36738fb3d56..552f2ffd69e6 100644 --- a/models/asymkey/ssh_key.go +++ b/models/asymkey/ssh_key.go @@ -179,45 +179,33 @@ func SearchPublicKeyByContentExact(ctx context.Context, content string) (*Public return key, nil } -// SearchPublicKey returns a list of public keys matching the provided arguments. -func SearchPublicKey(ctx context.Context, uid int64, fingerprint string) ([]*PublicKey, error) { - keys := make([]*PublicKey, 0, 5) +type FindPublicKeyOptions struct { + db.ListOptions + OwnerID int64 + Fingerprint string + KeyTypes []KeyType + NotKeytype KeyType + LoginSourceID int64 +} + +func (opts FindPublicKeyOptions) ToConds() builder.Cond { cond := builder.NewCond() - if uid != 0 { - cond = cond.And(builder.Eq{"owner_id": uid}) + if opts.OwnerID > 0 { + cond = cond.And(builder.Eq{"owner_id": opts.OwnerID}) } - if fingerprint != "" { - cond = cond.And(builder.Eq{"fingerprint": fingerprint}) + if opts.Fingerprint != "" { + cond = cond.And(builder.Eq{"fingerprint": opts.Fingerprint}) } - return keys, db.GetEngine(ctx).Where(cond).Find(&keys) -} - -// ListPublicKeys returns a list of public keys belongs to given user. -func ListPublicKeys(ctx context.Context, uid int64, listOptions db.ListOptions) ([]*PublicKey, error) { - sess := db.GetEngine(ctx).Where("owner_id = ? AND type != ?", uid, KeyTypePrincipal) - if listOptions.Page != 0 { - sess = db.SetSessionPagination(sess, &listOptions) - - keys := make([]*PublicKey, 0, listOptions.PageSize) - return keys, sess.Find(&keys) + if len(opts.KeyTypes) > 0 { + cond = cond.And(builder.In("type", opts.KeyTypes)) } - - keys := make([]*PublicKey, 0, 5) - return keys, sess.Find(&keys) -} - -// CountPublicKeys count public keys a user has -func CountPublicKeys(ctx context.Context, userID int64) (int64, error) { - sess := db.GetEngine(ctx).Where("owner_id = ? AND type != ?", userID, KeyTypePrincipal) - return sess.Count(&PublicKey{}) -} - -// ListPublicKeysBySource returns a list of synchronized public keys for a given user and login source. -func ListPublicKeysBySource(ctx context.Context, uid, authSourceID int64) ([]*PublicKey, error) { - keys := make([]*PublicKey, 0, 5) - return keys, db.GetEngine(ctx). - Where("owner_id = ? AND login_source_id = ?", uid, authSourceID). - Find(&keys) + if opts.NotKeytype > 0 { + cond = cond.And(builder.Neq{"type": opts.NotKeytype}) + } + if opts.LoginSourceID > 0 { + cond = cond.And(builder.Eq{"login_source_id": opts.LoginSourceID}) + } + return cond } // UpdatePublicKeyUpdated updates public key use time. @@ -394,7 +382,10 @@ func SynchronizePublicKeys(ctx context.Context, usr *user_model.User, s *auth.So // Get Public Keys from DB with current LDAP source var giteaKeys []string - keys, err := ListPublicKeysBySource(ctx, usr.ID, s.ID) + keys, err := db.Find[PublicKey](ctx, FindPublicKeyOptions{ + OwnerID: usr.ID, + LoginSourceID: s.ID, + }) if err != nil { log.Error("synchronizePublicKeys[%s]: Error listing Public SSH Keys for user %s: %v", s.Name, usr.Name, err) } diff --git a/models/asymkey/ssh_key_commit_verification.go b/models/asymkey/ssh_key_commit_verification.go index a61f0663b165..1c450221caf3 100644 --- a/models/asymkey/ssh_key_commit_verification.go +++ b/models/asymkey/ssh_key_commit_verification.go @@ -21,7 +21,10 @@ import ( func ParseCommitWithSSHSignature(ctx context.Context, c *git.Commit, committer *user_model.User) *CommitVerification { // Now try to associate the signature with the committer, if present if committer.ID != 0 { - keys, err := ListPublicKeys(ctx, committer.ID, db.ListOptions{}) + keys, err := db.Find[*PublicKey](ctx, FindPublicKeyOptions{ + OwnerID: committer.ID, + NotKeytype: KeyTypePrincipal, + }) if err != nil { // Skipping failed to get ssh keys of user log.Error("ListPublicKeys: %v", err) return &CommitVerification{ diff --git a/models/asymkey/ssh_key_deploy.go b/models/asymkey/ssh_key_deploy.go index e347604bcda3..8f9f454051b7 100644 --- a/models/asymkey/ssh_key_deploy.go +++ b/models/asymkey/ssh_key_deploy.go @@ -210,7 +210,7 @@ type ListDeployKeysOptions struct { Fingerprint string } -func (opt ListDeployKeysOptions) toCond() builder.Cond { +func (opt ListDeployKeysOptions) ToConds() builder.Cond { cond := builder.NewCond() if opt.RepoID != 0 { cond = cond.And(builder.Eq{"repo_id": opt.RepoID}) @@ -223,23 +223,3 @@ func (opt ListDeployKeysOptions) toCond() builder.Cond { } return cond } - -// ListDeployKeys returns a list of deploy keys matching the provided arguments. -func ListDeployKeys(ctx context.Context, opts *ListDeployKeysOptions) ([]*DeployKey, error) { - sess := db.GetEngine(ctx).Where(opts.toCond()) - - if opts.Page != 0 { - sess = db.SetSessionPagination(sess, opts) - - keys := make([]*DeployKey, 0, opts.PageSize) - return keys, sess.Find(&keys) - } - - keys := make([]*DeployKey, 0, 5) - return keys, sess.Find(&keys) -} - -// CountDeployKeys returns count deploy keys matching the provided arguments. -func CountDeployKeys(ctx context.Context, opts *ListDeployKeysOptions) (int64, error) { - return db.GetEngine(ctx).Where(opts.toCond()).Count(&DeployKey{}) -} diff --git a/models/user/external_login_user.go b/models/user/external_login_user.go index 4121c5d89faa..2eccddd581e2 100644 --- a/models/user/external_login_user.go +++ b/models/user/external_login_user.go @@ -96,19 +96,6 @@ func GetExternalLogin(ctx context.Context, externalLoginUser *ExternalLoginUser) return db.GetEngine(ctx).Get(externalLoginUser) } -// ListAccountLinks returns a map with the ExternalLoginUser and its LoginSource -func ListAccountLinks(ctx context.Context, user *User) ([]*ExternalLoginUser, error) { - externalAccounts := make([]*ExternalLoginUser, 0, 5) - err := db.GetEngine(ctx).Where("user_id=?", user.ID). - Desc("login_source_id"). - Find(&externalAccounts) - if err != nil { - return nil, err - } - - return externalAccounts, nil -} - // LinkExternalToUser link the external user to the user func LinkExternalToUser(ctx context.Context, user *User, externalLoginUser *ExternalLoginUser) error { has, err := db.GetEngine(ctx).Where("external_id=? AND login_source_id=?", externalLoginUser.ExternalID, externalLoginUser.LoginSourceID). @@ -173,21 +160,29 @@ func UpdateExternalUserByExternalID(ctx context.Context, external *ExternalLogin // FindExternalUserOptions represents an options to find external users type FindExternalUserOptions struct { + db.ListOptions Provider string - Limit int - Start int + UserID int64 + OrderBy string } -func (opts FindExternalUserOptions) toConds() builder.Cond { +func (opts FindExternalUserOptions) ToConds() builder.Cond { cond := builder.NewCond() if len(opts.Provider) > 0 { cond = cond.And(builder.Eq{"provider": opts.Provider}) } + if opts.UserID > 0 { + cond = cond.And(builder.Eq{"user_id": opts.UserID}) + } return cond } +func (opts FindExternalUserOptions) ToOrders() string { + return opts.OrderBy +} + // FindExternalUsersByProvider represents external users via provider -func FindExternalUsersByProvider(ctx context.Context, opts FindExternalUserOptions) ([]ExternalLoginUser, error) { +/*func FindExternalUsersByProvider(ctx context.Context, opts FindExternalUserOptions) ([]ExternalLoginUser, error) { var users []ExternalLoginUser err := db.GetEngine(ctx).Where(opts.toConds()). Limit(opts.Limit, opts.Start). @@ -197,4 +192,4 @@ func FindExternalUsersByProvider(ctx context.Context, opts FindExternalUserOptio return nil, err } return users, nil -} +}*/ diff --git a/routers/api/v1/repo/key.go b/routers/api/v1/repo/key.go index 47a4d14842d7..400eee5fe9b8 100644 --- a/routers/api/v1/repo/key.go +++ b/routers/api/v1/repo/key.go @@ -83,20 +83,14 @@ func ListDeployKeys(ctx *context.APIContext) { // "404": // "$ref": "#/responses/notFound" - opts := &asymkey_model.ListDeployKeysOptions{ + opts := asymkey_model.ListDeployKeysOptions{ ListOptions: utils.GetListOptions(ctx), RepoID: ctx.Repo.Repository.ID, KeyID: ctx.FormInt64("key_id"), Fingerprint: ctx.FormString("fingerprint"), } - keys, err := asymkey_model.ListDeployKeys(ctx, opts) - if err != nil { - ctx.InternalServerError(err) - return - } - - count, err := asymkey_model.CountDeployKeys(ctx, opts) + keys, count, err := db.FindAndCount[*asymkey_model.DeployKey](ctx, opts) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/user/key.go b/routers/api/v1/user/key.go index fd891699ce2a..f3a49f8779ef 100644 --- a/routers/api/v1/user/key.go +++ b/routers/api/v1/user/key.go @@ -8,6 +8,7 @@ import ( "net/http" asymkey_model "code.gitea.io/gitea/models/asymkey" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/perm" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" @@ -56,17 +57,22 @@ func listPublicKeys(ctx *context.APIContext, user *user_model.User) { username := ctx.Params("username") if fingerprint != "" { + var userID int64 // Unrestricted // Querying not just listing if username != "" { // Restrict to provided uid - keys, err = asymkey_model.SearchPublicKey(ctx, user.ID, fingerprint) - } else { - // Unrestricted - keys, err = asymkey_model.SearchPublicKey(ctx, 0, fingerprint) + userID = user.ID } + keys, err = db.Find[*asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ + OwnerID: userID, + Fingerprint: fingerprint, + }) count = len(keys) } else { - total, err2 := asymkey_model.CountPublicKeys(ctx, user.ID) + total, err2 := db.Count[asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ + OwnerID: user.ID, + NotKeytype: asymkey_model.KeyTypePrincipal, + }) if err2 != nil { ctx.InternalServerError(err) return @@ -74,7 +80,11 @@ func listPublicKeys(ctx *context.APIContext, user *user_model.User) { count = int(total) // Use ListPublicKeys - keys, err = asymkey_model.ListPublicKeys(ctx, user.ID, utils.GetListOptions(ctx)) + keys, err = db.Find[*asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ + ListOptions: utils.GetListOptions(ctx), + OwnerID: user.ID, + NotKeytype: asymkey_model.KeyTypePrincipal, + }) } if err != nil { diff --git a/routers/web/repo/setting/deploy_key.go b/routers/web/repo/setting/deploy_key.go index 579743ef3ca4..3d4420006c47 100644 --- a/routers/web/repo/setting/deploy_key.go +++ b/routers/web/repo/setting/deploy_key.go @@ -22,7 +22,7 @@ func DeployKeys(ctx *context.Context) { ctx.Data["PageIsSettingsKeys"] = true ctx.Data["DisableSSH"] = setting.SSH.Disabled - keys, err := asymkey_model.ListDeployKeys(ctx, &asymkey_model.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID}) + keys, err := db.Find[asymkey_model.DeployKey](ctx, asymkey_model.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID}) if err != nil { ctx.ServerError("ListDeployKeys", err) return @@ -39,7 +39,7 @@ func DeployKeysPost(ctx *context.Context) { ctx.Data["PageIsSettingsKeys"] = true ctx.Data["DisableSSH"] = setting.SSH.Disabled - keys, err := asymkey_model.ListDeployKeys(ctx, &asymkey_model.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID}) + keys, err := db.Find[asymkey_model.DeployKey](ctx, asymkey_model.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID}) if err != nil { ctx.ServerError("ListDeployKeys", err) return diff --git a/routers/web/user/home.go b/routers/web/user/home.go index db3778d9e181..b4fb25dfe0ee 100644 --- a/routers/web/user/home.go +++ b/routers/web/user/home.go @@ -759,7 +759,9 @@ func loadRepoByIDs(ctx *context.Context, ctxUser *user_model.User, issueCountByR // ShowSSHKeys output all the ssh keys of user by uid func ShowSSHKeys(ctx *context.Context) { - keys, err := asymkey_model.ListPublicKeys(ctx, ctx.ContextUser.ID, db.ListOptions{}) + keys, err := db.Find[asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ + OwnerID: ctx.ContextUser.ID, + }) if err != nil { ctx.ServerError("ListPublicKeys", err) return diff --git a/routers/web/user/setting/keys.go b/routers/web/user/setting/keys.go index 440885bb076d..82ff295a86a8 100644 --- a/routers/web/user/setting/keys.go +++ b/routers/web/user/setting/keys.go @@ -260,7 +260,10 @@ func DeleteKey(ctx *context.Context) { } func loadKeysData(ctx *context.Context) { - keys, err := asymkey_model.ListPublicKeys(ctx, ctx.Doer.ID, db.ListOptions{}) + keys, err := db.Find[*asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ + OwnerID: ctx.Doer.ID, + NotKeytype: asymkey_model.KeyTypePrincipal, + }) if err != nil { ctx.ServerError("ListPublicKeys", err) return diff --git a/routers/web/user/setting/security/security.go b/routers/web/user/setting/security/security.go index 153322dc3f1a..b7ceb83f76fa 100644 --- a/routers/web/user/setting/security/security.go +++ b/routers/web/user/setting/security/security.go @@ -76,7 +76,10 @@ func loadSecurityData(ctx *context.Context) { } ctx.Data["Tokens"] = tokens - accountLinks, err := user_model.ListAccountLinks(ctx, ctx.Doer) + accountLinks, err := db.Find[user_model.ExternalLoginUser](ctx, user_model.FindExternalUserOptions{ + UserID: ctx.Doer.ID, + OrderBy: "login_source_id DESC", + }) if err != nil { ctx.ServerError("ListAccountLinks", err) return diff --git a/services/asymkey/ssh_key_test.go b/services/asymkey/ssh_key_test.go index 3a39a9a1db49..fbd5d13ab2d2 100644 --- a/services/asymkey/ssh_key_test.go +++ b/services/asymkey/ssh_key_test.go @@ -67,7 +67,10 @@ ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ib for i, kase := range testCases { s.ID = int64(i) + 20 asymkey_model.AddPublicKeysBySource(db.DefaultContext, user, s, []string{kase.keyString}) - keys, err := asymkey_model.ListPublicKeysBySource(db.DefaultContext, user.ID, s.ID) + keys, err := db.Find[asymkey_model.PublicKey](db.DefaultContext, asymkey_model.FindPublicKeyOptions{ + OwnerID: user.ID, + LoginSourceID: s.ID, + }) assert.NoError(t, err) if err != nil { continue diff --git a/services/auth/httpsign.go b/services/auth/httpsign.go index d5c8ea33aa3b..c46f65ca8f6e 100644 --- a/services/auth/httpsign.go +++ b/services/auth/httpsign.go @@ -12,6 +12,7 @@ import ( "strings" asymkey_model "code.gitea.io/gitea/models/asymkey" + "code.gitea.io/gitea/models/db" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -92,7 +93,9 @@ func VerifyPubKey(r *http.Request) (*asymkey_model.PublicKey, error) { keyID := verifier.KeyId() - publicKeys, err := asymkey_model.SearchPublicKey(r.Context(), 0, keyID) + publicKeys, err := db.Find[*asymkey_model.PublicKey](r.Context(), asymkey_model.FindPublicKeyOptions{ + Fingerprint: keyID, + }) if err != nil { return nil, err } diff --git a/services/migrations/update.go b/services/migrations/update.go index d466832363b4..4a49206f82e2 100644 --- a/services/migrations/update.go +++ b/services/migrations/update.go @@ -36,8 +36,7 @@ func updateMigrationPosterIDByGitService(ctx context.Context, tp structs.GitServ } const batchSize = 100 - var start int - for { + for page := 0; ; page++ { select { case <-ctx.Done(): log.Warn("UpdateMigrationPosterIDByGitService(%s) cancelled", tp.Name()) @@ -45,10 +44,13 @@ func updateMigrationPosterIDByGitService(ctx context.Context, tp structs.GitServ default: } - users, err := user_model.FindExternalUsersByProvider(ctx, user_model.FindExternalUserOptions{ + users, err := db.Find[user_model.ExternalLoginUser](ctx, user_model.FindExternalUserOptions{ + ListOptions: db.ListOptions{ + PageSize: batchSize, + Page: page, + }, Provider: provider, - Start: start, - Limit: batchSize, + OrderBy: "login_source_id ASC, external_id ASC", }) if err != nil { return err @@ -70,7 +72,6 @@ func updateMigrationPosterIDByGitService(ctx context.Context, tp structs.GitServ if len(users) < batchSize { break } - start += len(users) } return nil } diff --git a/services/repository/delete.go b/services/repository/delete.go index ae91d3df9fa1..08d6800ee766 100644 --- a/services/repository/delete.go +++ b/services/repository/delete.go @@ -75,7 +75,7 @@ func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID } // Delete Deploy Keys - deployKeys, err := asymkey_model.ListDeployKeys(ctx, &asymkey_model.ListDeployKeysOptions{RepoID: repoID}) + deployKeys, err := db.Find[asymkey_model.DeployKey](ctx, asymkey_model.ListDeployKeysOptions{RepoID: repoID}) if err != nil { return fmt.Errorf("listDeployKeys: %w", err) } From 5572c2bcd8e013c7cecde750525e6809513a0092 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 21 Nov 2023 11:58:32 +0800 Subject: [PATCH 15/21] more refactors --- models/auth/access_token.go | 37 +-- models/auth/access_token_test.go | 6 +- models/auth/oauth2.go | 227 ------------------ models/auth/oauth2_grant.go | 217 +++++++++++++++++ models/auth/oauth2_list.go | 32 +++ models/user/external_login_user.go | 13 - routers/api/v1/user/app.go | 15 +- routers/web/admin/applications.go | 5 +- routers/web/org/setting_oauth2.go | 5 +- routers/web/user/setting/applications.go | 7 +- routers/web/user/setting/security/security.go | 2 +- 11 files changed, 284 insertions(+), 282 deletions(-) create mode 100644 models/auth/oauth2_grant.go create mode 100644 models/auth/oauth2_list.go diff --git a/models/auth/access_token.go b/models/auth/access_token.go index 8abcc622bc89..fa12dffb4be2 100644 --- a/models/auth/access_token.go +++ b/models/auth/access_token.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" + "xorm.io/builder" lru "github.com/hashicorp/golang-lru/v2" ) @@ -201,25 +202,18 @@ type ListAccessTokensOptions struct { UserID int64 } -// ListAccessTokens returns a list of access tokens belongs to given user. -func ListAccessTokens(ctx context.Context, opts ListAccessTokensOptions) ([]*AccessToken, error) { - sess := db.GetEngine(ctx).Where("uid=?", opts.UserID) - - if len(opts.Name) != 0 { - sess = sess.Where("name=?", opts.Name) - } - - sess = sess.Desc("created_unix") - - if opts.Page != 0 { - sess = db.SetSessionPagination(sess, &opts) - - tokens := make([]*AccessToken, 0, opts.PageSize) - return tokens, sess.Find(&tokens) +func (opts ListAccessTokensOptions) ToConds() builder.Cond { + cond := builder.NewCond() + // user id is required, otherwise it will return all result which maybe a possible bug + cond = cond.And(builder.Eq{"uid": opts.UserID}) + if len(opts.Name) > 0 { + cond = cond.And(builder.Eq{"name": opts.Name}) } + return cond +} - tokens := make([]*AccessToken, 0, 5) - return tokens, sess.Find(&tokens) +func (opts ListAccessTokensOptions) ToOrders() string { + return "created_unix DESC" } // UpdateAccessToken updates information of access token. @@ -228,15 +222,6 @@ func UpdateAccessToken(ctx context.Context, t *AccessToken) error { return err } -// CountAccessTokens count access tokens belongs to given user by options -func CountAccessTokens(ctx context.Context, opts ListAccessTokensOptions) (int64, error) { - sess := db.GetEngine(ctx).Where("uid=?", opts.UserID) - if len(opts.Name) != 0 { - sess = sess.Where("name=?", opts.Name) - } - return sess.Count(&AccessToken{}) -} - // DeleteAccessTokenByID deletes access token by given ID. func DeleteAccessTokenByID(ctx context.Context, id, userID int64) error { cnt, err := db.GetEngine(ctx).ID(id).Delete(&AccessToken{ diff --git a/models/auth/access_token_test.go b/models/auth/access_token_test.go index 72c937ffd6a7..4360f1a21433 100644 --- a/models/auth/access_token_test.go +++ b/models/auth/access_token_test.go @@ -85,7 +85,7 @@ func TestGetAccessTokenBySHA(t *testing.T) { func TestListAccessTokens(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - tokens, err := auth_model.ListAccessTokens(db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 1}) + tokens, err := db.Find[auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 1}) assert.NoError(t, err) if assert.Len(t, tokens, 2) { assert.Equal(t, int64(1), tokens[0].UID) @@ -94,14 +94,14 @@ func TestListAccessTokens(t *testing.T) { assert.Contains(t, []string{tokens[0].Name, tokens[1].Name}, "Token B") } - tokens, err = auth_model.ListAccessTokens(db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 2}) + tokens, err = db.Find[auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 2}) assert.NoError(t, err) if assert.Len(t, tokens, 1) { assert.Equal(t, int64(2), tokens[0].UID) assert.Equal(t, "Token A", tokens[0].Name) } - tokens, err = auth_model.ListAccessTokens(db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 100}) + tokens, err = db.Find[auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 100}) assert.NoError(t, err) assert.Empty(t, tokens) } diff --git a/models/auth/oauth2.go b/models/auth/oauth2.go index 76a4e9d835bc..cce5cf7ff1b1 100644 --- a/models/auth/oauth2.go +++ b/models/auth/oauth2.go @@ -6,7 +6,6 @@ package auth import ( "context" "encoding/base32" - "encoding/base64" "fmt" "net" "net/url" @@ -19,10 +18,8 @@ import ( "code.gitea.io/gitea/modules/util" uuid "github.com/google/uuid" - "github.com/minio/sha256-simd" "golang.org/x/crypto/bcrypt" "xorm.io/builder" - "xorm.io/xorm" ) // OAuth2Application represents an OAuth2 client (RFC 6749) @@ -243,13 +240,6 @@ func GetOAuth2ApplicationByID(ctx context.Context, id int64) (app *OAuth2Applica return app, nil } -// GetOAuth2ApplicationsByUserID returns all oauth2 applications owned by the user -func GetOAuth2ApplicationsByUserID(ctx context.Context, userID int64) (apps []*OAuth2Application, err error) { - apps = make([]*OAuth2Application, 0) - err = db.GetEngine(ctx).Where("uid = ?", userID).Find(&apps) - return apps, err -} - // CreateOAuth2ApplicationOptions holds options to create an oauth2 application type CreateOAuth2ApplicationOptions struct { Name string @@ -372,223 +362,6 @@ func DeleteOAuth2Application(ctx context.Context, id, userid int64) error { return committer.Commit() } -// ListOAuth2Applications returns a list of oauth2 applications belongs to given user. -func ListOAuth2Applications(ctx context.Context, uid int64, listOptions db.ListOptions) ([]*OAuth2Application, int64, error) { - sess := db.GetEngine(ctx). - Where("uid=?", uid). - Desc("id") - - if listOptions.Page != 0 { - sess = db.SetSessionPagination(sess, &listOptions) - - apps := make([]*OAuth2Application, 0, listOptions.PageSize) - total, err := sess.FindAndCount(&apps) - return apps, total, err - } - - apps := make([]*OAuth2Application, 0, 5) - total, err := sess.FindAndCount(&apps) - return apps, total, err -} - -////////////////////////////////////////////////////// - -// OAuth2AuthorizationCode is a code to obtain an access token in combination with the client secret once. It has a limited lifetime. -type OAuth2AuthorizationCode struct { - ID int64 `xorm:"pk autoincr"` - Grant *OAuth2Grant `xorm:"-"` - GrantID int64 - Code string `xorm:"INDEX unique"` - CodeChallenge string - CodeChallengeMethod string - RedirectURI string - ValidUntil timeutil.TimeStamp `xorm:"index"` -} - -// TableName sets the table name to `oauth2_authorization_code` -func (code *OAuth2AuthorizationCode) TableName() string { - return "oauth2_authorization_code" -} - -// GenerateRedirectURI generates a redirect URI for a successful authorization request. State will be used if not empty. -func (code *OAuth2AuthorizationCode) GenerateRedirectURI(state string) (*url.URL, error) { - redirect, err := url.Parse(code.RedirectURI) - if err != nil { - return nil, err - } - q := redirect.Query() - if state != "" { - q.Set("state", state) - } - q.Set("code", code.Code) - redirect.RawQuery = q.Encode() - return redirect, err -} - -// Invalidate deletes the auth code from the database to invalidate this code -func (code *OAuth2AuthorizationCode) Invalidate(ctx context.Context) error { - _, err := db.GetEngine(ctx).ID(code.ID).NoAutoCondition().Delete(code) - return err -} - -// ValidateCodeChallenge validates the given verifier against the saved code challenge. This is part of the PKCE implementation. -func (code *OAuth2AuthorizationCode) ValidateCodeChallenge(verifier string) bool { - switch code.CodeChallengeMethod { - case "S256": - // base64url(SHA256(verifier)) see https://tools.ietf.org/html/rfc7636#section-4.6 - h := sha256.Sum256([]byte(verifier)) - hashedVerifier := base64.RawURLEncoding.EncodeToString(h[:]) - return hashedVerifier == code.CodeChallenge - case "plain": - return verifier == code.CodeChallenge - case "": - return true - default: - // unsupported method -> return false - return false - } -} - -// GetOAuth2AuthorizationByCode returns an authorization by its code -func GetOAuth2AuthorizationByCode(ctx context.Context, code string) (auth *OAuth2AuthorizationCode, err error) { - auth = new(OAuth2AuthorizationCode) - if has, err := db.GetEngine(ctx).Where("code = ?", code).Get(auth); err != nil { - return nil, err - } else if !has { - return nil, nil - } - auth.Grant = new(OAuth2Grant) - if has, err := db.GetEngine(ctx).ID(auth.GrantID).Get(auth.Grant); err != nil { - return nil, err - } else if !has { - return nil, nil - } - return auth, nil -} - -////////////////////////////////////////////////////// - -// OAuth2Grant represents the permission of an user for a specific application to access resources -type OAuth2Grant struct { - ID int64 `xorm:"pk autoincr"` - UserID int64 `xorm:"INDEX unique(user_application)"` - Application *OAuth2Application `xorm:"-"` - ApplicationID int64 `xorm:"INDEX unique(user_application)"` - Counter int64 `xorm:"NOT NULL DEFAULT 1"` - Scope string `xorm:"TEXT"` - Nonce string `xorm:"TEXT"` - CreatedUnix timeutil.TimeStamp `xorm:"created"` - UpdatedUnix timeutil.TimeStamp `xorm:"updated"` -} - -// TableName sets the table name to `oauth2_grant` -func (grant *OAuth2Grant) TableName() string { - return "oauth2_grant" -} - -// GenerateNewAuthorizationCode generates a new authorization code for a grant and saves it to the database -func (grant *OAuth2Grant) GenerateNewAuthorizationCode(ctx context.Context, redirectURI, codeChallenge, codeChallengeMethod string) (code *OAuth2AuthorizationCode, err error) { - rBytes, err := util.CryptoRandomBytes(32) - if err != nil { - return &OAuth2AuthorizationCode{}, err - } - // Add a prefix to the base32, this is in order to make it easier - // for code scanners to grab sensitive tokens. - codeSecret := "gta_" + base32Lower.EncodeToString(rBytes) - - code = &OAuth2AuthorizationCode{ - Grant: grant, - GrantID: grant.ID, - RedirectURI: redirectURI, - Code: codeSecret, - CodeChallenge: codeChallenge, - CodeChallengeMethod: codeChallengeMethod, - } - if err := db.Insert(ctx, code); err != nil { - return nil, err - } - return code, nil -} - -// IncreaseCounter increases the counter and updates the grant -func (grant *OAuth2Grant) IncreaseCounter(ctx context.Context) error { - _, err := db.GetEngine(ctx).ID(grant.ID).Incr("counter").Update(new(OAuth2Grant)) - if err != nil { - return err - } - updatedGrant, err := GetOAuth2GrantByID(ctx, grant.ID) - if err != nil { - return err - } - grant.Counter = updatedGrant.Counter - return nil -} - -// ScopeContains returns true if the grant scope contains the specified scope -func (grant *OAuth2Grant) ScopeContains(scope string) bool { - for _, currentScope := range strings.Split(grant.Scope, " ") { - if scope == currentScope { - return true - } - } - return false -} - -// SetNonce updates the current nonce value of a grant -func (grant *OAuth2Grant) SetNonce(ctx context.Context, nonce string) error { - grant.Nonce = nonce - _, err := db.GetEngine(ctx).ID(grant.ID).Cols("nonce").Update(grant) - if err != nil { - return err - } - return nil -} - -// GetOAuth2GrantByID returns the grant with the given ID -func GetOAuth2GrantByID(ctx context.Context, id int64) (grant *OAuth2Grant, err error) { - grant = new(OAuth2Grant) - if has, err := db.GetEngine(ctx).ID(id).Get(grant); err != nil { - return nil, err - } else if !has { - return nil, nil - } - return grant, err -} - -// GetOAuth2GrantsByUserID lists all grants of a certain user -func GetOAuth2GrantsByUserID(ctx context.Context, uid int64) ([]*OAuth2Grant, error) { - type joinedOAuth2Grant struct { - Grant *OAuth2Grant `xorm:"extends"` - Application *OAuth2Application `xorm:"extends"` - } - var results *xorm.Rows - var err error - if results, err = db.GetEngine(ctx). - Table("oauth2_grant"). - Where("user_id = ?", uid). - Join("INNER", "oauth2_application", "application_id = oauth2_application.id"). - Rows(new(joinedOAuth2Grant)); err != nil { - return nil, err - } - defer results.Close() - grants := make([]*OAuth2Grant, 0) - for results.Next() { - joinedGrant := new(joinedOAuth2Grant) - if err := results.Scan(joinedGrant); err != nil { - return nil, err - } - joinedGrant.Grant.Application = joinedGrant.Application - grants = append(grants, joinedGrant.Grant) - } - return grants, nil -} - -// RevokeOAuth2Grant deletes the grant with grantID and userID -func RevokeOAuth2Grant(ctx context.Context, grantID, userID int64) error { - _, err := db.GetEngine(ctx).Where(builder.Eq{"id": grantID, "user_id": userID}).Delete(&OAuth2Grant{}) - return err -} - // ErrOAuthClientIDInvalid will be thrown if client id cannot be found type ErrOAuthClientIDInvalid struct { ClientID string diff --git a/models/auth/oauth2_grant.go b/models/auth/oauth2_grant.go new file mode 100644 index 000000000000..9ffd76126c81 --- /dev/null +++ b/models/auth/oauth2_grant.go @@ -0,0 +1,217 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package auth + +import ( + "context" + "crypto/sha256" + "encoding/base64" + "net/url" + "strings" + + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/util" + + "xorm.io/builder" + "xorm.io/xorm" +) + +////////////////////////////////////////////////////// + +// OAuth2AuthorizationCode is a code to obtain an access token in combination with the client secret once. It has a limited lifetime. +type OAuth2AuthorizationCode struct { + ID int64 `xorm:"pk autoincr"` + Grant *OAuth2Grant `xorm:"-"` + GrantID int64 + Code string `xorm:"INDEX unique"` + CodeChallenge string + CodeChallengeMethod string + RedirectURI string + ValidUntil timeutil.TimeStamp `xorm:"index"` +} + +// TableName sets the table name to `oauth2_authorization_code` +func (code *OAuth2AuthorizationCode) TableName() string { + return "oauth2_authorization_code" +} + +// GenerateRedirectURI generates a redirect URI for a successful authorization request. State will be used if not empty. +func (code *OAuth2AuthorizationCode) GenerateRedirectURI(state string) (*url.URL, error) { + redirect, err := url.Parse(code.RedirectURI) + if err != nil { + return nil, err + } + q := redirect.Query() + if state != "" { + q.Set("state", state) + } + q.Set("code", code.Code) + redirect.RawQuery = q.Encode() + return redirect, err +} + +// Invalidate deletes the auth code from the database to invalidate this code +func (code *OAuth2AuthorizationCode) Invalidate(ctx context.Context) error { + _, err := db.GetEngine(ctx).ID(code.ID).NoAutoCondition().Delete(code) + return err +} + +// ValidateCodeChallenge validates the given verifier against the saved code challenge. This is part of the PKCE implementation. +func (code *OAuth2AuthorizationCode) ValidateCodeChallenge(verifier string) bool { + switch code.CodeChallengeMethod { + case "S256": + // base64url(SHA256(verifier)) see https://tools.ietf.org/html/rfc7636#section-4.6 + h := sha256.Sum256([]byte(verifier)) + hashedVerifier := base64.RawURLEncoding.EncodeToString(h[:]) + return hashedVerifier == code.CodeChallenge + case "plain": + return verifier == code.CodeChallenge + case "": + return true + default: + // unsupported method -> return false + return false + } +} + +// GetOAuth2AuthorizationByCode returns an authorization by its code +func GetOAuth2AuthorizationByCode(ctx context.Context, code string) (auth *OAuth2AuthorizationCode, err error) { + auth = new(OAuth2AuthorizationCode) + if has, err := db.GetEngine(ctx).Where("code = ?", code).Get(auth); err != nil { + return nil, err + } else if !has { + return nil, nil + } + auth.Grant = new(OAuth2Grant) + if has, err := db.GetEngine(ctx).ID(auth.GrantID).Get(auth.Grant); err != nil { + return nil, err + } else if !has { + return nil, nil + } + return auth, nil +} + +////////////////////////////////////////////////////// + +// OAuth2Grant represents the permission of an user for a specific application to access resources +type OAuth2Grant struct { + ID int64 `xorm:"pk autoincr"` + UserID int64 `xorm:"INDEX unique(user_application)"` + Application *OAuth2Application `xorm:"-"` + ApplicationID int64 `xorm:"INDEX unique(user_application)"` + Counter int64 `xorm:"NOT NULL DEFAULT 1"` + Scope string `xorm:"TEXT"` + Nonce string `xorm:"TEXT"` + CreatedUnix timeutil.TimeStamp `xorm:"created"` + UpdatedUnix timeutil.TimeStamp `xorm:"updated"` +} + +// TableName sets the table name to `oauth2_grant` +func (grant *OAuth2Grant) TableName() string { + return "oauth2_grant" +} + +// GenerateNewAuthorizationCode generates a new authorization code for a grant and saves it to the database +func (grant *OAuth2Grant) GenerateNewAuthorizationCode(ctx context.Context, redirectURI, codeChallenge, codeChallengeMethod string) (code *OAuth2AuthorizationCode, err error) { + rBytes, err := util.CryptoRandomBytes(32) + if err != nil { + return &OAuth2AuthorizationCode{}, err + } + // Add a prefix to the base32, this is in order to make it easier + // for code scanners to grab sensitive tokens. + codeSecret := "gta_" + base32Lower.EncodeToString(rBytes) + + code = &OAuth2AuthorizationCode{ + Grant: grant, + GrantID: grant.ID, + RedirectURI: redirectURI, + Code: codeSecret, + CodeChallenge: codeChallenge, + CodeChallengeMethod: codeChallengeMethod, + } + if err := db.Insert(ctx, code); err != nil { + return nil, err + } + return code, nil +} + +// IncreaseCounter increases the counter and updates the grant +func (grant *OAuth2Grant) IncreaseCounter(ctx context.Context) error { + _, err := db.GetEngine(ctx).ID(grant.ID).Incr("counter").Update(new(OAuth2Grant)) + if err != nil { + return err + } + updatedGrant, err := GetOAuth2GrantByID(ctx, grant.ID) + if err != nil { + return err + } + grant.Counter = updatedGrant.Counter + return nil +} + +// ScopeContains returns true if the grant scope contains the specified scope +func (grant *OAuth2Grant) ScopeContains(scope string) bool { + for _, currentScope := range strings.Split(grant.Scope, " ") { + if scope == currentScope { + return true + } + } + return false +} + +// SetNonce updates the current nonce value of a grant +func (grant *OAuth2Grant) SetNonce(ctx context.Context, nonce string) error { + grant.Nonce = nonce + _, err := db.GetEngine(ctx).ID(grant.ID).Cols("nonce").Update(grant) + if err != nil { + return err + } + return nil +} + +// GetOAuth2GrantByID returns the grant with the given ID +func GetOAuth2GrantByID(ctx context.Context, id int64) (grant *OAuth2Grant, err error) { + grant = new(OAuth2Grant) + if has, err := db.GetEngine(ctx).ID(id).Get(grant); err != nil { + return nil, err + } else if !has { + return nil, nil + } + return grant, err +} + +// GetOAuth2GrantsByUserID lists all grants of a certain user +func GetOAuth2GrantsByUserID(ctx context.Context, uid int64) ([]*OAuth2Grant, error) { + type joinedOAuth2Grant struct { + Grant *OAuth2Grant `xorm:"extends"` + Application *OAuth2Application `xorm:"extends"` + } + var results *xorm.Rows + var err error + if results, err = db.GetEngine(ctx). + Table("oauth2_grant"). + Where("user_id = ?", uid). + Join("INNER", "oauth2_application", "application_id = oauth2_application.id"). + Rows(new(joinedOAuth2Grant)); err != nil { + return nil, err + } + defer results.Close() + grants := make([]*OAuth2Grant, 0) + for results.Next() { + joinedGrant := new(joinedOAuth2Grant) + if err := results.Scan(joinedGrant); err != nil { + return nil, err + } + joinedGrant.Grant.Application = joinedGrant.Application + grants = append(grants, joinedGrant.Grant) + } + return grants, nil +} + +// RevokeOAuth2Grant deletes the grant with grantID and userID +func RevokeOAuth2Grant(ctx context.Context, grantID, userID int64) error { + _, err := db.GetEngine(ctx).Where(builder.Eq{"id": grantID, "user_id": userID}).Delete(&OAuth2Grant{}) + return err +} diff --git a/models/auth/oauth2_list.go b/models/auth/oauth2_list.go new file mode 100644 index 000000000000..c55f10b3c85d --- /dev/null +++ b/models/auth/oauth2_list.go @@ -0,0 +1,32 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package auth + +import ( + "code.gitea.io/gitea/models/db" + + "xorm.io/builder" +) + +type FindOAuth2ApplicationsOptions struct { + db.ListOptions + // OwnerID is the user id or org id of the owner of the application + OwnerID int64 + // find global applications, if true, then OwnerID will be igonred + IsGlobal bool +} + +func (opts FindOAuth2ApplicationsOptions) ToConds() builder.Cond { + conds := builder.NewCond() + if opts.IsGlobal { + conds = conds.And(builder.Eq{"uid": 0}) + } else if opts.OwnerID != 0 { + conds = conds.And(builder.Eq{"uid": opts.OwnerID}) + } + return conds +} + +func (opts FindOAuth2ApplicationsOptions) ToOrders() string { + return "id DESC" +} diff --git a/models/user/external_login_user.go b/models/user/external_login_user.go index 2eccddd581e2..0db702f22520 100644 --- a/models/user/external_login_user.go +++ b/models/user/external_login_user.go @@ -180,16 +180,3 @@ func (opts FindExternalUserOptions) ToConds() builder.Cond { func (opts FindExternalUserOptions) ToOrders() string { return opts.OrderBy } - -// FindExternalUsersByProvider represents external users via provider -/*func FindExternalUsersByProvider(ctx context.Context, opts FindExternalUserOptions) ([]ExternalLoginUser, error) { - var users []ExternalLoginUser - err := db.GetEngine(ctx).Where(opts.toConds()). - Limit(opts.Limit, opts.Start). - OrderBy("login_source_id ASC, external_id ASC"). - Find(&users) - if err != nil { - return nil, err - } - return users, nil -}*/ diff --git a/routers/api/v1/user/app.go b/routers/api/v1/user/app.go index fef0240b0ff6..249f62ad36e3 100644 --- a/routers/api/v1/user/app.go +++ b/routers/api/v1/user/app.go @@ -12,6 +12,7 @@ import ( "strings" auth_model "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/context" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" @@ -48,12 +49,7 @@ func ListAccessTokens(ctx *context.APIContext) { opts := auth_model.ListAccessTokensOptions{UserID: ctx.ContextUser.ID, ListOptions: utils.GetListOptions(ctx)} - count, err := auth_model.CountAccessTokens(ctx, opts) - if err != nil { - ctx.InternalServerError(err) - return - } - tokens, err := auth_model.ListAccessTokens(ctx, opts) + tokens, count, err := db.FindAndCount[auth_model.AccessToken](ctx, opts) if err != nil { ctx.InternalServerError(err) return @@ -168,7 +164,7 @@ func DeleteAccessToken(ctx *context.APIContext) { tokenID, _ := strconv.ParseInt(token, 0, 64) if tokenID == 0 { - tokens, err := auth_model.ListAccessTokens(ctx, auth_model.ListAccessTokensOptions{ + tokens, err := db.Find[auth_model.AccessToken](ctx, auth_model.ListAccessTokensOptions{ Name: token, UserID: ctx.ContextUser.ID, }) @@ -266,7 +262,10 @@ func ListOauth2Applications(ctx *context.APIContext) { // "200": // "$ref": "#/responses/OAuth2ApplicationList" - apps, total, err := auth_model.ListOAuth2Applications(ctx, ctx.Doer.ID, utils.GetListOptions(ctx)) + apps, total, err := db.FindAndCount[*auth_model.OAuth2Application](ctx, auth_model.FindOAuth2ApplicationsOptions{ + ListOptions: utils.GetListOptions(ctx), + OwnerID: ctx.Doer.ID, + }) if err != nil { ctx.Error(http.StatusInternalServerError, "ListOAuth2Applications", err) return diff --git a/routers/web/admin/applications.go b/routers/web/admin/applications.go index b26912db4821..b6f7bcd2a5b2 100644 --- a/routers/web/admin/applications.go +++ b/routers/web/admin/applications.go @@ -8,6 +8,7 @@ import ( "net/http" "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/setting" @@ -33,7 +34,9 @@ func Applications(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("settings.applications") ctx.Data["PageIsAdminApplications"] = true - apps, err := auth.GetOAuth2ApplicationsByUserID(ctx, 0) + apps, err := db.Find[auth.OAuth2Application](ctx, auth.FindOAuth2ApplicationsOptions{ + IsGlobal: true, + }) if err != nil { ctx.ServerError("GetOAuth2ApplicationsByUserID", err) return diff --git a/routers/web/org/setting_oauth2.go b/routers/web/org/setting_oauth2.go index 0045bce4c932..ca4fe09f380c 100644 --- a/routers/web/org/setting_oauth2.go +++ b/routers/web/org/setting_oauth2.go @@ -8,6 +8,7 @@ import ( "net/http" "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/setting" @@ -35,7 +36,9 @@ func Applications(ctx *context.Context) { ctx.Data["PageIsOrgSettings"] = true ctx.Data["PageIsSettingsApplications"] = true - apps, err := auth.GetOAuth2ApplicationsByUserID(ctx, ctx.Org.Organization.ID) + apps, err := db.Find[auth.OAuth2Application](ctx, auth.FindOAuth2ApplicationsOptions{ + OwnerID: ctx.Org.Organization.ID, + }) if err != nil { ctx.ServerError("GetOAuth2ApplicationsByUserID", err) return diff --git a/routers/web/user/setting/applications.go b/routers/web/user/setting/applications.go index ee44d48dce56..69a93dbf03ae 100644 --- a/routers/web/user/setting/applications.go +++ b/routers/web/user/setting/applications.go @@ -8,6 +8,7 @@ import ( "net/http" auth_model "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/setting" @@ -88,7 +89,7 @@ func DeleteApplication(ctx *context.Context) { func loadApplicationsData(ctx *context.Context) { ctx.Data["AccessTokenScopePublicOnly"] = auth_model.AccessTokenScopePublicOnly - tokens, err := auth_model.ListAccessTokens(ctx, auth_model.ListAccessTokensOptions{UserID: ctx.Doer.ID}) + tokens, err := db.Find[auth_model.AccessToken](ctx, auth_model.ListAccessTokensOptions{UserID: ctx.Doer.ID}) if err != nil { ctx.ServerError("ListAccessTokens", err) return @@ -97,7 +98,9 @@ func loadApplicationsData(ctx *context.Context) { ctx.Data["EnableOAuth2"] = setting.OAuth2.Enable ctx.Data["IsAdmin"] = ctx.Doer.IsAdmin if setting.OAuth2.Enable { - ctx.Data["Applications"], err = auth_model.GetOAuth2ApplicationsByUserID(ctx, ctx.Doer.ID) + ctx.Data["Applications"], err = db.Find[auth_model.OAuth2Application](ctx, auth_model.FindOAuth2ApplicationsOptions{ + OwnerID: ctx.Doer.ID, + }) if err != nil { ctx.ServerError("GetOAuth2ApplicationsByUserID", err) return diff --git a/routers/web/user/setting/security/security.go b/routers/web/user/setting/security/security.go index b7ceb83f76fa..2edfaa71a9d7 100644 --- a/routers/web/user/setting/security/security.go +++ b/routers/web/user/setting/security/security.go @@ -69,7 +69,7 @@ func loadSecurityData(ctx *context.Context) { } ctx.Data["WebAuthnCredentials"] = credentials - tokens, err := auth_model.ListAccessTokens(ctx, auth_model.ListAccessTokensOptions{UserID: ctx.Doer.ID}) + tokens, err := db.Find[auth_model.AccessToken](ctx, auth_model.ListAccessTokensOptions{UserID: ctx.Doer.ID}) if err != nil { ctx.ServerError("ListAccessTokens", err) return From 463add45daa01c083fc51f6eb635411e4861d462 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 21 Nov 2023 12:01:33 +0800 Subject: [PATCH 16/21] Fix check --- models/auth/access_token.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/auth/access_token.go b/models/auth/access_token.go index fa12dffb4be2..63331b484125 100644 --- a/models/auth/access_token.go +++ b/models/auth/access_token.go @@ -15,9 +15,9 @@ import ( "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" - "xorm.io/builder" lru "github.com/hashicorp/golang-lru/v2" + "xorm.io/builder" ) // ErrAccessTokenNotExist represents a "AccessTokenNotExist" kind of error. From abac7accc295aa2df76828d7867e61476a2bc7c0 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 22 Nov 2023 10:18:36 +0800 Subject: [PATCH 17/21] follow delvh's suggestion --- models/activities/notification_test.go | 43 ++++++++++++++++++++++++++ routers/api/v1/user/key.go | 14 ++------- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/models/activities/notification_test.go b/models/activities/notification_test.go index d46debfecc1a..1fa51542fd5f 100644 --- a/models/activities/notification_test.go +++ b/models/activities/notification_test.go @@ -31,6 +31,27 @@ func TestCreateOrUpdateIssueNotifications(t *testing.T) { assert.Equal(t, activities_model.NotificationStatusUnread, notf.Status) } +func TestNotificationsForUser(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + notfs, err := db.Find[activities_model.Notification](db.DefaultContext, activities_model.FindNotificationOptions{ + UserID: user.ID, + Status: []activities_model.NotificationStatus{ + activities_model.NotificationStatusRead, + activities_model.NotificationStatusUnread, + }, + }) + assert.NoError(t, err) + if assert.Len(t, notfs, 3) { + assert.EqualValues(t, 5, notfs[0].ID) + assert.EqualValues(t, user.ID, notfs[0].UserID) + assert.EqualValues(t, 4, notfs[1].ID) + assert.EqualValues(t, user.ID, notfs[1].UserID) + assert.EqualValues(t, 2, notfs[2].ID) + assert.EqualValues(t, user.ID, notfs[2].UserID) + } +} + func TestNotification_GetRepo(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{RepoID: 1}) @@ -40,6 +61,28 @@ func TestNotification_GetRepo(t *testing.T) { assert.EqualValues(t, notf.RepoID, repo.ID) } +func TestGetNotificationCount(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) + cnt, err := db.Count[activities_model.Notification](db.DefaultContext, activities_model.FindNotificationOptions{ + UserID: user.ID, + Status: []activities_model.NotificationStatus{ + activities_model.NotificationStatusRead, + }, + }) + assert.NoError(t, err) + assert.EqualValues(t, 0, cnt) + + cnt, err = db.Count[activities_model.Notification](db.DefaultContext, activities_model.FindNotificationOptions{ + UserID: user.ID, + Status: []activities_model.NotificationStatus{ + activities_model.NotificationStatusUnread, + }, + }) + assert.NoError(t, err) + assert.EqualValues(t, 1, cnt) +} + func TestNotification_GetIssue(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{RepoID: 1}) diff --git a/routers/api/v1/user/key.go b/routers/api/v1/user/key.go index f3a49f8779ef..7fa5668a6a1a 100644 --- a/routers/api/v1/user/key.go +++ b/routers/api/v1/user/key.go @@ -69,22 +69,14 @@ func listPublicKeys(ctx *context.APIContext, user *user_model.User) { }) count = len(keys) } else { - total, err2 := db.Count[asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ - OwnerID: user.ID, - NotKeytype: asymkey_model.KeyTypePrincipal, - }) - if err2 != nil { - ctx.InternalServerError(err) - return - } - count = int(total) - + var total int64 // Use ListPublicKeys - keys, err = db.Find[*asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ + keys, total, err = db.FindAndCount[*asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ ListOptions: utils.GetListOptions(ctx), OwnerID: user.ID, NotKeytype: asymkey_model.KeyTypePrincipal, }) + count = int(total) } if err != nil { From 7952cd06f2cdadf809e5d4a7f810f184b1fd5e3d Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 23 Nov 2023 20:44:00 +0800 Subject: [PATCH 18/21] Keep all db.Find and db.FindAndCount with pointer of struct and make review eaiser --- cmd/admin_auth.go | 2 +- models/activities/notification_test.go | 2 +- models/asymkey/ssh_key.go | 2 +- models/auth/access_token_test.go | 6 +- models/auth/oauth2.go | 201 ++++++++++++++++ models/auth/oauth2_grant.go | 217 ------------------ models/db/list_test.go | 4 +- models/organization/org_test.go | 4 +- models/project/project_test.go | 6 +- models/webhook/webhook_test.go | 8 +- routers/api/actions/artifacts.go | 4 +- routers/api/actions/runner/utils.go | 8 +- routers/api/v1/notify/user.go | 2 +- routers/api/v1/org/action.go | 2 +- routers/api/v1/user/app.go | 4 +- routers/web/admin/applications.go | 2 +- routers/web/admin/auths.go | 4 +- routers/web/admin/users.go | 8 +- routers/web/org/setting.go | 2 +- routers/web/org/setting_oauth2.go | 2 +- routers/web/repo/actions/view.go | 2 +- routers/web/repo/setting/deploy_key.go | 4 +- routers/web/repo/setting/webhook.go | 2 +- routers/web/shared/actions/variables.go | 2 +- routers/web/shared/secrets/secrets.go | 2 +- routers/web/user/home.go | 2 +- routers/web/user/setting/applications.go | 4 +- routers/web/user/setting/profile.go | 2 +- routers/web/user/setting/security/security.go | 4 +- routers/web/user/setting/webhooks.go | 2 +- services/asymkey/ssh_key_test.go | 2 +- services/auth/source/oauth2/init.go | 2 +- services/auth/sspi.go | 2 +- services/auth/sync.go | 2 +- services/migrations/update.go | 2 +- services/repository/delete.go | 6 +- services/repository/hooks.go | 2 +- tests/integration/auth_ldap_test.go | 2 +- tests/integration/org_count_test.go | 2 +- 39 files changed, 261 insertions(+), 277 deletions(-) delete mode 100644 models/auth/oauth2_grant.go diff --git a/cmd/admin_auth.go b/cmd/admin_auth.go index ec92e342d4d4..f4a89212c6f9 100644 --- a/cmd/admin_auth.go +++ b/cmd/admin_auth.go @@ -63,7 +63,7 @@ func runListAuth(c *cli.Context) error { return err } - authSources, err := db.Find[auth_model.Source](ctx, auth_model.FindSourcesOptions{}) + authSources, err := db.Find[*auth_model.Source](ctx, auth_model.FindSourcesOptions{}) if err != nil { return err } diff --git a/models/activities/notification_test.go b/models/activities/notification_test.go index 1fa51542fd5f..1b66d6fd2f57 100644 --- a/models/activities/notification_test.go +++ b/models/activities/notification_test.go @@ -34,7 +34,7 @@ func TestCreateOrUpdateIssueNotifications(t *testing.T) { func TestNotificationsForUser(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - notfs, err := db.Find[activities_model.Notification](db.DefaultContext, activities_model.FindNotificationOptions{ + notfs, err := db.Find[*activities_model.Notification](db.DefaultContext, activities_model.FindNotificationOptions{ UserID: user.ID, Status: []activities_model.NotificationStatus{ activities_model.NotificationStatusRead, diff --git a/models/asymkey/ssh_key.go b/models/asymkey/ssh_key.go index 552f2ffd69e6..177e99227a64 100644 --- a/models/asymkey/ssh_key.go +++ b/models/asymkey/ssh_key.go @@ -382,7 +382,7 @@ func SynchronizePublicKeys(ctx context.Context, usr *user_model.User, s *auth.So // Get Public Keys from DB with current LDAP source var giteaKeys []string - keys, err := db.Find[PublicKey](ctx, FindPublicKeyOptions{ + keys, err := db.Find[*PublicKey](ctx, FindPublicKeyOptions{ OwnerID: usr.ID, LoginSourceID: s.ID, }) diff --git a/models/auth/access_token_test.go b/models/auth/access_token_test.go index 4360f1a21433..9f90511fa948 100644 --- a/models/auth/access_token_test.go +++ b/models/auth/access_token_test.go @@ -85,7 +85,7 @@ func TestGetAccessTokenBySHA(t *testing.T) { func TestListAccessTokens(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - tokens, err := db.Find[auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 1}) + tokens, err := db.Find[*auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 1}) assert.NoError(t, err) if assert.Len(t, tokens, 2) { assert.Equal(t, int64(1), tokens[0].UID) @@ -94,14 +94,14 @@ func TestListAccessTokens(t *testing.T) { assert.Contains(t, []string{tokens[0].Name, tokens[1].Name}, "Token B") } - tokens, err = db.Find[auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 2}) + tokens, err = db.Find[*auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 2}) assert.NoError(t, err) if assert.Len(t, tokens, 1) { assert.Equal(t, int64(2), tokens[0].UID) assert.Equal(t, "Token A", tokens[0].Name) } - tokens, err = db.Find[auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 100}) + tokens, err = db.Find[*auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 100}) assert.NoError(t, err) assert.Empty(t, tokens) } diff --git a/models/auth/oauth2.go b/models/auth/oauth2.go index cce5cf7ff1b1..9d53fffc7869 100644 --- a/models/auth/oauth2.go +++ b/models/auth/oauth2.go @@ -5,7 +5,9 @@ package auth import ( "context" + "crypto/sha256" "encoding/base32" + "encoding/base64" "fmt" "net" "net/url" @@ -20,6 +22,7 @@ import ( uuid "github.com/google/uuid" "golang.org/x/crypto/bcrypt" "xorm.io/builder" + "xorm.io/xorm" ) // OAuth2Application represents an OAuth2 client (RFC 6749) @@ -362,6 +365,204 @@ func DeleteOAuth2Application(ctx context.Context, id, userid int64) error { return committer.Commit() } +////////////////////////////////////////////////////// + +// OAuth2AuthorizationCode is a code to obtain an access token in combination with the client secret once. It has a limited lifetime. +type OAuth2AuthorizationCode struct { + ID int64 `xorm:"pk autoincr"` + Grant *OAuth2Grant `xorm:"-"` + GrantID int64 + Code string `xorm:"INDEX unique"` + CodeChallenge string + CodeChallengeMethod string + RedirectURI string + ValidUntil timeutil.TimeStamp `xorm:"index"` +} + +// TableName sets the table name to `oauth2_authorization_code` +func (code *OAuth2AuthorizationCode) TableName() string { + return "oauth2_authorization_code" +} + +// GenerateRedirectURI generates a redirect URI for a successful authorization request. State will be used if not empty. +func (code *OAuth2AuthorizationCode) GenerateRedirectURI(state string) (*url.URL, error) { + redirect, err := url.Parse(code.RedirectURI) + if err != nil { + return nil, err + } + q := redirect.Query() + if state != "" { + q.Set("state", state) + } + q.Set("code", code.Code) + redirect.RawQuery = q.Encode() + return redirect, err +} + +// Invalidate deletes the auth code from the database to invalidate this code +func (code *OAuth2AuthorizationCode) Invalidate(ctx context.Context) error { + _, err := db.GetEngine(ctx).ID(code.ID).NoAutoCondition().Delete(code) + return err +} + +// ValidateCodeChallenge validates the given verifier against the saved code challenge. This is part of the PKCE implementation. +func (code *OAuth2AuthorizationCode) ValidateCodeChallenge(verifier string) bool { + switch code.CodeChallengeMethod { + case "S256": + // base64url(SHA256(verifier)) see https://tools.ietf.org/html/rfc7636#section-4.6 + h := sha256.Sum256([]byte(verifier)) + hashedVerifier := base64.RawURLEncoding.EncodeToString(h[:]) + return hashedVerifier == code.CodeChallenge + case "plain": + return verifier == code.CodeChallenge + case "": + return true + default: + // unsupported method -> return false + return false + } +} + +// GetOAuth2AuthorizationByCode returns an authorization by its code +func GetOAuth2AuthorizationByCode(ctx context.Context, code string) (auth *OAuth2AuthorizationCode, err error) { + auth = new(OAuth2AuthorizationCode) + if has, err := db.GetEngine(ctx).Where("code = ?", code).Get(auth); err != nil { + return nil, err + } else if !has { + return nil, nil + } + auth.Grant = new(OAuth2Grant) + if has, err := db.GetEngine(ctx).ID(auth.GrantID).Get(auth.Grant); err != nil { + return nil, err + } else if !has { + return nil, nil + } + return auth, nil +} + +////////////////////////////////////////////////////// + +// OAuth2Grant represents the permission of an user for a specific application to access resources +type OAuth2Grant struct { + ID int64 `xorm:"pk autoincr"` + UserID int64 `xorm:"INDEX unique(user_application)"` + Application *OAuth2Application `xorm:"-"` + ApplicationID int64 `xorm:"INDEX unique(user_application)"` + Counter int64 `xorm:"NOT NULL DEFAULT 1"` + Scope string `xorm:"TEXT"` + Nonce string `xorm:"TEXT"` + CreatedUnix timeutil.TimeStamp `xorm:"created"` + UpdatedUnix timeutil.TimeStamp `xorm:"updated"` +} + +// TableName sets the table name to `oauth2_grant` +func (grant *OAuth2Grant) TableName() string { + return "oauth2_grant" +} + +// GenerateNewAuthorizationCode generates a new authorization code for a grant and saves it to the database +func (grant *OAuth2Grant) GenerateNewAuthorizationCode(ctx context.Context, redirectURI, codeChallenge, codeChallengeMethod string) (code *OAuth2AuthorizationCode, err error) { + rBytes, err := util.CryptoRandomBytes(32) + if err != nil { + return &OAuth2AuthorizationCode{}, err + } + // Add a prefix to the base32, this is in order to make it easier + // for code scanners to grab sensitive tokens. + codeSecret := "gta_" + base32Lower.EncodeToString(rBytes) + + code = &OAuth2AuthorizationCode{ + Grant: grant, + GrantID: grant.ID, + RedirectURI: redirectURI, + Code: codeSecret, + CodeChallenge: codeChallenge, + CodeChallengeMethod: codeChallengeMethod, + } + if err := db.Insert(ctx, code); err != nil { + return nil, err + } + return code, nil +} + +// IncreaseCounter increases the counter and updates the grant +func (grant *OAuth2Grant) IncreaseCounter(ctx context.Context) error { + _, err := db.GetEngine(ctx).ID(grant.ID).Incr("counter").Update(new(OAuth2Grant)) + if err != nil { + return err + } + updatedGrant, err := GetOAuth2GrantByID(ctx, grant.ID) + if err != nil { + return err + } + grant.Counter = updatedGrant.Counter + return nil +} + +// ScopeContains returns true if the grant scope contains the specified scope +func (grant *OAuth2Grant) ScopeContains(scope string) bool { + for _, currentScope := range strings.Split(grant.Scope, " ") { + if scope == currentScope { + return true + } + } + return false +} + +// SetNonce updates the current nonce value of a grant +func (grant *OAuth2Grant) SetNonce(ctx context.Context, nonce string) error { + grant.Nonce = nonce + _, err := db.GetEngine(ctx).ID(grant.ID).Cols("nonce").Update(grant) + if err != nil { + return err + } + return nil +} + +// GetOAuth2GrantByID returns the grant with the given ID +func GetOAuth2GrantByID(ctx context.Context, id int64) (grant *OAuth2Grant, err error) { + grant = new(OAuth2Grant) + if has, err := db.GetEngine(ctx).ID(id).Get(grant); err != nil { + return nil, err + } else if !has { + return nil, nil + } + return grant, err +} + +// GetOAuth2GrantsByUserID lists all grants of a certain user +func GetOAuth2GrantsByUserID(ctx context.Context, uid int64) ([]*OAuth2Grant, error) { + type joinedOAuth2Grant struct { + Grant *OAuth2Grant `xorm:"extends"` + Application *OAuth2Application `xorm:"extends"` + } + var results *xorm.Rows + var err error + if results, err = db.GetEngine(ctx). + Table("oauth2_grant"). + Where("user_id = ?", uid). + Join("INNER", "oauth2_application", "application_id = oauth2_application.id"). + Rows(new(joinedOAuth2Grant)); err != nil { + return nil, err + } + defer results.Close() + grants := make([]*OAuth2Grant, 0) + for results.Next() { + joinedGrant := new(joinedOAuth2Grant) + if err := results.Scan(joinedGrant); err != nil { + return nil, err + } + joinedGrant.Grant.Application = joinedGrant.Application + grants = append(grants, joinedGrant.Grant) + } + return grants, nil +} + +// RevokeOAuth2Grant deletes the grant with grantID and userID +func RevokeOAuth2Grant(ctx context.Context, grantID, userID int64) error { + _, err := db.GetEngine(ctx).Where(builder.Eq{"id": grantID, "user_id": userID}).Delete(&OAuth2Grant{}) + return err +} + // ErrOAuthClientIDInvalid will be thrown if client id cannot be found type ErrOAuthClientIDInvalid struct { ClientID string diff --git a/models/auth/oauth2_grant.go b/models/auth/oauth2_grant.go deleted file mode 100644 index 9ffd76126c81..000000000000 --- a/models/auth/oauth2_grant.go +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright 2023 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package auth - -import ( - "context" - "crypto/sha256" - "encoding/base64" - "net/url" - "strings" - - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/modules/timeutil" - "code.gitea.io/gitea/modules/util" - - "xorm.io/builder" - "xorm.io/xorm" -) - -////////////////////////////////////////////////////// - -// OAuth2AuthorizationCode is a code to obtain an access token in combination with the client secret once. It has a limited lifetime. -type OAuth2AuthorizationCode struct { - ID int64 `xorm:"pk autoincr"` - Grant *OAuth2Grant `xorm:"-"` - GrantID int64 - Code string `xorm:"INDEX unique"` - CodeChallenge string - CodeChallengeMethod string - RedirectURI string - ValidUntil timeutil.TimeStamp `xorm:"index"` -} - -// TableName sets the table name to `oauth2_authorization_code` -func (code *OAuth2AuthorizationCode) TableName() string { - return "oauth2_authorization_code" -} - -// GenerateRedirectURI generates a redirect URI for a successful authorization request. State will be used if not empty. -func (code *OAuth2AuthorizationCode) GenerateRedirectURI(state string) (*url.URL, error) { - redirect, err := url.Parse(code.RedirectURI) - if err != nil { - return nil, err - } - q := redirect.Query() - if state != "" { - q.Set("state", state) - } - q.Set("code", code.Code) - redirect.RawQuery = q.Encode() - return redirect, err -} - -// Invalidate deletes the auth code from the database to invalidate this code -func (code *OAuth2AuthorizationCode) Invalidate(ctx context.Context) error { - _, err := db.GetEngine(ctx).ID(code.ID).NoAutoCondition().Delete(code) - return err -} - -// ValidateCodeChallenge validates the given verifier against the saved code challenge. This is part of the PKCE implementation. -func (code *OAuth2AuthorizationCode) ValidateCodeChallenge(verifier string) bool { - switch code.CodeChallengeMethod { - case "S256": - // base64url(SHA256(verifier)) see https://tools.ietf.org/html/rfc7636#section-4.6 - h := sha256.Sum256([]byte(verifier)) - hashedVerifier := base64.RawURLEncoding.EncodeToString(h[:]) - return hashedVerifier == code.CodeChallenge - case "plain": - return verifier == code.CodeChallenge - case "": - return true - default: - // unsupported method -> return false - return false - } -} - -// GetOAuth2AuthorizationByCode returns an authorization by its code -func GetOAuth2AuthorizationByCode(ctx context.Context, code string) (auth *OAuth2AuthorizationCode, err error) { - auth = new(OAuth2AuthorizationCode) - if has, err := db.GetEngine(ctx).Where("code = ?", code).Get(auth); err != nil { - return nil, err - } else if !has { - return nil, nil - } - auth.Grant = new(OAuth2Grant) - if has, err := db.GetEngine(ctx).ID(auth.GrantID).Get(auth.Grant); err != nil { - return nil, err - } else if !has { - return nil, nil - } - return auth, nil -} - -////////////////////////////////////////////////////// - -// OAuth2Grant represents the permission of an user for a specific application to access resources -type OAuth2Grant struct { - ID int64 `xorm:"pk autoincr"` - UserID int64 `xorm:"INDEX unique(user_application)"` - Application *OAuth2Application `xorm:"-"` - ApplicationID int64 `xorm:"INDEX unique(user_application)"` - Counter int64 `xorm:"NOT NULL DEFAULT 1"` - Scope string `xorm:"TEXT"` - Nonce string `xorm:"TEXT"` - CreatedUnix timeutil.TimeStamp `xorm:"created"` - UpdatedUnix timeutil.TimeStamp `xorm:"updated"` -} - -// TableName sets the table name to `oauth2_grant` -func (grant *OAuth2Grant) TableName() string { - return "oauth2_grant" -} - -// GenerateNewAuthorizationCode generates a new authorization code for a grant and saves it to the database -func (grant *OAuth2Grant) GenerateNewAuthorizationCode(ctx context.Context, redirectURI, codeChallenge, codeChallengeMethod string) (code *OAuth2AuthorizationCode, err error) { - rBytes, err := util.CryptoRandomBytes(32) - if err != nil { - return &OAuth2AuthorizationCode{}, err - } - // Add a prefix to the base32, this is in order to make it easier - // for code scanners to grab sensitive tokens. - codeSecret := "gta_" + base32Lower.EncodeToString(rBytes) - - code = &OAuth2AuthorizationCode{ - Grant: grant, - GrantID: grant.ID, - RedirectURI: redirectURI, - Code: codeSecret, - CodeChallenge: codeChallenge, - CodeChallengeMethod: codeChallengeMethod, - } - if err := db.Insert(ctx, code); err != nil { - return nil, err - } - return code, nil -} - -// IncreaseCounter increases the counter and updates the grant -func (grant *OAuth2Grant) IncreaseCounter(ctx context.Context) error { - _, err := db.GetEngine(ctx).ID(grant.ID).Incr("counter").Update(new(OAuth2Grant)) - if err != nil { - return err - } - updatedGrant, err := GetOAuth2GrantByID(ctx, grant.ID) - if err != nil { - return err - } - grant.Counter = updatedGrant.Counter - return nil -} - -// ScopeContains returns true if the grant scope contains the specified scope -func (grant *OAuth2Grant) ScopeContains(scope string) bool { - for _, currentScope := range strings.Split(grant.Scope, " ") { - if scope == currentScope { - return true - } - } - return false -} - -// SetNonce updates the current nonce value of a grant -func (grant *OAuth2Grant) SetNonce(ctx context.Context, nonce string) error { - grant.Nonce = nonce - _, err := db.GetEngine(ctx).ID(grant.ID).Cols("nonce").Update(grant) - if err != nil { - return err - } - return nil -} - -// GetOAuth2GrantByID returns the grant with the given ID -func GetOAuth2GrantByID(ctx context.Context, id int64) (grant *OAuth2Grant, err error) { - grant = new(OAuth2Grant) - if has, err := db.GetEngine(ctx).ID(id).Get(grant); err != nil { - return nil, err - } else if !has { - return nil, nil - } - return grant, err -} - -// GetOAuth2GrantsByUserID lists all grants of a certain user -func GetOAuth2GrantsByUserID(ctx context.Context, uid int64) ([]*OAuth2Grant, error) { - type joinedOAuth2Grant struct { - Grant *OAuth2Grant `xorm:"extends"` - Application *OAuth2Application `xorm:"extends"` - } - var results *xorm.Rows - var err error - if results, err = db.GetEngine(ctx). - Table("oauth2_grant"). - Where("user_id = ?", uid). - Join("INNER", "oauth2_application", "application_id = oauth2_application.id"). - Rows(new(joinedOAuth2Grant)); err != nil { - return nil, err - } - defer results.Close() - grants := make([]*OAuth2Grant, 0) - for results.Next() { - joinedGrant := new(joinedOAuth2Grant) - if err := results.Scan(joinedGrant); err != nil { - return nil, err - } - joinedGrant.Grant.Application = joinedGrant.Application - grants = append(grants, joinedGrant.Grant) - } - return grants, nil -} - -// RevokeOAuth2Grant deletes the grant with grantID and userID -func RevokeOAuth2Grant(ctx context.Context, grantID, userID int64) error { - _, err := db.GetEngine(ctx).Where(builder.Eq{"id": grantID, "user_id": userID}).Delete(&OAuth2Grant{}) - return err -} diff --git a/models/db/list_test.go b/models/db/list_test.go index 45194611f8a4..776f7981c1c2 100644 --- a/models/db/list_test.go +++ b/models/db/list_test.go @@ -37,7 +37,7 @@ func TestFind(t *testing.T) { assert.NotEmpty(t, repoUnitCount) opts := mockListOptions{} - repoUnits, err := db.Find[repo_model.RepoUnit](db.DefaultContext, opts) + repoUnits, err := db.Find[*repo_model.RepoUnit](db.DefaultContext, opts) assert.NoError(t, err) assert.Len(t, repoUnits, repoUnitCount) @@ -45,7 +45,7 @@ func TestFind(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, repoUnitCount, cnt) - repoUnits, newCnt, err := db.FindAndCount[repo_model.RepoUnit](db.DefaultContext, opts) + repoUnits, newCnt, err := db.FindAndCount[*repo_model.RepoUnit](db.DefaultContext, opts) assert.NoError(t, err) assert.EqualValues(t, cnt, newCnt) assert.Len(t, repoUnits, repoUnitCount) diff --git a/models/organization/org_test.go b/models/organization/org_test.go index 5e40dd41907b..4514ae85858c 100644 --- a/models/organization/org_test.go +++ b/models/organization/org_test.go @@ -183,7 +183,7 @@ func TestIsPublicMembership(t *testing.T) { func TestFindOrgs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - orgs, err := db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{ + orgs, err := db.Find[*organization.Organization](db.DefaultContext, organization.FindOrgOptions{ UserID: 4, IncludePrivate: true, }) @@ -192,7 +192,7 @@ func TestFindOrgs(t *testing.T) { assert.EqualValues(t, 3, orgs[0].ID) } - orgs, err = db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{ + orgs, err = db.Find[*organization.Organization](db.DefaultContext, organization.FindOrgOptions{ UserID: 4, IncludePrivate: false, }) diff --git a/models/project/project_test.go b/models/project/project_test.go index 7a37c1faf290..da4c3b2531e5 100644 --- a/models/project/project_test.go +++ b/models/project/project_test.go @@ -34,13 +34,13 @@ func TestIsProjectTypeValid(t *testing.T) { func TestGetProjects(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - projects, err := db.Find[Project](db.DefaultContext, SearchOptions{RepoID: 1}) + projects, err := db.Find[*Project](db.DefaultContext, SearchOptions{RepoID: 1}) assert.NoError(t, err) // 1 value for this repo exists in the fixtures assert.Len(t, projects, 1) - projects, err = db.Find[Project](db.DefaultContext, SearchOptions{RepoID: 3}) + projects, err = db.Find[*Project](db.DefaultContext, SearchOptions{RepoID: 3}) assert.NoError(t, err) // 1 value for this repo exists in the fixtures @@ -109,7 +109,7 @@ func TestProjectsSort(t *testing.T) { } for _, tt := range tests { - projects, count, err := db.FindAndCount[Project](db.DefaultContext, SearchOptions{ + projects, count, err := db.FindAndCount[*Project](db.DefaultContext, SearchOptions{ OrderBy: GetSearchOrderByBySortType(tt.sortType), }) assert.NoError(t, err) diff --git a/models/webhook/webhook_test.go b/models/webhook/webhook_test.go index 694fd7a873f3..4c5eecc97140 100644 --- a/models/webhook/webhook_test.go +++ b/models/webhook/webhook_test.go @@ -123,7 +123,7 @@ func TestGetWebhookByOwnerID(t *testing.T) { func TestGetActiveWebhooksByRepoID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{RepoID: 1, IsActive: util.OptionalBoolTrue}) + hooks, err := db.Find[*Webhook](db.DefaultContext, ListWebhookOptions{RepoID: 1, IsActive: util.OptionalBoolTrue}) assert.NoError(t, err) if assert.Len(t, hooks, 1) { assert.Equal(t, int64(1), hooks[0].ID) @@ -133,7 +133,7 @@ func TestGetActiveWebhooksByRepoID(t *testing.T) { func TestGetWebhooksByRepoID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{RepoID: 1}) + hooks, err := db.Find[*Webhook](db.DefaultContext, ListWebhookOptions{RepoID: 1}) assert.NoError(t, err) if assert.Len(t, hooks, 2) { assert.Equal(t, int64(1), hooks[0].ID) @@ -143,7 +143,7 @@ func TestGetWebhooksByRepoID(t *testing.T) { func TestGetActiveWebhooksByOwnerID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{OwnerID: 3, IsActive: util.OptionalBoolTrue}) + hooks, err := db.Find[*Webhook](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) @@ -153,7 +153,7 @@ func TestGetActiveWebhooksByOwnerID(t *testing.T) { func TestGetWebhooksByOwnerID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{OwnerID: 3}) + hooks, err := db.Find[*Webhook](db.DefaultContext, ListWebhookOptions{OwnerID: 3}) assert.NoError(t, err) if assert.Len(t, hooks, 1) { assert.Equal(t, int64(3), hooks[0].ID) diff --git a/routers/api/actions/artifacts.go b/routers/api/actions/artifacts.go index 5411237103a0..19d788519a71 100644 --- a/routers/api/actions/artifacts.go +++ b/routers/api/actions/artifacts.go @@ -315,7 +315,7 @@ func (ar artifactRoutes) listArtifacts(ctx *ArtifactContext) { return } - artifacts, err := db.Find[actions.ActionArtifact](ctx, actions.FindArtifactsOptions{RunID: runID}) + artifacts, err := db.Find[*actions.ActionArtifact](ctx, actions.FindArtifactsOptions{RunID: runID}) if err != nil { log.Error("Error getting artifacts: %v", err) ctx.Error(http.StatusInternalServerError, err.Error()) @@ -377,7 +377,7 @@ func (ar artifactRoutes) getDownloadArtifactURL(ctx *ArtifactContext) { return } - artifacts, err := db.Find[actions.ActionArtifact](ctx, actions.FindArtifactsOptions{ + artifacts, err := db.Find[*actions.ActionArtifact](ctx, actions.FindArtifactsOptions{ RunID: runID, ArtifactName: itemPath, }) diff --git a/routers/api/actions/runner/utils.go b/routers/api/actions/runner/utils.go index d7ee3d8d4a38..ed95ae52723b 100644 --- a/routers/api/actions/runner/utils.go +++ b/routers/api/actions/runner/utils.go @@ -68,12 +68,12 @@ func getSecretsOfTask(ctx context.Context, task *actions_model.ActionTask) map[s return secrets } - ownerSecrets, err := db.Find[secret_model.Secret](ctx, secret_model.FindSecretsOptions{OwnerID: task.Job.Run.Repo.OwnerID}) + ownerSecrets, err := db.Find[*secret_model.Secret](ctx, secret_model.FindSecretsOptions{OwnerID: task.Job.Run.Repo.OwnerID}) if err != nil { log.Error("find secrets of owner %v: %v", task.Job.Run.Repo.OwnerID, err) // go on } - repoSecrets, err := db.Find[secret_model.Secret](ctx, secret_model.FindSecretsOptions{RepoID: task.Job.Run.RepoID}) + repoSecrets, err := db.Find[*secret_model.Secret](ctx, secret_model.FindSecretsOptions{RepoID: task.Job.Run.RepoID}) if err != nil { log.Error("find secrets of repo %v: %v", task.Job.Run.RepoID, err) // go on @@ -95,13 +95,13 @@ func getVariablesOfTask(ctx context.Context, task *actions_model.ActionTask) map variables := map[string]string{} // Org / User level - ownerVariables, err := db.Find[actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{OwnerID: task.Job.Run.Repo.OwnerID}) + ownerVariables, err := db.Find[*actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{OwnerID: task.Job.Run.Repo.OwnerID}) if err != nil { log.Error("find variables of org: %d, error: %v", task.Job.Run.Repo.OwnerID, err) } // Repo level - repoVariables, err := db.Find[actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{RepoID: task.Job.Run.RepoID}) + repoVariables, err := db.Find[*actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{RepoID: task.Job.Run.RepoID}) if err != nil { log.Error("find variables of repo: %d, error: %v", task.Job.Run.RepoID, err) } diff --git a/routers/api/v1/notify/user.go b/routers/api/v1/notify/user.go index 8f38b36921ec..9432e7d8d1d1 100644 --- a/routers/api/v1/notify/user.go +++ b/routers/api/v1/notify/user.go @@ -148,7 +148,7 @@ func ReadNotifications(ctx *context.APIContext) { statuses := ctx.FormStrings("status-types") opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread"}) } - nl, err := db.Find[activities_model.Notification](ctx, opts) + nl, err := db.Find[*activities_model.Notification](ctx, opts) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/org/action.go b/routers/api/v1/org/action.go index ddc74d865b18..1223ffcc002b 100644 --- a/routers/api/v1/org/action.go +++ b/routers/api/v1/org/action.go @@ -49,7 +49,7 @@ func ListActionsSecrets(ctx *context.APIContext) { ListOptions: utils.GetListOptions(ctx), } - secrets, count, err := db.FindAndCount[secret_model.Secret](ctx, opts) + secrets, count, err := db.FindAndCount[*secret_model.Secret](ctx, opts) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/user/app.go b/routers/api/v1/user/app.go index 249f62ad36e3..e97efe087793 100644 --- a/routers/api/v1/user/app.go +++ b/routers/api/v1/user/app.go @@ -49,7 +49,7 @@ func ListAccessTokens(ctx *context.APIContext) { opts := auth_model.ListAccessTokensOptions{UserID: ctx.ContextUser.ID, ListOptions: utils.GetListOptions(ctx)} - tokens, count, err := db.FindAndCount[auth_model.AccessToken](ctx, opts) + tokens, count, err := db.FindAndCount[*auth_model.AccessToken](ctx, opts) if err != nil { ctx.InternalServerError(err) return @@ -164,7 +164,7 @@ func DeleteAccessToken(ctx *context.APIContext) { tokenID, _ := strconv.ParseInt(token, 0, 64) if tokenID == 0 { - tokens, err := db.Find[auth_model.AccessToken](ctx, auth_model.ListAccessTokensOptions{ + tokens, err := db.Find[*auth_model.AccessToken](ctx, auth_model.ListAccessTokensOptions{ Name: token, UserID: ctx.ContextUser.ID, }) diff --git a/routers/web/admin/applications.go b/routers/web/admin/applications.go index b6f7bcd2a5b2..dc40c97b5a5d 100644 --- a/routers/web/admin/applications.go +++ b/routers/web/admin/applications.go @@ -34,7 +34,7 @@ func Applications(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("settings.applications") ctx.Data["PageIsAdminApplications"] = true - apps, err := db.Find[auth.OAuth2Application](ctx, auth.FindOAuth2ApplicationsOptions{ + apps, err := db.Find[*auth.OAuth2Application](ctx, auth.FindOAuth2ApplicationsOptions{ IsGlobal: true, }) if err != nil { diff --git a/routers/web/admin/auths.go b/routers/web/admin/auths.go index 2cf63c646d3d..3b85c7a6dd1e 100644 --- a/routers/web/admin/auths.go +++ b/routers/web/admin/auths.go @@ -49,7 +49,7 @@ func Authentications(ctx *context.Context) { ctx.Data["PageIsAdminAuthentications"] = true var err error - ctx.Data["Sources"], ctx.Data["Total"], err = db.FindAndCount[auth.Source](ctx, auth.FindSourcesOptions{}) + ctx.Data["Sources"], ctx.Data["Total"], err = db.FindAndCount[*auth.Source](ctx, auth.FindSourcesOptions{}) if err != nil { ctx.ServerError("auth.Sources", err) return @@ -284,7 +284,7 @@ func NewAuthSourcePost(ctx *context.Context) { ctx.RenderWithErr(err.Error(), tplAuthNew, form) return } - existing, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{LoginType: auth.SSPI}) + existing, err := db.Find[*auth.Source](ctx, auth.FindSourcesOptions{LoginType: auth.SSPI}) if err != nil || len(existing) > 0 { ctx.Data["Err_Type"] = true ctx.RenderWithErr(ctx.Tr("admin.auths.login_source_of_type_exist"), tplAuthNew, form) diff --git a/routers/web/admin/users.go b/routers/web/admin/users.go index 44c4fa751254..5dd870b55e63 100644 --- a/routers/web/admin/users.go +++ b/routers/web/admin/users.go @@ -93,7 +93,7 @@ func NewUser(ctx *context.Context) { ctx.Data["login_type"] = "0-0" - sources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ + sources, err := db.Find[*auth.Source](ctx, auth.FindSourcesOptions{ IsActive: util.OptionalBoolTrue, }) if err != nil { @@ -114,7 +114,7 @@ func NewUserPost(ctx *context.Context) { ctx.Data["DefaultUserVisibilityMode"] = setting.Service.DefaultUserVisibilityMode ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice() - sources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ + sources, err := db.Find[*auth.Source](ctx, auth.FindSourcesOptions{ IsActive: util.OptionalBoolTrue, }) if err != nil { @@ -237,7 +237,7 @@ func prepareUserInfo(ctx *context.Context) *user_model.User { ctx.Data["LoginSource"] = &auth.Source{} } - sources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{}) + sources, err := db.Find[*auth.Source](ctx, auth.FindSourcesOptions{}) if err != nil { ctx.ServerError("auth.Sources", err) return nil @@ -296,7 +296,7 @@ func ViewUser(ctx *context.Context) { ctx.Data["Emails"] = emails ctx.Data["EmailsTotal"] = len(emails) - orgs, err := db.Find[org_model.Organization](ctx, org_model.FindOrgOptions{ + orgs, err := db.Find[*org_model.Organization](ctx, org_model.FindOrgOptions{ ListOptions: db.ListOptions{ ListAll: true, }, diff --git a/routers/web/org/setting.go b/routers/web/org/setting.go index f0d9259d3fe4..de33e7c31a6b 100644 --- a/routers/web/org/setting.go +++ b/routers/web/org/setting.go @@ -215,7 +215,7 @@ func Webhooks(ctx *context.Context) { ctx.Data["BaseLinkNew"] = ctx.Org.OrgLink + "/settings/hooks" ctx.Data["Description"] = ctx.Tr("org.settings.hooks_desc") - ws, err := db.Find[webhook.Webhook](ctx, webhook.ListWebhookOptions{OwnerID: ctx.Org.Organization.ID}) + ws, err := db.Find[*webhook.Webhook](ctx, webhook.ListWebhookOptions{OwnerID: ctx.Org.Organization.ID}) if err != nil { ctx.ServerError("ListWebhooksByOpts", err) return diff --git a/routers/web/org/setting_oauth2.go b/routers/web/org/setting_oauth2.go index ca4fe09f380c..5dbfbe8f9bab 100644 --- a/routers/web/org/setting_oauth2.go +++ b/routers/web/org/setting_oauth2.go @@ -36,7 +36,7 @@ func Applications(ctx *context.Context) { ctx.Data["PageIsOrgSettings"] = true ctx.Data["PageIsSettingsApplications"] = true - apps, err := db.Find[auth.OAuth2Application](ctx, auth.FindOAuth2ApplicationsOptions{ + apps, err := db.Find[*auth.OAuth2Application](ctx, auth.FindOAuth2ApplicationsOptions{ OwnerID: ctx.Org.Organization.ID, }) if err != nil { diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go index 1cdae32a32fe..d21a3e376d4c 100644 --- a/routers/web/repo/actions/view.go +++ b/routers/web/repo/actions/view.go @@ -538,7 +538,7 @@ func ArtifactsDownloadView(ctx *context_module.Context) { return } - artifacts, err := db.Find[actions_model.ActionArtifact](ctx, actions_model.FindArtifactsOptions{ + artifacts, err := db.Find[*actions_model.ActionArtifact](ctx, actions_model.FindArtifactsOptions{ RunID: run.ID, ArtifactName: artifactName, }) diff --git a/routers/web/repo/setting/deploy_key.go b/routers/web/repo/setting/deploy_key.go index 3d4420006c47..dc73eb5f2fc7 100644 --- a/routers/web/repo/setting/deploy_key.go +++ b/routers/web/repo/setting/deploy_key.go @@ -22,7 +22,7 @@ func DeployKeys(ctx *context.Context) { ctx.Data["PageIsSettingsKeys"] = true ctx.Data["DisableSSH"] = setting.SSH.Disabled - keys, err := db.Find[asymkey_model.DeployKey](ctx, asymkey_model.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID}) + keys, err := db.Find[*asymkey_model.DeployKey](ctx, asymkey_model.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID}) if err != nil { ctx.ServerError("ListDeployKeys", err) return @@ -39,7 +39,7 @@ func DeployKeysPost(ctx *context.Context) { ctx.Data["PageIsSettingsKeys"] = true ctx.Data["DisableSSH"] = setting.SSH.Disabled - keys, err := db.Find[asymkey_model.DeployKey](ctx, asymkey_model.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID}) + keys, err := db.Find[*asymkey_model.DeployKey](ctx, asymkey_model.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID}) if err != nil { ctx.ServerError("ListDeployKeys", err) return diff --git a/routers/web/repo/setting/webhook.go b/routers/web/repo/setting/webhook.go index 5100bf782f06..4bd3f4d51860 100644 --- a/routers/web/repo/setting/webhook.go +++ b/routers/web/repo/setting/webhook.go @@ -47,7 +47,7 @@ func Webhooks(ctx *context.Context) { ctx.Data["BaseLinkNew"] = ctx.Repo.RepoLink + "/settings/hooks" ctx.Data["Description"] = ctx.Tr("repo.settings.hooks_desc", "https://docs.gitea.com/usage/webhooks") - ws, err := db.Find[webhook.Webhook](ctx, webhook.ListWebhookOptions{RepoID: ctx.Repo.Repository.ID}) + ws, err := db.Find[*webhook.Webhook](ctx, webhook.ListWebhookOptions{RepoID: ctx.Repo.Repository.ID}) if err != nil { ctx.ServerError("GetWebhooksByRepoID", err) return diff --git a/routers/web/shared/actions/variables.go b/routers/web/shared/actions/variables.go index 07a057520781..33e29b36eec6 100644 --- a/routers/web/shared/actions/variables.go +++ b/routers/web/shared/actions/variables.go @@ -18,7 +18,7 @@ import ( ) func SetVariablesContext(ctx *context.Context, ownerID, repoID int64) { - variables, err := db.Find[actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{ + variables, err := db.Find[*actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{ OwnerID: ownerID, RepoID: repoID, }) diff --git a/routers/web/shared/secrets/secrets.go b/routers/web/shared/secrets/secrets.go index c805da734ac0..2ffe6be1c023 100644 --- a/routers/web/shared/secrets/secrets.go +++ b/routers/web/shared/secrets/secrets.go @@ -15,7 +15,7 @@ import ( ) func SetSecretsContext(ctx *context.Context, ownerID, repoID int64) { - secrets, err := db.Find[secret_model.Secret](ctx, secret_model.FindSecretsOptions{OwnerID: ownerID, RepoID: repoID}) + secrets, err := db.Find[*secret_model.Secret](ctx, secret_model.FindSecretsOptions{OwnerID: ownerID, RepoID: repoID}) if err != nil { ctx.ServerError("FindSecrets", err) return diff --git a/routers/web/user/home.go b/routers/web/user/home.go index b4fb25dfe0ee..71866a0c85c4 100644 --- a/routers/web/user/home.go +++ b/routers/web/user/home.go @@ -759,7 +759,7 @@ func loadRepoByIDs(ctx *context.Context, ctxUser *user_model.User, issueCountByR // ShowSSHKeys output all the ssh keys of user by uid func ShowSSHKeys(ctx *context.Context) { - keys, err := db.Find[asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ + keys, err := db.Find[*asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ OwnerID: ctx.ContextUser.ID, }) if err != nil { diff --git a/routers/web/user/setting/applications.go b/routers/web/user/setting/applications.go index 69a93dbf03ae..7e0034153bc2 100644 --- a/routers/web/user/setting/applications.go +++ b/routers/web/user/setting/applications.go @@ -89,7 +89,7 @@ func DeleteApplication(ctx *context.Context) { func loadApplicationsData(ctx *context.Context) { ctx.Data["AccessTokenScopePublicOnly"] = auth_model.AccessTokenScopePublicOnly - tokens, err := db.Find[auth_model.AccessToken](ctx, auth_model.ListAccessTokensOptions{UserID: ctx.Doer.ID}) + tokens, err := db.Find[*auth_model.AccessToken](ctx, auth_model.ListAccessTokensOptions{UserID: ctx.Doer.ID}) if err != nil { ctx.ServerError("ListAccessTokens", err) return @@ -98,7 +98,7 @@ func loadApplicationsData(ctx *context.Context) { ctx.Data["EnableOAuth2"] = setting.OAuth2.Enable ctx.Data["IsAdmin"] = ctx.Doer.IsAdmin if setting.OAuth2.Enable { - ctx.Data["Applications"], err = db.Find[auth_model.OAuth2Application](ctx, auth_model.FindOAuth2ApplicationsOptions{ + ctx.Data["Applications"], err = db.Find[*auth_model.OAuth2Application](ctx, auth_model.FindOAuth2ApplicationsOptions{ OwnerID: ctx.Doer.ID, }) if err != nil { diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index d8331fef43f5..1aa25d41cbb6 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -214,7 +214,7 @@ func Organization(ctx *context.Context) { opts.Page = 1 } - orgs, total, err := db.FindAndCount[organization.Organization](ctx, opts) + orgs, total, err := db.FindAndCount[*organization.Organization](ctx, opts) if err != nil { ctx.ServerError("FindOrgs", err) return diff --git a/routers/web/user/setting/security/security.go b/routers/web/user/setting/security/security.go index 2edfaa71a9d7..6fe9ed3d0ed7 100644 --- a/routers/web/user/setting/security/security.go +++ b/routers/web/user/setting/security/security.go @@ -69,14 +69,14 @@ func loadSecurityData(ctx *context.Context) { } ctx.Data["WebAuthnCredentials"] = credentials - tokens, err := db.Find[auth_model.AccessToken](ctx, auth_model.ListAccessTokensOptions{UserID: ctx.Doer.ID}) + tokens, err := db.Find[*auth_model.AccessToken](ctx, auth_model.ListAccessTokensOptions{UserID: ctx.Doer.ID}) if err != nil { ctx.ServerError("ListAccessTokens", err) return } ctx.Data["Tokens"] = tokens - accountLinks, err := db.Find[user_model.ExternalLoginUser](ctx, user_model.FindExternalUserOptions{ + accountLinks, err := db.Find[*user_model.ExternalLoginUser](ctx, user_model.FindExternalUserOptions{ UserID: ctx.Doer.ID, OrderBy: "login_source_id DESC", }) diff --git a/routers/web/user/setting/webhooks.go b/routers/web/user/setting/webhooks.go index 679b72e50119..e3b0131fd2dc 100644 --- a/routers/web/user/setting/webhooks.go +++ b/routers/web/user/setting/webhooks.go @@ -25,7 +25,7 @@ func Webhooks(ctx *context.Context) { ctx.Data["BaseLinkNew"] = setting.AppSubURL + "/user/settings/hooks" ctx.Data["Description"] = ctx.Tr("settings.hooks.desc") - ws, err := db.Find[webhook.Webhook](ctx, webhook.ListWebhookOptions{OwnerID: ctx.Doer.ID}) + ws, err := db.Find[*webhook.Webhook](ctx, webhook.ListWebhookOptions{OwnerID: ctx.Doer.ID}) if err != nil { ctx.ServerError("ListWebhooksByOpts", err) return diff --git a/services/asymkey/ssh_key_test.go b/services/asymkey/ssh_key_test.go index fbd5d13ab2d2..e7e64f62bcf1 100644 --- a/services/asymkey/ssh_key_test.go +++ b/services/asymkey/ssh_key_test.go @@ -67,7 +67,7 @@ ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ib for i, kase := range testCases { s.ID = int64(i) + 20 asymkey_model.AddPublicKeysBySource(db.DefaultContext, user, s, []string{kase.keyString}) - keys, err := db.Find[asymkey_model.PublicKey](db.DefaultContext, asymkey_model.FindPublicKeyOptions{ + keys, err := db.Find[*asymkey_model.PublicKey](db.DefaultContext, asymkey_model.FindPublicKeyOptions{ OwnerID: user.ID, LoginSourceID: s.ID, }) diff --git a/services/auth/source/oauth2/init.go b/services/auth/source/oauth2/init.go index 3ad6e307f106..6795eecd880a 100644 --- a/services/auth/source/oauth2/init.go +++ b/services/auth/source/oauth2/init.go @@ -65,7 +65,7 @@ func ResetOAuth2(ctx context.Context) error { // initOAuth2Sources is used to load and register all active OAuth2 providers func initOAuth2Sources(ctx context.Context) error { - authSources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ + authSources, err := db.Find[*auth.Source](ctx, auth.FindSourcesOptions{ IsActive: util.OptionalBoolTrue, LoginType: auth.OAuth2, }) diff --git a/services/auth/sspi.go b/services/auth/sspi.go index 57ba0462c573..59144e6350e3 100644 --- a/services/auth/sspi.go +++ b/services/auth/sspi.go @@ -131,7 +131,7 @@ func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore, // getConfig retrieves the SSPI configuration from login sources func (s *SSPI) getConfig(ctx context.Context) (*sspi.Source, error) { - sources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ + sources, err := db.Find[*auth.Source](ctx, auth.FindSourcesOptions{ IsActive: util.OptionalBoolTrue, LoginType: auth.SSPI, }) diff --git a/services/auth/sync.go b/services/auth/sync.go index 7562ac812bd3..378e385f4064 100644 --- a/services/auth/sync.go +++ b/services/auth/sync.go @@ -15,7 +15,7 @@ import ( func SyncExternalUsers(ctx context.Context, updateExisting bool) error { log.Trace("Doing: SyncExternalUsers") - ls, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{}) + ls, err := db.Find[*auth.Source](ctx, auth.FindSourcesOptions{}) if err != nil { log.Error("SyncExternalUsers: %v", err) return err diff --git a/services/migrations/update.go b/services/migrations/update.go index 4a49206f82e2..3b65ef9aa4a8 100644 --- a/services/migrations/update.go +++ b/services/migrations/update.go @@ -44,7 +44,7 @@ func updateMigrationPosterIDByGitService(ctx context.Context, tp structs.GitServ default: } - users, err := db.Find[user_model.ExternalLoginUser](ctx, user_model.FindExternalUserOptions{ + users, err := db.Find[*user_model.ExternalLoginUser](ctx, user_model.FindExternalUserOptions{ ListOptions: db.ListOptions{ PageSize: batchSize, Page: page, diff --git a/services/repository/delete.go b/services/repository/delete.go index 08d6800ee766..2c20252ee8f6 100644 --- a/services/repository/delete.go +++ b/services/repository/delete.go @@ -54,13 +54,13 @@ func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID } // Query the action tasks of this repo, they will be needed after they have been deleted to remove the logs - tasks, err := db.Find[actions_model.ActionTask](ctx, actions_model.FindTaskOptions{RepoID: repoID}) + tasks, err := db.Find[*actions_model.ActionTask](ctx, actions_model.FindTaskOptions{RepoID: repoID}) if err != nil { return fmt.Errorf("find actions tasks of repo %v: %w", repoID, err) } // Query the artifacts of this repo, they will be needed after they have been deleted to remove artifacts files in ObjectStorage - artifacts, err := db.Find[actions_model.ActionArtifact](ctx, actions_model.FindArtifactsOptions{RepoID: repoID}) + artifacts, err := db.Find[*actions_model.ActionArtifact](ctx, actions_model.FindArtifactsOptions{RepoID: repoID}) if err != nil { return fmt.Errorf("list actions artifacts of repo %v: %w", repoID, err) } @@ -75,7 +75,7 @@ func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID } // Delete Deploy Keys - deployKeys, err := db.Find[asymkey_model.DeployKey](ctx, asymkey_model.ListDeployKeysOptions{RepoID: repoID}) + deployKeys, err := db.Find[*asymkey_model.DeployKey](ctx, asymkey_model.ListDeployKeysOptions{RepoID: repoID}) if err != nil { return fmt.Errorf("listDeployKeys: %w", err) } diff --git a/services/repository/hooks.go b/services/repository/hooks.go index 7b82f36b43fd..b841acd3f999 100644 --- a/services/repository/hooks.go +++ b/services/repository/hooks.go @@ -85,7 +85,7 @@ func GenerateGitHooks(ctx context.Context, templateRepo, generateRepo *repo_mode // GenerateWebhooks generates webhooks from a template repository func GenerateWebhooks(ctx context.Context, templateRepo, generateRepo *repo_model.Repository) error { - templateWebhooks, err := db.Find[webhook.Webhook](ctx, webhook.ListWebhookOptions{RepoID: templateRepo.ID}) + templateWebhooks, err := db.Find[*webhook.Webhook](ctx, webhook.ListWebhookOptions{RepoID: templateRepo.ID}) if err != nil { return err } diff --git a/tests/integration/auth_ldap_test.go b/tests/integration/auth_ldap_test.go index 1148b3ad3993..30a4ba7e51cf 100644 --- a/tests/integration/auth_ldap_test.go +++ b/tests/integration/auth_ldap_test.go @@ -414,7 +414,7 @@ func TestLDAPGroupTeamSyncAddMember(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ Name: gitLDAPUser.UserName, }) - usersOrgs, err := db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{ + usersOrgs, err := db.Find[*organization.Organization](db.DefaultContext, organization.FindOrgOptions{ UserID: user.ID, IncludePrivate: true, }) diff --git a/tests/integration/org_count_test.go b/tests/integration/org_count_test.go index 6386f53f0599..c02e2292dadb 100644 --- a/tests/integration/org_count_test.go +++ b/tests/integration/org_count_test.go @@ -118,7 +118,7 @@ func doCheckOrgCounts(username string, orgCounts map[string]int, strict bool, ca Name: username, }) - orgs, err := db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{ + orgs, err := db.Find[*organization.Organization](db.DefaultContext, organization.FindOrgOptions{ UserID: user.ID, IncludePrivate: true, }) From 395c8aa68d4dcf7741bdbd1e61d9a8aaa75b19b2 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 24 Nov 2023 00:06:00 +0800 Subject: [PATCH 19/21] Follow @wxiaoguang's suggestion --- cmd/admin_auth.go | 2 +- models/actions/run.go | 4 ++-- models/actions/schedule_spec_list.go | 2 +- models/activities/notification.go | 2 +- models/activities/notification_test.go | 20 +++++++++---------- models/asymkey/ssh_key.go | 2 +- models/asymkey/ssh_key_commit_verification.go | 2 +- models/auth/access_token_test.go | 6 +++--- models/db/list.go | 8 ++++---- models/db/list_test.go | 4 ++-- models/organization/org_test.go | 4 ++-- models/project/project_test.go | 6 +++--- models/webhook/webhook_test.go | 8 ++++---- routers/api/actions/artifacts.go | 4 ++-- routers/api/actions/artifacts_chunks.go | 2 +- routers/api/actions/runner/utils.go | 10 +++++----- routers/api/v1/notify/repo.go | 4 ++-- routers/api/v1/notify/user.go | 4 ++-- routers/api/v1/org/action.go | 2 +- routers/api/v1/org/org.go | 4 ++-- routers/api/v1/repo/hook.go | 2 +- routers/api/v1/repo/key.go | 2 +- routers/api/v1/user/app.go | 6 +++--- routers/api/v1/user/key.go | 4 ++-- routers/api/v1/utils/hook.go | 2 +- routers/web/admin/applications.go | 2 +- routers/web/admin/auths.go | 4 ++-- routers/web/admin/users.go | 8 ++++---- routers/web/org/projects.go | 2 +- routers/web/org/setting.go | 2 +- routers/web/org/setting_oauth2.go | 2 +- routers/web/repo/actions/actions.go | 4 ++-- routers/web/repo/actions/view.go | 2 +- routers/web/repo/issue.go | 8 ++++---- routers/web/repo/projects.go | 2 +- routers/web/repo/setting/deploy_key.go | 4 ++-- routers/web/repo/setting/webhook.go | 2 +- routers/web/shared/actions/runners.go | 4 ++-- routers/web/shared/actions/variables.go | 2 +- routers/web/shared/secrets/secrets.go | 2 +- routers/web/shared/user/header.go | 2 +- routers/web/user/home.go | 2 +- routers/web/user/notification.go | 4 ++-- routers/web/user/setting/applications.go | 4 ++-- routers/web/user/setting/keys.go | 2 +- routers/web/user/setting/profile.go | 2 +- routers/web/user/setting/security/security.go | 6 +++--- routers/web/user/setting/webhooks.go | 2 +- services/actions/clear_tasks.go | 4 ++-- services/actions/job_emitter.go | 2 +- services/actions/notifier_helper.go | 2 +- services/asymkey/ssh_key_test.go | 2 +- services/auth/httpsign.go | 2 +- services/auth/signin.go | 2 +- services/auth/source/oauth2/init.go | 2 +- services/auth/source/oauth2/providers.go | 2 +- services/auth/sspi.go | 2 +- services/auth/sync.go | 2 +- services/migrations/update.go | 2 +- services/pull/review.go | 2 +- services/repository/delete.go | 6 +++--- services/repository/hooks.go | 2 +- services/secrets/secrets.go | 6 +++--- services/user/user.go | 2 +- services/webhook/webhook.go | 4 ++-- tests/integration/auth_ldap_test.go | 2 +- tests/integration/org_count_test.go | 2 +- 67 files changed, 120 insertions(+), 120 deletions(-) diff --git a/cmd/admin_auth.go b/cmd/admin_auth.go index f4a89212c6f9..ec92e342d4d4 100644 --- a/cmd/admin_auth.go +++ b/cmd/admin_auth.go @@ -63,7 +63,7 @@ func runListAuth(c *cli.Context) error { return err } - authSources, err := db.Find[*auth_model.Source](ctx, auth_model.FindSourcesOptions{}) + authSources, err := db.Find[auth_model.Source](ctx, auth_model.FindSourcesOptions{}) if err != nil { return err } diff --git a/models/actions/run.go b/models/actions/run.go index 4367f603667c..4656aa22a293 100644 --- a/models/actions/run.go +++ b/models/actions/run.go @@ -170,7 +170,7 @@ func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) err // CancelRunningJobs cancels all running and waiting jobs associated with a specific workflow. func CancelRunningJobs(ctx context.Context, repoID int64, ref, workflowID string) error { // Find all runs in the specified repository, reference, and workflow with statuses 'Running' or 'Waiting'. - runs, total, err := db.FindAndCount[*ActionRun](ctx, FindRunOptions{ + runs, total, err := db.FindAndCount[ActionRun](ctx, FindRunOptions{ RepoID: repoID, Ref: ref, WorkflowID: workflowID, @@ -188,7 +188,7 @@ func CancelRunningJobs(ctx context.Context, repoID int64, ref, workflowID string // Iterate over each found run and cancel its associated jobs. for _, run := range runs { // Find all jobs associated with the current run. - jobs, err := db.Find[*ActionRunJob](ctx, FindRunJobOptions{ + jobs, err := db.Find[ActionRunJob](ctx, FindRunJobOptions{ RunID: run.ID, }) if err != nil { diff --git a/models/actions/schedule_spec_list.go b/models/actions/schedule_spec_list.go index 5aedc8364271..e9ae268a6e4a 100644 --- a/models/actions/schedule_spec_list.go +++ b/models/actions/schedule_spec_list.go @@ -89,7 +89,7 @@ func (opts FindSpecOptions) ToOrders() string { } func FindSpecs(ctx context.Context, opts FindSpecOptions) (SpecList, int64, error) { - specs, total, err := db.FindAndCount[*ActionScheduleSpec](ctx, opts) + specs, total, err := db.FindAndCount[ActionScheduleSpec](ctx, opts) if err != nil { return nil, 0, err } diff --git a/models/activities/notification.go b/models/activities/notification.go index f2abe7bdce26..5e313e50e3e4 100644 --- a/models/activities/notification.go +++ b/models/activities/notification.go @@ -131,7 +131,7 @@ func CreateOrUpdateIssueNotifications(ctx context.Context, issueID, commentID, n func createOrUpdateIssueNotifications(ctx context.Context, issueID, commentID, notificationAuthorID, receiverID int64) error { // init var toNotify container.Set[int64] - notifications, err := db.Find[*Notification](ctx, FindNotificationOptions{ + notifications, err := db.Find[Notification](ctx, FindNotificationOptions{ IssueID: issueID, }) if err != nil { diff --git a/models/activities/notification_test.go b/models/activities/notification_test.go index 1b66d6fd2f57..52f0eacba12c 100644 --- a/models/activities/notification_test.go +++ b/models/activities/notification_test.go @@ -34,7 +34,7 @@ func TestCreateOrUpdateIssueNotifications(t *testing.T) { func TestNotificationsForUser(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - notfs, err := db.Find[*activities_model.Notification](db.DefaultContext, activities_model.FindNotificationOptions{ + notfs, err := db.Find[activities_model.Notification](db.DefaultContext, activities_model.FindNotificationOptions{ UserID: user.ID, Status: []activities_model.NotificationStatus{ activities_model.NotificationStatusRead, @@ -61,6 +61,15 @@ func TestNotification_GetRepo(t *testing.T) { assert.EqualValues(t, notf.RepoID, repo.ID) } +func TestNotification_GetIssue(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{RepoID: 1}) + issue, err := notf.GetIssue(db.DefaultContext) + assert.NoError(t, err) + assert.Equal(t, issue, notf.Issue) + assert.EqualValues(t, notf.IssueID, issue.ID) +} + func TestGetNotificationCount(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) @@ -83,15 +92,6 @@ func TestGetNotificationCount(t *testing.T) { assert.EqualValues(t, 1, cnt) } -func TestNotification_GetIssue(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{RepoID: 1}) - issue, err := notf.GetIssue(db.DefaultContext) - assert.NoError(t, err) - assert.Equal(t, issue, notf.Issue) - assert.EqualValues(t, notf.IssueID, issue.ID) -} - func TestSetNotificationStatus(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) diff --git a/models/asymkey/ssh_key.go b/models/asymkey/ssh_key.go index 177e99227a64..552f2ffd69e6 100644 --- a/models/asymkey/ssh_key.go +++ b/models/asymkey/ssh_key.go @@ -382,7 +382,7 @@ func SynchronizePublicKeys(ctx context.Context, usr *user_model.User, s *auth.So // Get Public Keys from DB with current LDAP source var giteaKeys []string - keys, err := db.Find[*PublicKey](ctx, FindPublicKeyOptions{ + keys, err := db.Find[PublicKey](ctx, FindPublicKeyOptions{ OwnerID: usr.ID, LoginSourceID: s.ID, }) diff --git a/models/asymkey/ssh_key_commit_verification.go b/models/asymkey/ssh_key_commit_verification.go index 1c450221caf3..27c6df35786a 100644 --- a/models/asymkey/ssh_key_commit_verification.go +++ b/models/asymkey/ssh_key_commit_verification.go @@ -21,7 +21,7 @@ import ( func ParseCommitWithSSHSignature(ctx context.Context, c *git.Commit, committer *user_model.User) *CommitVerification { // Now try to associate the signature with the committer, if present if committer.ID != 0 { - keys, err := db.Find[*PublicKey](ctx, FindPublicKeyOptions{ + keys, err := db.Find[PublicKey](ctx, FindPublicKeyOptions{ OwnerID: committer.ID, NotKeytype: KeyTypePrincipal, }) diff --git a/models/auth/access_token_test.go b/models/auth/access_token_test.go index 9f90511fa948..4360f1a21433 100644 --- a/models/auth/access_token_test.go +++ b/models/auth/access_token_test.go @@ -85,7 +85,7 @@ func TestGetAccessTokenBySHA(t *testing.T) { func TestListAccessTokens(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - tokens, err := db.Find[*auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 1}) + tokens, err := db.Find[auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 1}) assert.NoError(t, err) if assert.Len(t, tokens, 2) { assert.Equal(t, int64(1), tokens[0].UID) @@ -94,14 +94,14 @@ func TestListAccessTokens(t *testing.T) { assert.Contains(t, []string{tokens[0].Name, tokens[1].Name}, "Token B") } - tokens, err = db.Find[*auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 2}) + tokens, err = db.Find[auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 2}) assert.NoError(t, err) if assert.Len(t, tokens, 1) { assert.Equal(t, int64(2), tokens[0].UID) assert.Equal(t, "Token A", tokens[0].Name) } - tokens, err = db.Find[*auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 100}) + tokens, err = db.Find[auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 100}) assert.NoError(t, err) assert.Empty(t, tokens) } diff --git a/models/db/list.go b/models/db/list.go index a9c1e53cac67..b2f932e89bf8 100644 --- a/models/db/list.go +++ b/models/db/list.go @@ -153,7 +153,7 @@ type FindOptionsOrder interface { } // Find represents a common find function which accept an options interface -func Find[T any](ctx context.Context, opts FindOptions) ([]T, error) { +func Find[T any](ctx context.Context, opts FindOptions) ([]*T, error) { sess := GetEngine(ctx).Where(opts.ToConds()) page, pageSize := opts.GetPage(), opts.GetPageSize() if !opts.IsListAll() && pageSize > 0 && page >= 1 { @@ -167,7 +167,7 @@ func Find[T any](ctx context.Context, opts FindOptions) ([]T, error) { if pageSize > 0 { findPageSize = pageSize } - objects := make([]T, 0, findPageSize) + objects := make([]*T, 0, findPageSize) if err := sess.Find(&objects); err != nil { return nil, err } @@ -181,7 +181,7 @@ func Count[T any](ctx context.Context, opts FindOptions) (int64, error) { } // FindAndCount represents a common findandcount function which accept an options interface -func FindAndCount[T any](ctx context.Context, opts FindOptions) ([]T, int64, error) { +func FindAndCount[T any](ctx context.Context, opts FindOptions) ([]*T, int64, error) { sess := GetEngine(ctx).Where(opts.ToConds()) page, pageSize := opts.GetPage(), opts.GetPageSize() if !opts.IsListAll() && pageSize > 0 && page >= 1 { @@ -195,7 +195,7 @@ func FindAndCount[T any](ctx context.Context, opts FindOptions) ([]T, int64, err if pageSize > 0 { findPageSize = pageSize } - objects := make([]T, 0, findPageSize) + objects := make([]*T, 0, findPageSize) cnt, err := sess.FindAndCount(&objects) if err != nil { return nil, 0, err diff --git a/models/db/list_test.go b/models/db/list_test.go index 776f7981c1c2..45194611f8a4 100644 --- a/models/db/list_test.go +++ b/models/db/list_test.go @@ -37,7 +37,7 @@ func TestFind(t *testing.T) { assert.NotEmpty(t, repoUnitCount) opts := mockListOptions{} - repoUnits, err := db.Find[*repo_model.RepoUnit](db.DefaultContext, opts) + repoUnits, err := db.Find[repo_model.RepoUnit](db.DefaultContext, opts) assert.NoError(t, err) assert.Len(t, repoUnits, repoUnitCount) @@ -45,7 +45,7 @@ func TestFind(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, repoUnitCount, cnt) - repoUnits, newCnt, err := db.FindAndCount[*repo_model.RepoUnit](db.DefaultContext, opts) + repoUnits, newCnt, err := db.FindAndCount[repo_model.RepoUnit](db.DefaultContext, opts) assert.NoError(t, err) assert.EqualValues(t, cnt, newCnt) assert.Len(t, repoUnits, repoUnitCount) diff --git a/models/organization/org_test.go b/models/organization/org_test.go index 4514ae85858c..5e40dd41907b 100644 --- a/models/organization/org_test.go +++ b/models/organization/org_test.go @@ -183,7 +183,7 @@ func TestIsPublicMembership(t *testing.T) { func TestFindOrgs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - orgs, err := db.Find[*organization.Organization](db.DefaultContext, organization.FindOrgOptions{ + orgs, err := db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{ UserID: 4, IncludePrivate: true, }) @@ -192,7 +192,7 @@ func TestFindOrgs(t *testing.T) { assert.EqualValues(t, 3, orgs[0].ID) } - orgs, err = db.Find[*organization.Organization](db.DefaultContext, organization.FindOrgOptions{ + orgs, err = db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{ UserID: 4, IncludePrivate: false, }) diff --git a/models/project/project_test.go b/models/project/project_test.go index da4c3b2531e5..7a37c1faf290 100644 --- a/models/project/project_test.go +++ b/models/project/project_test.go @@ -34,13 +34,13 @@ func TestIsProjectTypeValid(t *testing.T) { func TestGetProjects(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - projects, err := db.Find[*Project](db.DefaultContext, SearchOptions{RepoID: 1}) + projects, err := db.Find[Project](db.DefaultContext, SearchOptions{RepoID: 1}) assert.NoError(t, err) // 1 value for this repo exists in the fixtures assert.Len(t, projects, 1) - projects, err = db.Find[*Project](db.DefaultContext, SearchOptions{RepoID: 3}) + projects, err = db.Find[Project](db.DefaultContext, SearchOptions{RepoID: 3}) assert.NoError(t, err) // 1 value for this repo exists in the fixtures @@ -109,7 +109,7 @@ func TestProjectsSort(t *testing.T) { } for _, tt := range tests { - projects, count, err := db.FindAndCount[*Project](db.DefaultContext, SearchOptions{ + projects, count, err := db.FindAndCount[Project](db.DefaultContext, SearchOptions{ OrderBy: GetSearchOrderByBySortType(tt.sortType), }) assert.NoError(t, err) diff --git a/models/webhook/webhook_test.go b/models/webhook/webhook_test.go index 4c5eecc97140..694fd7a873f3 100644 --- a/models/webhook/webhook_test.go +++ b/models/webhook/webhook_test.go @@ -123,7 +123,7 @@ func TestGetWebhookByOwnerID(t *testing.T) { func TestGetActiveWebhooksByRepoID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hooks, err := db.Find[*Webhook](db.DefaultContext, ListWebhookOptions{RepoID: 1, IsActive: util.OptionalBoolTrue}) + hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{RepoID: 1, IsActive: util.OptionalBoolTrue}) assert.NoError(t, err) if assert.Len(t, hooks, 1) { assert.Equal(t, int64(1), hooks[0].ID) @@ -133,7 +133,7 @@ func TestGetActiveWebhooksByRepoID(t *testing.T) { func TestGetWebhooksByRepoID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hooks, err := db.Find[*Webhook](db.DefaultContext, ListWebhookOptions{RepoID: 1}) + hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{RepoID: 1}) assert.NoError(t, err) if assert.Len(t, hooks, 2) { assert.Equal(t, int64(1), hooks[0].ID) @@ -143,7 +143,7 @@ func TestGetWebhooksByRepoID(t *testing.T) { func TestGetActiveWebhooksByOwnerID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hooks, err := db.Find[*Webhook](db.DefaultContext, ListWebhookOptions{OwnerID: 3, IsActive: util.OptionalBoolTrue}) + hooks, err := db.Find[Webhook](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) @@ -153,7 +153,7 @@ func TestGetActiveWebhooksByOwnerID(t *testing.T) { func TestGetWebhooksByOwnerID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hooks, err := db.Find[*Webhook](db.DefaultContext, ListWebhookOptions{OwnerID: 3}) + hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{OwnerID: 3}) assert.NoError(t, err) if assert.Len(t, hooks, 1) { assert.Equal(t, int64(3), hooks[0].ID) diff --git a/routers/api/actions/artifacts.go b/routers/api/actions/artifacts.go index 19d788519a71..5411237103a0 100644 --- a/routers/api/actions/artifacts.go +++ b/routers/api/actions/artifacts.go @@ -315,7 +315,7 @@ func (ar artifactRoutes) listArtifacts(ctx *ArtifactContext) { return } - artifacts, err := db.Find[*actions.ActionArtifact](ctx, actions.FindArtifactsOptions{RunID: runID}) + artifacts, err := db.Find[actions.ActionArtifact](ctx, actions.FindArtifactsOptions{RunID: runID}) if err != nil { log.Error("Error getting artifacts: %v", err) ctx.Error(http.StatusInternalServerError, err.Error()) @@ -377,7 +377,7 @@ func (ar artifactRoutes) getDownloadArtifactURL(ctx *ArtifactContext) { return } - artifacts, err := db.Find[*actions.ActionArtifact](ctx, actions.FindArtifactsOptions{ + artifacts, err := db.Find[actions.ActionArtifact](ctx, actions.FindArtifactsOptions{ RunID: runID, ArtifactName: itemPath, }) diff --git a/routers/api/actions/artifacts_chunks.go b/routers/api/actions/artifacts_chunks.go index 0cbcbb383685..c7ab70afa950 100644 --- a/routers/api/actions/artifacts_chunks.go +++ b/routers/api/actions/artifacts_chunks.go @@ -87,7 +87,7 @@ func listChunksByRunID(st storage.ObjectStorage, runID int64) (map[int64][]*chun func mergeChunksForRun(ctx *ArtifactContext, st storage.ObjectStorage, runID int64, artifactName string) error { // read all db artifacts by name - artifacts, err := db.Find[*actions.ActionArtifact](ctx, actions.FindArtifactsOptions{ + artifacts, err := db.Find[actions.ActionArtifact](ctx, actions.FindArtifactsOptions{ RunID: runID, ArtifactName: artifactName, }) diff --git a/routers/api/actions/runner/utils.go b/routers/api/actions/runner/utils.go index ed95ae52723b..bf913f2c0578 100644 --- a/routers/api/actions/runner/utils.go +++ b/routers/api/actions/runner/utils.go @@ -68,12 +68,12 @@ func getSecretsOfTask(ctx context.Context, task *actions_model.ActionTask) map[s return secrets } - ownerSecrets, err := db.Find[*secret_model.Secret](ctx, secret_model.FindSecretsOptions{OwnerID: task.Job.Run.Repo.OwnerID}) + ownerSecrets, err := db.Find[secret_model.Secret](ctx, secret_model.FindSecretsOptions{OwnerID: task.Job.Run.Repo.OwnerID}) if err != nil { log.Error("find secrets of owner %v: %v", task.Job.Run.Repo.OwnerID, err) // go on } - repoSecrets, err := db.Find[*secret_model.Secret](ctx, secret_model.FindSecretsOptions{RepoID: task.Job.Run.RepoID}) + repoSecrets, err := db.Find[secret_model.Secret](ctx, secret_model.FindSecretsOptions{RepoID: task.Job.Run.RepoID}) if err != nil { log.Error("find secrets of repo %v: %v", task.Job.Run.RepoID, err) // go on @@ -95,13 +95,13 @@ func getVariablesOfTask(ctx context.Context, task *actions_model.ActionTask) map variables := map[string]string{} // Org / User level - ownerVariables, err := db.Find[*actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{OwnerID: task.Job.Run.Repo.OwnerID}) + ownerVariables, err := db.Find[actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{OwnerID: task.Job.Run.Repo.OwnerID}) if err != nil { log.Error("find variables of org: %d, error: %v", task.Job.Run.Repo.OwnerID, err) } // Repo level - repoVariables, err := db.Find[*actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{RepoID: task.Job.Run.RepoID}) + repoVariables, err := db.Find[actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{RepoID: task.Job.Run.RepoID}) if err != nil { log.Error("find variables of repo: %d, error: %v", task.Job.Run.RepoID, err) } @@ -201,7 +201,7 @@ func findTaskNeeds(ctx context.Context, task *actions_model.ActionTask) (map[str } needs := container.SetOf(task.Job.Needs...) - jobs, err := db.Find[*actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: task.Job.RunID}) + jobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: task.Job.RunID}) if err != nil { return nil, fmt.Errorf("FindRunJobs: %w", err) } diff --git a/routers/api/v1/notify/repo.go b/routers/api/v1/notify/repo.go index 6a2ba7e76c90..55ca6ad1fd57 100644 --- a/routers/api/v1/notify/repo.go +++ b/routers/api/v1/notify/repo.go @@ -115,7 +115,7 @@ func ListRepoNotifications(ctx *context.APIContext) { return } - nl, err := db.Find[*activities_model.Notification](ctx, opts) + nl, err := db.Find[activities_model.Notification](ctx, opts) if err != nil { ctx.InternalServerError(err) return @@ -203,7 +203,7 @@ func ReadRepoNotifications(ctx *context.APIContext) { opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread"}) log.Error("%v", opts.Status) } - nl, err := db.Find[*activities_model.Notification](ctx, opts) + nl, err := db.Find[activities_model.Notification](ctx, opts) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/notify/user.go b/routers/api/v1/notify/user.go index 9432e7d8d1d1..4abdfb2e925a 100644 --- a/routers/api/v1/notify/user.go +++ b/routers/api/v1/notify/user.go @@ -75,7 +75,7 @@ func ListNotifications(ctx *context.APIContext) { return } - nl, err := db.Find[*activities_model.Notification](ctx, opts) + nl, err := db.Find[activities_model.Notification](ctx, opts) if err != nil { ctx.InternalServerError(err) return @@ -148,7 +148,7 @@ func ReadNotifications(ctx *context.APIContext) { statuses := ctx.FormStrings("status-types") opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread"}) } - nl, err := db.Find[*activities_model.Notification](ctx, opts) + nl, err := db.Find[activities_model.Notification](ctx, opts) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/org/action.go b/routers/api/v1/org/action.go index 1223ffcc002b..ddc74d865b18 100644 --- a/routers/api/v1/org/action.go +++ b/routers/api/v1/org/action.go @@ -49,7 +49,7 @@ func ListActionsSecrets(ctx *context.APIContext) { ListOptions: utils.GetListOptions(ctx), } - secrets, count, err := db.FindAndCount[*secret_model.Secret](ctx, opts) + secrets, count, err := db.FindAndCount[secret_model.Secret](ctx, opts) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index 8b66bc94bfda..d5fac1e5b8cf 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -30,9 +30,9 @@ func listUserOrgs(ctx *context.APIContext, u *user_model.User) { UserID: u.ID, IncludePrivate: showPrivate, } - orgs, maxResults, err := db.FindAndCount[*organization.Organization](ctx, opts) + orgs, maxResults, err := db.FindAndCount[organization.Organization](ctx, opts) if err != nil { - ctx.Error(http.StatusInternalServerError, "db.FindAndCount[*organization.Organization]", err) + ctx.Error(http.StatusInternalServerError, "db.FindAndCount[organization.Organization]", err) return } diff --git a/routers/api/v1/repo/hook.go b/routers/api/v1/repo/hook.go index 1e4072056223..8859e3ae2369 100644 --- a/routers/api/v1/repo/hook.go +++ b/routers/api/v1/repo/hook.go @@ -59,7 +59,7 @@ func ListHooks(ctx *context.APIContext) { RepoID: ctx.Repo.Repository.ID, } - hooks, count, err := db.FindAndCount[*webhook.Webhook](ctx, opts) + hooks, count, err := db.FindAndCount[webhook.Webhook](ctx, opts) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/repo/key.go b/routers/api/v1/repo/key.go index 400eee5fe9b8..3dc5a60d1c65 100644 --- a/routers/api/v1/repo/key.go +++ b/routers/api/v1/repo/key.go @@ -90,7 +90,7 @@ func ListDeployKeys(ctx *context.APIContext) { Fingerprint: ctx.FormString("fingerprint"), } - keys, count, err := db.FindAndCount[*asymkey_model.DeployKey](ctx, opts) + keys, count, err := db.FindAndCount[asymkey_model.DeployKey](ctx, opts) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/user/app.go b/routers/api/v1/user/app.go index e97efe087793..edbc1d17b464 100644 --- a/routers/api/v1/user/app.go +++ b/routers/api/v1/user/app.go @@ -49,7 +49,7 @@ func ListAccessTokens(ctx *context.APIContext) { opts := auth_model.ListAccessTokensOptions{UserID: ctx.ContextUser.ID, ListOptions: utils.GetListOptions(ctx)} - tokens, count, err := db.FindAndCount[*auth_model.AccessToken](ctx, opts) + tokens, count, err := db.FindAndCount[auth_model.AccessToken](ctx, opts) if err != nil { ctx.InternalServerError(err) return @@ -164,7 +164,7 @@ func DeleteAccessToken(ctx *context.APIContext) { tokenID, _ := strconv.ParseInt(token, 0, 64) if tokenID == 0 { - tokens, err := db.Find[*auth_model.AccessToken](ctx, auth_model.ListAccessTokensOptions{ + tokens, err := db.Find[auth_model.AccessToken](ctx, auth_model.ListAccessTokensOptions{ Name: token, UserID: ctx.ContextUser.ID, }) @@ -262,7 +262,7 @@ func ListOauth2Applications(ctx *context.APIContext) { // "200": // "$ref": "#/responses/OAuth2ApplicationList" - apps, total, err := db.FindAndCount[*auth_model.OAuth2Application](ctx, auth_model.FindOAuth2ApplicationsOptions{ + apps, total, err := db.FindAndCount[auth_model.OAuth2Application](ctx, auth_model.FindOAuth2ApplicationsOptions{ ListOptions: utils.GetListOptions(ctx), OwnerID: ctx.Doer.ID, }) diff --git a/routers/api/v1/user/key.go b/routers/api/v1/user/key.go index 7fa5668a6a1a..dd185aa7d623 100644 --- a/routers/api/v1/user/key.go +++ b/routers/api/v1/user/key.go @@ -63,7 +63,7 @@ func listPublicKeys(ctx *context.APIContext, user *user_model.User) { // Restrict to provided uid userID = user.ID } - keys, err = db.Find[*asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ + keys, err = db.Find[asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ OwnerID: userID, Fingerprint: fingerprint, }) @@ -71,7 +71,7 @@ func listPublicKeys(ctx *context.APIContext, user *user_model.User) { } else { var total int64 // Use ListPublicKeys - keys, total, err = db.FindAndCount[*asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ + keys, total, err = db.FindAndCount[asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ ListOptions: utils.GetListOptions(ctx), OwnerID: user.ID, NotKeytype: asymkey_model.KeyTypePrincipal, diff --git a/routers/api/v1/utils/hook.go b/routers/api/v1/utils/hook.go index a25a922197d1..1207be25accb 100644 --- a/routers/api/v1/utils/hook.go +++ b/routers/api/v1/utils/hook.go @@ -27,7 +27,7 @@ func ListOwnerHooks(ctx *context.APIContext, owner *user_model.User) { OwnerID: owner.ID, } - hooks, count, err := db.FindAndCount[*webhook.Webhook](ctx, opts) + hooks, count, err := db.FindAndCount[webhook.Webhook](ctx, opts) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/web/admin/applications.go b/routers/web/admin/applications.go index dc40c97b5a5d..b6f7bcd2a5b2 100644 --- a/routers/web/admin/applications.go +++ b/routers/web/admin/applications.go @@ -34,7 +34,7 @@ func Applications(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("settings.applications") ctx.Data["PageIsAdminApplications"] = true - apps, err := db.Find[*auth.OAuth2Application](ctx, auth.FindOAuth2ApplicationsOptions{ + apps, err := db.Find[auth.OAuth2Application](ctx, auth.FindOAuth2ApplicationsOptions{ IsGlobal: true, }) if err != nil { diff --git a/routers/web/admin/auths.go b/routers/web/admin/auths.go index 3b85c7a6dd1e..2cf63c646d3d 100644 --- a/routers/web/admin/auths.go +++ b/routers/web/admin/auths.go @@ -49,7 +49,7 @@ func Authentications(ctx *context.Context) { ctx.Data["PageIsAdminAuthentications"] = true var err error - ctx.Data["Sources"], ctx.Data["Total"], err = db.FindAndCount[*auth.Source](ctx, auth.FindSourcesOptions{}) + ctx.Data["Sources"], ctx.Data["Total"], err = db.FindAndCount[auth.Source](ctx, auth.FindSourcesOptions{}) if err != nil { ctx.ServerError("auth.Sources", err) return @@ -284,7 +284,7 @@ func NewAuthSourcePost(ctx *context.Context) { ctx.RenderWithErr(err.Error(), tplAuthNew, form) return } - existing, err := db.Find[*auth.Source](ctx, auth.FindSourcesOptions{LoginType: auth.SSPI}) + existing, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{LoginType: auth.SSPI}) if err != nil || len(existing) > 0 { ctx.Data["Err_Type"] = true ctx.RenderWithErr(ctx.Tr("admin.auths.login_source_of_type_exist"), tplAuthNew, form) diff --git a/routers/web/admin/users.go b/routers/web/admin/users.go index 5dd870b55e63..44c4fa751254 100644 --- a/routers/web/admin/users.go +++ b/routers/web/admin/users.go @@ -93,7 +93,7 @@ func NewUser(ctx *context.Context) { ctx.Data["login_type"] = "0-0" - sources, err := db.Find[*auth.Source](ctx, auth.FindSourcesOptions{ + sources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ IsActive: util.OptionalBoolTrue, }) if err != nil { @@ -114,7 +114,7 @@ func NewUserPost(ctx *context.Context) { ctx.Data["DefaultUserVisibilityMode"] = setting.Service.DefaultUserVisibilityMode ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice() - sources, err := db.Find[*auth.Source](ctx, auth.FindSourcesOptions{ + sources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ IsActive: util.OptionalBoolTrue, }) if err != nil { @@ -237,7 +237,7 @@ func prepareUserInfo(ctx *context.Context) *user_model.User { ctx.Data["LoginSource"] = &auth.Source{} } - sources, err := db.Find[*auth.Source](ctx, auth.FindSourcesOptions{}) + sources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{}) if err != nil { ctx.ServerError("auth.Sources", err) return nil @@ -296,7 +296,7 @@ func ViewUser(ctx *context.Context) { ctx.Data["Emails"] = emails ctx.Data["EmailsTotal"] = len(emails) - orgs, err := db.Find[*org_model.Organization](ctx, org_model.FindOrgOptions{ + orgs, err := db.Find[org_model.Organization](ctx, org_model.FindOrgOptions{ ListOptions: db.ListOptions{ ListAll: true, }, diff --git a/routers/web/org/projects.go b/routers/web/org/projects.go index 45bbf0fb9b2c..03798a712c2e 100644 --- a/routers/web/org/projects.go +++ b/routers/web/org/projects.go @@ -60,7 +60,7 @@ func Projects(ctx *context.Context) { } else { projectType = project_model.TypeIndividual } - projects, total, err := db.FindAndCount[*project_model.Project](ctx, project_model.SearchOptions{ + projects, total, err := db.FindAndCount[project_model.Project](ctx, project_model.SearchOptions{ ListOptions: db.ListOptions{ Page: page, PageSize: setting.UI.IssuePagingNum, diff --git a/routers/web/org/setting.go b/routers/web/org/setting.go index de33e7c31a6b..f0d9259d3fe4 100644 --- a/routers/web/org/setting.go +++ b/routers/web/org/setting.go @@ -215,7 +215,7 @@ func Webhooks(ctx *context.Context) { ctx.Data["BaseLinkNew"] = ctx.Org.OrgLink + "/settings/hooks" ctx.Data["Description"] = ctx.Tr("org.settings.hooks_desc") - ws, err := db.Find[*webhook.Webhook](ctx, webhook.ListWebhookOptions{OwnerID: ctx.Org.Organization.ID}) + ws, err := db.Find[webhook.Webhook](ctx, webhook.ListWebhookOptions{OwnerID: ctx.Org.Organization.ID}) if err != nil { ctx.ServerError("ListWebhooksByOpts", err) return diff --git a/routers/web/org/setting_oauth2.go b/routers/web/org/setting_oauth2.go index 5dbfbe8f9bab..ca4fe09f380c 100644 --- a/routers/web/org/setting_oauth2.go +++ b/routers/web/org/setting_oauth2.go @@ -36,7 +36,7 @@ func Applications(ctx *context.Context) { ctx.Data["PageIsOrgSettings"] = true ctx.Data["PageIsSettingsApplications"] = true - apps, err := db.Find[*auth.OAuth2Application](ctx, auth.FindOAuth2ApplicationsOptions{ + apps, err := db.Find[auth.OAuth2Application](ctx, auth.FindOAuth2ApplicationsOptions{ OwnerID: ctx.Org.Organization.ID, }) if err != nil { diff --git a/routers/web/repo/actions/actions.go b/routers/web/repo/actions/actions.go index cd039de6cdd1..3b10f0b9571e 100644 --- a/routers/web/repo/actions/actions.go +++ b/routers/web/repo/actions/actions.go @@ -75,7 +75,7 @@ func List(ctx *context.Context) { } // Get all runner labels - runners, err := db.Find[*actions_model.ActionRunner](ctx, actions_model.FindRunnerOptions{ + runners, err := db.Find[actions_model.ActionRunner](ctx, actions_model.FindRunnerOptions{ RepoID: ctx.Repo.Repository.ID, WithAvailable: true, }) @@ -168,7 +168,7 @@ func List(ctx *context.Context) { opts.Status = []actions_model.Status{actions_model.Status(status)} } - runs, total, err := db.FindAndCount[*actions_model.ActionRun](ctx, opts) + runs, total, err := db.FindAndCount[actions_model.ActionRun](ctx, opts) if err != nil { ctx.Error(http.StatusInternalServerError, err.Error()) return diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go index d21a3e376d4c..1cdae32a32fe 100644 --- a/routers/web/repo/actions/view.go +++ b/routers/web/repo/actions/view.go @@ -538,7 +538,7 @@ func ArtifactsDownloadView(ctx *context_module.Context) { return } - artifacts, err := db.Find[*actions_model.ActionArtifact](ctx, actions_model.FindArtifactsOptions{ + artifacts, err := db.Find[actions_model.ActionArtifact](ctx, actions_model.FindArtifactsOptions{ RunID: run.ID, ArtifactName: artifactName, }) diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 1693b0135e8c..fad4a10de814 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -569,7 +569,7 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) { repoOwnerType = project_model.TypeOrganization } var err error - projects, err := db.Find[*project_model.Project](ctx, project_model.SearchOptions{ + projects, err := db.Find[project_model.Project](ctx, project_model.SearchOptions{ ListOptions: db.ListOptionsAll, RepoID: repo.ID, IsClosed: util.OptionalBoolFalse, @@ -579,7 +579,7 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) { ctx.ServerError("GetProjects", err) return } - projects2, err := db.Find[*project_model.Project](ctx, project_model.SearchOptions{ + projects2, err := db.Find[project_model.Project](ctx, project_model.SearchOptions{ ListOptions: db.ListOptionsAll, OwnerID: repo.OwnerID, IsClosed: util.OptionalBoolFalse, @@ -592,7 +592,7 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) { ctx.Data["OpenProjects"] = append(projects, projects2...) - projects, err = db.Find[*project_model.Project](ctx, project_model.SearchOptions{ + projects, err = db.Find[project_model.Project](ctx, project_model.SearchOptions{ ListOptions: db.ListOptionsAll, RepoID: repo.ID, IsClosed: util.OptionalBoolTrue, @@ -602,7 +602,7 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) { ctx.ServerError("GetProjects", err) return } - projects2, err = db.Find[*project_model.Project](ctx, project_model.SearchOptions{ + projects2, err = db.Find[project_model.Project](ctx, project_model.SearchOptions{ ListOptions: db.ListOptionsAll, OwnerID: repo.OwnerID, IsClosed: util.OptionalBoolTrue, diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go index 098a95744beb..199a06524546 100644 --- a/routers/web/repo/projects.go +++ b/routers/web/repo/projects.go @@ -72,7 +72,7 @@ func Projects(ctx *context.Context) { total = repo.NumClosedProjects } - projects, count, err := db.FindAndCount[*project_model.Project](ctx, project_model.SearchOptions{ + projects, count, err := db.FindAndCount[project_model.Project](ctx, project_model.SearchOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.IssuePagingNum, Page: page, diff --git a/routers/web/repo/setting/deploy_key.go b/routers/web/repo/setting/deploy_key.go index dc73eb5f2fc7..3d4420006c47 100644 --- a/routers/web/repo/setting/deploy_key.go +++ b/routers/web/repo/setting/deploy_key.go @@ -22,7 +22,7 @@ func DeployKeys(ctx *context.Context) { ctx.Data["PageIsSettingsKeys"] = true ctx.Data["DisableSSH"] = setting.SSH.Disabled - keys, err := db.Find[*asymkey_model.DeployKey](ctx, asymkey_model.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID}) + keys, err := db.Find[asymkey_model.DeployKey](ctx, asymkey_model.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID}) if err != nil { ctx.ServerError("ListDeployKeys", err) return @@ -39,7 +39,7 @@ func DeployKeysPost(ctx *context.Context) { ctx.Data["PageIsSettingsKeys"] = true ctx.Data["DisableSSH"] = setting.SSH.Disabled - keys, err := db.Find[*asymkey_model.DeployKey](ctx, asymkey_model.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID}) + keys, err := db.Find[asymkey_model.DeployKey](ctx, asymkey_model.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID}) if err != nil { ctx.ServerError("ListDeployKeys", err) return diff --git a/routers/web/repo/setting/webhook.go b/routers/web/repo/setting/webhook.go index 4bd3f4d51860..5100bf782f06 100644 --- a/routers/web/repo/setting/webhook.go +++ b/routers/web/repo/setting/webhook.go @@ -47,7 +47,7 @@ func Webhooks(ctx *context.Context) { ctx.Data["BaseLinkNew"] = ctx.Repo.RepoLink + "/settings/hooks" ctx.Data["Description"] = ctx.Tr("repo.settings.hooks_desc", "https://docs.gitea.com/usage/webhooks") - ws, err := db.Find[*webhook.Webhook](ctx, webhook.ListWebhookOptions{RepoID: ctx.Repo.Repository.ID}) + ws, err := db.Find[webhook.Webhook](ctx, webhook.ListWebhookOptions{RepoID: ctx.Repo.Repository.ID}) if err != nil { ctx.ServerError("GetWebhooksByRepoID", err) return diff --git a/routers/web/shared/actions/runners.go b/routers/web/shared/actions/runners.go index 042393ed721d..ae9a37672418 100644 --- a/routers/web/shared/actions/runners.go +++ b/routers/web/shared/actions/runners.go @@ -17,7 +17,7 @@ import ( // RunnersList prepares data for runners list func RunnersList(ctx *context.Context, opts actions_model.FindRunnerOptions) { - runners, count, err := db.FindAndCount[*actions_model.ActionRunner](ctx, opts) + runners, count, err := db.FindAndCount[actions_model.ActionRunner](ctx, opts) if err != nil { ctx.ServerError("CountRunners", err) return @@ -84,7 +84,7 @@ func RunnerDetails(ctx *context.Context, page int, runnerID, ownerID, repoID int RunnerID: runner.ID, } - tasks, count, err := db.FindAndCount[*actions_model.ActionTask](ctx, opts) + tasks, count, err := db.FindAndCount[actions_model.ActionTask](ctx, opts) if err != nil { ctx.ServerError("CountTasks", err) return diff --git a/routers/web/shared/actions/variables.go b/routers/web/shared/actions/variables.go index 33e29b36eec6..07a057520781 100644 --- a/routers/web/shared/actions/variables.go +++ b/routers/web/shared/actions/variables.go @@ -18,7 +18,7 @@ import ( ) func SetVariablesContext(ctx *context.Context, ownerID, repoID int64) { - variables, err := db.Find[*actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{ + variables, err := db.Find[actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{ OwnerID: ownerID, RepoID: repoID, }) diff --git a/routers/web/shared/secrets/secrets.go b/routers/web/shared/secrets/secrets.go index 2ffe6be1c023..c805da734ac0 100644 --- a/routers/web/shared/secrets/secrets.go +++ b/routers/web/shared/secrets/secrets.go @@ -15,7 +15,7 @@ import ( ) func SetSecretsContext(ctx *context.Context, ownerID, repoID int64) { - secrets, err := db.Find[*secret_model.Secret](ctx, secret_model.FindSecretsOptions{OwnerID: ownerID, RepoID: repoID}) + secrets, err := db.Find[secret_model.Secret](ctx, secret_model.FindSecretsOptions{OwnerID: ownerID, RepoID: repoID}) if err != nil { ctx.ServerError("FindSecrets", err) return diff --git a/routers/web/shared/user/header.go b/routers/web/shared/user/header.go index 10c3146ecc62..411d499eb4f7 100644 --- a/routers/web/shared/user/header.go +++ b/routers/web/shared/user/header.go @@ -60,7 +60,7 @@ func PrepareContextForProfileBigAvatar(ctx *context.Context) { } showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID) - orgs, err := db.Find[*organization.Organization](ctx, organization.FindOrgOptions{ + orgs, err := db.Find[organization.Organization](ctx, organization.FindOrgOptions{ UserID: ctx.ContextUser.ID, IncludePrivate: showPrivate, }) diff --git a/routers/web/user/home.go b/routers/web/user/home.go index 71866a0c85c4..b4fb25dfe0ee 100644 --- a/routers/web/user/home.go +++ b/routers/web/user/home.go @@ -759,7 +759,7 @@ func loadRepoByIDs(ctx *context.Context, ctxUser *user_model.User, issueCountByR // ShowSSHKeys output all the ssh keys of user by uid func ShowSSHKeys(ctx *context.Context) { - keys, err := db.Find[*asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ + keys, err := db.Find[asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ OwnerID: ctx.ContextUser.ID, }) if err != nil { diff --git a/routers/web/user/notification.go b/routers/web/user/notification.go index 50f500a8dcbd..26f77cfc3a36 100644 --- a/routers/web/user/notification.go +++ b/routers/web/user/notification.go @@ -109,7 +109,7 @@ func getNotifications(ctx *context.Context) { } statuses := []activities_model.NotificationStatus{status, activities_model.NotificationStatusPinned} - nls, err := db.Find[*activities_model.Notification](ctx, activities_model.FindNotificationOptions{ + nls, err := db.Find[activities_model.Notification](ctx, activities_model.FindNotificationOptions{ ListOptions: db.ListOptions{ PageSize: perPage, Page: page, @@ -118,7 +118,7 @@ func getNotifications(ctx *context.Context) { Status: statuses, }) if err != nil { - ctx.ServerError("db.Find[*activities_model.Notification]", err) + ctx.ServerError("db.Find[activities_model.Notification]", err) return } diff --git a/routers/web/user/setting/applications.go b/routers/web/user/setting/applications.go index 7e0034153bc2..69a93dbf03ae 100644 --- a/routers/web/user/setting/applications.go +++ b/routers/web/user/setting/applications.go @@ -89,7 +89,7 @@ func DeleteApplication(ctx *context.Context) { func loadApplicationsData(ctx *context.Context) { ctx.Data["AccessTokenScopePublicOnly"] = auth_model.AccessTokenScopePublicOnly - tokens, err := db.Find[*auth_model.AccessToken](ctx, auth_model.ListAccessTokensOptions{UserID: ctx.Doer.ID}) + tokens, err := db.Find[auth_model.AccessToken](ctx, auth_model.ListAccessTokensOptions{UserID: ctx.Doer.ID}) if err != nil { ctx.ServerError("ListAccessTokens", err) return @@ -98,7 +98,7 @@ func loadApplicationsData(ctx *context.Context) { ctx.Data["EnableOAuth2"] = setting.OAuth2.Enable ctx.Data["IsAdmin"] = ctx.Doer.IsAdmin if setting.OAuth2.Enable { - ctx.Data["Applications"], err = db.Find[*auth_model.OAuth2Application](ctx, auth_model.FindOAuth2ApplicationsOptions{ + ctx.Data["Applications"], err = db.Find[auth_model.OAuth2Application](ctx, auth_model.FindOAuth2ApplicationsOptions{ OwnerID: ctx.Doer.ID, }) if err != nil { diff --git a/routers/web/user/setting/keys.go b/routers/web/user/setting/keys.go index 82ff295a86a8..0dfb506fa967 100644 --- a/routers/web/user/setting/keys.go +++ b/routers/web/user/setting/keys.go @@ -260,7 +260,7 @@ func DeleteKey(ctx *context.Context) { } func loadKeysData(ctx *context.Context) { - keys, err := db.Find[*asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ + keys, err := db.Find[asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ OwnerID: ctx.Doer.ID, NotKeytype: asymkey_model.KeyTypePrincipal, }) diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index 1aa25d41cbb6..d8331fef43f5 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -214,7 +214,7 @@ func Organization(ctx *context.Context) { opts.Page = 1 } - orgs, total, err := db.FindAndCount[*organization.Organization](ctx, opts) + orgs, total, err := db.FindAndCount[organization.Organization](ctx, opts) if err != nil { ctx.ServerError("FindOrgs", err) return diff --git a/routers/web/user/setting/security/security.go b/routers/web/user/setting/security/security.go index 6fe9ed3d0ed7..3647d606eef8 100644 --- a/routers/web/user/setting/security/security.go +++ b/routers/web/user/setting/security/security.go @@ -69,14 +69,14 @@ func loadSecurityData(ctx *context.Context) { } ctx.Data["WebAuthnCredentials"] = credentials - tokens, err := db.Find[*auth_model.AccessToken](ctx, auth_model.ListAccessTokensOptions{UserID: ctx.Doer.ID}) + tokens, err := db.Find[auth_model.AccessToken](ctx, auth_model.ListAccessTokensOptions{UserID: ctx.Doer.ID}) if err != nil { ctx.ServerError("ListAccessTokens", err) return } ctx.Data["Tokens"] = tokens - accountLinks, err := db.Find[*user_model.ExternalLoginUser](ctx, user_model.FindExternalUserOptions{ + accountLinks, err := db.Find[user_model.ExternalLoginUser](ctx, user_model.FindExternalUserOptions{ UserID: ctx.Doer.ID, OrderBy: "login_source_id DESC", }) @@ -111,7 +111,7 @@ func loadSecurityData(ctx *context.Context) { } ctx.Data["AccountLinks"] = sources - authSources, err := db.Find[*auth_model.Source](ctx, auth_model.FindSourcesOptions{ + authSources, err := db.Find[auth_model.Source](ctx, auth_model.FindSourcesOptions{ IsActive: util.OptionalBoolNone, LoginType: auth_model.OAuth2, }) diff --git a/routers/web/user/setting/webhooks.go b/routers/web/user/setting/webhooks.go index e3b0131fd2dc..679b72e50119 100644 --- a/routers/web/user/setting/webhooks.go +++ b/routers/web/user/setting/webhooks.go @@ -25,7 +25,7 @@ func Webhooks(ctx *context.Context) { ctx.Data["BaseLinkNew"] = setting.AppSubURL + "/user/settings/hooks" ctx.Data["Description"] = ctx.Tr("settings.hooks.desc") - ws, err := db.Find[*webhook.Webhook](ctx, webhook.ListWebhookOptions{OwnerID: ctx.Doer.ID}) + ws, err := db.Find[webhook.Webhook](ctx, webhook.ListWebhookOptions{OwnerID: ctx.Doer.ID}) if err != nil { ctx.ServerError("ListWebhooksByOpts", err) return diff --git a/services/actions/clear_tasks.go b/services/actions/clear_tasks.go index a108dcdf1f6a..67373782d5c9 100644 --- a/services/actions/clear_tasks.go +++ b/services/actions/clear_tasks.go @@ -33,7 +33,7 @@ func StopEndlessTasks(ctx context.Context) error { } func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error { - tasks, err := db.Find[*actions_model.ActionTask](ctx, opts) + tasks, err := db.Find[actions_model.ActionTask](ctx, opts) if err != nil { return fmt.Errorf("find tasks: %w", err) } @@ -74,7 +74,7 @@ func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error { // CancelAbandonedJobs cancels the jobs which have waiting status, but haven't been picked by a runner for a long time func CancelAbandonedJobs(ctx context.Context) error { - jobs, err := db.Find[*actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{ + jobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{ Statuses: []actions_model.Status{actions_model.StatusWaiting, actions_model.StatusBlocked}, UpdatedBefore: timeutil.TimeStamp(time.Now().Add(-setting.Actions.AbandonedJobTimeout).Unix()), }) diff --git a/services/actions/job_emitter.go b/services/actions/job_emitter.go index fd3825f75ed1..fe39312386d9 100644 --- a/services/actions/job_emitter.go +++ b/services/actions/job_emitter.go @@ -44,7 +44,7 @@ func jobEmitterQueueHandler(items ...*jobUpdate) []*jobUpdate { } func checkJobsOfRun(ctx context.Context, runID int64) error { - jobs, err := db.Find[*actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: runID}) + jobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: runID}) if err != nil { return err } diff --git a/services/actions/notifier_helper.go b/services/actions/notifier_helper.go index 1f7413d562fb..175b8a411873 100644 --- a/services/actions/notifier_helper.go +++ b/services/actions/notifier_helper.go @@ -299,7 +299,7 @@ func handleWorkflows( continue } - alljobs, err := db.Find[*actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID}) + alljobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID}) if err != nil { log.Error("FindRunJobs: %v", err) continue diff --git a/services/asymkey/ssh_key_test.go b/services/asymkey/ssh_key_test.go index e7e64f62bcf1..fbd5d13ab2d2 100644 --- a/services/asymkey/ssh_key_test.go +++ b/services/asymkey/ssh_key_test.go @@ -67,7 +67,7 @@ ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ib for i, kase := range testCases { s.ID = int64(i) + 20 asymkey_model.AddPublicKeysBySource(db.DefaultContext, user, s, []string{kase.keyString}) - keys, err := db.Find[*asymkey_model.PublicKey](db.DefaultContext, asymkey_model.FindPublicKeyOptions{ + keys, err := db.Find[asymkey_model.PublicKey](db.DefaultContext, asymkey_model.FindPublicKeyOptions{ OwnerID: user.ID, LoginSourceID: s.ID, }) diff --git a/services/auth/httpsign.go b/services/auth/httpsign.go index c46f65ca8f6e..b604349f80d6 100644 --- a/services/auth/httpsign.go +++ b/services/auth/httpsign.go @@ -93,7 +93,7 @@ func VerifyPubKey(r *http.Request) (*asymkey_model.PublicKey, error) { keyID := verifier.KeyId() - publicKeys, err := db.Find[*asymkey_model.PublicKey](r.Context(), asymkey_model.FindPublicKeyOptions{ + publicKeys, err := db.Find[asymkey_model.PublicKey](r.Context(), asymkey_model.FindPublicKeyOptions{ Fingerprint: keyID, }) if err != nil { diff --git a/services/auth/signin.go b/services/auth/signin.go index 023f05000f69..fafe3ef3c67b 100644 --- a/services/auth/signin.go +++ b/services/auth/signin.go @@ -86,7 +86,7 @@ func UserSignIn(ctx context.Context, username, password string) (*user_model.Use } } - sources, err := db.Find[*auth.Source](ctx, auth.FindSourcesOptions{ + sources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ IsActive: util.OptionalBoolTrue, }) if err != nil { diff --git a/services/auth/source/oauth2/init.go b/services/auth/source/oauth2/init.go index 6795eecd880a..3ad6e307f106 100644 --- a/services/auth/source/oauth2/init.go +++ b/services/auth/source/oauth2/init.go @@ -65,7 +65,7 @@ func ResetOAuth2(ctx context.Context) error { // initOAuth2Sources is used to load and register all active OAuth2 providers func initOAuth2Sources(ctx context.Context) error { - authSources, err := db.Find[*auth.Source](ctx, auth.FindSourcesOptions{ + authSources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ IsActive: util.OptionalBoolTrue, LoginType: auth.OAuth2, }) diff --git a/services/auth/source/oauth2/providers.go b/services/auth/source/oauth2/providers.go index ac2f2dc6c1b0..f4edb507f277 100644 --- a/services/auth/source/oauth2/providers.go +++ b/services/auth/source/oauth2/providers.go @@ -108,7 +108,7 @@ func CreateProviderFromSource(source *auth.Source) (Provider, error) { // GetOAuth2Providers returns the list of configured OAuth2 providers func GetOAuth2Providers(ctx context.Context, isActive util.OptionalBool) ([]Provider, error) { - authSources, err := db.Find[*auth.Source](ctx, auth.FindSourcesOptions{ + authSources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ IsActive: isActive, LoginType: auth.OAuth2, }) diff --git a/services/auth/sspi.go b/services/auth/sspi.go index 59144e6350e3..57ba0462c573 100644 --- a/services/auth/sspi.go +++ b/services/auth/sspi.go @@ -131,7 +131,7 @@ func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore, // getConfig retrieves the SSPI configuration from login sources func (s *SSPI) getConfig(ctx context.Context) (*sspi.Source, error) { - sources, err := db.Find[*auth.Source](ctx, auth.FindSourcesOptions{ + sources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ IsActive: util.OptionalBoolTrue, LoginType: auth.SSPI, }) diff --git a/services/auth/sync.go b/services/auth/sync.go index 378e385f4064..7562ac812bd3 100644 --- a/services/auth/sync.go +++ b/services/auth/sync.go @@ -15,7 +15,7 @@ import ( func SyncExternalUsers(ctx context.Context, updateExisting bool) error { log.Trace("Doing: SyncExternalUsers") - ls, err := db.Find[*auth.Source](ctx, auth.FindSourcesOptions{}) + ls, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{}) if err != nil { log.Error("SyncExternalUsers: %v", err) return err diff --git a/services/migrations/update.go b/services/migrations/update.go index 3b65ef9aa4a8..4a49206f82e2 100644 --- a/services/migrations/update.go +++ b/services/migrations/update.go @@ -44,7 +44,7 @@ func updateMigrationPosterIDByGitService(ctx context.Context, tp structs.GitServ default: } - users, err := db.Find[*user_model.ExternalLoginUser](ctx, user_model.FindExternalUserOptions{ + users, err := db.Find[user_model.ExternalLoginUser](ctx, user_model.FindExternalUserOptions{ ListOptions: db.ListOptions{ PageSize: batchSize, Page: page, diff --git a/services/pull/review.go b/services/pull/review.go index 1d3a8003f73d..e48f3801547d 100644 --- a/services/pull/review.go +++ b/services/pull/review.go @@ -50,7 +50,7 @@ func InvalidateCodeComments(ctx context.Context, prs issues_model.PullRequestLis } issueIDs := prs.GetIssueIDs() - codeComments, err := db.Find[*issues_model.Comment](ctx, issues_model.FindCommentsOptions{ + codeComments, err := db.Find[issues_model.Comment](ctx, issues_model.FindCommentsOptions{ ListOptions: db.ListOptions{ ListAll: true, }, diff --git a/services/repository/delete.go b/services/repository/delete.go index 2c20252ee8f6..08d6800ee766 100644 --- a/services/repository/delete.go +++ b/services/repository/delete.go @@ -54,13 +54,13 @@ func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID } // Query the action tasks of this repo, they will be needed after they have been deleted to remove the logs - tasks, err := db.Find[*actions_model.ActionTask](ctx, actions_model.FindTaskOptions{RepoID: repoID}) + tasks, err := db.Find[actions_model.ActionTask](ctx, actions_model.FindTaskOptions{RepoID: repoID}) if err != nil { return fmt.Errorf("find actions tasks of repo %v: %w", repoID, err) } // Query the artifacts of this repo, they will be needed after they have been deleted to remove artifacts files in ObjectStorage - artifacts, err := db.Find[*actions_model.ActionArtifact](ctx, actions_model.FindArtifactsOptions{RepoID: repoID}) + artifacts, err := db.Find[actions_model.ActionArtifact](ctx, actions_model.FindArtifactsOptions{RepoID: repoID}) if err != nil { return fmt.Errorf("list actions artifacts of repo %v: %w", repoID, err) } @@ -75,7 +75,7 @@ func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID } // Delete Deploy Keys - deployKeys, err := db.Find[*asymkey_model.DeployKey](ctx, asymkey_model.ListDeployKeysOptions{RepoID: repoID}) + deployKeys, err := db.Find[asymkey_model.DeployKey](ctx, asymkey_model.ListDeployKeysOptions{RepoID: repoID}) if err != nil { return fmt.Errorf("listDeployKeys: %w", err) } diff --git a/services/repository/hooks.go b/services/repository/hooks.go index b841acd3f999..7b82f36b43fd 100644 --- a/services/repository/hooks.go +++ b/services/repository/hooks.go @@ -85,7 +85,7 @@ func GenerateGitHooks(ctx context.Context, templateRepo, generateRepo *repo_mode // GenerateWebhooks generates webhooks from a template repository func GenerateWebhooks(ctx context.Context, templateRepo, generateRepo *repo_model.Repository) error { - templateWebhooks, err := db.Find[*webhook.Webhook](ctx, webhook.ListWebhookOptions{RepoID: templateRepo.ID}) + templateWebhooks, err := db.Find[webhook.Webhook](ctx, webhook.ListWebhookOptions{RepoID: templateRepo.ID}) if err != nil { return err } diff --git a/services/secrets/secrets.go b/services/secrets/secrets.go index e1e5da64e50d..97e15ba6c7fc 100644 --- a/services/secrets/secrets.go +++ b/services/secrets/secrets.go @@ -15,7 +15,7 @@ func CreateOrUpdateSecret(ctx context.Context, ownerID, repoID int64, name, data return nil, false, err } - s, err := db.Find[*secret_model.Secret](ctx, secret_model.FindSecretsOptions{ + s, err := db.Find[secret_model.Secret](ctx, secret_model.FindSecretsOptions{ OwnerID: ownerID, RepoID: repoID, Name: name, @@ -40,7 +40,7 @@ func CreateOrUpdateSecret(ctx context.Context, ownerID, repoID int64, name, data } func DeleteSecretByID(ctx context.Context, ownerID, repoID, secretID int64) error { - s, err := db.Find[*secret_model.Secret](ctx, secret_model.FindSecretsOptions{ + s, err := db.Find[secret_model.Secret](ctx, secret_model.FindSecretsOptions{ OwnerID: ownerID, RepoID: repoID, SecretID: secretID, @@ -60,7 +60,7 @@ func DeleteSecretByName(ctx context.Context, ownerID, repoID int64, name string) return err } - s, err := db.Find[*secret_model.Secret](ctx, secret_model.FindSecretsOptions{ + s, err := db.Find[secret_model.Secret](ctx, secret_model.FindSecretsOptions{ OwnerID: ownerID, RepoID: repoID, Name: name, diff --git a/services/user/user.go b/services/user/user.go index 667559f793a8..932e359c9f99 100644 --- a/services/user/user.go +++ b/services/user/user.go @@ -172,7 +172,7 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) error { // An alternative option here would be write a function which would delete all organizations but it seems // but such a function would likely get out of date for { - orgs, err := db.Find[*organization.Organization](ctx, organization.FindOrgOptions{ + orgs, err := db.Find[organization.Organization](ctx, organization.FindOrgOptions{ ListOptions: db.ListOptions{ PageSize: repo_model.RepositoryListDefaultPageSize, Page: 1, diff --git a/services/webhook/webhook.go b/services/webhook/webhook.go index 96c1779e053f..ac18da352528 100644 --- a/services/webhook/webhook.go +++ b/services/webhook/webhook.go @@ -223,7 +223,7 @@ func PrepareWebhooks(ctx context.Context, source EventSource, event webhook_modu var ws []*webhook_model.Webhook if source.Repository != nil { - repoHooks, err := db.Find[*webhook_model.Webhook](ctx, webhook_model.ListWebhookOptions{ + repoHooks, err := db.Find[webhook_model.Webhook](ctx, webhook_model.ListWebhookOptions{ RepoID: source.Repository.ID, IsActive: util.OptionalBoolTrue, }) @@ -237,7 +237,7 @@ func PrepareWebhooks(ctx context.Context, source EventSource, event webhook_modu // append additional webhooks of a user or organization if owner != nil { - ownerHooks, err := db.Find[*webhook_model.Webhook](ctx, webhook_model.ListWebhookOptions{ + ownerHooks, err := db.Find[webhook_model.Webhook](ctx, webhook_model.ListWebhookOptions{ OwnerID: owner.ID, IsActive: util.OptionalBoolTrue, }) diff --git a/tests/integration/auth_ldap_test.go b/tests/integration/auth_ldap_test.go index 30a4ba7e51cf..1148b3ad3993 100644 --- a/tests/integration/auth_ldap_test.go +++ b/tests/integration/auth_ldap_test.go @@ -414,7 +414,7 @@ func TestLDAPGroupTeamSyncAddMember(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ Name: gitLDAPUser.UserName, }) - usersOrgs, err := db.Find[*organization.Organization](db.DefaultContext, organization.FindOrgOptions{ + usersOrgs, err := db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{ UserID: user.ID, IncludePrivate: true, }) diff --git a/tests/integration/org_count_test.go b/tests/integration/org_count_test.go index c02e2292dadb..6386f53f0599 100644 --- a/tests/integration/org_count_test.go +++ b/tests/integration/org_count_test.go @@ -118,7 +118,7 @@ func doCheckOrgCounts(username string, orgCounts map[string]int, strict bool, ca Name: username, }) - orgs, err := db.Find[*organization.Organization](db.DefaultContext, organization.FindOrgOptions{ + orgs, err := db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{ UserID: user.ID, IncludePrivate: true, }) From 743f9ff2ba3ca58437e9265b7aaebef9e46e9b92 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 24 Nov 2023 00:12:04 +0800 Subject: [PATCH 20/21] make review easier --- models/activities/notification.go | 376 +++++++++++++++++++++++ models/activities/notification_list.go | 393 ------------------------- 2 files changed, 376 insertions(+), 393 deletions(-) delete mode 100644 models/activities/notification_list.go diff --git a/models/activities/notification.go b/models/activities/notification.go index 5e313e50e3e4..133ef17a4e84 100644 --- a/models/activities/notification.go +++ b/models/activities/notification.go @@ -17,6 +17,7 @@ import ( "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/container" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" @@ -376,6 +377,381 @@ func (n *Notification) APIURL() string { return setting.AppURL + "api/v1/notifications/threads/" + strconv.FormatInt(n.ID, 10) } +// FindNotificationOptions represent the filters for notifications. If an ID is 0 it will be ignored. +type FindNotificationOptions struct { + db.ListOptions + UserID int64 + RepoID int64 + IssueID int64 + Status []NotificationStatus + Source []NotificationSource + UpdatedAfterUnix int64 + UpdatedBeforeUnix int64 +} + +// ToCond will convert each condition into a xorm-Cond +func (opts FindNotificationOptions) ToConds() builder.Cond { + cond := builder.NewCond() + if opts.UserID != 0 { + cond = cond.And(builder.Eq{"notification.user_id": opts.UserID}) + } + if opts.RepoID != 0 { + cond = cond.And(builder.Eq{"notification.repo_id": opts.RepoID}) + } + if opts.IssueID != 0 { + cond = cond.And(builder.Eq{"notification.issue_id": opts.IssueID}) + } + if len(opts.Status) > 0 { + if len(opts.Status) == 1 { + cond = cond.And(builder.Eq{"notification.status": opts.Status[0]}) + } else { + cond = cond.And(builder.In("notification.status", opts.Status)) + } + } + if len(opts.Source) > 0 { + cond = cond.And(builder.In("notification.source", opts.Source)) + } + if opts.UpdatedAfterUnix != 0 { + cond = cond.And(builder.Gte{"notification.updated_unix": opts.UpdatedAfterUnix}) + } + if opts.UpdatedBeforeUnix != 0 { + cond = cond.And(builder.Lte{"notification.updated_unix": opts.UpdatedBeforeUnix}) + } + return cond +} + +func (opts FindNotificationOptions) ToOrders() string { + return "notification.updated_unix DESC" +} + +func notificationExists(notifications []*Notification, issueID, userID int64) bool { + for _, notification := range notifications { + if notification.IssueID == issueID && notification.UserID == userID { + return true + } + } + + return false +} + +// UserIDCount is a simple coalition of UserID and Count +type UserIDCount struct { + UserID int64 + Count int64 +} + +// GetUIDsAndNotificationCounts between the two provided times +func GetUIDsAndNotificationCounts(ctx context.Context, since, until timeutil.TimeStamp) ([]UserIDCount, error) { + sql := `SELECT user_id, count(*) AS count FROM notification ` + + `WHERE user_id IN (SELECT user_id FROM notification WHERE updated_unix >= ? AND ` + + `updated_unix < ?) AND status = ? GROUP BY user_id` + var res []UserIDCount + return res, db.GetEngine(ctx).SQL(sql, since, until, NotificationStatusUnread).Find(&res) +} + +// NotificationList contains a list of notifications +type NotificationList []*Notification + +// LoadAttributes load Repo Issue User and Comment if not loaded +func (nl NotificationList) LoadAttributes(ctx context.Context) error { + if _, _, err := nl.LoadRepos(ctx); err != nil { + return err + } + if _, err := nl.LoadIssues(ctx); err != nil { + return err + } + if _, err := nl.LoadUsers(ctx); err != nil { + return err + } + if _, err := nl.LoadComments(ctx); err != nil { + return err + } + return nil +} + +func (nl NotificationList) getPendingRepoIDs() []int64 { + ids := make(container.Set[int64], len(nl)) + for _, notification := range nl { + if notification.Repository != nil { + continue + } + ids.Add(notification.RepoID) + } + return ids.Values() +} + +// LoadRepos loads repositories from database +func (nl NotificationList) LoadRepos(ctx context.Context) (repo_model.RepositoryList, []int, error) { + if len(nl) == 0 { + return repo_model.RepositoryList{}, []int{}, nil + } + + repoIDs := nl.getPendingRepoIDs() + repos := make(map[int64]*repo_model.Repository, len(repoIDs)) + left := len(repoIDs) + for left > 0 { + limit := db.DefaultMaxInSize + if left < limit { + limit = left + } + rows, err := db.GetEngine(ctx). + In("id", repoIDs[:limit]). + Rows(new(repo_model.Repository)) + if err != nil { + return nil, nil, err + } + + for rows.Next() { + var repo repo_model.Repository + err = rows.Scan(&repo) + if err != nil { + rows.Close() + return nil, nil, err + } + + repos[repo.ID] = &repo + } + _ = rows.Close() + + left -= limit + repoIDs = repoIDs[limit:] + } + + failed := []int{} + + reposList := make(repo_model.RepositoryList, 0, len(repoIDs)) + for i, notification := range nl { + if notification.Repository == nil { + notification.Repository = repos[notification.RepoID] + } + if notification.Repository == nil { + log.Error("Notification[%d]: RepoID: %d not found", notification.ID, notification.RepoID) + failed = append(failed, i) + continue + } + var found bool + for _, r := range reposList { + if r.ID == notification.RepoID { + found = true + break + } + } + if !found { + reposList = append(reposList, notification.Repository) + } + } + return reposList, failed, nil +} + +func (nl NotificationList) getPendingIssueIDs() []int64 { + ids := make(container.Set[int64], len(nl)) + for _, notification := range nl { + if notification.Issue != nil { + continue + } + ids.Add(notification.IssueID) + } + return ids.Values() +} + +// LoadIssues loads issues from database +func (nl NotificationList) LoadIssues(ctx context.Context) ([]int, error) { + if len(nl) == 0 { + return []int{}, nil + } + + issueIDs := nl.getPendingIssueIDs() + issues := make(map[int64]*issues_model.Issue, len(issueIDs)) + left := len(issueIDs) + for left > 0 { + limit := db.DefaultMaxInSize + if left < limit { + limit = left + } + rows, err := db.GetEngine(ctx). + In("id", issueIDs[:limit]). + Rows(new(issues_model.Issue)) + if err != nil { + return nil, err + } + + for rows.Next() { + var issue issues_model.Issue + err = rows.Scan(&issue) + if err != nil { + rows.Close() + return nil, err + } + + issues[issue.ID] = &issue + } + _ = rows.Close() + + left -= limit + issueIDs = issueIDs[limit:] + } + + failures := []int{} + + for i, notification := range nl { + if notification.Issue == nil { + notification.Issue = issues[notification.IssueID] + if notification.Issue == nil { + if notification.IssueID != 0 { + log.Error("Notification[%d]: IssueID: %d Not Found", notification.ID, notification.IssueID) + failures = append(failures, i) + } + continue + } + notification.Issue.Repo = notification.Repository + } + } + return failures, nil +} + +// Without returns the notification list without the failures +func (nl NotificationList) Without(failures []int) NotificationList { + if len(failures) == 0 { + return nl + } + remaining := make([]*Notification, 0, len(nl)) + last := -1 + var i int + for _, i = range failures { + remaining = append(remaining, nl[last+1:i]...) + last = i + } + if len(nl) > i { + remaining = append(remaining, nl[i+1:]...) + } + return remaining +} + +func (nl NotificationList) getPendingCommentIDs() []int64 { + ids := make(container.Set[int64], len(nl)) + for _, notification := range nl { + if notification.CommentID == 0 || notification.Comment != nil { + continue + } + ids.Add(notification.CommentID) + } + return ids.Values() +} + +func (nl NotificationList) getUserIDs() []int64 { + ids := make(container.Set[int64], len(nl)) + for _, notification := range nl { + if notification.UserID == 0 || notification.User != nil { + continue + } + ids.Add(notification.UserID) + } + return ids.Values() +} + +// LoadUsers loads users from database +func (nl NotificationList) LoadUsers(ctx context.Context) ([]int, error) { + if len(nl) == 0 { + return []int{}, nil + } + + userIDs := nl.getUserIDs() + users := make(map[int64]*user_model.User, len(userIDs)) + left := len(userIDs) + for left > 0 { + limit := db.DefaultMaxInSize + if left < limit { + limit = left + } + rows, err := db.GetEngine(ctx). + In("id", userIDs[:limit]). + Rows(new(user_model.User)) + if err != nil { + return nil, err + } + + for rows.Next() { + var user user_model.User + err = rows.Scan(&user) + if err != nil { + rows.Close() + return nil, err + } + + users[user.ID] = &user + } + _ = rows.Close() + + left -= limit + userIDs = userIDs[limit:] + } + + failures := []int{} + for i, notification := range nl { + if notification.UserID > 0 && notification.User == nil && users[notification.UserID] != nil { + notification.User = users[notification.UserID] + if notification.User == nil { + log.Error("Notification[%d]: UserID[%d] failed to load", notification.ID, notification.UserID) + failures = append(failures, i) + continue + } + } + } + return failures, nil +} + +// LoadComments loads comments from database +func (nl NotificationList) LoadComments(ctx context.Context) ([]int, error) { + if len(nl) == 0 { + return []int{}, nil + } + + commentIDs := nl.getPendingCommentIDs() + comments := make(map[int64]*issues_model.Comment, len(commentIDs)) + left := len(commentIDs) + for left > 0 { + limit := db.DefaultMaxInSize + if left < limit { + limit = left + } + rows, err := db.GetEngine(ctx). + In("id", commentIDs[:limit]). + Rows(new(issues_model.Comment)) + if err != nil { + return nil, err + } + + for rows.Next() { + var comment issues_model.Comment + err = rows.Scan(&comment) + if err != nil { + rows.Close() + return nil, err + } + + comments[comment.ID] = &comment + } + _ = rows.Close() + + left -= limit + commentIDs = commentIDs[limit:] + } + + failures := []int{} + for i, notification := range nl { + if notification.CommentID > 0 && notification.Comment == nil && comments[notification.CommentID] != nil { + notification.Comment = comments[notification.CommentID] + if notification.Comment == nil { + log.Error("Notification[%d]: CommentID[%d] failed to load", notification.ID, notification.CommentID) + failures = append(failures, i) + continue + } + notification.Comment.Issue = notification.Issue + } + } + return failures, nil +} + // SetIssueReadBy sets issue to be read by given user. func SetIssueReadBy(ctx context.Context, issueID, userID int64) error { if err := issues_model.UpdateIssueUserByRead(ctx, userID, issueID); err != nil { diff --git a/models/activities/notification_list.go b/models/activities/notification_list.go deleted file mode 100644 index 23dacae4595c..000000000000 --- a/models/activities/notification_list.go +++ /dev/null @@ -1,393 +0,0 @@ -// Copyright 2023 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package activities - -import ( - "context" - - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/container" - "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/timeutil" - - "xorm.io/builder" -) - -// FindNotificationOptions represent the filters for notifications. If an ID is 0 it will be ignored. -type FindNotificationOptions struct { - db.ListOptions - UserID int64 - RepoID int64 - IssueID int64 - Status []NotificationStatus - Source []NotificationSource - UpdatedAfterUnix int64 - UpdatedBeforeUnix int64 -} - -// ToCond will convert each condition into a xorm-Cond -func (opts FindNotificationOptions) ToConds() builder.Cond { - cond := builder.NewCond() - if opts.UserID != 0 { - cond = cond.And(builder.Eq{"notification.user_id": opts.UserID}) - } - if opts.RepoID != 0 { - cond = cond.And(builder.Eq{"notification.repo_id": opts.RepoID}) - } - if opts.IssueID != 0 { - cond = cond.And(builder.Eq{"notification.issue_id": opts.IssueID}) - } - if len(opts.Status) > 0 { - if len(opts.Status) == 1 { - cond = cond.And(builder.Eq{"notification.status": opts.Status[0]}) - } else { - cond = cond.And(builder.In("notification.status", opts.Status)) - } - } - if len(opts.Source) > 0 { - cond = cond.And(builder.In("notification.source", opts.Source)) - } - if opts.UpdatedAfterUnix != 0 { - cond = cond.And(builder.Gte{"notification.updated_unix": opts.UpdatedAfterUnix}) - } - if opts.UpdatedBeforeUnix != 0 { - cond = cond.And(builder.Lte{"notification.updated_unix": opts.UpdatedBeforeUnix}) - } - return cond -} - -func (opts FindNotificationOptions) ToOrders() string { - return "notification.updated_unix DESC" -} - -func notificationExists(notifications []*Notification, issueID, userID int64) bool { - for _, notification := range notifications { - if notification.IssueID == issueID && notification.UserID == userID { - return true - } - } - - return false -} - -// UserIDCount is a simple coalition of UserID and Count -type UserIDCount struct { - UserID int64 - Count int64 -} - -// GetUIDsAndNotificationCounts between the two provided times -func GetUIDsAndNotificationCounts(ctx context.Context, since, until timeutil.TimeStamp) ([]UserIDCount, error) { - sql := `SELECT user_id, count(*) AS count FROM notification ` + - `WHERE user_id IN (SELECT user_id FROM notification WHERE updated_unix >= ? AND ` + - `updated_unix < ?) AND status = ? GROUP BY user_id` - var res []UserIDCount - return res, db.GetEngine(ctx).SQL(sql, since, until, NotificationStatusUnread).Find(&res) -} - -// NotificationList contains a list of notifications -type NotificationList []*Notification - -// LoadAttributes load Repo Issue User and Comment if not loaded -func (nl NotificationList) LoadAttributes(ctx context.Context) error { - if _, _, err := nl.LoadRepos(ctx); err != nil { - return err - } - if _, err := nl.LoadIssues(ctx); err != nil { - return err - } - if _, err := nl.LoadUsers(ctx); err != nil { - return err - } - if _, err := nl.LoadComments(ctx); err != nil { - return err - } - return nil -} - -func (nl NotificationList) getPendingRepoIDs() []int64 { - ids := make(container.Set[int64], len(nl)) - for _, notification := range nl { - if notification.Repository != nil { - continue - } - ids.Add(notification.RepoID) - } - return ids.Values() -} - -// LoadRepos loads repositories from database -func (nl NotificationList) LoadRepos(ctx context.Context) (repo_model.RepositoryList, []int, error) { - if len(nl) == 0 { - return repo_model.RepositoryList{}, []int{}, nil - } - - repoIDs := nl.getPendingRepoIDs() - repos := make(map[int64]*repo_model.Repository, len(repoIDs)) - left := len(repoIDs) - for left > 0 { - limit := db.DefaultMaxInSize - if left < limit { - limit = left - } - rows, err := db.GetEngine(ctx). - In("id", repoIDs[:limit]). - Rows(new(repo_model.Repository)) - if err != nil { - return nil, nil, err - } - - for rows.Next() { - var repo repo_model.Repository - err = rows.Scan(&repo) - if err != nil { - rows.Close() - return nil, nil, err - } - - repos[repo.ID] = &repo - } - _ = rows.Close() - - left -= limit - repoIDs = repoIDs[limit:] - } - - failed := []int{} - - reposList := make(repo_model.RepositoryList, 0, len(repoIDs)) - for i, notification := range nl { - if notification.Repository == nil { - notification.Repository = repos[notification.RepoID] - } - if notification.Repository == nil { - log.Error("Notification[%d]: RepoID: %d not found", notification.ID, notification.RepoID) - failed = append(failed, i) - continue - } - var found bool - for _, r := range reposList { - if r.ID == notification.RepoID { - found = true - break - } - } - if !found { - reposList = append(reposList, notification.Repository) - } - } - return reposList, failed, nil -} - -func (nl NotificationList) getPendingIssueIDs() []int64 { - ids := make(container.Set[int64], len(nl)) - for _, notification := range nl { - if notification.Issue != nil { - continue - } - ids.Add(notification.IssueID) - } - return ids.Values() -} - -// LoadIssues loads issues from database -func (nl NotificationList) LoadIssues(ctx context.Context) ([]int, error) { - if len(nl) == 0 { - return []int{}, nil - } - - issueIDs := nl.getPendingIssueIDs() - issues := make(map[int64]*issues_model.Issue, len(issueIDs)) - left := len(issueIDs) - for left > 0 { - limit := db.DefaultMaxInSize - if left < limit { - limit = left - } - rows, err := db.GetEngine(ctx). - In("id", issueIDs[:limit]). - Rows(new(issues_model.Issue)) - if err != nil { - return nil, err - } - - for rows.Next() { - var issue issues_model.Issue - err = rows.Scan(&issue) - if err != nil { - rows.Close() - return nil, err - } - - issues[issue.ID] = &issue - } - _ = rows.Close() - - left -= limit - issueIDs = issueIDs[limit:] - } - - failures := []int{} - - for i, notification := range nl { - if notification.Issue == nil { - notification.Issue = issues[notification.IssueID] - if notification.Issue == nil { - if notification.IssueID != 0 { - log.Error("Notification[%d]: IssueID: %d Not Found", notification.ID, notification.IssueID) - failures = append(failures, i) - } - continue - } - notification.Issue.Repo = notification.Repository - } - } - return failures, nil -} - -// Without returns the notification list without the failures -func (nl NotificationList) Without(failures []int) NotificationList { - if len(failures) == 0 { - return nl - } - remaining := make([]*Notification, 0, len(nl)) - last := -1 - var i int - for _, i = range failures { - remaining = append(remaining, nl[last+1:i]...) - last = i - } - if len(nl) > i { - remaining = append(remaining, nl[i+1:]...) - } - return remaining -} - -func (nl NotificationList) getPendingCommentIDs() []int64 { - ids := make(container.Set[int64], len(nl)) - for _, notification := range nl { - if notification.CommentID == 0 || notification.Comment != nil { - continue - } - ids.Add(notification.CommentID) - } - return ids.Values() -} - -func (nl NotificationList) getUserIDs() []int64 { - ids := make(container.Set[int64], len(nl)) - for _, notification := range nl { - if notification.UserID == 0 || notification.User != nil { - continue - } - ids.Add(notification.UserID) - } - return ids.Values() -} - -// LoadUsers loads users from database -func (nl NotificationList) LoadUsers(ctx context.Context) ([]int, error) { - if len(nl) == 0 { - return []int{}, nil - } - - userIDs := nl.getUserIDs() - users := make(map[int64]*user_model.User, len(userIDs)) - left := len(userIDs) - for left > 0 { - limit := db.DefaultMaxInSize - if left < limit { - limit = left - } - rows, err := db.GetEngine(ctx). - In("id", userIDs[:limit]). - Rows(new(user_model.User)) - if err != nil { - return nil, err - } - - for rows.Next() { - var user user_model.User - err = rows.Scan(&user) - if err != nil { - rows.Close() - return nil, err - } - - users[user.ID] = &user - } - _ = rows.Close() - - left -= limit - userIDs = userIDs[limit:] - } - - failures := []int{} - for i, notification := range nl { - if notification.UserID > 0 && notification.User == nil && users[notification.UserID] != nil { - notification.User = users[notification.UserID] - if notification.User == nil { - log.Error("Notification[%d]: UserID[%d] failed to load", notification.ID, notification.UserID) - failures = append(failures, i) - continue - } - } - } - return failures, nil -} - -// LoadComments loads comments from database -func (nl NotificationList) LoadComments(ctx context.Context) ([]int, error) { - if len(nl) == 0 { - return []int{}, nil - } - - commentIDs := nl.getPendingCommentIDs() - comments := make(map[int64]*issues_model.Comment, len(commentIDs)) - left := len(commentIDs) - for left > 0 { - limit := db.DefaultMaxInSize - if left < limit { - limit = left - } - rows, err := db.GetEngine(ctx). - In("id", commentIDs[:limit]). - Rows(new(issues_model.Comment)) - if err != nil { - return nil, err - } - - for rows.Next() { - var comment issues_model.Comment - err = rows.Scan(&comment) - if err != nil { - rows.Close() - return nil, err - } - - comments[comment.ID] = &comment - } - _ = rows.Close() - - left -= limit - commentIDs = commentIDs[limit:] - } - - failures := []int{} - for i, notification := range nl { - if notification.CommentID > 0 && notification.Comment == nil && comments[notification.CommentID] != nil { - notification.Comment = comments[notification.CommentID] - if notification.Comment == nil { - log.Error("Notification[%d]: CommentID[%d] failed to load", notification.ID, notification.CommentID) - failures = append(failures, i) - continue - } - notification.Comment.Issue = notification.Issue - } - } - return failures, nil -} From 3345e908508d1342ac4d116450555c8465402149 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 24 Nov 2023 00:17:09 +0800 Subject: [PATCH 21/21] make review easier --- models/activities/notification.go | 94 +++++++++++++++---------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/models/activities/notification.go b/models/activities/notification.go index 133ef17a4e84..230bcdd6e805 100644 --- a/models/activities/notification.go +++ b/models/activities/notification.go @@ -79,6 +79,53 @@ func init() { db.RegisterModel(new(Notification)) } +// FindNotificationOptions represent the filters for notifications. If an ID is 0 it will be ignored. +type FindNotificationOptions struct { + db.ListOptions + UserID int64 + RepoID int64 + IssueID int64 + Status []NotificationStatus + Source []NotificationSource + UpdatedAfterUnix int64 + UpdatedBeforeUnix int64 +} + +// ToCond will convert each condition into a xorm-Cond +func (opts FindNotificationOptions) ToConds() builder.Cond { + cond := builder.NewCond() + if opts.UserID != 0 { + cond = cond.And(builder.Eq{"notification.user_id": opts.UserID}) + } + if opts.RepoID != 0 { + cond = cond.And(builder.Eq{"notification.repo_id": opts.RepoID}) + } + if opts.IssueID != 0 { + cond = cond.And(builder.Eq{"notification.issue_id": opts.IssueID}) + } + if len(opts.Status) > 0 { + if len(opts.Status) == 1 { + cond = cond.And(builder.Eq{"notification.status": opts.Status[0]}) + } else { + cond = cond.And(builder.In("notification.status", opts.Status)) + } + } + if len(opts.Source) > 0 { + cond = cond.And(builder.In("notification.source", opts.Source)) + } + if opts.UpdatedAfterUnix != 0 { + cond = cond.And(builder.Gte{"notification.updated_unix": opts.UpdatedAfterUnix}) + } + if opts.UpdatedBeforeUnix != 0 { + cond = cond.And(builder.Lte{"notification.updated_unix": opts.UpdatedBeforeUnix}) + } + return cond +} + +func (opts FindNotificationOptions) ToOrders() string { + return "notification.updated_unix DESC" +} + // CreateRepoTransferNotification creates notification for the user a repository was transferred to func CreateRepoTransferNotification(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) error { return db.WithTx(ctx, func(ctx context.Context) error { @@ -377,53 +424,6 @@ func (n *Notification) APIURL() string { return setting.AppURL + "api/v1/notifications/threads/" + strconv.FormatInt(n.ID, 10) } -// FindNotificationOptions represent the filters for notifications. If an ID is 0 it will be ignored. -type FindNotificationOptions struct { - db.ListOptions - UserID int64 - RepoID int64 - IssueID int64 - Status []NotificationStatus - Source []NotificationSource - UpdatedAfterUnix int64 - UpdatedBeforeUnix int64 -} - -// ToCond will convert each condition into a xorm-Cond -func (opts FindNotificationOptions) ToConds() builder.Cond { - cond := builder.NewCond() - if opts.UserID != 0 { - cond = cond.And(builder.Eq{"notification.user_id": opts.UserID}) - } - if opts.RepoID != 0 { - cond = cond.And(builder.Eq{"notification.repo_id": opts.RepoID}) - } - if opts.IssueID != 0 { - cond = cond.And(builder.Eq{"notification.issue_id": opts.IssueID}) - } - if len(opts.Status) > 0 { - if len(opts.Status) == 1 { - cond = cond.And(builder.Eq{"notification.status": opts.Status[0]}) - } else { - cond = cond.And(builder.In("notification.status", opts.Status)) - } - } - if len(opts.Source) > 0 { - cond = cond.And(builder.In("notification.source", opts.Source)) - } - if opts.UpdatedAfterUnix != 0 { - cond = cond.And(builder.Gte{"notification.updated_unix": opts.UpdatedAfterUnix}) - } - if opts.UpdatedBeforeUnix != 0 { - cond = cond.And(builder.Lte{"notification.updated_unix": opts.UpdatedBeforeUnix}) - } - return cond -} - -func (opts FindNotificationOptions) ToOrders() string { - return "notification.updated_unix DESC" -} - func notificationExists(notifications []*Notification, issueID, userID int64) bool { for _, notification := range notifications { if notification.IssueID == issueID && notification.UserID == userID {