diff --git a/.editorconfig b/.editorconfig
index c0946ac997..e23e4cd649 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -17,6 +17,7 @@ insert_final_newline = false
[templates/swagger/v1_json.tmpl]
indent_style = space
+insert_final_newline = false
[templates/user/auth/oidc_wellknown.tmpl]
indent_style = space
diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index 83410dc07c..f2af1709e4 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -336,7 +336,7 @@ module.exports = {
'@typescript-eslint/no-unsafe-unary-minus': [2],
'@typescript-eslint/no-unused-expressions': [0],
'@typescript-eslint/no-unused-vars': [2, {vars: 'all', args: 'all', caughtErrors: 'all', ignoreRestSiblings: false, argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_', destructuredArrayIgnorePattern: '^_'}],
- '@typescript-eslint/no-use-before-define': [0],
+ '@typescript-eslint/no-use-before-define': [2, {functions: false, classes: true, variables: true, allowNamedExports: true, typedefs: false, enums: false, ignoreTypeReferences: true}],
'@typescript-eslint/no-useless-constructor': [0],
'@typescript-eslint/no-useless-empty-export': [0],
'@typescript-eslint/no-wrapper-object-types': [2],
@@ -693,7 +693,7 @@ module.exports = {
'no-unused-labels': [2],
'no-unused-private-class-members': [2],
'no-unused-vars': [0], // handled by @typescript-eslint/no-unused-vars
- 'no-use-before-define': [2, {functions: false, classes: true, variables: true, allowNamedExports: true}],
+ 'no-use-before-define': [0], // handled by @typescript-eslint/no-use-before-define
'no-use-extend-native/no-use-extend-native': [2],
'no-useless-backreference': [2],
'no-useless-call': [2],
diff --git a/.github/labeler.yml b/.github/labeler.yml
index 46efbcb194..0af43cd029 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -41,7 +41,7 @@ modifies/internal:
- ".dockerignore"
- "docker/**"
- ".editorconfig"
- - ".eslintrc.yaml"
+ - ".eslintrc.cjs"
- ".golangci.yml"
- ".gitpod.yml"
- ".markdownlint.yaml"
@@ -49,7 +49,7 @@ modifies/internal:
- "stylelint.config.js"
- ".yamllint.yaml"
- ".github/**"
- - ".gitea/"
+ - ".gitea/**"
- ".devcontainer/**"
- "build.go"
- "build/**"
@@ -73,9 +73,9 @@ modifies/go:
modifies/frontend:
- changed-files:
- any-glob-to-any-file:
- - "**/*.js"
- - "**/*.ts"
- - "**/*.vue"
+ - "*.js"
+ - "*.ts"
+ - "web_src/**"
docs-update-needed:
- changed-files:
diff --git a/.github/workflows/files-changed.yml b/.github/workflows/files-changed.yml
index 7c1fb02442..be27537924 100644
--- a/.github/workflows/files-changed.yml
+++ b/.github/workflows/files-changed.yml
@@ -51,14 +51,16 @@ jobs:
- "options/locale/locale_en-US.ini"
frontend:
- - "**/*.js"
+ - "*.js"
+ - "*.ts"
- "web_src/**"
+ - "tools/*.js"
+ - "tools/*.ts"
- "assets/emoji.json"
- "package.json"
- "package-lock.json"
- "Makefile"
- - ".eslintrc.yaml"
- - "stylelint.config.js"
+ - ".eslintrc.cjs"
- ".npmrc"
docs:
@@ -85,6 +87,7 @@ jobs:
swagger:
- "templates/swagger/v1_json.tmpl"
+ - "templates/swagger/v1_input.json"
- "Makefile"
- "package.json"
- "package-lock.json"
diff --git a/.github/workflows/release-tag-version.yml b/.github/workflows/release-tag-version.yml
index f67b76f408..08bb9baecf 100644
--- a/.github/workflows/release-tag-version.yml
+++ b/.github/workflows/release-tag-version.yml
@@ -88,9 +88,9 @@ jobs:
# 1.2
# 1.2.3
tags: |
+ type=semver,pattern={{version}}
type=semver,pattern={{major}}
type=semver,pattern={{major}}.{{minor}}
- type=semver,pattern={{version}}
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
@@ -126,9 +126,9 @@ jobs:
# 1.2
# 1.2.3
tags: |
+ type=semver,pattern={{version}}
type=semver,pattern={{major}}
type=semver,pattern={{major}}.{{minor}}
- type=semver,pattern={{version}}
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
diff --git a/Makefile b/Makefile
index 89a6f1261f..d4b416156f 100644
--- a/Makefile
+++ b/Makefile
@@ -165,10 +165,8 @@ ifdef DEPS_PLAYWRIGHT
endif
SWAGGER_SPEC := templates/swagger/v1_json.tmpl
-SWAGGER_SPEC_S_TMPL := s|"basePath": *"/api/v1"|"basePath": "{{AppSubUrl \| JSEscape}}/api/v1"|g
-SWAGGER_SPEC_S_JSON := s|"basePath": *"{{AppSubUrl \| JSEscape}}/api/v1"|"basePath": "/api/v1"|g
+SWAGGER_SPEC_INPUT := templates/swagger/v1_input.json
SWAGGER_EXCLUDE := code.gitea.io/sdk
-SWAGGER_NEWLINE_COMMAND := -e '$$a\'
TEST_MYSQL_HOST ?= mysql:3306
TEST_MYSQL_DBNAME ?= testgitea
@@ -271,10 +269,8 @@ endif
.PHONY: generate-swagger
generate-swagger: $(SWAGGER_SPEC) ## generate the swagger spec from code comments
-$(SWAGGER_SPEC): $(GO_SOURCES_NO_BINDATA)
- $(GO) run $(SWAGGER_PACKAGE) generate spec -x "$(SWAGGER_EXCLUDE)" -o './$(SWAGGER_SPEC)'
- $(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
- $(SED_INPLACE) $(SWAGGER_NEWLINE_COMMAND) './$(SWAGGER_SPEC)'
+$(SWAGGER_SPEC): $(GO_SOURCES_NO_BINDATA) $(SWAGGER_SPEC_INPUT)
+ $(GO) run $(SWAGGER_PACKAGE) generate spec --exclude "$(SWAGGER_EXCLUDE)" --input "$(SWAGGER_SPEC_INPUT)" --output './$(SWAGGER_SPEC)'
.PHONY: swagger-check
swagger-check: generate-swagger
@@ -287,9 +283,11 @@ swagger-check: generate-swagger
.PHONY: swagger-validate
swagger-validate: ## check if the swagger spec is valid
- $(SED_INPLACE) '$(SWAGGER_SPEC_S_JSON)' './$(SWAGGER_SPEC)'
+ @# swagger "validate" requires that the "basePath" must start with a slash, but we are using Golang template "{{...}}"
+ @$(SED_INPLACE) -E -e 's|"basePath":( *)"(.*)"|"basePath":\1"/\2"|g' './$(SWAGGER_SPEC)' # add a prefix slash to basePath
+ @# FIXME: there are some warnings
$(GO) run $(SWAGGER_PACKAGE) validate './$(SWAGGER_SPEC)'
- $(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
+ @$(SED_INPLACE) -E -e 's|"basePath":( *)"/(.*)"|"basePath":\1"\2"|g' './$(SWAGGER_SPEC)' # remove the prefix slash from basePath
.PHONY: checks
checks: checks-frontend checks-backend ## run various consistency checks
@@ -380,6 +378,7 @@ lint-go-gopls: ## lint go files with gopls
.PHONY: lint-editorconfig
lint-editorconfig:
+ @echo "Running editorconfig check..."
@$(GO) run $(EDITORCONFIG_CHECKER_PACKAGE) $(EDITORCONFIG_FILES)
.PHONY: lint-actions
@@ -471,7 +470,9 @@ tidy-check: tidy
go-licenses: $(GO_LICENSE_FILE) ## regenerate go licenses
$(GO_LICENSE_FILE): go.mod go.sum
- -$(GO) run $(GO_LICENSES_PACKAGE) save . --force --save_path=$(GO_LICENSE_TMP_DIR) 2>/dev/null
+ @rm -rf $(GO_LICENSE_FILE)
+ $(GO) install $(GO_LICENSES_PACKAGE)
+ -GOOS=linux CGO_ENABLED=1 go-licenses save . --force --save_path=$(GO_LICENSE_TMP_DIR) 2>/dev/null
$(GO) run build/generate-go-licenses.go $(GO_LICENSE_TMP_DIR) $(GO_LICENSE_FILE)
@rm -rf $(GO_LICENSE_TMP_DIR)
diff --git a/cmd/web_acme.go b/cmd/web_acme.go
index 5daf0f55f2..bca4ae0212 100644
--- a/cmd/web_acme.go
+++ b/cmd/web_acme.go
@@ -54,10 +54,6 @@ func runACME(listenAddr string, m http.Handler) error {
altTLSALPNPort = p
}
- // FIXME: this path is not right, it uses "AppWorkPath" incorrectly, and writes the data into "AppWorkPath/https"
- // Ideally it should migrate to AppDataPath write to "AppDataPath/https"
- certmagic.Default.Storage = &certmagic.FileStorage{Path: setting.AcmeLiveDirectory}
- magic := certmagic.NewDefault()
// Try to use private CA root if provided, otherwise defaults to system's trust
var certPool *x509.CertPool
if setting.AcmeCARoot != "" {
@@ -67,7 +63,13 @@ func runACME(listenAddr string, m http.Handler) error {
log.Warn("Failed to parse CA Root certificate, using default CA trust: %v", err)
}
}
- myACME := certmagic.NewACMEIssuer(magic, certmagic.ACMEIssuer{
+ // FIXME: this path is not right, it uses "AppWorkPath" incorrectly, and writes the data into "AppWorkPath/https"
+ // Ideally it should migrate to AppDataPath write to "AppDataPath/https"
+ // And one more thing, no idea why we should set the global default variables here
+ // But it seems that the current ACME code needs these global variables to make renew work.
+ // Otherwise, "renew" will use incorrect storage path
+ certmagic.Default.Storage = &certmagic.FileStorage{Path: setting.AcmeLiveDirectory}
+ certmagic.DefaultACME = certmagic.ACMEIssuer{
CA: setting.AcmeURL,
TrustedRoots: certPool,
Email: setting.AcmeEmail,
@@ -77,8 +79,10 @@ func runACME(listenAddr string, m http.Handler) error {
ListenHost: setting.HTTPAddr,
AltTLSALPNPort: altTLSALPNPort,
AltHTTPPort: altHTTPPort,
- })
+ }
+ magic := certmagic.NewDefault()
+ myACME := certmagic.NewACMEIssuer(magic, certmagic.DefaultACME)
magic.Issuers = []certmagic.Issuer{myACME}
// this obtains certificates or renews them if necessary
diff --git a/go.mod b/go.mod
index ca5d47aff4..4b7025eb92 100644
--- a/go.mod
+++ b/go.mod
@@ -8,7 +8,7 @@ go 1.24
godebug x509negativeserial=1
require (
- code.gitea.io/actions-proto-go v0.4.0
+ code.gitea.io/actions-proto-go v0.4.1
code.gitea.io/gitea-vet v0.2.3
code.gitea.io/sdk/gitea v0.20.0
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
@@ -24,7 +24,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.0
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
- github.com/ProtonMail/go-crypto v1.1.5
+ github.com/ProtonMail/go-crypto v1.1.6
github.com/PuerkitoBio/goquery v1.10.2
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.3
github.com/alecthomas/chroma/v2 v2.15.0
@@ -117,10 +117,10 @@ require (
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
github.com/yuin/goldmark-meta v1.1.0
gitlab.com/gitlab-org/api/client-go v0.123.0
- golang.org/x/crypto v0.33.0
+ golang.org/x/crypto v0.35.0
golang.org/x/image v0.24.0
golang.org/x/net v0.35.0
- golang.org/x/oauth2 v0.26.0
+ golang.org/x/oauth2 v0.27.0
golang.org/x/sync v0.11.0
golang.org/x/sys v0.30.0
golang.org/x/text v0.22.0
@@ -318,7 +318,7 @@ replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0
-replace github.com/nektos/act => gitea.com/gitea/act v0.261.3
+replace github.com/nektos/act => gitea.com/gitea/act v0.261.4
// TODO: the only difference is in `PutObject`: the fork doesn't use `NewVerifyingReader(r, sha256.New(), oid, expectedSize)`, need to figure out why
replace github.com/charmbracelet/git-lfs-transfer => gitea.com/gitea/git-lfs-transfer v0.2.0
diff --git a/go.sum b/go.sum
index f2bae16405..18a586e404 100644
--- a/go.sum
+++ b/go.sum
@@ -1,7 +1,7 @@
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
-code.gitea.io/actions-proto-go v0.4.0 h1:OsPBPhodXuQnsspG1sQ4eRE1PeoZyofd7+i73zCwnsU=
-code.gitea.io/actions-proto-go v0.4.0/go.mod h1:mn7Wkqz6JbnTOHQpot3yDeHx+O5C9EGhMEE+htvHBas=
+code.gitea.io/actions-proto-go v0.4.1 h1:l0EYhjsgpUe/1VABo2eK7zcoNX2W44WOnb0MSLrKfls=
+code.gitea.io/actions-proto-go v0.4.1/go.mod h1:mn7Wkqz6JbnTOHQpot3yDeHx+O5C9EGhMEE+htvHBas=
code.gitea.io/gitea-vet v0.2.3 h1:gdFmm6WOTM65rE8FUBTRzeQZYzXePKSSB1+r574hWwI=
code.gitea.io/gitea-vet v0.2.3/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE=
code.gitea.io/sdk/gitea v0.20.0 h1:Zm/QDwwZK1awoM4AxdjeAQbxolzx2rIP8dDfmKu+KoU=
@@ -16,8 +16,8 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
-gitea.com/gitea/act v0.261.3 h1:BhiYpGJQKGq0XMYYICCYAN4KnsEWHyLbA6dxhZwFcV4=
-gitea.com/gitea/act v0.261.3/go.mod h1:Pg5C9kQY1CEA3QjthjhlrqOC/QOT5NyWNjOjRHw23Ok=
+gitea.com/gitea/act v0.261.4 h1:Tf9eLlvsYFtKcpuxlMvf9yT3g4Hshb2Beqw6C1STuH8=
+gitea.com/gitea/act v0.261.4/go.mod h1:Pg5C9kQY1CEA3QjthjhlrqOC/QOT5NyWNjOjRHw23Ok=
gitea.com/gitea/git-lfs-transfer v0.2.0 h1:baHaNoBSRaeq/xKayEXwiDQtlIjps4Ac/Ll4KqLMB40=
gitea.com/gitea/git-lfs-transfer v0.2.0/go.mod h1:UrXUCm3xLQkq15fu7qlXHUMlrhdlXHoi13KH2Dfiits=
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed h1:EZZBtilMLSZNWtHHcgq2mt6NSGhJSZBuduAlinMEmso=
@@ -71,8 +71,8 @@ github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSC
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
-github.com/ProtonMail/go-crypto v1.1.5 h1:eoAQfK2dwL+tFSFpr7TbOaPNUbPiJj4fLYwwGE1FQO4=
-github.com/ProtonMail/go-crypto v1.1.5/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
+github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw=
+github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/PuerkitoBio/goquery v1.10.2 h1:7fh2BdHcG6VFZsK7toXBT/Bh1z5Wmy8Q9MV9HqT2AM8=
github.com/PuerkitoBio/goquery v1.10.2/go.mod h1:0guWGjcLu9AYC7C1GHnpysHy056u9aEkUHwhdnePMCU=
github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
@@ -831,8 +831,9 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
-golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
+golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
+golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa h1:t2QcU6V556bFjYgu4L6C+6VrCPyJZ+eyRsABUPs1mz4=
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk=
golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ=
@@ -868,8 +869,8 @@ golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
-golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE=
-golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
+golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
+golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
diff --git a/models/activities/action.go b/models/activities/action.go
index adc442b88b..52dffe07fd 100644
--- a/models/activities/action.go
+++ b/models/activities/action.go
@@ -454,6 +454,24 @@ func ActivityReadable(user, doer *user_model.User) bool {
doer != nil && (doer.IsAdmin || user.ID == doer.ID)
}
+func FeedDateCond(opts GetFeedsOptions) builder.Cond {
+ cond := builder.NewCond()
+ if opts.Date == "" {
+ return cond
+ }
+
+ dateLow, err := time.ParseInLocation("2006-01-02", opts.Date, setting.DefaultUILocation)
+ if err != nil {
+ log.Warn("Unable to parse %s, filter not applied: %v", opts.Date, err)
+ } else {
+ dateHigh := dateLow.Add(86399000000000) // 23h59m59s
+
+ cond = cond.And(builder.Gte{"`action`.created_unix": dateLow.Unix()})
+ cond = cond.And(builder.Lte{"`action`.created_unix": dateHigh.Unix()})
+ }
+ return cond
+}
+
func ActivityQueryCondition(ctx context.Context, opts GetFeedsOptions) (builder.Cond, error) {
cond := builder.NewCond()
@@ -534,17 +552,7 @@ func ActivityQueryCondition(ctx context.Context, opts GetFeedsOptions) (builder.
cond = cond.And(builder.Eq{"is_deleted": false})
}
- if opts.Date != "" {
- dateLow, err := time.ParseInLocation("2006-01-02", opts.Date, setting.DefaultUILocation)
- if err != nil {
- log.Warn("Unable to parse %s, filter not applied: %v", opts.Date, err)
- } else {
- dateHigh := dateLow.Add(86399000000000) // 23h59m59s
-
- cond = cond.And(builder.Gte{"`action`.created_unix": dateLow.Unix()})
- cond = cond.And(builder.Lte{"`action`.created_unix": dateHigh.Unix()})
- }
- }
+ cond = cond.And(FeedDateCond(opts))
return cond, nil
}
diff --git a/models/activities/action_list.go b/models/activities/action_list.go
index 5f9acb8f2a..f7ea48f03e 100644
--- a/models/activities/action_list.go
+++ b/models/activities/action_list.go
@@ -208,9 +208,31 @@ func GetFeeds(ctx context.Context, opts GetFeedsOptions) (ActionList, int64, err
return nil, 0, fmt.Errorf("need at least one of these filters: RequestedUser, RequestedTeam, RequestedRepo")
}
- cond, err := ActivityQueryCondition(ctx, opts)
- if err != nil {
- return nil, 0, err
+ var err error
+ var cond builder.Cond
+ // if the actor is the requested user or is an administrator, we can skip the ActivityQueryCondition
+ if opts.Actor != nil && opts.RequestedUser != nil && (opts.Actor.IsAdmin || opts.Actor.ID == opts.RequestedUser.ID) {
+ cond = builder.Eq{
+ "user_id": opts.RequestedUser.ID,
+ }.And(
+ FeedDateCond(opts),
+ )
+
+ if !opts.IncludeDeleted {
+ cond = cond.And(builder.Eq{"is_deleted": false})
+ }
+
+ if !opts.IncludePrivate {
+ cond = cond.And(builder.Eq{"is_private": false})
+ }
+ if opts.OnlyPerformedBy {
+ cond = cond.And(builder.Eq{"act_user_id": opts.RequestedUser.ID})
+ }
+ } else {
+ cond, err = ActivityQueryCondition(ctx, opts)
+ if err != nil {
+ return nil, 0, err
+ }
}
actions := make([]*Action, 0, opts.PageSize)
diff --git a/models/admin/task.go b/models/admin/task.go
index 10f8e6d570..0541a8ec78 100644
--- a/models/admin/task.go
+++ b/models/admin/task.go
@@ -44,7 +44,7 @@ func init() {
// TranslatableMessage represents JSON struct that can be translated with a Locale
type TranslatableMessage struct {
Format string
- Args []any `json:"omitempty"`
+ Args []any `json:",omitempty"`
}
// LoadRepo loads repository of the task
diff --git a/models/auth/access_token_scope.go b/models/auth/access_token_scope.go
index 897ff3fc9e..0e5b2e96e6 100644
--- a/models/auth/access_token_scope.go
+++ b/models/auth/access_token_scope.go
@@ -5,6 +5,7 @@ package auth
import (
"fmt"
+ "slices"
"strings"
"code.gitea.io/gitea/models/perm"
@@ -14,7 +15,7 @@ import (
type AccessTokenScopeCategory int
const (
- AccessTokenScopeCategoryActivityPub = iota
+ AccessTokenScopeCategoryActivityPub AccessTokenScopeCategory = iota
AccessTokenScopeCategoryAdmin
AccessTokenScopeCategoryMisc // WARN: this is now just a placeholder, don't remove it which will change the following values
AccessTokenScopeCategoryNotification
@@ -193,6 +194,14 @@ var accessTokenScopes = map[AccessTokenScopeLevel]map[AccessTokenScopeCategory]A
},
}
+func GetAccessTokenCategories() (res []string) {
+ for _, cat := range accessTokenScopes[Read] {
+ res = append(res, strings.TrimPrefix(string(cat), "read:"))
+ }
+ slices.Sort(res)
+ return res
+}
+
// GetRequiredScopes gets the specific scopes for a given level and categories
func GetRequiredScopes(level AccessTokenScopeLevel, scopeCategories ...AccessTokenScopeCategory) []AccessTokenScope {
scopes := make([]AccessTokenScope, 0, len(scopeCategories))
@@ -270,6 +279,9 @@ func (s AccessTokenScope) parse() (accessTokenScopeBitmap, error) {
// StringSlice returns the AccessTokenScope as a []string
func (s AccessTokenScope) StringSlice() []string {
+ if s == "" {
+ return nil
+ }
return strings.Split(string(s), ",")
}
diff --git a/models/auth/access_token_scope_test.go b/models/auth/access_token_scope_test.go
index a6097e45d7..9e4aa83633 100644
--- a/models/auth/access_token_scope_test.go
+++ b/models/auth/access_token_scope_test.go
@@ -17,6 +17,7 @@ type scopeTestNormalize struct {
}
func TestAccessTokenScope_Normalize(t *testing.T) {
+ assert.Equal(t, []string{"activitypub", "admin", "issue", "misc", "notification", "organization", "package", "repository", "user"}, GetAccessTokenCategories())
tests := []scopeTestNormalize{
{"", "", nil},
{"write:misc,write:notification,read:package,write:notification,public-only", "public-only,write:misc,write:notification,read:package", nil},
@@ -25,7 +26,7 @@ func TestAccessTokenScope_Normalize(t *testing.T) {
{"write:activitypub,write:admin,write:misc,write:notification,write:organization,write:package,write:issue,write:repository,write:user,public-only", "public-only,all", nil},
}
- for _, scope := range []string{"activitypub", "admin", "misc", "notification", "organization", "package", "issue", "repository", "user"} {
+ for _, scope := range GetAccessTokenCategories() {
tests = append(tests,
scopeTestNormalize{AccessTokenScope(fmt.Sprintf("read:%s", scope)), AccessTokenScope(fmt.Sprintf("read:%s", scope)), nil},
scopeTestNormalize{AccessTokenScope(fmt.Sprintf("write:%s", scope)), AccessTokenScope(fmt.Sprintf("write:%s", scope)), nil},
@@ -59,7 +60,7 @@ func TestAccessTokenScope_HasScope(t *testing.T) {
{"public-only", "read:issue", false, nil},
}
- for _, scope := range []string{"activitypub", "admin", "misc", "notification", "organization", "package", "issue", "repository", "user"} {
+ for _, scope := range GetAccessTokenCategories() {
tests = append(tests,
scopeTestHasScope{
AccessTokenScope(fmt.Sprintf("read:%s", scope)),
diff --git a/models/issues/pull_list.go b/models/issues/pull_list.go
index 1ddb94e566..b685175f8e 100644
--- a/models/issues/pull_list.go
+++ b/models/issues/pull_list.go
@@ -28,11 +28,16 @@ type PullRequestsOptions struct {
Labels []int64
MilestoneID int64
PosterID int64
+ BaseBranch string
}
func listPullRequestStatement(ctx context.Context, baseRepoID int64, opts *PullRequestsOptions) *xorm.Session {
sess := db.GetEngine(ctx).Where("pull_request.base_repo_id=?", baseRepoID)
+ if opts.BaseBranch != "" {
+ sess.And("pull_request.base_branch=?", opts.BaseBranch)
+ }
+
sess.Join("INNER", "issue", "pull_request.issue_id = issue.id")
switch opts.State {
case "closed", "open":
@@ -56,7 +61,7 @@ func listPullRequestStatement(ctx context.Context, baseRepoID int64, opts *PullR
}
// GetUnmergedPullRequestsByHeadInfo returns all pull requests that are open and has not been merged
-func GetUnmergedPullRequestsByHeadInfo(ctx context.Context, repoID int64, branch string) ([]*PullRequest, error) {
+func GetUnmergedPullRequestsByHeadInfo(ctx context.Context, repoID int64, branch string) (PullRequestList, error) {
prs := make([]*PullRequest, 0, 2)
sess := db.GetEngine(ctx).
Join("INNER", "issue", "issue.id = pull_request.issue_id").
@@ -111,7 +116,7 @@ func HasUnmergedPullRequestsByHeadInfo(ctx context.Context, repoID int64, branch
// GetUnmergedPullRequestsByBaseInfo returns all pull requests that are open and has not been merged
// by given base information (repo and branch).
-func GetUnmergedPullRequestsByBaseInfo(ctx context.Context, repoID int64, branch string) ([]*PullRequest, error) {
+func GetUnmergedPullRequestsByBaseInfo(ctx context.Context, repoID int64, branch string) (PullRequestList, error) {
prs := make([]*PullRequest, 0, 2)
return prs, db.GetEngine(ctx).
Where("base_repo_id=? AND base_branch=? AND has_merged=? AND issue.is_closed=?",
diff --git a/models/issues/pull_list_test.go b/models/issues/pull_list_test.go
index c7a898ca4e..f5553e7885 100644
--- a/models/issues/pull_list_test.go
+++ b/models/issues/pull_list_test.go
@@ -16,11 +16,11 @@ import (
func TestPullRequestList_LoadAttributes(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- prs := []*issues_model.PullRequest{
+ prs := issues_model.PullRequestList{
unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}),
unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}),
}
- assert.NoError(t, issues_model.PullRequestList(prs).LoadAttributes(db.DefaultContext))
+ assert.NoError(t, prs.LoadAttributes(db.DefaultContext))
for _, pr := range prs {
assert.NotNil(t, pr.Issue)
assert.Equal(t, pr.IssueID, pr.Issue.ID)
@@ -32,11 +32,11 @@ func TestPullRequestList_LoadAttributes(t *testing.T) {
func TestPullRequestList_LoadReviewCommentsCounts(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- prs := []*issues_model.PullRequest{
+ prs := issues_model.PullRequestList{
unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}),
unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}),
}
- reviewComments, err := issues_model.PullRequestList(prs).LoadReviewCommentsCounts(db.DefaultContext)
+ reviewComments, err := prs.LoadReviewCommentsCounts(db.DefaultContext)
assert.NoError(t, err)
assert.Len(t, reviewComments, 2)
for _, pr := range prs {
@@ -47,11 +47,11 @@ func TestPullRequestList_LoadReviewCommentsCounts(t *testing.T) {
func TestPullRequestList_LoadReviews(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- prs := []*issues_model.PullRequest{
+ prs := issues_model.PullRequestList{
unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}),
unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}),
}
- reviewList, err := issues_model.PullRequestList(prs).LoadReviews(db.DefaultContext)
+ reviewList, err := prs.LoadReviews(db.DefaultContext)
assert.NoError(t, err)
// 1, 7, 8, 9, 10, 22
assert.Len(t, reviewList, 6)
diff --git a/models/organization/org_list.go b/models/organization/org_list.go
index 4c4168af1f..78ac0e704a 100644
--- a/models/organization/org_list.go
+++ b/models/organization/org_list.go
@@ -124,6 +124,7 @@ func GetUserOrgsList(ctx context.Context, user *user_model.User) ([]*MinimalOrg,
if err := db.GetEngine(ctx).Select(columnsStr).
Table("user").
Where(builder.In("`user`.`id`", queryUserOrgIDs(user.ID, true))).
+ OrderBy("`user`.lower_name ASC").
Find(&orgs); err != nil {
return nil, err
}
diff --git a/models/packages/descriptor.go b/models/packages/descriptor.go
index 803b73c968..d251fcc4a9 100644
--- a/models/packages/descriptor.go
+++ b/models/packages/descriptor.go
@@ -110,9 +110,12 @@ func GetPackageDescriptor(ctx context.Context, pv *PackageVersion) (*PackageDesc
if err != nil {
return nil, err
}
- repository, err := repo_model.GetRepositoryByID(ctx, p.RepoID)
- if err != nil && !repo_model.IsErrRepoNotExist(err) {
- return nil, err
+ var repository *repo_model.Repository
+ if p.RepoID > 0 {
+ repository, err = repo_model.GetRepositoryByID(ctx, p.RepoID)
+ if err != nil && !repo_model.IsErrRepoNotExist(err) {
+ return nil, err
+ }
}
creator, err := user_model.GetUserByID(ctx, pv.CreatorID)
if err != nil {
diff --git a/models/repo/repo.go b/models/repo/repo.go
index 4e27dbaf14..d42792faa2 100644
--- a/models/repo/repo.go
+++ b/models/repo/repo.go
@@ -646,13 +646,15 @@ func (repo *Repository) DescriptionHTML(ctx context.Context) template.HTML {
type CloneLink struct {
SSH string
HTTPS string
+ Tea string
}
-// ComposeHTTPSCloneURL returns HTTPS clone URL based on given owner and repository name.
+// ComposeHTTPSCloneURL returns HTTPS clone URL based on the given owner and repository name.
func ComposeHTTPSCloneURL(ctx context.Context, owner, repo string) string {
return fmt.Sprintf("%s%s/%s.git", httplib.GuessCurrentAppURL(ctx), url.PathEscape(owner), url.PathEscape(repo))
}
+// ComposeSSHCloneURL returns SSH clone URL based on the given owner and repository name.
func ComposeSSHCloneURL(doer *user_model.User, ownerName, repoName string) string {
sshUser := setting.SSH.User
sshDomain := setting.SSH.Domain
@@ -686,11 +688,17 @@ func ComposeSSHCloneURL(doer *user_model.User, ownerName, repoName string) strin
return fmt.Sprintf("%s@%s:%s/%s.git", sshUser, sshHost, url.PathEscape(ownerName), url.PathEscape(repoName))
}
+// ComposeTeaCloneCommand returns Tea CLI clone command based on the given owner and repository name.
+func ComposeTeaCloneCommand(ctx context.Context, owner, repo string) string {
+ return fmt.Sprintf("tea clone %s/%s", url.PathEscape(owner), url.PathEscape(repo))
+}
+
func (repo *Repository) cloneLink(ctx context.Context, doer *user_model.User, repoPathName string) *CloneLink {
- cl := new(CloneLink)
- cl.SSH = ComposeSSHCloneURL(doer, repo.OwnerName, repoPathName)
- cl.HTTPS = ComposeHTTPSCloneURL(ctx, repo.OwnerName, repoPathName)
- return cl
+ return &CloneLink{
+ SSH: ComposeSSHCloneURL(doer, repo.OwnerName, repoPathName),
+ HTTPS: ComposeHTTPSCloneURL(ctx, repo.OwnerName, repoPathName),
+ Tea: ComposeTeaCloneCommand(ctx, repo.OwnerName, repoPathName),
+ }
}
// CloneLink returns clone URLs of repository.
diff --git a/models/repo/user_repo.go b/models/repo/user_repo.go
index a9b1360df1..232087d865 100644
--- a/models/repo/user_repo.go
+++ b/models/repo/user_repo.go
@@ -5,6 +5,7 @@ package repo
import (
"context"
+ "strings"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/perm"
@@ -149,9 +150,9 @@ func GetRepoAssignees(ctx context.Context, repo *Repository) (_ []*user_model.Us
// If isShowFullName is set to true, also include full name prefix search
func GetIssuePostersWithSearch(ctx context.Context, repo *Repository, isPull bool, search string, isShowFullName bool) ([]*user_model.User, error) {
users := make([]*user_model.User, 0, 30)
- var prefixCond builder.Cond = builder.Like{"name", search + "%"}
+ var prefixCond builder.Cond = builder.Like{"lower_name", strings.ToLower(search) + "%"}
if isShowFullName {
- prefixCond = prefixCond.Or(builder.Like{"full_name", "%" + search + "%"})
+ prefixCond = prefixCond.Or(db.BuildCaseInsensitiveLike("full_name", "%"+search+"%"))
}
cond := builder.In("`user`.id",
diff --git a/models/repo/user_repo_test.go b/models/repo/user_repo_test.go
index 44ebe5f214..50c970344c 100644
--- a/models/repo/user_repo_test.go
+++ b/models/repo/user_repo_test.go
@@ -12,6 +12,7 @@ import (
user_model "code.gitea.io/gitea/models/user"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
func TestRepoAssignees(t *testing.T) {
@@ -38,3 +39,19 @@ func TestRepoAssignees(t *testing.T) {
assert.NotContains(t, []int64{users[0].ID, users[1].ID, users[2].ID}, 15)
}
}
+
+func TestGetIssuePostersWithSearch(t *testing.T) {
+ assert.NoError(t, unittest.PrepareTestDatabase())
+
+ repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
+
+ users, err := repo_model.GetIssuePostersWithSearch(db.DefaultContext, repo2, false, "USER", false /* full name */)
+ require.NoError(t, err)
+ require.Len(t, users, 1)
+ assert.Equal(t, "user2", users[0].Name)
+
+ users, err = repo_model.GetIssuePostersWithSearch(db.DefaultContext, repo2, false, "TW%O", true /* full name */)
+ require.NoError(t, err)
+ require.Len(t, users, 1)
+ assert.Equal(t, "user2", users[0].Name)
+}
diff --git a/modules/markup/sanitizer_default_test.go b/modules/markup/sanitizer_default_test.go
index e6fbae5056..5282916944 100644
--- a/modules/markup/sanitizer_default_test.go
+++ b/modules/markup/sanitizer_default_test.go
@@ -62,6 +62,10 @@ func TestSanitizer(t *testing.T) {
`bad`, `bad`,
`bad`, `bad`,
`bad`, `bad`,
+
+ // Some classes and attributes are used by the frontend framework and will execute JS code, so make sure they are removed
+ `
txt
`, `txt
`,
+ `txt
`, `txt
`,
}
for i := 0; i < len(testCases); i += 2 {
diff --git a/modules/setting/server.go b/modules/setting/server.go
index d7a71578d4..e15b790906 100644
--- a/modules/setting/server.go
+++ b/modules/setting/server.go
@@ -169,20 +169,24 @@ func loadServerFrom(rootCfg ConfigProvider) {
HTTPAddr = sec.Key("HTTP_ADDR").MustString("0.0.0.0")
HTTPPort = sec.Key("HTTP_PORT").MustString("3000")
+ // DEPRECATED should not be removed because users maybe upgrade from lower version to the latest version
+ // if these are removed, the warning will not be shown
+ if sec.HasKey("ENABLE_ACME") {
+ EnableAcme = sec.Key("ENABLE_ACME").MustBool(false)
+ } else {
+ deprecatedSetting(rootCfg, "server", "ENABLE_LETSENCRYPT", "server", "ENABLE_ACME", "v1.19.0")
+ EnableAcme = sec.Key("ENABLE_LETSENCRYPT").MustBool(false)
+ }
+
Protocol = HTTP
protocolCfg := sec.Key("PROTOCOL").String()
+ if protocolCfg != "https" && EnableAcme {
+ log.Fatal("ACME could only be used with HTTPS protocol")
+ }
+
switch protocolCfg {
case "https":
Protocol = HTTPS
-
- // DEPRECATED should not be removed because users maybe upgrade from lower version to the latest version
- // if these are removed, the warning will not be shown
- if sec.HasKey("ENABLE_ACME") {
- EnableAcme = sec.Key("ENABLE_ACME").MustBool(false)
- } else {
- deprecatedSetting(rootCfg, "server", "ENABLE_LETSENCRYPT", "server", "ENABLE_ACME", "v1.19.0")
- EnableAcme = sec.Key("ENABLE_LETSENCRYPT").MustBool(false)
- }
if EnableAcme {
AcmeURL = sec.Key("ACME_URL").MustString("")
AcmeCARoot = sec.Key("ACME_CA_ROOT").MustString("")
@@ -210,6 +214,9 @@ func loadServerFrom(rootCfg ConfigProvider) {
deprecatedSetting(rootCfg, "server", "LETSENCRYPT_EMAIL", "server", "ACME_EMAIL", "v1.19.0")
AcmeEmail = sec.Key("LETSENCRYPT_EMAIL").MustString("")
}
+ if AcmeEmail == "" {
+ log.Fatal("ACME Email is not set (ACME_EMAIL).")
+ }
} else {
CertFile = sec.Key("CERT_FILE").String()
KeyFile = sec.Key("KEY_FILE").String()
diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini
index 3f2ac68802..ec914d2b2e 100644
--- a/options/locale/locale_cs-CZ.ini
+++ b/options/locale/locale_cs-CZ.ini
@@ -911,7 +911,6 @@ delete_token_success=Token byl odstraněn. Aplikace, které jej používají ji
repo_and_org_access=Repozitář a přístup organizace
permissions_public_only=Pouze veřejnost
permissions_access_all=Vše (veřejné, soukromé a omezené)
-select_permissions=Vyberte oprávnění
permission_not_set=Není nastaveno
permission_no_access=Bez přístupu
permission_read=Přečtené
@@ -2580,7 +2579,6 @@ diff.commit=revize
diff.git-notes=Poznámky
diff.data_not_available=Rozdílový obsah není dostupný
diff.options_button=Možnosti rozdílového porovnání
-diff.show_diff_stats=Zobrazit statistiky
diff.download_patch=Stáhněte soubor záplaty
diff.download_diff=Stáhněte rozdílový soubor
diff.show_split_view=Rozdělené zobrazení
diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini
index f1eada3990..0bec9305aa 100644
--- a/options/locale/locale_de-DE.ini
+++ b/options/locale/locale_de-DE.ini
@@ -910,7 +910,6 @@ delete_token_success=Der Zugriffstoken wurde gelöscht. Anwendungen die diesen T
repo_and_org_access=Repository- und Organisationszugriff
permissions_public_only=Nur öffentlich
permissions_access_all=Alle (öffentlich, privat und begrenzt)
-select_permissions=Berechtigungen auswählen
permission_not_set=Nicht festgelegt
permission_no_access=Kein Zugriff
permission_read=Lesen
@@ -2569,7 +2568,6 @@ diff.commit=Commit
diff.git-notes=Hinweise
diff.data_not_available=Keine Diff-Daten verfügbar
diff.options_button=Diff-Optionen
-diff.show_diff_stats=Statistiken anzeigen
diff.download_patch=Patch-Datei herunterladen
diff.download_diff=Vergleichs-Datei herunterladen
diff.show_split_view=Geteilte Ansicht
diff --git a/options/locale/locale_el-GR.ini b/options/locale/locale_el-GR.ini
index 7fb4151f17..fe338d8906 100644
--- a/options/locale/locale_el-GR.ini
+++ b/options/locale/locale_el-GR.ini
@@ -810,7 +810,6 @@ delete_token_success=Το διακριτικό έχει διαγραφεί. Οι
repo_and_org_access=Πρόσβαση στο Αποθετήριο και Οργανισμό
permissions_public_only=Δημόσια μόνο
permissions_access_all=Όλα (δημόσια, ιδιωτικά, και περιορισμένα)
-select_permissions=Επιλέξτε δικαιώματα
permission_no_access=Καμία Πρόσβαση
permission_read=Αναγνωσμένες
permission_write=Ανάγνωση και Εγγραφή
@@ -2317,7 +2316,6 @@ diff.commit=υποβολή
diff.git-notes=Σημειώσεις
diff.data_not_available=Δεν Υπάρχει Διαθέσιμο Περιεχόμενο Diff
diff.options_button=Επιλογές Diff
-diff.show_diff_stats=Εμφάνιση Στατιστικών
diff.download_patch=Λήψη Αρχείου Patch
diff.download_diff=Λήψη Αρχείου Diff
diff.show_split_view=Διαιρεμένη Προβολή
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index c2c5b07b65..1da2fb61ad 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -917,7 +917,6 @@ delete_token_success = The token has been deleted. Applications using it no long
repo_and_org_access = Repository and Organization Access
permissions_public_only = Public only
permissions_access_all = All (public, private, and limited)
-select_permissions = Select permissions
permission_not_set = Not set
permission_no_access = No Access
permission_read = Read
@@ -1465,6 +1464,8 @@ issues.filter_milestones = Filter Milestone
issues.filter_projects = Filter Project
issues.filter_labels = Filter Label
issues.filter_reviewers = Filter Reviewer
+issues.filter_no_results = No results
+issues.filter_no_results_placeholder = Try adjusting your search filters.
issues.new = New Issue
issues.new.title_empty = Title cannot be empty
issues.new.labels = Labels
@@ -2593,7 +2594,6 @@ diff.commit = commit
diff.git-notes = Notes
diff.data_not_available = Diff Content Not Available
diff.options_button = Diff Options
-diff.show_diff_stats = Show Stats
diff.download_patch = Download Patch File
diff.download_diff = Download Diff File
diff.show_split_view = Split View
diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini
index c399b1209c..f856eaebd6 100644
--- a/options/locale/locale_es-ES.ini
+++ b/options/locale/locale_es-ES.ini
@@ -806,7 +806,6 @@ delete_token_success=El token ha sido eliminado. Las aplicaciones que lo usen ya
repo_and_org_access=Acceso al Repositorio y a la Organización
permissions_public_only=Sólo público
permissions_access_all=Todo (público, privado y limitado)
-select_permissions=Seleccionar permisos
permission_no_access=Sin acceso
permission_read=Leídas
permission_write=Lectura y Escritura
@@ -2298,7 +2297,6 @@ diff.commit=commit
diff.git-notes=Notas
diff.data_not_available=El contenido del Diff no está disponible
diff.options_button=Opciones de diferencias
-diff.show_diff_stats=Mostrar estadísticas
diff.download_patch=Descargar archivo de parche
diff.download_diff=Descargar archivo de diferencias
diff.show_split_view=Dividir vista
diff --git a/options/locale/locale_fa-IR.ini b/options/locale/locale_fa-IR.ini
index 3d34e01722..c82cfc61bd 100644
--- a/options/locale/locale_fa-IR.ini
+++ b/options/locale/locale_fa-IR.ini
@@ -1777,7 +1777,6 @@ diff.commit=کامیت
diff.git-notes=یادداشتها
diff.data_not_available=محتوای تفاوت ها در دسترس نیست
diff.options_button=تنظیمات (diff) تغییرات
-diff.show_diff_stats=نمایش وضعیت
diff.download_patch=دانلود پرونده وصله
diff.download_diff=دانلود فایل تغییرات diff
diff.show_split_view=مشاهده تقسیم شده
diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini
index 9d652fabad..a2e17ef6ed 100644
--- a/options/locale/locale_fr-FR.ini
+++ b/options/locale/locale_fr-FR.ini
@@ -917,7 +917,6 @@ delete_token_success=Ce jeton a été supprimé. Les applications l'utilisant n'
repo_and_org_access=Accès aux Organisations et Dépôts
permissions_public_only=Publique uniquement
permissions_access_all=Tout (public, privé et limité)
-select_permissions=Sélectionner les autorisations
permission_not_set=Non défini
permission_no_access=Aucun accès
permission_read=Lecture
@@ -1701,7 +1700,9 @@ issues.time_estimate_invalid=Le format du temps estimé est invalide
issues.start_tracking_history=`a commencé son travail %s.`
issues.tracker_auto_close=Le minuteur sera automatiquement arrêté quand le ticket sera fermé.
issues.tracking_already_started=`Vous avez déjà un minuteur en cours sur un autre ticket !`
+issues.stop_tracking=Arrêter le minuteur
issues.stop_tracking_history=a travaillé sur %[1]s %[2]s
+issues.cancel_tracking=Abandonner
issues.cancel_tracking_history=`a abandonné son minuteur %s.`
issues.del_time=Supprimer ce minuteur du journal
issues.add_time_history=a pointé du temps de travail sur %[1]s, %[2]s
@@ -2590,7 +2591,6 @@ diff.commit=révision
diff.git-notes=Notes
diff.data_not_available=Contenu de la comparaison indisponible
diff.options_button=Option de Diff
-diff.show_diff_stats=Voir les Statistiques
diff.download_patch=Télécharger le Fichier Patch
diff.download_diff=Télécharger le Fichier des Différences
diff.show_split_view=Vue séparée
diff --git a/options/locale/locale_ga-IE.ini b/options/locale/locale_ga-IE.ini
index cc7051fb65..1009dbbdca 100644
--- a/options/locale/locale_ga-IE.ini
+++ b/options/locale/locale_ga-IE.ini
@@ -917,7 +917,6 @@ delete_token_success=Tá an comhartha scriosta. Níl rochtain ag iarratais a ús
repo_and_org_access=Rochtain Stórála agus Eagraíochta
permissions_public_only=Poiblí amháin
permissions_access_all=Gach (poiblí, príobháideach agus teoranta)
-select_permissions=Roghnaigh ceadanna
permission_not_set=Níl leagtha
permission_no_access=Gan rochtain
permission_read=Léigh
@@ -1464,6 +1463,8 @@ issues.filter_milestones=Cloch Mhíle Scagaire
issues.filter_projects=Tionscadal Scagaire
issues.filter_labels=Lipéad Scagaire
issues.filter_reviewers=Athbhreithneoir Scagaire
+issues.filter_no_results=Gan torthaí
+issues.filter_no_results_placeholder=Bain triail as do scagairí cuardaigh a choigeartú.
issues.new=Eagrán Nua
issues.new.title_empty=Ní féidir leis an teideal a bheith folamh
issues.new.labels=Lipéid
@@ -1701,7 +1702,9 @@ issues.time_estimate_invalid=Tá formáid meastachán ama neamhbhailí
issues.start_tracking_history=thosaigh ag obair %s
issues.tracker_auto_close=Stopfar ama go huathoibríoch nuair a dhúnfar an tsaincheist seo
issues.tracking_already_started=`Tá tús curtha agat cheana féin ag rianú ama ar eagrán eile!`
+issues.stop_tracking=Stad uaineadóir
issues.stop_tracking_history=d'oibrigh do %[1]s %[2]s
+issues.cancel_tracking=Caith amach
issues.cancel_tracking_history=`rianú ama curtha ar ceal %s`
issues.del_time=Scrios an log ama seo
issues.add_time_history=cuireadh am caite %[1]s %[2]s leis
@@ -2590,7 +2593,6 @@ diff.commit=tiomantas
diff.git-notes=Nótaí
diff.data_not_available=Níl Ábhar Difríochtaí Ar Fáil
diff.options_button=Roghanna Diff
-diff.show_diff_stats=Taispeáin Staitisticí
diff.download_patch=Íoslódáil an comhad paiste
diff.download_diff=Íoslódáil Comhad Diff
diff.show_split_view=Amharc Scoilt
diff --git a/options/locale/locale_hu-HU.ini b/options/locale/locale_hu-HU.ini
index 4767a48547..08a71c27d2 100644
--- a/options/locale/locale_hu-HU.ini
+++ b/options/locale/locale_hu-HU.ini
@@ -1098,7 +1098,6 @@ diff.parent=szülő
diff.commit=commit
diff.git-notes=Megjegyzések
diff.data_not_available=A különbségek nem megjeleníthetőek
-diff.show_diff_stats=Statisztikák mutatása
diff.show_split_view=Osztott nézet
diff.show_unified_view=Egyesített nézet
diff.stats_desc=%d fájl változott, egészen pontosan %d új sor hozzáadva és %d régi sor törölve
diff --git a/options/locale/locale_it-IT.ini b/options/locale/locale_it-IT.ini
index 29512f47f3..48a43210bf 100644
--- a/options/locale/locale_it-IT.ini
+++ b/options/locale/locale_it-IT.ini
@@ -1929,7 +1929,6 @@ diff.commit=commit
diff.git-notes=Note
diff.data_not_available=Dati Diff non disponibili
diff.options_button=Opzioni Diff
-diff.show_diff_stats=Mostra statistiche
diff.download_patch=Scarica il file Patch
diff.download_diff=Scarica il file Diff
diff.show_split_view=Visualizzazione separata
diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini
index bc29d530b4..cf0d4bffa7 100644
--- a/options/locale/locale_ja-JP.ini
+++ b/options/locale/locale_ja-JP.ini
@@ -385,6 +385,12 @@ show_only_public=公開のみ表示
issues.in_your_repos=あなたのリポジトリ
+guide_title=アクティビティはありません
+guide_desc=現在フォロー中のリポジトリやユーザーがないため、表示するコンテンツがありません。 以下のリンクから、興味のあるリポジトリやユーザーを探すことができます。
+explore_repos=リポジトリを探す
+explore_users=ユーザーを探す
+empty_org=組織はまだありません。
+empty_repo=リポジトリはまだありません。
[explore]
repos=リポジトリ
@@ -911,7 +917,6 @@ delete_token_success=トークンを削除しました。 削除したトーク
repo_and_org_access=リポジトリと組織へのアクセス
permissions_public_only=公開のみ
permissions_access_all=すべて (公開、プライベート、限定)
-select_permissions=許可の選択
permission_not_set=設定なし
permission_no_access=アクセス不可
permission_read=読み取り
@@ -1348,6 +1353,8 @@ editor.new_branch_name_desc=新しいブランチ名…
editor.cancel=キャンセル
editor.filename_cannot_be_empty=ファイル名は空にできません。
editor.filename_is_invalid=`ファイル名が不正です: "%s"`
+editor.commit_email=コミット メールアドレス
+editor.invalid_commit_email=コミットに使うメールアドレスが正しくありません。
editor.branch_does_not_exist=このリポジトリにブランチ "%s" は存在しません。
editor.branch_already_exists=ブランチ "%s" は、このリポジトリに既に存在します。
editor.directory_is_a_file=ディレクトリ名 "%s" はすでにリポジトリ内のファイルで使用されています。
@@ -1693,7 +1700,9 @@ issues.time_estimate_invalid=見積時間のフォーマットが不正です
issues.start_tracking_history=が作業を開始 %s
issues.tracker_auto_close=タイマーは、このイシューがクローズされると自動的に終了します
issues.tracking_already_started=`別のイシューで既にタイムトラッキングを開始しています!`
+issues.stop_tracking=タイマー終了
issues.stop_tracking_history=が %[1]s の作業を終了 %[2]s
+issues.cancel_tracking=破棄
issues.cancel_tracking_history=`がタイムトラッキングを中止 %s`
issues.del_time=このタイムログを削除
issues.add_time_history=が作業時間 %[1]s を追加 %[2]s
@@ -2329,6 +2338,8 @@ settings.event_fork=フォーク
settings.event_fork_desc=リポジトリがフォークされたとき。
settings.event_wiki=Wiki
settings.event_wiki_desc=Wikiページが作成・名前変更・編集・削除されたとき。
+settings.event_statuses=ステータス
+settings.event_statuses_desc=APIによってコミットのステータスが更新されたとき。
settings.event_release=リリース
settings.event_release_desc=リポジトリでリリースが作成・更新・削除されたとき。
settings.event_push=プッシュ
@@ -2580,7 +2591,6 @@ diff.commit=コミット
diff.git-notes=Notes
diff.data_not_available=差分はありません
diff.options_button=差分オプション
-diff.show_diff_stats=統計情報を表示
diff.download_patch=Patchファイルをダウンロード
diff.download_diff=Diffファイルをダウンロード
diff.show_split_view=分割表示
@@ -2876,6 +2886,14 @@ view_as_role=表示: %s
view_as_public_hint=READMEを公開ユーザーとして見ています。
view_as_member_hint=READMEをこの組織のメンバーとして見ています。
+worktime=作業時間
+worktime.date_range_start=期間 (自)
+worktime.date_range_end=期間 (至)
+worktime.query=集計
+worktime.time=時間
+worktime.by_repositories=リポジトリ別
+worktime.by_milestones=マイルストーン別
+worktime.by_members=メンバー別
[admin]
maintenance=メンテナンス
diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini
index d2df0813ae..7c30d0bb3c 100644
--- a/options/locale/locale_lv-LV.ini
+++ b/options/locale/locale_lv-LV.ini
@@ -814,7 +814,6 @@ delete_token_success=Pilnvara tika izdzēsta. Lietojumprogrammām, kas izmantoja
repo_and_org_access=Repozitorija un organizācijas piekļuve
permissions_public_only=Tikai publiskie
permissions_access_all=Visi (publiskie, privātie un ierobežotie)
-select_permissions=Norādiet tiesības
permission_no_access=Nav piekļuves
permission_read=Skatīšanās
permission_write=Skatīšanās un raksīšanas
@@ -2317,7 +2316,6 @@ diff.commit=revīzija
diff.git-notes=Piezīmes
diff.data_not_available=Satura salīdzināšana nav pieejama
diff.options_button=Salīdzināšanas iespējas
-diff.show_diff_stats=Rādīt statistiku
diff.download_patch=Lejupielādēt ielāpa failu
diff.download_diff=Lejupielādēt izmaiņu failu
diff.show_split_view=Dalītais skats
diff --git a/options/locale/locale_nl-NL.ini b/options/locale/locale_nl-NL.ini
index c23df29e99..650e8d4e23 100644
--- a/options/locale/locale_nl-NL.ini
+++ b/options/locale/locale_nl-NL.ini
@@ -1864,7 +1864,6 @@ diff.commit=commit
diff.git-notes=Notities
diff.data_not_available=Diff gegevens niet beschikbaar
diff.options_button=Diff opties
-diff.show_diff_stats=Statistieken weergeven
diff.download_patch=Download Patch-bestand
diff.download_diff=Download Diff-bestand
diff.show_split_view=Zij-aan-zij weergave
diff --git a/options/locale/locale_pl-PL.ini b/options/locale/locale_pl-PL.ini
index d03018c0d9..55a82e9629 100644
--- a/options/locale/locale_pl-PL.ini
+++ b/options/locale/locale_pl-PL.ini
@@ -1728,7 +1728,6 @@ diff.commit=commit
diff.git-notes=Notatki
diff.data_not_available=Informacje nt. zmian nie są dostępne
diff.options_button=Opcje porównania
-diff.show_diff_stats=Pokaż statystyki
diff.download_patch=Ściągnij plik aktualizacji
diff.download_diff=Ściągnij plik porównania
diff.show_split_view=Widok podzielony
diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini
index 33aad76023..f4b479344d 100644
--- a/options/locale/locale_pt-BR.ini
+++ b/options/locale/locale_pt-BR.ini
@@ -812,7 +812,6 @@ delete_token_success=O token foi excluído. Os aplicativos que o utilizam já n
repo_and_org_access=Acesso ao Repositório e Organização
permissions_public_only=Apenas público
permissions_access_all=Todos (público, privado e limitado)
-select_permissions=Selecionar permissões
permission_no_access=Sem acesso
permission_read=Ler
permission_write=Ler e escrever
@@ -2282,7 +2281,6 @@ diff.commit=commit
diff.git-notes=Notas
diff.data_not_available=Conteúdo de diff não disponível
diff.options_button=Opções de diferenças
-diff.show_diff_stats=Mostrar estatísticas
diff.download_patch=Baixar arquivo de patch
diff.download_diff=Baixar arquivo de diferenças
diff.show_split_view=Visão dividida
diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini
index 3582755d5e..6485fdf73a 100644
--- a/options/locale/locale_pt-PT.ini
+++ b/options/locale/locale_pt-PT.ini
@@ -917,7 +917,6 @@ delete_token_success=O código foi eliminado. Aplicações que o usavam deixaram
repo_and_org_access=Acesso aos repositórios e às organizações
permissions_public_only=Apenas público
permissions_access_all=Tudo (público, privado e limitado)
-select_permissions=Escolher permissões
permission_not_set=Não definido
permission_no_access=Sem acesso
permission_read=Lidas
@@ -1464,6 +1463,8 @@ issues.filter_milestones=Filtrar etapa
issues.filter_projects=Filtrar planeamento
issues.filter_labels=Filtrar rótulo
issues.filter_reviewers=Filtrar revisor
+issues.filter_no_results=Sem resultados
+issues.filter_no_results_placeholder=Tente ajustar os seus filtros de pesquisa.
issues.new=Questão nova
issues.new.title_empty=O título não pode estar vazio
issues.new.labels=Rótulos
@@ -2592,7 +2593,6 @@ diff.commit=cometimento
diff.git-notes=Notas
diff.data_not_available=O conteúdo das diferenças não está disponível
diff.options_button=Opções das diferenças
-diff.show_diff_stats=Mostrar estatísticas
diff.download_patch=Descarregar ficheiro patch
diff.download_diff=Descarregar ficheiro diff
diff.show_split_view=Visualização em 2 colunas
diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini
index 0aa776b78a..6140766291 100644
--- a/options/locale/locale_ru-RU.ini
+++ b/options/locale/locale_ru-RU.ini
@@ -807,7 +807,6 @@ delete_token_success=Токен удалён. Приложения, исполь
repo_and_org_access=Доступ к репозиторию и организации
permissions_public_only=Только публичные
permissions_access_all=Все (публичные, приватные и ограниченные)
-select_permissions=Выбрать разрешения
permission_no_access=Нет доступа
permission_read=Прочитанные
permission_write=Чтение и запись
@@ -2268,7 +2267,6 @@ diff.commit=Коммит
diff.git-notes=Заметки
diff.data_not_available=Разница недоступна
diff.options_button=Опции Diff
-diff.show_diff_stats=Показать статистику
diff.download_patch=Скачать Patch файл
diff.download_diff=Скачать Diff файл
diff.show_split_view=Разделённый вид
diff --git a/options/locale/locale_si-LK.ini b/options/locale/locale_si-LK.ini
index 80db8862fe..4857fa8d88 100644
--- a/options/locale/locale_si-LK.ini
+++ b/options/locale/locale_si-LK.ini
@@ -1739,7 +1739,6 @@ diff.commit=කැප
diff.git-notes=සටහන්
diff.data_not_available=Diff අන්තර්ගත ලබාගත නොහැක
diff.options_button=විවිධ විකල්ප
-diff.show_diff_stats=සංඛ්යාන පෙන්වන්න
diff.download_patch=පැච් ගොනුව බාගත
diff.download_diff=බාගත Dff ගොනුව
diff.show_split_view=භේදය දැක්ම
diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini
index 0454512402..72e3f4f9c5 100644
--- a/options/locale/locale_tr-TR.ini
+++ b/options/locale/locale_tr-TR.ini
@@ -895,7 +895,6 @@ delete_token_success=Jeton silindi. Onu kullanan uygulamalar artık hesabınıza
repo_and_org_access=Depo ve Organizasyon Erişimi
permissions_public_only=Yalnızca herkese açık
permissions_access_all=Tümü (herkese açık, özel ve sınırlı)
-select_permissions=İzinleri seçin
permission_not_set=Ayarlanmadı
permission_no_access=Erişim Yok
permission_read=Okunmuş
@@ -2470,7 +2469,6 @@ diff.commit=işleme
diff.git-notes=Notlar
diff.data_not_available=Farklı İçerik Mevut Değil
diff.options_button=Diff Seçenekleri
-diff.show_diff_stats=İstatistikleri Göster
diff.download_patch=Yama Dosyasını İndir
diff.download_diff=Diff Dosyasını İndir
diff.show_split_view=Görünümü Böl
diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini
index 25ebb843a9..4071659304 100644
--- a/options/locale/locale_uk-UA.ini
+++ b/options/locale/locale_uk-UA.ini
@@ -1789,7 +1789,6 @@ diff.commit=коміт
diff.git-notes=Примітки
diff.data_not_available=Різниця недоступна
diff.options_button=Параметри порівняння
-diff.show_diff_stats=Показати статистику
diff.download_patch=Завантажити патч
diff.download_diff=Завантажити файл різниці
diff.show_split_view=Розділений перегляд
diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini
index 3b6aca4e92..fe44b7067b 100644
--- a/options/locale/locale_zh-CN.ini
+++ b/options/locale/locale_zh-CN.ini
@@ -910,7 +910,6 @@ delete_token_success=令牌已经被删除。使用该令牌的应用将不再
repo_and_org_access=仓库和组织访问权限
permissions_public_only=仅公开
permissions_access_all=全部(公开、私有和受限)
-select_permissions=选择权限
permission_not_set=未设置
permission_no_access=无访问权限
permission_read=可读
@@ -2569,7 +2568,6 @@ diff.commit=当前提交
diff.git-notes=Notes
diff.data_not_available=比较内容不可用
diff.options_button=Diff 选项
-diff.show_diff_stats=显示统计
diff.download_patch=下载 Patch 文件
diff.download_diff=下载 Diff 文件
diff.show_split_view=分列视图
diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini
index 737f183f73..4f3cfe20c8 100644
--- a/options/locale/locale_zh-TW.ini
+++ b/options/locale/locale_zh-TW.ini
@@ -907,7 +907,6 @@ delete_token_success=已刪除 Token。使用此 Token 的應用程式無法再
repo_and_org_access=儲存庫和組織存取
permissions_public_only=僅公開
permissions_access_all=全部 (公開、私有與受限)
-select_permissions=選擇權限
permission_not_set=尚未設定
permission_no_access=沒有權限
permission_read=讀取
@@ -2560,7 +2559,6 @@ diff.commit=當前提交
diff.git-notes=備註
diff.data_not_available=沒有內容比較可以使用
diff.options_button=差異選項
-diff.show_diff_stats=顯示統計資料
diff.download_patch=下載 Patch 檔
diff.download_diff=下載差異檔
diff.show_split_view=分割檢視
diff --git a/routers/api/packages/composer/api.go b/routers/api/packages/composer/api.go
index a3bcf80417..a3ea2c2f9a 100644
--- a/routers/api/packages/composer/api.go
+++ b/routers/api/packages/composer/api.go
@@ -66,6 +66,7 @@ type PackageMetadataResponse struct {
}
// PackageVersionMetadata contains package metadata
+// https://getcomposer.org/doc/05-repositories.md#package
type PackageVersionMetadata struct {
*composer_module.Metadata
Name string `json:"name"`
@@ -73,6 +74,7 @@ type PackageVersionMetadata struct {
Type string `json:"type"`
Created time.Time `json:"time"`
Dist Dist `json:"dist"`
+ Source Source `json:"source"`
}
// Dist contains package download information
@@ -82,6 +84,13 @@ type Dist struct {
Checksum string `json:"shasum"`
}
+// Source contains package source information
+type Source struct {
+ URL string `json:"url"`
+ Type string `json:"type"`
+ Reference string `json:"reference"`
+}
+
func createPackageMetadataResponse(registryURL string, pds []*packages_model.PackageDescriptor) *PackageMetadataResponse {
versions := make([]*PackageVersionMetadata, 0, len(pds))
@@ -94,7 +103,7 @@ func createPackageMetadataResponse(registryURL string, pds []*packages_model.Pac
}
}
- versions = append(versions, &PackageVersionMetadata{
+ pkg := PackageVersionMetadata{
Name: pd.Package.Name,
Version: pd.Version.Version,
Type: packageType,
@@ -105,7 +114,16 @@ func createPackageMetadataResponse(registryURL string, pds []*packages_model.Pac
URL: fmt.Sprintf("%s/files/%s/%s/%s", registryURL, url.PathEscape(pd.Package.LowerName), url.PathEscape(pd.Version.LowerVersion), url.PathEscape(pd.Files[0].File.LowerName)),
Checksum: pd.Files[0].Blob.HashSHA1,
},
- })
+ }
+ if pd.Repository != nil {
+ pkg.Source = Source{
+ URL: pd.Repository.HTMLURL(),
+ Type: "git",
+ Reference: pd.Version.Version,
+ }
+ }
+
+ versions = append(versions, &pkg)
}
return &PackageMetadataResponse{
diff --git a/routers/api/packages/maven/api.go b/routers/api/packages/maven/api.go
index 167fe42b56..ec6b9cfb0e 100644
--- a/routers/api/packages/maven/api.go
+++ b/routers/api/packages/maven/api.go
@@ -8,7 +8,6 @@ import (
"strings"
packages_model "code.gitea.io/gitea/models/packages"
- maven_module "code.gitea.io/gitea/modules/packages/maven"
)
// MetadataResponse https://maven.apache.org/ref/3.2.5/maven-repository-metadata/repository-metadata.html
@@ -22,7 +21,7 @@ type MetadataResponse struct {
}
// pds is expected to be sorted ascending by CreatedUnix
-func createMetadataResponse(pds []*packages_model.PackageDescriptor) *MetadataResponse {
+func createMetadataResponse(pds []*packages_model.PackageDescriptor, groupID, artifactID string) *MetadataResponse {
var release *packages_model.PackageDescriptor
versions := make([]string, 0, len(pds))
@@ -35,11 +34,9 @@ func createMetadataResponse(pds []*packages_model.PackageDescriptor) *MetadataRe
latest := pds[len(pds)-1]
- metadata := latest.Metadata.(*maven_module.Metadata)
-
resp := &MetadataResponse{
- GroupID: metadata.GroupID,
- ArtifactID: metadata.ArtifactID,
+ GroupID: groupID,
+ ArtifactID: artifactID,
Latest: latest.Version.Version,
Version: versions,
}
diff --git a/routers/api/packages/maven/maven.go b/routers/api/packages/maven/maven.go
index 4d04d4d1e9..4f9ced25b4 100644
--- a/routers/api/packages/maven/maven.go
+++ b/routers/api/packages/maven/maven.go
@@ -84,20 +84,19 @@ func handlePackageFile(ctx *context.Context, serveContent bool) {
}
func serveMavenMetadata(ctx *context.Context, params parameters) {
- // /com/foo/project/maven-metadata.xml[.md5/.sha1/.sha256/.sha512]
-
- pvs, err := packages_model.GetVersionsByPackageName(ctx, ctx.Package.Owner.ID, packages_model.TypeMaven, params.toInternalPackageName())
- if errors.Is(err, util.ErrNotExist) {
- pvs, err = packages_model.GetVersionsByPackageName(ctx, ctx.Package.Owner.ID, packages_model.TypeMaven, params.toInternalPackageNameLegacy())
- }
+ // path pattern: /com/foo/project/maven-metadata.xml[.md5/.sha1/.sha256/.sha512]
+ // in case there are legacy package names ("GroupID-ArtifactID") we need to check both, new packages always use ":" as separator("GroupID:ArtifactID")
+ pvsLegacy, err := packages_model.GetVersionsByPackageName(ctx, ctx.Package.Owner.ID, packages_model.TypeMaven, params.toInternalPackageNameLegacy())
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
- if len(pvs) == 0 {
- apiError(ctx, http.StatusNotFound, packages_model.ErrPackageNotExist)
+ pvs, err := packages_model.GetVersionsByPackageName(ctx, ctx.Package.Owner.ID, packages_model.TypeMaven, params.toInternalPackageName())
+ if err != nil {
+ apiError(ctx, http.StatusInternalServerError, err)
return
}
+ pvs = append(pvsLegacy, pvs...)
pds, err := packages_model.GetPackageDescriptors(ctx, pvs)
if err != nil {
@@ -110,7 +109,7 @@ func serveMavenMetadata(ctx *context.Context, params parameters) {
return pds[i].Version.CreatedUnix < pds[j].Version.CreatedUnix
})
- xmlMetadata, err := xml.Marshal(createMetadataResponse(pds))
+ xmlMetadata, err := xml.Marshal(createMetadataResponse(pds, params.GroupID, params.ArtifactID))
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 907a2f08fe..bc76b5285e 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -7,8 +7,6 @@
// This documentation describes the Gitea API.
//
// Schemes: https, http
-// BasePath: /api/v1
-// Version: {{AppVer | JSEscape}}
// License: MIT http://opensource.org/licenses/MIT
//
// Consumes:
diff --git a/routers/api/v1/repo/collaborators.go b/routers/api/v1/repo/collaborators.go
index c397d7972b..a54225f0fd 100644
--- a/routers/api/v1/repo/collaborators.go
+++ b/routers/api/v1/repo/collaborators.go
@@ -7,6 +7,7 @@ package repo
import (
"errors"
"net/http"
+ "strings"
"code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access"
@@ -274,12 +275,13 @@ func GetRepoPermissions(ctx *context.APIContext) {
// "403":
// "$ref": "#/responses/forbidden"
- if !ctx.Doer.IsAdmin && ctx.Doer.LoginName != ctx.PathParam("collaborator") && !ctx.IsUserRepoAdmin() {
+ collaboratorUsername := ctx.PathParam("collaborator")
+ if !ctx.Doer.IsAdmin && ctx.Doer.LowerName != strings.ToLower(collaboratorUsername) && !ctx.IsUserRepoAdmin() {
ctx.APIError(http.StatusForbidden, "Only admins can query all permissions, repo admins can query all repo permissions, collaborators can query only their own")
return
}
- collaborator, err := user_model.GetUserByName(ctx, ctx.PathParam("collaborator"))
+ collaborator, err := user_model.GetUserByName(ctx, collaboratorUsername)
if err != nil {
if user_model.IsErrUserNotExist(err) {
ctx.APIError(http.StatusNotFound, err)
diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go
index 1f61ac031a..412f2cfb58 100644
--- a/routers/api/v1/repo/pull.go
+++ b/routers/api/v1/repo/pull.go
@@ -59,6 +59,10 @@ func ListPullRequests(ctx *context.APIContext) {
// description: Name of the repo
// type: string
// required: true
+ // - name: base_branch
+ // in: query
+ // description: Filter by target base branch of the pull request
+ // type: string
// - name: state
// in: query
// description: State of pull request
@@ -132,6 +136,7 @@ func ListPullRequests(ctx *context.APIContext) {
Labels: labelIDs,
MilestoneID: ctx.FormInt64("milestone"),
PosterID: posterID,
+ BaseBranch: ctx.FormTrim("base_branch"),
})
if err != nil {
ctx.APIErrorInternal(err)
diff --git a/routers/web/devtest/mock_actions.go b/routers/web/devtest/mock_actions.go
index e6539bb31f..3ce75dfad2 100644
--- a/routers/web/devtest/mock_actions.go
+++ b/routers/web/devtest/mock_actions.go
@@ -52,13 +52,22 @@ func generateMockStepsLog(logCur actions.LogCursor) (stepsLog []*actions.ViewSte
return stepsLog
}
-func MockActionsRunsJobs(ctx *context.Context) {
- req := web.GetForm(ctx).(*actions.ViewRequest)
+func MockActionsView(ctx *context.Context) {
+ ctx.Data["RunID"] = ctx.PathParam("run")
+ ctx.Data["JobID"] = ctx.PathParam("job")
+ ctx.HTML(http.StatusOK, "devtest/repo-action-view")
+}
+func MockActionsRunsJobs(ctx *context.Context) {
+ runID := ctx.PathParamInt64("run")
+
+ req := web.GetForm(ctx).(*actions.ViewRequest)
resp := &actions.ViewResponse{}
resp.State.Run.TitleHTML = `mock run title link`
resp.State.Run.Status = actions_model.StatusRunning.String()
- resp.State.Run.CanCancel = true
+ resp.State.Run.CanCancel = runID == 10
+ resp.State.Run.CanApprove = runID == 20
+ resp.State.Run.CanRerun = runID == 30
resp.State.Run.CanDeleteArtifact = true
resp.State.Run.WorkflowID = "workflow-id"
resp.State.Run.WorkflowLink = "./workflow-link"
@@ -85,6 +94,29 @@ func MockActionsRunsJobs(ctx *context.Context) {
Size: 1024 * 1024,
Status: "completed",
})
+
+ resp.State.Run.Jobs = append(resp.State.Run.Jobs, &actions.ViewJob{
+ ID: runID * 10,
+ Name: "job 100",
+ Status: actions_model.StatusRunning.String(),
+ CanRerun: true,
+ Duration: "1h",
+ })
+ resp.State.Run.Jobs = append(resp.State.Run.Jobs, &actions.ViewJob{
+ ID: runID*10 + 1,
+ Name: "job 101",
+ Status: actions_model.StatusWaiting.String(),
+ CanRerun: false,
+ Duration: "2h",
+ })
+ resp.State.Run.Jobs = append(resp.State.Run.Jobs, &actions.ViewJob{
+ ID: runID*10 + 2,
+ Name: "job 102",
+ Status: actions_model.StatusFailure.String(),
+ CanRerun: false,
+ Duration: "3h",
+ })
+
resp.State.CurrentJob.Steps = append(resp.State.CurrentJob.Steps, &actions.ViewJobStep{
Summary: "step 0 (mock slow)",
Duration: time.Hour.String(),
diff --git a/routers/web/repo/commit.go b/routers/web/repo/commit.go
index 9c12ef9297..2728eda8b6 100644
--- a/routers/web/repo/commit.go
+++ b/routers/web/repo/commit.go
@@ -344,18 +344,30 @@ func Diff(ctx *context.Context) {
ctx.Data["Reponame"] = repoName
var parentCommit *git.Commit
+ var parentCommitID string
if commit.ParentCount() > 0 {
parentCommit, err = gitRepo.GetCommit(parents[0])
if err != nil {
ctx.NotFound(err)
return
}
+ parentCommitID = parentCommit.ID.String()
}
setCompareContext(ctx, parentCommit, commit, userName, repoName)
ctx.Data["Title"] = commit.Summary() + " · " + base.ShortSha(commitID)
ctx.Data["Commit"] = commit
ctx.Data["Diff"] = diff
+ if !fileOnly {
+ diffTree, err := gitdiff.GetDiffTree(ctx, gitRepo, false, parentCommitID, commitID)
+ if err != nil {
+ ctx.ServerError("GetDiffTree", err)
+ return
+ }
+
+ ctx.PageData["DiffFiles"] = transformDiffTreeForUI(diffTree, nil)
+ }
+
statuses, _, err := git_model.GetLatestCommitStatus(ctx, ctx.Repo.Repository.ID, commitID, db.ListOptionsAll)
if err != nil {
log.Error("GetLatestCommitStatus: %v", err)
diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go
index 71bce759a9..5165636a52 100644
--- a/routers/web/repo/compare.go
+++ b/routers/web/repo/compare.go
@@ -633,6 +633,16 @@ func PrepareCompareDiff(
ctx.Data["Diff"] = diff
ctx.Data["DiffNotAvailable"] = diff.NumFiles == 0
+ if !fileOnly {
+ diffTree, err := gitdiff.GetDiffTree(ctx, ci.HeadGitRepo, false, beforeCommitID, headCommitID)
+ if err != nil {
+ ctx.ServerError("GetDiffTree", err)
+ return false
+ }
+
+ ctx.PageData["DiffFiles"] = transformDiffTreeForUI(diffTree, nil)
+ }
+
headCommit, err := ci.HeadGitRepo.GetCommit(headCommitID)
if err != nil {
ctx.ServerError("GetCommit", err)
diff --git a/routers/web/repo/githttp.go b/routers/web/repo/githttp.go
index e27040edc6..5b7b0188dc 100644
--- a/routers/web/repo/githttp.go
+++ b/routers/web/repo/githttp.go
@@ -78,7 +78,7 @@ func httpBase(ctx *context.Context) *serviceHandler {
strings.HasSuffix(ctx.Req.URL.Path, "git-upload-archive") {
isPull = true
} else {
- isPull = ctx.Req.Method == "GET"
+ isPull = ctx.Req.Method == "HEAD" || ctx.Req.Method == "GET"
}
var accessMode perm.AccessMode
diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go
index 223f8d017e..0769f456ec 100644
--- a/routers/web/repo/pull.go
+++ b/routers/web/repo/pull.go
@@ -761,6 +761,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi
var methodWithError string
var diff *gitdiff.Diff
+ shouldGetUserSpecificDiff := false
// if we're not logged in or only a single commit (or commit range) is shown we
// have to load only the diff and not get the viewed information
@@ -772,6 +773,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi
} else {
diff, err = gitdiff.SyncAndGetUserSpecificDiff(ctx, ctx.Doer.ID, pull, gitRepo, diffOptions, files...)
methodWithError = "SyncAndGetUserSpecificDiff"
+ shouldGetUserSpecificDiff = true
}
if err != nil {
ctx.ServerError(methodWithError, err)
@@ -816,6 +818,27 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi
}
}
+ if !fileOnly {
+ // note: use mergeBase is set to false because we already have the merge base from the pull request info
+ diffTree, err := gitdiff.GetDiffTree(ctx, gitRepo, false, pull.MergeBase, headCommitID)
+ if err != nil {
+ ctx.ServerError("GetDiffTree", err)
+ return
+ }
+
+ filesViewedState := make(map[string]pull_model.ViewedState)
+ if shouldGetUserSpecificDiff {
+ // This sort of sucks because we already fetch this when getting the diff
+ review, err := pull_model.GetNewestReviewState(ctx, ctx.Doer.ID, issue.ID)
+ if err == nil && review != nil && review.UpdatedFiles != nil {
+ // If there wasn't an error and we have a review with updated files, use that
+ filesViewedState = review.UpdatedFiles
+ }
+ }
+
+ ctx.PageData["DiffFiles"] = transformDiffTreeForUI(diffTree, filesViewedState)
+ }
+
ctx.Data["Diff"] = diff
ctx.Data["DiffNotAvailable"] = diff.NumFiles == 0
diff --git a/routers/web/repo/tree.go b/routers/web/repo/tree.go
index b4d214e4d0..4b8211c957 100644
--- a/routers/web/repo/tree.go
+++ b/routers/web/repo/tree.go
@@ -7,9 +7,11 @@ import (
"errors"
"net/http"
+ pull_model "code.gitea.io/gitea/models/pull"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/gitdiff"
files_service "code.gitea.io/gitea/services/repository/files"
"github.com/go-enry/go-enry/v2"
@@ -55,6 +57,36 @@ func isExcludedEntry(entry *git.TreeEntry) bool {
return false
}
+type FileDiffFile struct {
+ Name string
+ NameHash string
+ IsSubmodule bool
+ IsViewed bool
+ Status string
+}
+
+// transformDiffTreeForUI transforms a DiffTree into a slice of FileDiffFile for UI rendering
+// it also takes a map of file names to their viewed state, which is used to mark files as viewed
+func transformDiffTreeForUI(diffTree *gitdiff.DiffTree, filesViewedState map[string]pull_model.ViewedState) []FileDiffFile {
+ files := make([]FileDiffFile, 0, len(diffTree.Files))
+
+ for _, file := range diffTree.Files {
+ nameHash := git.HashFilePathForWebUI(file.HeadPath)
+ isSubmodule := file.HeadMode == git.EntryModeCommit
+ isViewed := filesViewedState[file.HeadPath] == pull_model.Viewed
+
+ files = append(files, FileDiffFile{
+ Name: file.HeadPath,
+ NameHash: nameHash,
+ IsSubmodule: isSubmodule,
+ IsViewed: isViewed,
+ Status: file.Status,
+ })
+ }
+
+ return files
+}
+
func Tree(ctx *context.Context) {
recursive := ctx.FormBool("recursive")
diff --git a/routers/web/user/setting/applications.go b/routers/web/user/setting/applications.go
index cf71d01dc1..1f6c97a5cc 100644
--- a/routers/web/user/setting/applications.go
+++ b/routers/web/user/setting/applications.go
@@ -6,12 +6,14 @@ package setting
import (
"net/http"
+ "strings"
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/setting"
"code.gitea.io/gitea/modules/templates"
+ "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
@@ -39,18 +41,29 @@ func ApplicationsPost(ctx *context.Context) {
ctx.Data["PageIsSettingsApplications"] = true
ctx.Data["UserDisabledFeatures"] = user_model.DisabledFeaturesWithLoginType(ctx.Doer)
- if ctx.HasError() {
- loadApplicationsData(ctx)
-
- ctx.HTML(http.StatusOK, tplSettingsApplications)
- return
+ _ = ctx.Req.ParseForm()
+ var scopeNames []string
+ for k, v := range ctx.Req.Form {
+ if strings.HasPrefix(k, "scope-") {
+ scopeNames = append(scopeNames, v...)
+ }
}
- scope, err := form.GetScope()
+ scope, err := auth_model.AccessTokenScope(strings.Join(scopeNames, ",")).Normalize()
if err != nil {
ctx.ServerError("GetScope", err)
return
}
+ if scope == "" || scope == auth_model.AccessTokenScopePublicOnly {
+ ctx.Flash.Error(ctx.Tr("settings.at_least_one_permission"), true)
+ }
+
+ if ctx.HasError() {
+ loadApplicationsData(ctx)
+ ctx.HTML(http.StatusOK, tplSettingsApplications)
+ return
+ }
+
t := &auth_model.AccessToken{
UID: ctx.Doer.ID,
Name: form.Name,
@@ -99,7 +112,14 @@ func loadApplicationsData(ctx *context.Context) {
}
ctx.Data["Tokens"] = tokens
ctx.Data["EnableOAuth2"] = setting.OAuth2.Enabled
- ctx.Data["IsAdmin"] = ctx.Doer.IsAdmin
+
+ // Handle specific ordered token categories for admin or non-admin users
+ tokenCategoryNames := auth_model.GetAccessTokenCategories()
+ if !ctx.Doer.IsAdmin {
+ tokenCategoryNames = util.SliceRemoveAll(tokenCategoryNames, "admin")
+ }
+ ctx.Data["TokenCategories"] = tokenCategoryNames
+
if setting.OAuth2.Enabled {
ctx.Data["Applications"], err = db.Find[auth_model.OAuth2Application](ctx, auth_model.FindOAuth2ApplicationsOptions{
OwnerID: ctx.Doer.ID,
diff --git a/routers/web/web.go b/routers/web/web.go
index bba31ffb3a..4116a68322 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -1640,6 +1640,7 @@ func registerRoutes(m *web.Router) {
m.Any("", devtest.List)
m.Any("/fetch-action-test", devtest.FetchActionTest)
m.Any("/{sub}", devtest.Tmpl)
+ m.Get("/repo-action-view/{run}/{job}", devtest.MockActionsView)
m.Post("/actions-mock/runs/{run}/jobs/{job}", web.Bind(actions.ViewRequest{}), devtest.MockActionsRunsJobs)
})
}
diff --git a/services/context/api.go b/services/context/api.go
index 230c3456d1..c163de036c 100644
--- a/services/context/api.go
+++ b/services/context/api.go
@@ -291,6 +291,11 @@ func RepoRefForAPI(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
ctx := GetAPIContext(req)
+ if ctx.Repo.Repository.IsEmpty {
+ ctx.APIErrorNotFound("repository is empty")
+ return
+ }
+
if ctx.Repo.GitRepo == nil {
ctx.APIErrorInternal(fmt.Errorf("no open git repo"))
return
diff --git a/services/context/context.go b/services/context/context.go
index 5e08fba442..f3a0f0bb5f 100644
--- a/services/context/context.go
+++ b/services/context/context.go
@@ -213,13 +213,16 @@ func Contexter() func(next http.Handler) http.Handler {
// Attention: this function changes ctx.Data and ctx.Flash
// If HasError is called, then before Redirect, the error message should be stored by ctx.Flash.Error(ctx.GetErrMsg()) again.
func (ctx *Context) HasError() bool {
- hasErr, ok := ctx.Data["HasError"]
- if !ok {
+ hasErr, _ := ctx.Data["HasError"].(bool)
+ hasErr = hasErr || ctx.Flash.ErrorMsg != ""
+ if !hasErr {
return false
}
- ctx.Flash.ErrorMsg = ctx.GetErrMsg()
+ if ctx.Flash.ErrorMsg == "" {
+ ctx.Flash.ErrorMsg = ctx.GetErrMsg()
+ }
ctx.Data["Flash"] = ctx.Flash
- return hasErr.(bool)
+ return hasErr
}
// GetErrMsg returns error message in form validation.
diff --git a/services/forms/user_form.go b/services/forms/user_form.go
index ed79936add..c9ce71e886 100644
--- a/services/forms/user_form.go
+++ b/services/forms/user_form.go
@@ -7,9 +7,7 @@ package forms
import (
"mime/multipart"
"net/http"
- "strings"
- auth_model "code.gitea.io/gitea/models/auth"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web/middleware"
@@ -347,8 +345,7 @@ func (f *EditVariableForm) Validate(req *http.Request, errs binding.Errors) bind
// NewAccessTokenForm form for creating access token
type NewAccessTokenForm struct {
- Name string `binding:"Required;MaxSize(255)" locale:"settings.token_name"`
- Scope []string
+ Name string `binding:"Required;MaxSize(255)" locale:"settings.token_name"`
}
// Validate validates the fields
@@ -357,12 +354,6 @@ func (f *NewAccessTokenForm) Validate(req *http.Request, errs binding.Errors) bi
return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
}
-func (f *NewAccessTokenForm) GetScope() (auth_model.AccessTokenScope, error) {
- scope := strings.Join(f.Scope, ",")
- s, err := auth_model.AccessTokenScope(scope).Normalize()
- return s, err
-}
-
// EditOAuth2ApplicationForm form for editing oauth2 applications
type EditOAuth2ApplicationForm struct {
Name string `binding:"Required;MaxSize(255)" form:"application_name"`
diff --git a/services/forms/user_form_test.go b/services/forms/user_form_test.go
index 66050187c9..b4120f20ed 100644
--- a/services/forms/user_form_test.go
+++ b/services/forms/user_form_test.go
@@ -4,10 +4,8 @@
package forms
import (
- "strconv"
"testing"
- auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/modules/setting"
"github.com/gobwas/glob"
@@ -104,28 +102,3 @@ func TestRegisterForm_IsDomainAllowed_BlockedEmail(t *testing.T) {
assert.Equal(t, v.valid, form.IsEmailDomainAllowed())
}
}
-
-func TestNewAccessTokenForm_GetScope(t *testing.T) {
- tests := []struct {
- form NewAccessTokenForm
- scope auth_model.AccessTokenScope
- expectedErr error
- }{
- {
- form: NewAccessTokenForm{Name: "test", Scope: []string{"read:repository"}},
- scope: "read:repository",
- },
- {
- form: NewAccessTokenForm{Name: "test", Scope: []string{"read:repository", "write:user"}},
- scope: "read:repository,write:user",
- },
- }
-
- for i, test := range tests {
- t.Run(strconv.Itoa(i), func(t *testing.T) {
- scope, err := test.form.GetScope()
- assert.Equal(t, test.expectedErr, err)
- assert.Equal(t, test.scope, scope)
- })
- }
-}
diff --git a/services/packages/package_update.go b/services/packages/package_update.go
index 8d851fac53..4a22ee7a62 100644
--- a/services/packages/package_update.go
+++ b/services/packages/package_update.go
@@ -44,16 +44,17 @@ func UnlinkFromRepository(ctx context.Context, pkg *packages_model.Package, doer
}
repo, err := repo_model.GetRepositoryByID(ctx, pkg.RepoID)
- if err != nil {
+ if err != nil && !repo_model.IsErrRepoNotExist(err) {
return fmt.Errorf("error getting repository %d: %w", pkg.RepoID, err)
}
-
- perms, err := access_model.GetUserRepoPermission(ctx, repo, doer)
- if err != nil {
- return fmt.Errorf("error getting permissions for user %d on repository %d: %w", doer.ID, repo.ID, err)
- }
- if !perms.CanWrite(unit.TypePackages) {
- return util.ErrPermissionDenied
+ if err == nil {
+ perms, err := access_model.GetUserRepoPermission(ctx, repo, doer)
+ if err != nil {
+ return fmt.Errorf("error getting permissions for user %d on repository %d: %w", doer.ID, repo.ID, err)
+ }
+ if !perms.CanWrite(unit.TypePackages) {
+ return util.ErrPermissionDenied
+ }
}
user, err := user_model.GetUserByID(ctx, pkg.OwnerID)
diff --git a/services/pull/pull.go b/services/pull/pull.go
index 5d3758eca6..e4db3127b9 100644
--- a/services/pull/pull.go
+++ b/services/pull/pull.go
@@ -407,11 +407,10 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
}
if isSync {
- requests := issues_model.PullRequestList(prs)
- if err = requests.LoadAttributes(ctx); err != nil {
+ if err = prs.LoadAttributes(ctx); err != nil {
log.Error("PullRequestList.LoadAttributes: %v", err)
}
- if invalidationErr := checkForInvalidation(ctx, requests, repoID, doer, branch); invalidationErr != nil {
+ if invalidationErr := checkForInvalidation(ctx, prs, repoID, doer, branch); invalidationErr != nil {
log.Error("checkForInvalidation: %v", invalidationErr)
}
if err == nil {
@@ -645,7 +644,7 @@ func retargetBranchPulls(ctx context.Context, doer *user_model.User, repoID int6
return err
}
- if err := issues_model.PullRequestList(prs).LoadAttributes(ctx); err != nil {
+ if err := prs.LoadAttributes(ctx); err != nil {
return err
}
@@ -672,11 +671,11 @@ func AdjustPullsCausedByBranchDeleted(ctx context.Context, doer *user_model.User
return err
}
- if err := issues_model.PullRequestList(prs).LoadAttributes(ctx); err != nil {
+ if err := prs.LoadAttributes(ctx); err != nil {
return err
}
- issues_model.PullRequestList(prs).SetHeadRepo(repo)
- if err := issues_model.PullRequestList(prs).LoadRepositories(ctx); err != nil {
+ prs.SetHeadRepo(repo)
+ if err := prs.LoadRepositories(ctx); err != nil {
return err
}
@@ -707,11 +706,11 @@ func AdjustPullsCausedByBranchDeleted(ctx context.Context, doer *user_model.User
return err
}
- if err := issues_model.PullRequestList(prs).LoadAttributes(ctx); err != nil {
+ if err := prs.LoadAttributes(ctx); err != nil {
return err
}
- issues_model.PullRequestList(prs).SetBaseRepo(repo)
- if err := issues_model.PullRequestList(prs).LoadRepositories(ctx); err != nil {
+ prs.SetBaseRepo(repo)
+ if err := prs.LoadRepositories(ctx); err != nil {
return err
}
@@ -744,7 +743,7 @@ func CloseRepoBranchesPulls(ctx context.Context, doer *user_model.User, repo *re
return err
}
- if err = issues_model.PullRequestList(prs).LoadAttributes(ctx); err != nil {
+ if err = prs.LoadAttributes(ctx); err != nil {
return err
}
diff --git a/services/repository/delete.go b/services/repository/delete.go
index fb3fffdca7..3b953d3ec7 100644
--- a/services/repository/delete.go
+++ b/services/repository/delete.go
@@ -14,6 +14,7 @@ import (
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/organization"
+ packages_model "code.gitea.io/gitea/models/packages"
access_model "code.gitea.io/gitea/models/perm/access"
project_model "code.gitea.io/gitea/models/project"
repo_model "code.gitea.io/gitea/models/repo"
@@ -267,6 +268,11 @@ func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID
return err
}
+ // unlink packages linked to this repository
+ if err = packages_model.UnlinkRepositoryFromAllPackages(ctx, repoID); err != nil {
+ return err
+ }
+
if err = committer.Commit(); err != nil {
return err
}
diff --git a/services/repository/repository.go b/services/repository/repository.go
index 59b4491132..fcc617979e 100644
--- a/services/repository/repository.go
+++ b/services/repository/repository.go
@@ -11,7 +11,6 @@ import (
"code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/organization"
- packages_model "code.gitea.io/gitea/models/packages"
repo_model "code.gitea.io/gitea/models/repo"
system_model "code.gitea.io/gitea/models/system"
"code.gitea.io/gitea/models/unit"
@@ -63,11 +62,7 @@ func DeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_mod
notify_service.DeleteRepository(ctx, doer, repo)
}
- if err := DeleteRepositoryDirectly(ctx, doer, repo.ID); err != nil {
- return err
- }
-
- return packages_model.UnlinkRepositoryFromAllPackages(ctx, repo.ID)
+ return DeleteRepositoryDirectly(ctx, doer, repo.ID)
}
// PushCreateRepo creates a repository when a new repository is pushed to an appropriate namespace
diff --git a/services/webhook/deliver.go b/services/webhook/deliver.go
index 4707602cdf..df32d5741e 100644
--- a/services/webhook/deliver.go
+++ b/services/webhook/deliver.go
@@ -18,6 +18,7 @@ import (
"sync"
"time"
+ user_model "code.gitea.io/gitea/models/user"
webhook_model "code.gitea.io/gitea/models/webhook"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/hostmatcher"
@@ -92,10 +93,10 @@ func newDefaultRequest(ctx context.Context, w *webhook_model.Webhook, t *webhook
}
body = []byte(t.PayloadContent)
- return req, body, addDefaultHeaders(req, []byte(w.Secret), t, body)
+ return req, body, addDefaultHeaders(req, []byte(w.Secret), w, t, body)
}
-func addDefaultHeaders(req *http.Request, secret []byte, t *webhook_model.HookTask, payloadContent []byte) error {
+func addDefaultHeaders(req *http.Request, secret []byte, w *webhook_model.Webhook, t *webhook_model.HookTask, payloadContent []byte) error {
var signatureSHA1 string
var signatureSHA256 string
if len(secret) > 0 {
@@ -112,10 +113,27 @@ func addDefaultHeaders(req *http.Request, secret []byte, t *webhook_model.HookTa
event := t.EventType.Event()
eventType := string(t.EventType)
+ targetType := "default"
+ if w.IsSystemWebhook {
+ targetType = "system"
+ } else if w.RepoID != 0 {
+ targetType = "repository"
+ } else if w.OwnerID != 0 {
+ owner, err := user_model.GetUserByID(req.Context(), w.OwnerID)
+ if owner != nil && err == nil {
+ if owner.IsOrganization() {
+ targetType = "organization"
+ } else {
+ targetType = "user"
+ }
+ }
+ }
+
req.Header.Add("X-Gitea-Delivery", t.UUID)
req.Header.Add("X-Gitea-Event", event)
req.Header.Add("X-Gitea-Event-Type", eventType)
req.Header.Add("X-Gitea-Signature", signatureSHA256)
+ req.Header.Add("X-Gitea-Hook-Installation-Target-Type", targetType)
req.Header.Add("X-Gogs-Delivery", t.UUID)
req.Header.Add("X-Gogs-Event", event)
req.Header.Add("X-Gogs-Event-Type", eventType)
@@ -125,6 +143,7 @@ func addDefaultHeaders(req *http.Request, secret []byte, t *webhook_model.HookTa
req.Header["X-GitHub-Delivery"] = []string{t.UUID}
req.Header["X-GitHub-Event"] = []string{event}
req.Header["X-GitHub-Event-Type"] = []string{eventType}
+ req.Header["X-GitHub-Hook-Installation-Target-Type"] = []string{targetType}
return nil
}
diff --git a/services/webhook/matrix.go b/services/webhook/matrix.go
index ec21712837..fb602f3860 100644
--- a/services/webhook/matrix.go
+++ b/services/webhook/matrix.go
@@ -56,7 +56,7 @@ func newMatrixRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_mo
}
req.Header.Set("Content-Type", "application/json")
- return req, body, addDefaultHeaders(req, []byte(w.Secret), t, body) // likely useless, but has always been sent historially
+ return req, body, addDefaultHeaders(req, []byte(w.Secret), w, t, body) // likely useless, but has always been sent historially
}
const matrixPayloadSizeLimit = 1024 * 64
diff --git a/services/webhook/payloader.go b/services/webhook/payloader.go
index c29ad8ac92..d98c20f479 100644
--- a/services/webhook/payloader.go
+++ b/services/webhook/payloader.go
@@ -107,7 +107,7 @@ func newJSONRequest[T any](pc payloadConvertor[T], w *webhook_model.Webhook, t *
req.Header.Set("Content-Type", "application/json")
if withDefaultHeaders {
- return req, body, addDefaultHeaders(req, []byte(w.Secret), t, body)
+ return req, body, addDefaultHeaders(req, []byte(w.Secret), w, t, body)
}
return req, body, nil
}
diff --git a/templates/admin/user/view_details.tmpl b/templates/admin/user/view_details.tmpl
index be2f32b5ec..db61bc9359 100644
--- a/templates/admin/user/view_details.tmpl
+++ b/templates/admin/user/view_details.tmpl
@@ -9,30 +9,25 @@
{{if .User.IsAdmin}}
{{ctx.Locale.Tr "admin.users.admin"}}
{{end}}
+ {{if .User.IsTypeBot}}
+ {{ctx.Locale.Tr "admin.users.bot"}}
+ {{end}}
{{ctx.Locale.Tr "admin.users.auth_source"}}:
- {{if eq .LoginSource.ID 0}}
- {{ctx.Locale.Tr "admin.users.local"}}
- {{else}}
- {{.LoginSource.Name}}
- {{end}}
+ {{Iif (eq .LoginSource.ID 0) (ctx.Locale.Tr "admin.users.local") .LoginSource.Name}}
{{ctx.Locale.Tr "admin.users.activated"}}:
- {{if .User.IsActive}}
- {{svg "octicon-check"}}
- {{else}}
- {{svg "octicon-x"}}
- {{end}}
+ {{svg (Iif .User.IsActive "octicon-check" "octicon-x")}}
+
+
+ {{ctx.Locale.Tr "admin.users.prohibit_login"}}:
+ {{svg (Iif .User.ProhibitLogin "octicon-check" "octicon-x")}}
{{ctx.Locale.Tr "admin.users.restricted"}}:
- {{if .User.IsRestricted}}
- {{svg "octicon-check"}}
- {{else}}
- {{svg "octicon-x"}}
- {{end}}
+ {{svg (Iif .User.IsRestricted "octicon-check" "octicon-x")}}
{{ctx.Locale.Tr "settings.visibility"}}:
@@ -42,11 +37,7 @@
{{ctx.Locale.Tr "admin.users.2fa"}}:
- {{if .TwoFactorEnabled}}
- {{svg "octicon-check"}}
- {{else}}
- {{svg "octicon-x"}}
- {{end}}
+ {{svg (Iif .TwoFactorEnabled "octicon-check" "octicon-x")}}
{{if .User.Language}}
diff --git a/templates/admin/user/view_emails.tmpl b/templates/admin/user/view_emails.tmpl
index 22ce305a88..7e77206f1c 100644
--- a/templates/admin/user/view_emails.tmpl
+++ b/templates/admin/user/view_emails.tmpl
@@ -3,7 +3,7 @@
- {{.Email}}
+
{{.Email}}
{{if .IsPrimary}}
{{ctx.Locale.Tr "settings.primary"}}
{{end}}
diff --git a/templates/base/alert.tmpl b/templates/base/alert.tmpl
index 760d3bfa2c..3f6d77a645 100644
--- a/templates/base/alert.tmpl
+++ b/templates/base/alert.tmpl
@@ -1,20 +1,20 @@
-{{if .Flash.ErrorMsg}}
+{{- if .Flash.ErrorMsg -}}
{{.Flash.ErrorMsg | SanitizeHTML}}
-{{end}}
-{{if .Flash.SuccessMsg}}
+{{- end -}}
+{{- if .Flash.SuccessMsg -}}
{{.Flash.SuccessMsg | SanitizeHTML}}
-{{end}}
-{{if .Flash.InfoMsg}}
+{{- end -}}
+{{- if .Flash.InfoMsg -}}
{{.Flash.InfoMsg | SanitizeHTML}}
-{{end}}
-{{if .Flash.WarningMsg}}
+{{- end -}}
+{{- if .Flash.WarningMsg -}}
{{.Flash.WarningMsg | SanitizeHTML}}
-{{end}}
+{{- end -}}
diff --git a/templates/base/paginate.tmpl b/templates/base/paginate.tmpl
index 9a7a6322f7..253892c009 100644
--- a/templates/base/paginate.tmpl
+++ b/templates/base/paginate.tmpl
@@ -17,7 +17,7 @@
{{if eq .Num -1}}
...
{{else}}
-
{{.Num}}
+
{{.Num}}
{{end}}
{{end}}
diff --git a/templates/devtest/repo-action-view.tmpl b/templates/devtest/repo-action-view.tmpl
index 9c6bdf13da..677eccc062 100644
--- a/templates/devtest/repo-action-view.tmpl
+++ b/templates/devtest/repo-action-view.tmpl
@@ -1,8 +1,13 @@
{{template "base/head" .}}
+
{{template "repo/actions/view_component" (dict
- "RunIndex" 1
- "JobIndex" 2
+ "RunIndex" (or .RunID 10)
+ "JobIndex" (or .JobID 100)
"ActionsURL" (print AppSubUrl "/devtest/actions-mock")
)}}
diff --git a/templates/repo/clone_panel.tmpl b/templates/repo/clone_panel.tmpl
index b813860150..2ed8f52fbe 100644
--- a/templates/repo/clone_panel.tmpl
+++ b/templates/repo/clone_panel.tmpl
@@ -14,6 +14,7 @@
{{if $.CloneButtonShowSSH}}
{{end}}
+
diff --git a/templates/repo/diff/box.tmpl b/templates/repo/diff/box.tmpl
index a3b64b8a11..1a0a5c04a8 100644
--- a/templates/repo/diff/box.tmpl
+++ b/templates/repo/diff/box.tmpl
@@ -1,6 +1,6 @@
{{$showFileTree := (and (not .DiffNotAvailable) (gt .Diff.NumFiles 1))}}
-
+
{{if $showFileTree}}
{{end}}
-
-
{{end}}
{{if $showFileTree}}
@@ -106,7 +80,7 @@
{{$showFileViewToggle := or $isImage (and (not $file.IsIncomplete) $isCsv)}}
{{$isExpandable := or (gt $file.Addition 0) (gt $file.Deletion 0) $file.IsBin}}
{{$isReviewFile := and $.IsSigned $.PageIsPullFiles (not $.Repository.IsArchived) $.IsShowingAllCommits}}
-