Merge remote-tracking branch 'upstream/main' into feat/api-project-boards
This commit is contained in:
15
.github/workflows/disk-clean.yml
vendored
15
.github/workflows/disk-clean.yml
vendored
@@ -8,21 +8,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
# FIXME: https://github.com/jlumbroso/free-disk-space/issues/17
|
||||
- name: same as 'large-packages' but without 'google-cloud-sdk'
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get remove -y '^dotnet-.*' || true
|
||||
sudo apt-get remove -y '^llvm-.*' || true
|
||||
sudo apt-get remove -y 'php.*' || true
|
||||
sudo apt-get remove -y '^mongodb-.*' || true
|
||||
sudo apt-get remove -y '^mysql-.*' || true
|
||||
sudo apt-get remove -y azure-cli google-chrome-stable firefox powershell mono-devel libgl1-mesa-dri || true
|
||||
sudo apt-get autoremove -y
|
||||
sudo apt-get clean
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
- name: Free Disk Space (Ubuntu)
|
||||
uses: jlumbroso/free-disk-space@main
|
||||
with:
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<img src="https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml/badge.svg?branch=main">
|
||||
</a>
|
||||
<a href="https://discord.gg/Gitea" title="Join the Discord chat at https://discord.gg/Gitea">
|
||||
<img src="https://img.shields.io/discord/322538954119184384.svg">
|
||||
<img src="https://img.shields.io/discord/322538954119184384.svg?logo=discord&logoColor=white&label=Discord&color=5865F2">
|
||||
</a>
|
||||
<a href="https://app.codecov.io/gh/go-gitea/gitea" title="Codecov">
|
||||
<img src="https://codecov.io/gh/go-gitea/gitea/branch/main/graph/badge.svg">
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ Please note: authentication is only supported when the SMTP server communication
|
||||
|
||||
- STARTTLS (also known as Opportunistic TLS) via port 587. Initial connection is done over cleartext, but then be upgraded over TLS if the server supports it.
|
||||
- SMTPS connection (SMTP over TLS) via the default port 465. Connection to the server use TLS from the beginning.
|
||||
- Forced SMTPS connection with `IS_TLS_ENABLED=true`. (These are both known as Implicit TLS.)
|
||||
- Forced SMTPS connection with `PROTOCOL=smtps`. (These are both known as Implicit TLS.)
|
||||
This is due to protections imposed by the Go internal libraries against STRIPTLS attacks.
|
||||
|
||||
Note that Implicit TLS is recommended by [RFC8314](https://tools.ietf.org/html/rfc8314#section-3) since 2018.
|
||||
|
||||
@@ -55,13 +55,13 @@ PASSWD = `password`
|
||||
|
||||
要发送测试邮件以验证设置,请转到 Gitea > 站点管理 > 配置 > SMTP 邮件配置。
|
||||
|
||||
有关所有选项的完整列表,请查看[配置速查表](doc/administration/config-cheat-sheet.zh-cn.md)。
|
||||
有关所有选项的完整列表,请查看[配置速查表](doc/administration/config-cheat-sheet.md)。
|
||||
|
||||
请注意:只有在使用 TLS 或 `HOST=localhost` 加密 SMTP 服务器通信时才支持身份验证。TLS 加密可以通过以下方式进行:
|
||||
|
||||
- 通过端口 587 的 STARTTLS(也称为 Opportunistic TLS)。初始连接是明文的,但如果服务器支持,则可以升级为 TLS。
|
||||
- 通过默认端口 465 的 SMTPS 连接。连接到服务器从一开始就使用 TLS。
|
||||
- 使用 `IS_TLS_ENABLED=true` 进行强制的 SMTPS 连接。(这两种方式都被称为 Implicit TLS)
|
||||
- 使用 `PROTOCOL=smtps` 进行强制的 SMTPS 连接。(这两种方式都被称为 Implicit TLS)
|
||||
这是由于 Go 内部库对 STRIPTLS 攻击的保护机制。
|
||||
|
||||
请注意,自2018年起,[RFC8314](https://tools.ietf.org/html/rfc8314#section-3) 推荐使用 Implicit TLS。
|
||||
|
||||
@@ -39,7 +39,6 @@ If a bug fix is targeted on 1.20.1 but 1.20.1 is not released yet, you can get t
|
||||
|
||||
To migrate from Gogs to Gitea:
|
||||
|
||||
- [Gogs version 0.9.146 or less](installation/upgrade-from-gogs.md)
|
||||
- [Gogs version 0.11.46.0418](https://github.com/go-gitea/gitea/issues/4286)
|
||||
|
||||
To migrate from GitHub to Gitea, you can use Gitea's built-in migration form.
|
||||
|
||||
@@ -41,7 +41,6 @@ menu:
|
||||
|
||||
要从Gogs迁移到Gitea:
|
||||
|
||||
- [Gogs版本0.9.146或更低](installation/upgrade-from-gogs.md)
|
||||
- [Gogs版本0.11.46.0418](https://github.com/go-gitea/gitea/issues/4286)
|
||||
|
||||
要从GitHub迁移到Gitea,您可以使用Gitea内置的迁移表单。
|
||||
|
||||
@@ -114,7 +114,7 @@ If you cannot see the settings page, please make sure that you have the right pe
|
||||
|
||||
The format of the registration token is a random string `D0gvfu2iHfUjNqCYVljVyRV14fISpJxxxxxxxxxx`.
|
||||
|
||||
A registration token can also be obtained from the gitea [command-line interface](../../administration/command-line.en-us.md#actions-generate-runner-token):
|
||||
A registration token can also be obtained from the gitea [command-line interface](../../administration/command-line.md#actions-generate-runner-token):
|
||||
|
||||
```
|
||||
gitea --config /etc/gitea/app.ini actions generate-runner-token
|
||||
|
||||
@@ -113,7 +113,7 @@ Runner级别决定了从哪里获取注册令牌。
|
||||
|
||||
注册令牌的格式是一个随机字符串 `D0gvfu2iHfUjNqCYVljVyRV14fISpJxxxxxxxxxx`。
|
||||
|
||||
注册令牌也可以通过 Gitea 的 [命令行](../../administration/command-line.en-us.md#actions-generate-runner-token) 获得:
|
||||
注册令牌也可以通过 Gitea 的 [命令行](../../administration/command-line.md#actions-generate-runner-token) 获得:
|
||||
|
||||
### 注册Runner
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ First of all, you need a Gitea instance.
|
||||
You can follow the [documentation](installation/from-package.md) to set up a new instance or upgrade your existing one.
|
||||
It doesn't matter how you install or run Gitea, as long as its version is 1.19.0 or higher.
|
||||
|
||||
Actions are disabled by default, so you need to add the following to the configuration file to enable it:
|
||||
Since 1.21.0, Actions are enabled by default. If you are using versions before 1.21.0, you need to add the following to the configuration file to enable it:
|
||||
|
||||
```ini
|
||||
[actions]
|
||||
|
||||
@@ -23,7 +23,7 @@ menu:
|
||||
您可以按照[文档](installation/from-package.md) 来设置一个新实例或升级现有实例。
|
||||
无论您如何安装或运行Gitea,只要版本号是1.19.0或更高即可。
|
||||
|
||||
默认情况下,Actions是禁用的,因此您需要将以下内容添加到配置文件中以启用它:
|
||||
从1.21.0开始,默认情况下,Actions是启用的。如果您正在使用1.21.0之前的版本,您需要将以下内容添加到配置文件中以启用它:
|
||||
|
||||
```ini
|
||||
[actions]
|
||||
|
||||
@@ -198,7 +198,7 @@ administrative user.
|
||||
field is set to `mail.com`, then Gitea will expect the `user email` field
|
||||
for an authenticated GIT instance to be `gituser@mail.com`.[^2]
|
||||
|
||||
**Note**: PAM support is added via [build-time flags](installation/install-from-source.md#build),
|
||||
**Note**: PAM support is added via [build-time flags](installation/from-source.md#build),
|
||||
and the official binaries provided do not have this enabled. PAM requires that
|
||||
the necessary libpam dynamic library be available and the necessary PAM
|
||||
development headers be accessible to the compiler.
|
||||
|
||||
@@ -162,7 +162,7 @@ PAM提供了一种机制,通过对用户进行PAM认证来自动将其添加
|
||||
- PAM电子邮件域:用户认证时要附加的电子邮件后缀。例如,如果登录系统期望一个名为gituse的用户,
|
||||
并且将此字段设置为mail.com,那么Gitea在验证一个GIT实例的用户时将期望user emai字段为gituser@mail.com[^2]。
|
||||
|
||||
**Note**: PAM 支持通过[build-time flags](installation/install-from-source.md#build)添加,
|
||||
**Note**: PAM 支持通过[build-time flags](installation/from-source.md#build)添加,
|
||||
而官方提供的二进制文件通常不会默认启用此功能。PAM需要确保系统上有必要的libpam动态库,并且编译器可以访问必要的PAM开发头文件。
|
||||
|
||||
[^1]: 例如,在Debian "Bullseye"上使用标准Linux登录,可以使用`common-session-noninteractive`。这个值对于其他版本的Debian,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.Find[ActionRunJob](ctx, FindRunJobOptions{
|
||||
RunID: run.ID,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -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})
|
||||
@@ -83,17 +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
|
||||
}
|
||||
|
||||
func CountRunJobs(ctx context.Context, opts FindRunJobOptions) (int64, error) {
|
||||
return db.GetEngine(ctx).Where(opts.toConds()).Count(new(ActionRunJob))
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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 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)
|
||||
func (opts FindSpecOptions) ToOrders() string {
|
||||
return "`id` DESC"
|
||||
}
|
||||
var specs SpecList
|
||||
total, err := e.Desc("id").FindAndCount(&specs)
|
||||
|
||||
func FindSpecs(ctx context.Context, opts FindSpecOptions) (SpecList, int64, error) {
|
||||
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))
|
||||
}
|
||||
|
||||
@@ -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 ""
|
||||
}
|
||||
|
||||
@@ -20,6 +20,10 @@ type ActionTaskOutput struct {
|
||||
OutputValue string `xorm:"MEDIUMTEXT"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
db.RegisterModel(new(ActionTaskOutput))
|
||||
}
|
||||
|
||||
// FindTaskOutputByTaskID returns the outputs of the task.
|
||||
func FindTaskOutputByTaskID(ctx context.Context, taskID int64) ([]*ActionTaskOutput, error) {
|
||||
var outputs []*ActionTaskOutput
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
|
||||
"xorm.io/builder"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -93,7 +92,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})
|
||||
@@ -105,8 +104,12 @@ func (opts *FindNotificationOptions) ToCond() builder.Cond {
|
||||
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))
|
||||
}
|
||||
@@ -119,24 +122,8 @@ func (opts *FindNotificationOptions) ToCond() builder.Cond {
|
||||
return cond
|
||||
}
|
||||
|
||||
// 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())
|
||||
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{})
|
||||
func (opts FindNotificationOptions) ToOrders() string {
|
||||
return "notification.updated_unix DESC"
|
||||
}
|
||||
|
||||
// CreateRepoTransferNotification creates notification for the user a repository was transferred to
|
||||
@@ -192,7 +179,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
|
||||
}
|
||||
@@ -273,23 +262,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,
|
||||
@@ -341,35 +313,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 {
|
||||
@@ -481,17 +424,47 @@ func (n *Notification) APIURL() string {
|
||||
return setting.AppURL + "api/v1/notifications/threads/" + strconv.FormatInt(n.ID, 10)
|
||||
}
|
||||
|
||||
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 {
|
||||
var err error
|
||||
for i := 0; i < len(nl); i++ {
|
||||
err = nl[i].LoadAttributes(ctx)
|
||||
if err != nil && !issues_model.IsErrCommentNotExist(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
|
||||
}
|
||||
@@ -665,6 +638,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 {
|
||||
@@ -717,30 +752,6 @@ func (nl NotificationList) LoadComments(ctx context.Context) ([]int, error) {
|
||||
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 {
|
||||
|
||||
@@ -34,8 +34,13 @@ func TestCreateOrUpdateIssueNotifications(t *testing.T) {
|
||||
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)
|
||||
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)
|
||||
@@ -68,11 +73,21 @@ func TestNotification_GetIssue(t *testing.T) {
|
||||
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)
|
||||
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 = activities_model.GetNotificationCount(db.DefaultContext, user, activities_model.NotificationStatusUnread)
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
if len(opts.KeyTypes) > 0 {
|
||||
cond = cond.And(builder.In("type", opts.KeyTypes))
|
||||
}
|
||||
|
||||
// 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 opts.NotKeytype > 0 {
|
||||
cond = cond.And(builder.Neq{"type": opts.NotKeytype})
|
||||
}
|
||||
|
||||
keys := make([]*PublicKey, 0, 5)
|
||||
return keys, sess.Find(&keys)
|
||||
if opts.LoginSourceID > 0 {
|
||||
cond = cond.And(builder.Eq{"login_source_id": opts.LoginSourceID})
|
||||
}
|
||||
|
||||
// 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)
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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{})
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru/v2"
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
// ErrAccessTokenNotExist represents a "AccessTokenNotExist" kind of error.
|
||||
@@ -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)
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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{
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/base32"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
@@ -19,7 +20,6 @@ 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"
|
||||
@@ -243,13 +243,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,25 +365,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.
|
||||
|
||||
32
models/auth/oauth2_list.go
Normal file
32
models/auth/oauth2_list.go
Normal file
@@ -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"
|
||||
}
|
||||
@@ -242,6 +242,7 @@ func CreateSource(ctx context.Context, source *Source) error {
|
||||
}
|
||||
|
||||
type FindSourcesOptions struct {
|
||||
db.ListOptions
|
||||
IsActive util.OptionalBool
|
||||
LoginType Type
|
||||
}
|
||||
@@ -257,27 +258,22 @@ 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{
|
||||
|
||||
exist, err := db.Exists[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.
|
||||
@@ -346,12 +342,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
|
||||
|
||||
@@ -264,3 +264,8 @@ func inTransaction(ctx context.Context) (*xorm.Session, bool) {
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
func Exists[T any](ctx context.Context, opts FindOptions) (bool, error) {
|
||||
var bean T
|
||||
return GetEngine(ctx).Where(opts.ToConds()).Exist(&bean)
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
const (
|
||||
// DefaultMaxInSize represents default variables number on IN () in SQL
|
||||
DefaultMaxInSize = 50
|
||||
defaultFindSliceSize = 10
|
||||
)
|
||||
|
||||
// Paginator is the base for different ListOptions types
|
||||
@@ -52,7 +53,12 @@ type ListOptions struct {
|
||||
ListAll bool // if true, then PageSize and Page will not be taken
|
||||
}
|
||||
|
||||
var _ Paginator = &ListOptions{}
|
||||
var ListOptionsAll = ListOptions{ListAll: true}
|
||||
|
||||
var (
|
||||
_ Paginator = &ListOptions{}
|
||||
_ FindOptions = ListOptions{}
|
||||
)
|
||||
|
||||
// GetSkipTake returns the skip and take values
|
||||
func (opts *ListOptions) GetSkipTake() (skip, take int) {
|
||||
@@ -67,8 +73,16 @@ 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 {
|
||||
func (opts ListOptions) IsListAll() bool {
|
||||
return opts.ListAll
|
||||
}
|
||||
|
||||
@@ -85,6 +99,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 +142,63 @@ 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
|
||||
}
|
||||
|
||||
// Find represents a common find function which accept an options interface
|
||||
func Find[T any](ctx context.Context, opts FindOptions, objects *[]T) error {
|
||||
sess := GetEngine(ctx).Where(opts.ToConds())
|
||||
if !opts.IsListAll() {
|
||||
sess.Limit(opts.GetSkipTake())
|
||||
type FindOptionsOrder interface {
|
||||
ToOrders() string
|
||||
}
|
||||
return sess.Find(objects)
|
||||
|
||||
// Find represents a common find function which accept an options interface
|
||||
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 {
|
||||
sess.Limit(pageSize, (page-1)*pageSize)
|
||||
}
|
||||
if newOpt, ok := opts.(FindOptionsOrder); ok && newOpt.ToOrders() != "" {
|
||||
sess.OrderBy(newOpt.ToOrders())
|
||||
}
|
||||
|
||||
findPageSize := defaultFindSliceSize
|
||||
if pageSize > 0 {
|
||||
findPageSize = pageSize
|
||||
}
|
||||
objects := make([]*T, 0, findPageSize)
|
||||
if err := sess.Find(&objects); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
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)
|
||||
}
|
||||
return sess.FindAndCount(objects)
|
||||
if newOpt, ok := opts.(FindOptionsOrder); ok && newOpt.ToOrders() != "" {
|
||||
sess.OrderBy(newOpt.ToOrders())
|
||||
}
|
||||
|
||||
findPageSize := defaultFindSliceSize
|
||||
if pageSize > 0 {
|
||||
findPageSize = pageSize
|
||||
}
|
||||
objects := make([]*T, 0, findPageSize)
|
||||
cnt, err := sess.FindAndCount(&objects)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return objects, cnt, nil
|
||||
}
|
||||
|
||||
@@ -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,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)
|
||||
}
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
@@ -203,16 +203,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})
|
||||
@@ -237,9 +237,8 @@ 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 (opts SearchOptions) ToOrders() string {
|
||||
return opts.OrderBy.String()
|
||||
}
|
||||
|
||||
func GetSearchOrderByBySortType(sortType string) db.SearchOrderBy {
|
||||
@@ -255,22 +254,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 {
|
||||
e = e.Limit(setting.UI.IssuePagingNum, (opts.Page-1)*setting.UI.IssuePagingNum)
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -584,9 +584,9 @@ func (repo *Repository) DescriptionHTML(ctx context.Context) template.HTML {
|
||||
}, repo.Description)
|
||||
if err != nil {
|
||||
log.Error("Failed to render description for %s (ID: %d): %v", repo.Name, repo.ID, err)
|
||||
return template.HTML(markup.Sanitize(repo.Description))
|
||||
return template.HTML(markup.SanitizeDescription(repo.Description))
|
||||
}
|
||||
return template.HTML(markup.Sanitize(desc))
|
||||
return template.HTML(markup.SanitizeDescription(desc))
|
||||
}
|
||||
|
||||
// CloneLink represents different types of clone URLs of repository.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,28 +160,23 @@ 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
|
||||
}
|
||||
|
||||
// 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
|
||||
func (opts FindExternalUserOptions) ToOrders() string {
|
||||
return opts.OrderBy
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -563,6 +563,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
|
||||
ctx.Data["CanWriteCode"] = ctx.Repo.CanWrite(unit_model.TypeCode)
|
||||
ctx.Data["CanWriteIssues"] = ctx.Repo.CanWrite(unit_model.TypeIssues)
|
||||
ctx.Data["CanWritePulls"] = ctx.Repo.CanWrite(unit_model.TypePullRequests)
|
||||
ctx.Data["CanWriteActions"] = ctx.Repo.CanWrite(unit_model.TypeActions)
|
||||
|
||||
canSignedUserFork, err := repo_module.CanUserForkRepo(ctx, ctx.Doer, ctx.Repo.Repository)
|
||||
if err != nil {
|
||||
|
||||
@@ -26,7 +26,7 @@ func handleDeleteOrphanedRepos(ctx context.Context, logger log.Logger, autofix b
|
||||
|
||||
// countOrphanedRepos count repository where user of owner_id do not exist
|
||||
func countOrphanedRepos(ctx context.Context) (int64, error) {
|
||||
return db.CountOrphanedObjects(ctx, "repository", "user", "repository.owner_id=user.id")
|
||||
return db.CountOrphanedObjects(ctx, "repository", "user", "repository.owner_id=`user`.id")
|
||||
}
|
||||
|
||||
// deleteOrphanedRepos delete repository where user of owner_id do not exist
|
||||
@@ -43,7 +43,7 @@ func deleteOrphanedRepos(ctx context.Context) (int64, error) {
|
||||
default:
|
||||
var ids []int64
|
||||
if err := e.Table("`repository`").
|
||||
Join("LEFT", "`user`", "repository.owner_id=user.id").
|
||||
Join("LEFT", "`user`", "repository.owner_id=`user`.id").
|
||||
Where(builder.IsNull{"`user`.id"}).
|
||||
Select("`repository`.id").Limit(batchSize).Find(&ids); err != nil {
|
||||
return deleted, err
|
||||
|
||||
104
modules/graceful/manager_common.go
Normal file
104
modules/graceful/manager_common.go
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package graceful
|
||||
|
||||
import (
|
||||
"context"
|
||||
"runtime/pprof"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type systemdNotifyMsg string
|
||||
|
||||
const (
|
||||
readyMsg systemdNotifyMsg = "READY=1"
|
||||
stoppingMsg systemdNotifyMsg = "STOPPING=1"
|
||||
reloadingMsg systemdNotifyMsg = "RELOADING=1"
|
||||
watchdogMsg systemdNotifyMsg = "WATCHDOG=1"
|
||||
)
|
||||
|
||||
func statusMsg(msg string) systemdNotifyMsg {
|
||||
return systemdNotifyMsg("STATUS=" + msg)
|
||||
}
|
||||
|
||||
// Manager manages the graceful shutdown process
|
||||
type Manager struct {
|
||||
ctx context.Context
|
||||
isChild bool
|
||||
forked bool
|
||||
lock sync.RWMutex
|
||||
state state
|
||||
shutdownCtx context.Context
|
||||
hammerCtx context.Context
|
||||
terminateCtx context.Context
|
||||
managerCtx context.Context
|
||||
shutdownCtxCancel context.CancelFunc
|
||||
hammerCtxCancel context.CancelFunc
|
||||
terminateCtxCancel context.CancelFunc
|
||||
managerCtxCancel context.CancelFunc
|
||||
runningServerWaitGroup sync.WaitGroup
|
||||
createServerWaitGroup sync.WaitGroup
|
||||
terminateWaitGroup sync.WaitGroup
|
||||
shutdownRequested chan struct{}
|
||||
|
||||
toRunAtShutdown []func()
|
||||
toRunAtTerminate []func()
|
||||
}
|
||||
|
||||
func newGracefulManager(ctx context.Context) *Manager {
|
||||
manager := &Manager{ctx: ctx, shutdownRequested: make(chan struct{})}
|
||||
manager.createServerWaitGroup.Add(numberOfServersToCreate)
|
||||
manager.prepare(ctx)
|
||||
manager.start()
|
||||
return manager
|
||||
}
|
||||
|
||||
func (g *Manager) prepare(ctx context.Context) {
|
||||
g.terminateCtx, g.terminateCtxCancel = context.WithCancel(ctx)
|
||||
g.shutdownCtx, g.shutdownCtxCancel = context.WithCancel(ctx)
|
||||
g.hammerCtx, g.hammerCtxCancel = context.WithCancel(ctx)
|
||||
g.managerCtx, g.managerCtxCancel = context.WithCancel(ctx)
|
||||
|
||||
g.terminateCtx = pprof.WithLabels(g.terminateCtx, pprof.Labels("graceful-lifecycle", "with-terminate"))
|
||||
g.shutdownCtx = pprof.WithLabels(g.shutdownCtx, pprof.Labels("graceful-lifecycle", "with-shutdown"))
|
||||
g.hammerCtx = pprof.WithLabels(g.hammerCtx, pprof.Labels("graceful-lifecycle", "with-hammer"))
|
||||
g.managerCtx = pprof.WithLabels(g.managerCtx, pprof.Labels("graceful-lifecycle", "with-manager"))
|
||||
|
||||
if !g.setStateTransition(stateInit, stateRunning) {
|
||||
panic("invalid graceful manager state: transition from init to running failed")
|
||||
}
|
||||
}
|
||||
|
||||
// DoImmediateHammer causes an immediate hammer
|
||||
func (g *Manager) DoImmediateHammer() {
|
||||
g.notify(statusMsg("Sending immediate hammer"))
|
||||
g.doHammerTime(0 * time.Second)
|
||||
}
|
||||
|
||||
// DoGracefulShutdown causes a graceful shutdown
|
||||
func (g *Manager) DoGracefulShutdown() {
|
||||
g.lock.Lock()
|
||||
select {
|
||||
case <-g.shutdownRequested:
|
||||
default:
|
||||
close(g.shutdownRequested)
|
||||
}
|
||||
forked := g.forked
|
||||
g.lock.Unlock()
|
||||
|
||||
if !forked {
|
||||
g.notify(stoppingMsg)
|
||||
} else {
|
||||
g.notify(statusMsg("Shutting down after fork"))
|
||||
}
|
||||
g.doShutdown()
|
||||
}
|
||||
|
||||
// RegisterServer registers the running of a listening server, in the case of unix this means that the parent process can now die.
|
||||
// Any call to RegisterServer must be matched by a call to ServerDone
|
||||
func (g *Manager) RegisterServer() {
|
||||
KillParent()
|
||||
g.runningServerWaitGroup.Add(1)
|
||||
}
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"os/signal"
|
||||
"runtime/pprof"
|
||||
"strconv"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -22,51 +21,6 @@ import (
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
// Manager manages the graceful shutdown process
|
||||
type Manager struct {
|
||||
isChild bool
|
||||
forked bool
|
||||
lock *sync.RWMutex
|
||||
state state
|
||||
shutdownCtx context.Context
|
||||
hammerCtx context.Context
|
||||
terminateCtx context.Context
|
||||
managerCtx context.Context
|
||||
shutdownCtxCancel context.CancelFunc
|
||||
hammerCtxCancel context.CancelFunc
|
||||
terminateCtxCancel context.CancelFunc
|
||||
managerCtxCancel context.CancelFunc
|
||||
runningServerWaitGroup sync.WaitGroup
|
||||
createServerWaitGroup sync.WaitGroup
|
||||
terminateWaitGroup sync.WaitGroup
|
||||
|
||||
toRunAtShutdown []func()
|
||||
toRunAtTerminate []func()
|
||||
}
|
||||
|
||||
func newGracefulManager(ctx context.Context) *Manager {
|
||||
manager := &Manager{
|
||||
isChild: len(os.Getenv(listenFDsEnv)) > 0 && os.Getppid() > 1,
|
||||
lock: &sync.RWMutex{},
|
||||
}
|
||||
manager.createServerWaitGroup.Add(numberOfServersToCreate)
|
||||
manager.start(ctx)
|
||||
return manager
|
||||
}
|
||||
|
||||
type systemdNotifyMsg string
|
||||
|
||||
const (
|
||||
readyMsg systemdNotifyMsg = "READY=1"
|
||||
stoppingMsg systemdNotifyMsg = "STOPPING=1"
|
||||
reloadingMsg systemdNotifyMsg = "RELOADING=1"
|
||||
watchdogMsg systemdNotifyMsg = "WATCHDOG=1"
|
||||
)
|
||||
|
||||
func statusMsg(msg string) systemdNotifyMsg {
|
||||
return systemdNotifyMsg("STATUS=" + msg)
|
||||
}
|
||||
|
||||
func pidMsg() systemdNotifyMsg {
|
||||
return systemdNotifyMsg("MAINPID=" + strconv.Itoa(os.Getpid()))
|
||||
}
|
||||
@@ -89,27 +43,13 @@ func (g *Manager) notify(msg systemdNotifyMsg) {
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Manager) start(ctx context.Context) {
|
||||
// Make contexts
|
||||
g.terminateCtx, g.terminateCtxCancel = context.WithCancel(ctx)
|
||||
g.shutdownCtx, g.shutdownCtxCancel = context.WithCancel(ctx)
|
||||
g.hammerCtx, g.hammerCtxCancel = context.WithCancel(ctx)
|
||||
g.managerCtx, g.managerCtxCancel = context.WithCancel(ctx)
|
||||
|
||||
// Next add pprof labels to these contexts
|
||||
g.terminateCtx = pprof.WithLabels(g.terminateCtx, pprof.Labels("graceful-lifecycle", "with-terminate"))
|
||||
g.shutdownCtx = pprof.WithLabels(g.shutdownCtx, pprof.Labels("graceful-lifecycle", "with-shutdown"))
|
||||
g.hammerCtx = pprof.WithLabels(g.hammerCtx, pprof.Labels("graceful-lifecycle", "with-hammer"))
|
||||
g.managerCtx = pprof.WithLabels(g.managerCtx, pprof.Labels("graceful-lifecycle", "with-manager"))
|
||||
|
||||
func (g *Manager) start() {
|
||||
// Now label this and all goroutines created by this goroutine with the graceful-lifecycle manager
|
||||
pprof.SetGoroutineLabels(g.managerCtx)
|
||||
defer pprof.SetGoroutineLabels(ctx)
|
||||
defer pprof.SetGoroutineLabels(g.ctx)
|
||||
|
||||
g.isChild = len(os.Getenv(listenFDsEnv)) > 0 && os.Getppid() > 1
|
||||
|
||||
// Set the running state & handle signals
|
||||
if !g.setStateTransition(stateInit, stateRunning) {
|
||||
panic("invalid graceful manager state: transition from init to running failed")
|
||||
}
|
||||
g.notify(statusMsg("Starting Gitea"))
|
||||
g.notify(pidMsg())
|
||||
go g.handleSignals(g.managerCtx)
|
||||
@@ -118,11 +58,9 @@ func (g *Manager) start(ctx context.Context) {
|
||||
startupDone := make(chan struct{})
|
||||
go func() {
|
||||
defer close(startupDone)
|
||||
// Wait till we're done getting all of the listeners and then close
|
||||
// the unused ones
|
||||
// Wait till we're done getting all the listeners and then close the unused ones
|
||||
g.createServerWaitGroup.Wait()
|
||||
// Ignore the error here there's not much we can do with it
|
||||
// They're logged in the CloseProvidedListeners function
|
||||
// Ignore the error here there's not much we can do with it, they're logged in the CloseProvidedListeners function
|
||||
_ = CloseProvidedListeners()
|
||||
g.notify(readyMsg)
|
||||
}()
|
||||
@@ -133,7 +71,7 @@ func (g *Manager) start(ctx context.Context) {
|
||||
return
|
||||
case <-g.IsShutdown():
|
||||
func() {
|
||||
// When waitgroup counter goes negative it will panic - we don't care about this so we can just ignore it.
|
||||
// When WaitGroup counter goes negative it will panic - we don't care about this so we can just ignore it.
|
||||
defer func() {
|
||||
_ = recover()
|
||||
}()
|
||||
@@ -255,29 +193,3 @@ func (g *Manager) DoGracefulRestart() {
|
||||
g.doShutdown()
|
||||
}
|
||||
}
|
||||
|
||||
// DoImmediateHammer causes an immediate hammer
|
||||
func (g *Manager) DoImmediateHammer() {
|
||||
g.notify(statusMsg("Sending immediate hammer"))
|
||||
g.doHammerTime(0 * time.Second)
|
||||
}
|
||||
|
||||
// DoGracefulShutdown causes a graceful shutdown
|
||||
func (g *Manager) DoGracefulShutdown() {
|
||||
g.lock.Lock()
|
||||
if !g.forked {
|
||||
g.lock.Unlock()
|
||||
g.notify(stoppingMsg)
|
||||
} else {
|
||||
g.lock.Unlock()
|
||||
g.notify(statusMsg("Shutting down after fork"))
|
||||
}
|
||||
g.doShutdown()
|
||||
}
|
||||
|
||||
// RegisterServer registers the running of a listening server, in the case of unix this means that the parent process can now die.
|
||||
// Any call to RegisterServer must be matched by a call to ServerDone
|
||||
func (g *Manager) RegisterServer() {
|
||||
KillParent()
|
||||
g.runningServerWaitGroup.Add(1)
|
||||
}
|
||||
|
||||
@@ -7,11 +7,9 @@
|
||||
package graceful
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"runtime/pprof"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
@@ -30,64 +28,11 @@ const (
|
||||
acceptHammerCode = svc.Accepted(hammerCode)
|
||||
)
|
||||
|
||||
// Manager manages the graceful shutdown process
|
||||
type Manager struct {
|
||||
ctx context.Context
|
||||
isChild bool
|
||||
lock *sync.RWMutex
|
||||
state state
|
||||
shutdownCtx context.Context
|
||||
hammerCtx context.Context
|
||||
terminateCtx context.Context
|
||||
managerCtx context.Context
|
||||
shutdownCtxCancel context.CancelFunc
|
||||
hammerCtxCancel context.CancelFunc
|
||||
terminateCtxCancel context.CancelFunc
|
||||
managerCtxCancel context.CancelFunc
|
||||
runningServerWaitGroup sync.WaitGroup
|
||||
createServerWaitGroup sync.WaitGroup
|
||||
terminateWaitGroup sync.WaitGroup
|
||||
shutdownRequested chan struct{}
|
||||
|
||||
toRunAtShutdown []func()
|
||||
toRunAtTerminate []func()
|
||||
}
|
||||
|
||||
func newGracefulManager(ctx context.Context) *Manager {
|
||||
manager := &Manager{
|
||||
isChild: false,
|
||||
lock: &sync.RWMutex{},
|
||||
ctx: ctx,
|
||||
}
|
||||
manager.createServerWaitGroup.Add(numberOfServersToCreate)
|
||||
manager.start()
|
||||
return manager
|
||||
}
|
||||
|
||||
func (g *Manager) start() {
|
||||
// Make contexts
|
||||
g.terminateCtx, g.terminateCtxCancel = context.WithCancel(g.ctx)
|
||||
g.shutdownCtx, g.shutdownCtxCancel = context.WithCancel(g.ctx)
|
||||
g.hammerCtx, g.hammerCtxCancel = context.WithCancel(g.ctx)
|
||||
g.managerCtx, g.managerCtxCancel = context.WithCancel(g.ctx)
|
||||
|
||||
// Next add pprof labels to these contexts
|
||||
g.terminateCtx = pprof.WithLabels(g.terminateCtx, pprof.Labels("graceful-lifecycle", "with-terminate"))
|
||||
g.shutdownCtx = pprof.WithLabels(g.shutdownCtx, pprof.Labels("graceful-lifecycle", "with-shutdown"))
|
||||
g.hammerCtx = pprof.WithLabels(g.hammerCtx, pprof.Labels("graceful-lifecycle", "with-hammer"))
|
||||
g.managerCtx = pprof.WithLabels(g.managerCtx, pprof.Labels("graceful-lifecycle", "with-manager"))
|
||||
|
||||
// Now label this and all goroutines created by this goroutine with the graceful-lifecycle manager
|
||||
pprof.SetGoroutineLabels(g.managerCtx)
|
||||
defer pprof.SetGoroutineLabels(g.ctx)
|
||||
|
||||
// Make channels
|
||||
g.shutdownRequested = make(chan struct{})
|
||||
|
||||
// Set the running state
|
||||
if !g.setStateTransition(stateInit, stateRunning) {
|
||||
panic("invalid graceful manager state: transition from init to running failed")
|
||||
}
|
||||
if skip, _ := strconv.ParseBool(os.Getenv("SKIP_MINWINSVC")); skip {
|
||||
log.Trace("Skipping SVC check as SKIP_MINWINSVC is set")
|
||||
return
|
||||
@@ -201,30 +146,6 @@ hammerLoop:
|
||||
return false, 0
|
||||
}
|
||||
|
||||
// DoImmediateHammer causes an immediate hammer
|
||||
func (g *Manager) DoImmediateHammer() {
|
||||
g.doHammerTime(0 * time.Second)
|
||||
}
|
||||
|
||||
// DoGracefulShutdown causes a graceful shutdown
|
||||
func (g *Manager) DoGracefulShutdown() {
|
||||
g.lock.Lock()
|
||||
select {
|
||||
case <-g.shutdownRequested:
|
||||
g.lock.Unlock()
|
||||
default:
|
||||
close(g.shutdownRequested)
|
||||
g.lock.Unlock()
|
||||
g.doShutdown()
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterServer registers the running of a listening server.
|
||||
// Any call to RegisterServer must be matched by a call to ServerDone
|
||||
func (g *Manager) RegisterServer() {
|
||||
g.runningServerWaitGroup.Add(1)
|
||||
}
|
||||
|
||||
func (g *Manager) awaitServer(limit time.Duration) bool {
|
||||
c := make(chan struct{})
|
||||
go func() {
|
||||
@@ -249,3 +170,11 @@ func (g *Manager) awaitServer(limit time.Duration) bool {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Manager) notify(msg systemdNotifyMsg) {
|
||||
// Windows doesn't use systemd to notify
|
||||
}
|
||||
|
||||
func KillParent() {
|
||||
// Windows doesn't need to "kill parent" because there is no graceful restart
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
// any modification to the underlying policies once it's been created.
|
||||
type Sanitizer struct {
|
||||
defaultPolicy *bluemonday.Policy
|
||||
descriptionPolicy *bluemonday.Policy
|
||||
rendererPolicies map[string]*bluemonday.Policy
|
||||
init sync.Once
|
||||
}
|
||||
@@ -41,6 +42,7 @@ func NewSanitizer() {
|
||||
func InitializeSanitizer() {
|
||||
sanitizer.rendererPolicies = map[string]*bluemonday.Policy{}
|
||||
sanitizer.defaultPolicy = createDefaultPolicy()
|
||||
sanitizer.descriptionPolicy = createRepoDescriptionPolicy()
|
||||
|
||||
for name, renderer := range renderers {
|
||||
sanitizerRules := renderer.SanitizerRules()
|
||||
@@ -161,6 +163,27 @@ func createDefaultPolicy() *bluemonday.Policy {
|
||||
return policy
|
||||
}
|
||||
|
||||
// createRepoDescriptionPolicy returns a minimal more strict policy that is used for
|
||||
// repository descriptions.
|
||||
func createRepoDescriptionPolicy() *bluemonday.Policy {
|
||||
policy := bluemonday.NewPolicy()
|
||||
|
||||
// Allow italics and bold.
|
||||
policy.AllowElements("i", "b", "em", "strong")
|
||||
|
||||
// Allow code.
|
||||
policy.AllowElements("code")
|
||||
|
||||
// Allow links
|
||||
policy.AllowAttrs("href", "target", "rel").OnElements("a")
|
||||
|
||||
// Allow classes for emojis
|
||||
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^emoji$`)).OnElements("img", "span")
|
||||
policy.AllowAttrs("aria-label").OnElements("span")
|
||||
|
||||
return policy
|
||||
}
|
||||
|
||||
func addSanitizerRules(policy *bluemonday.Policy, rules []setting.MarkupSanitizerRule) {
|
||||
for _, rule := range rules {
|
||||
if rule.AllowDataURIImages {
|
||||
@@ -176,6 +199,12 @@ func addSanitizerRules(policy *bluemonday.Policy, rules []setting.MarkupSanitize
|
||||
}
|
||||
}
|
||||
|
||||
// SanitizeDescription sanitizes the HTML generated for a repository description.
|
||||
func SanitizeDescription(s string) string {
|
||||
NewSanitizer()
|
||||
return sanitizer.descriptionPolicy.Sanitize(s)
|
||||
}
|
||||
|
||||
// Sanitize takes a string that contains a HTML fragment or document and applies policy whitelist.
|
||||
func Sanitize(s string) string {
|
||||
NewSanitizer()
|
||||
|
||||
@@ -73,6 +73,28 @@ func Test_Sanitizer(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDescriptionSanitizer(t *testing.T) {
|
||||
NewSanitizer()
|
||||
|
||||
testCases := []string{
|
||||
`<h1>Title</h1>`, `Title`,
|
||||
`<img src='img.png' alt='image'>`, ``,
|
||||
`<span class="emoji" aria-label="thumbs up">THUMBS UP</span>`, `<span class="emoji" aria-label="thumbs up">THUMBS UP</span>`,
|
||||
`<span style="color: red">Hello World</span>`, `<span>Hello World</span>`,
|
||||
`<br>`, ``,
|
||||
`<a href="https://example.com" target="_blank" rel="noopener noreferrer">https://example.com</a>`, `<a href="https://example.com" target="_blank" rel="noopener noreferrer">https://example.com</a>`,
|
||||
`<mark>Important!</mark>`, `Important!`,
|
||||
`<details>Click me! <summary>Nothing to see here.</summary></details>`, `Click me! Nothing to see here.`,
|
||||
`<input type="hidden">`, ``,
|
||||
`<b>I</b> have a <i>strong</i> <strong>opinion</strong> about <em>this</em>.`, `<b>I</b> have a <i>strong</i> <strong>opinion</strong> about <em>this</em>.`,
|
||||
`Provides alternative <code>wg(8)</code> tool`, `Provides alternative <code>wg(8)</code> tool`,
|
||||
}
|
||||
|
||||
for i := 0; i < len(testCases); i += 2 {
|
||||
assert.Equal(t, testCases[i+1], SanitizeDescription(testCases[i]))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSanitizeNonEscape(t *testing.T) {
|
||||
descStr := "<scrİpt><script>alert(document.domain)</script></scrİpt>"
|
||||
|
||||
|
||||
@@ -136,6 +136,10 @@ func (r *Route) Get(pattern string, h ...any) {
|
||||
r.Methods("GET", pattern, h...)
|
||||
}
|
||||
|
||||
func (r *Route) Options(pattern string, h ...any) {
|
||||
r.Methods("OPTIONS", pattern, h...)
|
||||
}
|
||||
|
||||
// GetOptions delegate get and options method
|
||||
func (r *Route) GetOptions(pattern string, h ...any) {
|
||||
r.Methods("GET,OPTIONS", pattern, h...)
|
||||
|
||||
@@ -3529,7 +3529,11 @@ runs.status = Status
|
||||
runs.actors_no_select = All actors
|
||||
runs.status_no_select = All status
|
||||
runs.no_results = No results matched.
|
||||
runs.no_workflows = There are no workflows yet.
|
||||
runs.no_workflows.quick_start = Don't know how to start with Gitea Action? See <a target="_blank" rel="noopener noreferrer" href="%s">the quick start guide</a>.
|
||||
runs.no_workflows.documentation = For more information on the Gitea Action, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
|
||||
runs.no_runs = The workflow has no runs yet.
|
||||
runs.empty_commit_message = (empty commit message)
|
||||
|
||||
workflow.disable = Disable Workflow
|
||||
workflow.disable_success = Workflow '%s' disabled successfully.
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
@@ -67,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
|
||||
@@ -94,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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Copyright 2016 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Package v1 Gitea API.
|
||||
// Package v1 Gitea API
|
||||
//
|
||||
// This documentation describes the Gitea API.
|
||||
//
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -30,14 +30,9 @@ func listUserOrgs(ctx *context.APIContext, u *user_model.User) {
|
||||
UserID: u.ID,
|
||||
IncludePrivate: showPrivate,
|
||||
}
|
||||
orgs, err := organization.FindOrgs(ctx, opts)
|
||||
orgs, maxResults, err := db.FindAndCount[organization.Organization](ctx, opts)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "FindOrgs", err)
|
||||
return
|
||||
}
|
||||
maxResults, err := organization.CountOrgs(ctx, opts)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "CountOrgs", err)
|
||||
ctx.Error(http.StatusInternalServerError, "db.FindAndCount[organization.Organization]", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,25 +57,26 @@ 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)
|
||||
if err2 != nil {
|
||||
ctx.InternalServerError(err)
|
||||
return
|
||||
}
|
||||
count = int(total)
|
||||
|
||||
var total int64
|
||||
// Use ListPublicKeys
|
||||
keys, err = asymkey_model.ListPublicKeys(ctx, user.ID, utils.GetListOptions(ctx))
|
||||
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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -33,6 +33,10 @@ func DummyOK(w http.ResponseWriter, req *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func DummyBadRequest(w http.ResponseWriter, req *http.Request) {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
}
|
||||
|
||||
func RobotsTxt(w http.ResponseWriter, req *http.Request) {
|
||||
robotsTxt := util.FilePathJoinAbs(setting.CustomPath, "public/robots.txt")
|
||||
if ok, _ := util.IsExist(robotsTxt); !ok {
|
||||
|
||||
@@ -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"
|
||||
@@ -59,9 +60,12 @@ func Projects(ctx *context.Context) {
|
||||
} else {
|
||||
projectType = project_model.TypeIndividual
|
||||
}
|
||||
projects, total, err := project_model.FindProjects(ctx, project_model.SearchOptions{
|
||||
OwnerID: ctx.ContextUser.ID,
|
||||
projects, total, err := db.FindAndCount[project_model.Project](ctx, project_model.SearchOptions{
|
||||
ListOptions: db.ListOptions{
|
||||
Page: page,
|
||||
PageSize: setting.UI.IssuePagingNum,
|
||||
},
|
||||
OwnerID: ctx.ContextUser.ID,
|
||||
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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -287,7 +287,7 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
|
||||
Operation: operation,
|
||||
FromTreePath: ctx.Repo.TreePath,
|
||||
TreePath: form.TreePath,
|
||||
ContentReader: strings.NewReader(form.Content),
|
||||
ContentReader: strings.NewReader(strings.ReplaceAll(form.Content, "\r", "")),
|
||||
},
|
||||
},
|
||||
Signoff: form.Signoff,
|
||||
|
||||
@@ -569,9 +569,9 @@ 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{
|
||||
projects, err := db.Find[project_model.Project](ctx, project_model.SearchOptions{
|
||||
ListOptions: db.ListOptionsAll,
|
||||
RepoID: repo.ID,
|
||||
Page: -1,
|
||||
IsClosed: util.OptionalBoolFalse,
|
||||
Type: project_model.TypeRepository,
|
||||
})
|
||||
@@ -579,9 +579,9 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) {
|
||||
ctx.ServerError("GetProjects", err)
|
||||
return
|
||||
}
|
||||
projects2, _, err := project_model.FindProjects(ctx, project_model.SearchOptions{
|
||||
projects2, err := db.Find[project_model.Project](ctx, project_model.SearchOptions{
|
||||
ListOptions: db.ListOptionsAll,
|
||||
OwnerID: repo.OwnerID,
|
||||
Page: -1,
|
||||
IsClosed: util.OptionalBoolFalse,
|
||||
Type: repoOwnerType,
|
||||
})
|
||||
@@ -592,9 +592,9 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) {
|
||||
|
||||
ctx.Data["OpenProjects"] = append(projects, projects2...)
|
||||
|
||||
projects, _, err = project_model.FindProjects(ctx, project_model.SearchOptions{
|
||||
projects, err = db.Find[project_model.Project](ctx, project_model.SearchOptions{
|
||||
ListOptions: db.ListOptionsAll,
|
||||
RepoID: repo.ID,
|
||||
Page: -1,
|
||||
IsClosed: util.OptionalBoolTrue,
|
||||
Type: project_model.TypeRepository,
|
||||
})
|
||||
@@ -602,9 +602,9 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) {
|
||||
ctx.ServerError("GetProjects", err)
|
||||
return
|
||||
}
|
||||
projects2, _, err = project_model.FindProjects(ctx, project_model.SearchOptions{
|
||||
projects2, err = db.Find[project_model.Project](ctx, project_model.SearchOptions{
|
||||
ListOptions: db.ListOptionsAll,
|
||||
OwnerID: repo.OwnerID,
|
||||
Page: -1,
|
||||
IsClosed: util.OptionalBoolTrue,
|
||||
Type: repoOwnerType,
|
||||
})
|
||||
|
||||
@@ -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"
|
||||
@@ -71,9 +72,12 @@ func Projects(ctx *context.Context) {
|
||||
total = repo.NumClosedProjects
|
||||
}
|
||||
|
||||
projects, count, err := project_model.FindProjects(ctx, project_model.SearchOptions{
|
||||
RepoID: repo.ID,
|
||||
projects, count, err := db.FindAndCount[project_model.Project](ctx, project_model.SearchOptions{
|
||||
ListOptions: db.ListOptions{
|
||||
PageSize: setting.UI.IssuePagingNum,
|
||||
Page: page,
|
||||
},
|
||||
RepoID: repo.ID,
|
||||
IsClosed: util.OptionalBoolOf(isShowClosed),
|
||||
OrderBy: project_model.GetSearchOrderByBySortType(sortType),
|
||||
Type: project_model.TypeRepository,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -89,18 +84,13 @@ func RunnerDetails(ctx *context.Context, page int, runnerID, ownerID, repoID int
|
||||
RunnerID: runner.ID,
|
||||
}
|
||||
|
||||
count, err := actions_model.CountTasks(ctx, opts)
|
||||
tasks, count, err := db.FindAndCount[actions_model.ActionTask](ctx, opts)
|
||||
if err != nil {
|
||||
ctx.ServerError("CountTasks", err)
|
||||
return
|
||||
}
|
||||
|
||||
tasks, err := actions_model.FindTasks(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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -60,7 +60,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,
|
||||
})
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -103,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)
|
||||
@@ -409,5 +424,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})
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
@@ -68,14 +69,17 @@ 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
|
||||
}
|
||||
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
|
||||
@@ -107,7 +111,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,
|
||||
})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -533,8 +533,10 @@ func registerRoutes(m *web.Route) {
|
||||
m.Post("/authorize", web.Bind(forms.AuthorizationForm{}), auth.AuthorizeOAuth)
|
||||
}, ignSignInAndCsrf, reqSignIn)
|
||||
m.Get("/login/oauth/userinfo", ignSignInAndCsrf, auth.InfoOAuth)
|
||||
m.Options("/login/oauth/access_token", CorsHandler(), misc.DummyBadRequest)
|
||||
m.Post("/login/oauth/access_token", CorsHandler(), web.Bind(forms.AccessTokenForm{}), ignSignInAndCsrf, auth.AccessTokenOAuth)
|
||||
m.Get("/login/oauth/keys", ignSignInAndCsrf, auth.OIDCKeys)
|
||||
m.Options("/login/oauth/introspect", CorsHandler(), misc.DummyBadRequest)
|
||||
m.Post("/login/oauth/introspect", CorsHandler(), web.Bind(forms.IntrospectTokenForm{}), ignSignInAndCsrf, auth.IntrospectOAuth)
|
||||
|
||||
m.Group("/user/settings", func() {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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()),
|
||||
})
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -11,6 +11,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"
|
||||
@@ -298,7 +299,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
|
||||
@@ -377,7 +378,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,
|
||||
@@ -408,7 +409,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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user