Merge remote-tracking branch 'upstream/main' into sync-issue-pr-and-more

This commit is contained in:
Chongyi Zheng 2022-07-13 03:09:14 -04:00
commit 696f58f83c
No known key found for this signature in database
GPG Key ID: CC2953E050C19686
48 changed files with 3028 additions and 151 deletions

12
.spectral.yaml Normal file
View File

@ -0,0 +1,12 @@
extends: [[spectral:oas, all]]
rules:
info-contact: off
oas2-api-host: off
oas2-parameter-description: off
oas2-schema: off
oas2-valid-schema-example: off
openapi-tags: off
operation-description: off
operation-singular-tag: off
operation-tag-defined: off

View File

@ -4,9 +4,15 @@ This changelog goes through all the changes that have been made in each release
without substantial changes to our git log; to see the highlights of what has without substantial changes to our git log; to see the highlights of what has
been added to each release, please refer to the [blog](https://blog.gitea.io). been added to each release, please refer to the [blog](https://blog.gitea.io).
## [1.16.9](https://github.com/go-gitea/gitea/releases/tag/v1.16.9) - 2022-06-21 ## [1.16.9](https://github.com/go-gitea/gitea/releases/tag/v1.16.9) - 2022-07-12
* SECURITY
* Add write check for creating Commit status (#20332) (#20334)
* Check for permission when fetching user controlled issues (#20133) (#20196)
* BUGFIXES * BUGFIXES
* Hide notify mail setting ui if not enabled (#20138) (#20337)
* Add write check for creating Commit status (#20332) (#20334)
* Only show Followers that current user can access (#20220) (#20253)
* Release page show all tags in compare dropdown (#20070) (#20071) * Release page show all tags in compare dropdown (#20070) (#20071)
* Fix permission check for delete tag (#19985) (#20001) * Fix permission check for delete tag (#19985) (#20001)
* Only log non ErrNotExist errors in git.GetNote (#19884) (#19905) * Only log non ErrNotExist errors in git.GetNote (#19884) (#19905)

View File

@ -62,7 +62,7 @@ ENV GITEA_CUSTOM /var/lib/gitea/custom
ENV GITEA_TEMP /tmp/gitea ENV GITEA_TEMP /tmp/gitea
ENV TMPDIR /tmp/gitea ENV TMPDIR /tmp/gitea
#TODO add to docs the ability to define the ini to load (usefull to test and revert a config) #TODO add to docs the ability to define the ini to load (useful to test and revert a config)
ENV GITEA_APP_INI /etc/gitea/app.ini ENV GITEA_APP_INI /etc/gitea/app.ini
ENV HOME "/var/lib/gitea/git" ENV HOME "/var/lib/gitea/git"
VOLUME ["/var/lib/gitea", "/etc/gitea"] VOLUME ["/var/lib/gitea", "/etc/gitea"]

View File

@ -312,6 +312,7 @@ lint: lint-frontend lint-backend
lint-frontend: node_modules lint-frontend: node_modules
npx eslint --color --max-warnings=0 web_src/js build templates *.config.js docs/assets/js npx eslint --color --max-warnings=0 web_src/js build templates *.config.js docs/assets/js
npx stylelint --color --max-warnings=0 web_src/less npx stylelint --color --max-warnings=0 web_src/less
npx spectral lint -q -F hint $(SWAGGER_SPEC)
.PHONY: lint-backend .PHONY: lint-backend
lint-backend: golangci-lint vet editorconfig-checker lint-backend: golangci-lint vet editorconfig-checker
@ -770,7 +771,7 @@ generate-manpage:
@mkdir -p man/man1/ man/man5 @mkdir -p man/man1/ man/man5
@./gitea docs --man > man/man1/gitea.1 @./gitea docs --man > man/man1/gitea.1
@gzip -9 man/man1/gitea.1 && echo man/man1/gitea.1.gz created @gzip -9 man/man1/gitea.1 && echo man/man1/gitea.1.gz created
@#TODO A smal script witch format config-cheat-sheet.en-us.md nicely to suit as config man page @#TODO A small script that formats config-cheat-sheet.en-us.md nicely for use as a config man page
.PHONY: pr\#% .PHONY: pr\#%
pr\#%: clean-all pr\#%: clean-all

View File

@ -102,7 +102,7 @@ NOTES:
Translations are done through Crowdin. If you want to translate to a new language ask one of the managers in the Crowdin project to add a new language there. Translations are done through Crowdin. If you want to translate to a new language ask one of the managers in the Crowdin project to add a new language there.
You can also just create an issue for adding a language or ask on discord on the #translation channel. If you need context or find some translation issues, you can leave a comment on the string or ask on Discord. For general translation questions there is a section in the docs. Currently a bit empty but we hope fo fill it as questions pop up. You can also just create an issue for adding a language or ask on discord on the #translation channel. If you need context or find some translation issues, you can leave a comment on the string or ask on Discord. For general translation questions there is a section in the docs. Currently a bit empty but we hope to fill it as questions pop up.
https://docs.gitea.io/en-us/translation-guidelines/ https://docs.gitea.io/en-us/translation-guidelines/

View File

@ -82,7 +82,7 @@ var (
}, },
cli.BoolFlag{ cli.BoolFlag{
Name: "no-system", Name: "no-system",
Usage: "Do not show system proceses", Usage: "Do not show system processes",
}, },
cli.BoolFlag{ cli.BoolFlag{
Name: "stacktraces", Name: "stacktraces",

View File

@ -2232,6 +2232,7 @@ ROUTER = console
;BLOCKED_DOMAINS = ;BLOCKED_DOMAINS =
;; ;;
;; Allow private addresses defined by RFC 1918, RFC 1122, RFC 4632 and RFC 4291 (false by default) ;; Allow private addresses defined by RFC 1918, RFC 1122, RFC 4632 and RFC 4291 (false by default)
;; If a domain is allowed by ALLOWED_DOMAINS, this option will be ignored.
;ALLOW_LOCALNETWORKS = false ;ALLOW_LOCALNETWORKS = false
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1083,7 +1083,7 @@ Task queue configuration has been moved to `queue.task`. However, the below conf
- `RETRY_BACKOFF`: **3**: Backoff time per http/https request retry (seconds) - `RETRY_BACKOFF`: **3**: Backoff time per http/https request retry (seconds)
- `ALLOWED_DOMAINS`: **\<empty\>**: Domains allowlist for migrating repositories, default is blank. It means everything will be allowed. Multiple domains could be separated by commas. Wildcard is supported: `github.com, *.github.com`. - `ALLOWED_DOMAINS`: **\<empty\>**: Domains allowlist for migrating repositories, default is blank. It means everything will be allowed. Multiple domains could be separated by commas. Wildcard is supported: `github.com, *.github.com`.
- `BLOCKED_DOMAINS`: **\<empty\>**: Domains blocklist for migrating repositories, default is blank. Multiple domains could be separated by commas. When `ALLOWED_DOMAINS` is not blank, this option has a higher priority to deny domains. Wildcard is supported. - `BLOCKED_DOMAINS`: **\<empty\>**: Domains blocklist for migrating repositories, default is blank. Multiple domains could be separated by commas. When `ALLOWED_DOMAINS` is not blank, this option has a higher priority to deny domains. Wildcard is supported.
- `ALLOW_LOCALNETWORKS`: **false**: Allow private addresses defined by RFC 1918, RFC 1122, RFC 4632 and RFC 4291 - `ALLOW_LOCALNETWORKS`: **false**: Allow private addresses defined by RFC 1918, RFC 1122, RFC 4632 and RFC 4291. If a domain is allowed by `ALLOWED_DOMAINS`, this option will be ignored.
- `SKIP_TLS_VERIFY`: **false**: Allow skip tls verify - `SKIP_TLS_VERIFY`: **false**: Allow skip tls verify
## Federation (`federation`) ## Federation (`federation`)

View File

@ -346,7 +346,7 @@ ALLOW_DATA_URI_IMAGES = true
- `ALLOW_DATA_URI_IMAGES`: **false** 允许 data uri 图片 (`<img src="data:image/png;base64,..."/>`)。 - `ALLOW_DATA_URI_IMAGES`: **false** 允许 data uri 图片 (`<img src="data:image/png;base64,..."/>`)。
多个净化规则可以被同时定义只要section名称最后一位不重复即可。如 `[markup.sanitizer.TeX-2]` 多个净化规则可以被同时定义只要section名称最后一位不重复即可。如 `[markup.sanitizer.TeX-2]`
为了针对一种渲染类型进行一个特殊的净化策略,必须使用形如 `[markup.sanitizer.asciidoc.rule-1]` 的方式来命名 seciton。 为了针对一种渲染类型进行一个特殊的净化策略,必须使用形如 `[markup.sanitizer.asciidoc.rule-1]` 的方式来命名 section。
如果此规则没有匹配到任何渲染类型,它将会被应用到所有的渲染类型。 如果此规则没有匹配到任何渲染类型,它将会被应用到所有的渲染类型。
## Time (`time`) ## Time (`time`)

View File

@ -202,7 +202,7 @@ You can display STL file directly in Gitea by adding:
to the file `templates/custom/footer.tmpl` to the file `templates/custom/footer.tmpl`
You also need to download the content of the library [Madeleine.js](https://jinjunho.github.io/Madeleine.js/) and place it under `$GITEA_CUSTOM/public/` folder. You also need to download the content of the library [Madeleine.js](https://github.com/beige90/Madeleine.js) and place it under `$GITEA_CUSTOM/public/` folder.
You should end-up with a folder structure similar to: You should end-up with a folder structure similar to:

View File

@ -23,7 +23,7 @@ Publish [NuGet](https://www.nuget.org/) packages for your user or organization.
## Requirements ## Requirements
To work with the NuGet package registry, you can use command-line interface tools as well as NuGet features in various IDEs like Visual Studio. To work with the NuGet package registry, you can use command-line interface tools as well as NuGet features in various IDEs like Visual Studio.
More informations about NuGet clients can be found in [the official documentation](https://docs.microsoft.com/en-us/nuget/install-nuget-client-tools). More information about NuGet clients can be found in [the official documentation](https://docs.microsoft.com/en-us/nuget/install-nuget-client-tools).
The following examples use the `dotnet nuget` tool. The following examples use the `dotnet nuget` tool.
## Configuring the package registry ## Configuring the package registry

View File

@ -201,7 +201,7 @@ func (c *compareDump) assertEquals(repoBefore, repoAfter *repo_model.Repository)
"Assignees": {ignore: true}, // not implemented yet "Assignees": {ignore: true}, // not implemented yet
"Head": {nested: comparePullRequestBranch}, "Head": {nested: comparePullRequestBranch},
"Base": {nested: comparePullRequestBranch}, "Base": {nested: comparePullRequestBranch},
"Labels": {ignore: true}, // because org labels are not handled propery "Labels": {ignore: true}, // because org labels are not handled properly
}).([]*base.PullRequest) }).([]*base.PullRequest)
assert.True(c.t, ok) assert.True(c.t, ok)
assert.GreaterOrEqual(c.t, len(prs), 1) assert.GreaterOrEqual(c.t, len(prs), 1)

View File

@ -100,7 +100,7 @@ func TxContext() (*Context, Committer, error) {
} }
// WithTx represents executing database operations on a transaction // WithTx represents executing database operations on a transaction
// you can optionally change the context to a parrent one // you can optionally change the context to a parent one
func WithTx(f func(ctx context.Context) error, stdCtx ...context.Context) error { func WithTx(f func(ctx context.Context) error, stdCtx ...context.Context) error {
parentCtx := DefaultContext parentCtx := DefaultContext
if len(stdCtx) != 0 && stdCtx[0] != nil { if len(stdCtx) != 0 && stdCtx[0] != nil {

View File

@ -62,7 +62,7 @@ func GetUnmergedPullRequestsByHeadInfo(repoID int64, branch string) ([]*PullRequ
Find(&prs) Find(&prs)
} }
// CanMaintainerWriteToBranch check whether user is a matainer and could write to the branch // CanMaintainerWriteToBranch check whether user is a maintainer and could write to the branch
func CanMaintainerWriteToBranch(p access_model.Permission, branch string, user *user_model.User) bool { func CanMaintainerWriteToBranch(p access_model.Permission, branch string, user *user_model.User) bool {
if p.CanWrite(unit.TypeCode) { if p.CanWrite(unit.TypeCode) {
return true return true

View File

@ -55,7 +55,7 @@ func GetTeamRepositories(ctx context.Context, opts *SearchTeamRepoOptions) ([]*r
Find(&repos) Find(&repos)
} }
// AddTeamRepo addes a repo for an organization's team // AddTeamRepo adds a repo for an organization's team
func AddTeamRepo(ctx context.Context, orgID, teamID, repoID int64) error { func AddTeamRepo(ctx context.Context, orgID, teamID, repoID int64) error {
_, err := db.GetEngine(ctx).Insert(&TeamRepo{ _, err := db.GetEngine(ctx).Insert(&TeamRepo{
OrgID: orgID, OrgID: orgID,

View File

@ -86,7 +86,13 @@ func updateUserAccess(accessMap map[int64]*userAccess, user *user_model.User, mo
// FIXME: do cross-comparison so reduce deletions and additions to the minimum? // FIXME: do cross-comparison so reduce deletions and additions to the minimum?
func refreshAccesses(ctx context.Context, repo *repo_model.Repository, accessMap map[int64]*userAccess) (err error) { func refreshAccesses(ctx context.Context, repo *repo_model.Repository, accessMap map[int64]*userAccess) (err error) {
minMode := perm.AccessModeRead minMode := perm.AccessModeRead
if !repo.IsPrivate { if err := repo.GetOwner(ctx); err != nil {
return fmt.Errorf("GetOwner: %v", err)
}
// If the repo isn't private and isn't owned by a organization,
// increase the minMode to Write.
if !repo.IsPrivate && !repo.Owner.IsOrganization() {
minMode = perm.AccessModeWrite minMode = perm.AccessModeWrite
} }

View File

@ -23,7 +23,7 @@ import (
// UTF8BOM is the utf-8 byte-order marker // UTF8BOM is the utf-8 byte-order marker
var UTF8BOM = []byte{'\xef', '\xbb', '\xbf'} var UTF8BOM = []byte{'\xef', '\xbb', '\xbf'}
// ToUTF8WithFallbackReader detects the encoding of content and coverts to UTF-8 reader if possible // ToUTF8WithFallbackReader detects the encoding of content and converts to UTF-8 reader if possible
func ToUTF8WithFallbackReader(rd io.Reader) io.Reader { func ToUTF8WithFallbackReader(rd io.Reader) io.Reader {
buf := make([]byte, 2048) buf := make([]byte, 2048)
n, err := util.ReadAtMost(rd, buf) n, err := util.ReadAtMost(rd, buf)
@ -76,7 +76,7 @@ func ToUTF8WithErr(content []byte) (string, error) {
return string(result), err return string(result), err
} }
// ToUTF8WithFallback detects the encoding of content and coverts to UTF-8 if possible // ToUTF8WithFallback detects the encoding of content and converts to UTF-8 if possible
func ToUTF8WithFallback(content []byte) []byte { func ToUTF8WithFallback(content []byte) []byte {
bs, _ := io.ReadAll(ToUTF8WithFallbackReader(bytes.NewReader(content))) bs, _ := io.ReadAll(ToUTF8WithFallbackReader(bytes.NewReader(content)))
return bs return bs
@ -191,7 +191,7 @@ func DetectEncoding(content []byte) (string, error) {
break break
} }
// Otherwise check if this results is earlier in the DetectedCharsetOrder than our current top guesss // Otherwise check if this results is earlier in the DetectedCharsetOrder than our current top guess
resultPriority, resultHas := setting.Repository.DetectedCharsetScore[strings.ToLower(strings.TrimSpace(result.Charset))] resultPriority, resultHas := setting.Repository.DetectedCharsetScore[strings.ToLower(strings.TrimSpace(result.Charset))]
if resultHas && (!has || resultPriority < priority) { if resultHas && (!has || resultPriority < priority) {
topResult = result topResult = result

View File

@ -32,8 +32,8 @@ func iterateUserAccounts(ctx context.Context, each func(*user.User) error) error
// Ref: https://github.com/go-gitea/gitea/pull/19085 & https://github.com/go-gitea/gitea/pull/17688 // Ref: https://github.com/go-gitea/gitea/pull/19085 & https://github.com/go-gitea/gitea/pull/17688
func checkUserEmail(ctx context.Context, logger log.Logger, _ bool) error { func checkUserEmail(ctx context.Context, logger log.Logger, _ bool) error {
// We could use quirky SQL to get all users that start without a [a-zA-Z0-9], but that would mean // We could use quirky SQL to get all users that start without a [a-zA-Z0-9], but that would mean
// DB provider-specific SQL and only works _now_. So instead we iterate trough all user accounts and // DB provider-specific SQL and only works _now_. So instead we iterate through all user accounts
// use the user.ValidateEmail function to be future-proof. // and use the user.ValidateEmail function to be future-proof.
var invalidUserCount int64 var invalidUserCount int64
if err := iterateUserAccounts(ctx, func(u *user.User) error { if err := iterateUserAccounts(ctx, func(u *user.User) error {
// Only check for users, skip // Only check for users, skip

View File

@ -125,14 +125,14 @@ func (hl *HostMatchList) checkIP(ip net.IP) bool {
// MatchHostName checks if the host matches an allow/deny(block) list // MatchHostName checks if the host matches an allow/deny(block) list
func (hl *HostMatchList) MatchHostName(host string) bool { func (hl *HostMatchList) MatchHostName(host string) bool {
if hl == nil {
return false
}
hostname, _, err := net.SplitHostPort(host) hostname, _, err := net.SplitHostPort(host)
if err != nil { if err != nil {
hostname = host hostname = host
} }
if hl == nil {
return false
}
if hl.checkPattern(hostname) { if hl.checkPattern(hostname) {
return true return true
} }

View File

@ -103,7 +103,7 @@ func (m *Manager) getLevelDB(connection string) (*leveldb.DB, error) {
db, ok = m.LevelDBConnections[dataDir] db, ok = m.LevelDBConnections[dataDir]
if ok { if ok {
db.count++ db.count++
log.Warn("Duplicate connnection to level db: %s with different connection strings. Initial connection: %s. This connection: %s", dataDir, db.name[0], connection) log.Warn("Duplicate connection to level db: %s with different connection strings. Initial connection: %s. This connection: %s", dataDir, db.name[0], connection)
db.name = append(db.name, connection) db.name = append(db.name, connection)
m.LevelDBConnections[connection] = db m.LevelDBConnections[connection] = db
return db.db, nil return db.db, nil

View File

@ -156,6 +156,12 @@ func parsePostgreSQLHostPort(info string) (string, string) {
} else if len(info) > 0 { } else if len(info) > 0 {
host = info host = info
} }
if host == "" {
host = "127.0.0.1"
}
if port == "" {
port = "5432"
}
return host, port return host, port
} }
@ -173,6 +179,7 @@ func getPostgreSQLConnectionString(dbHost, dbUser, dbPasswd, dbName, dbParam, db
// ParseMSSQLHostPort splits the host into host and port // ParseMSSQLHostPort splits the host into host and port
func ParseMSSQLHostPort(info string) (string, string) { func ParseMSSQLHostPort(info string) (string, string) {
// the default port "0" might be related to MSSQL's dynamic port, maybe it should be double-confirmed in the future
host, port := "127.0.0.1", "0" host, port := "127.0.0.1", "0"
if strings.Contains(info, ":") { if strings.Contains(info, ":") {
host = strings.Split(info, ":")[0] host = strings.Split(info, ":")[0]
@ -183,5 +190,11 @@ func ParseMSSQLHostPort(info string) (string, string) {
} else if len(info) > 0 { } else if len(info) > 0 {
host = info host = info
} }
if host == "" {
host = "127.0.0.1"
}
if port == "" {
port = "0"
}
return host, port return host, port
} }

View File

@ -60,7 +60,7 @@ func SetLocaleCookie(resp http.ResponseWriter, lang string, expiry int) {
} }
// DeleteLocaleCookie convenience function to delete the locale cookie consistently // DeleteLocaleCookie convenience function to delete the locale cookie consistently
// Setting the lang cookie will trigger the middleware to reset the language ot previous state. // Setting the lang cookie will trigger the middleware to reset the language to previous state.
func DeleteLocaleCookie(resp http.ResponseWriter) { func DeleteLocaleCookie(resp http.ResponseWriter) {
SetCookie(resp, "lang", "", SetCookie(resp, "lang", "",
-1, -1,

View File

@ -25,7 +25,7 @@ func UpdateFuncInfo(ctx context.Context, funcInfo *FuncInfo) {
record.lock.Unlock() record.lock.Unlock()
} }
// MarkLongPolling marks the reuqest is a long-polling request, and the logger may output different message for it // MarkLongPolling marks the request is a long-polling request, and the logger may output different message for it
func MarkLongPolling(resp http.ResponseWriter, req *http.Request) { func MarkLongPolling(resp http.ResponseWriter, req *http.Request) {
record, ok := req.Context().Value(contextKey).(*requestRecord) record, ok := req.Context().Value(contextKey).(*requestRecord)
if !ok { if !ok {

View File

@ -6,7 +6,7 @@
/bazel-* /bazel-*
# Directories for the Bazel IntelliJ plugin containing the generated # Directories for the Bazel IntelliJ plugin containing the generated
# IntelliJ project files and plugin configuration. Seperate directories are # IntelliJ project files and plugin configuration. Separate directories are
# for the IntelliJ, Android Studio and CLion versions of the plugin. # for the IntelliJ, Android Studio and CLion versions of the plugin.
/.ijwb/ /.ijwb/
/.aswb/ /.aswb/

View File

@ -932,7 +932,7 @@ form.name_pattern_not_allowed = The pattern '%s' is not allowed in a repository
need_auth = Authorization need_auth = Authorization
migrate_options = Migration Options migrate_options = Migration Options
migrate_service = Migration Service migrate_service = Migration Service
migrate_options_mirror_helper = This repository will be a <span class="text blue">mirror</span> migrate_options_mirror_helper = This repository will be a mirror
migrate_options_lfs = Migrate LFS files migrate_options_lfs = Migrate LFS files
migrate_options_lfs_endpoint.label = LFS Endpoint migrate_options_lfs_endpoint.label = LFS Endpoint
migrate_options_lfs_endpoint.description = Migration will attempt to use your Git remote to <a target="_blank" rel="noopener noreferrer" href="%s">determine the LFS server</a>. You can also specify a custom endpoint if the repository LFS data is stored somewhere else. migrate_options_lfs_endpoint.description = Migration will attempt to use your Git remote to <a target="_blank" rel="noopener noreferrer" href="%s">determine the LFS server</a>. You can also specify a custom endpoint if the repository LFS data is stored somewhere else.

View File

@ -1303,6 +1303,7 @@ issues.previous=Anterior
issues.next=Seguinte issues.next=Seguinte
issues.open_title=Aberta issues.open_title=Aberta
issues.closed_title=Fechada issues.closed_title=Fechada
issues.draft_title=Rascunho
issues.num_comments=%d comentários issues.num_comments=%d comentários
issues.commented_at=`comentou <a href="#%s">%s</a>` issues.commented_at=`comentou <a href="#%s">%s</a>`
issues.delete_comment_confirm=Tem a certeza que quer eliminar este comentário? issues.delete_comment_confirm=Tem a certeza que quer eliminar este comentário?

View File

@ -861,7 +861,9 @@ default_branch=默认分支
default_branch_helper=默认分支是用于合并请求和代码提交的基础分支。 default_branch_helper=默认分支是用于合并请求和代码提交的基础分支。
mirror_prune=修剪 mirror_prune=修剪
mirror_prune_desc=删除过时的远程跟踪引用 mirror_prune_desc=删除过时的远程跟踪引用
mirror_interval=镜像间隔 (有效的时间单位是 'h', 'm', 's')。0 禁用自动定期同步 (最短间隔: %s)
mirror_interval_invalid=镜像间隔无效。 mirror_interval_invalid=镜像间隔无效。
mirror_sync_on_commit=推送提交时同步
mirror_address=从URL克隆 mirror_address=从URL克隆
mirror_address_desc=在授权框中输入必要的凭据。 mirror_address_desc=在授权框中输入必要的凭据。
mirror_address_url_invalid=URL无效。请检查您所输入的URL是否正确。 mirror_address_url_invalid=URL无效。请检查您所输入的URL是否正确。
@ -1301,6 +1303,7 @@ issues.previous=上一页
issues.next=下一页 issues.next=下一页
issues.open_title=开启中 issues.open_title=开启中
issues.closed_title=已关闭 issues.closed_title=已关闭
issues.draft_title=草稿
issues.num_comments=%d 条评论 issues.num_comments=%d 条评论
issues.commented_at=`评论于 <a href="#%s">%s</a>` issues.commented_at=`评论于 <a href="#%s">%s</a>`
issues.delete_comment_confirm=您确定要删除该条评论吗? issues.delete_comment_confirm=您确定要删除该条评论吗?

2888
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,7 @@
}, },
"devDependencies": { "devDependencies": {
"@happy-dom/jest-environment": "4.0.1", "@happy-dom/jest-environment": "4.0.1",
"@stoplight/spectral-cli": "6.4.1",
"eslint": "8.15.0", "eslint": "8.15.0",
"eslint-plugin-html": "6.2.0", "eslint-plugin-html": "6.2.0",
"eslint-plugin-import": "2.26.0", "eslint-plugin-import": "2.26.0",

View File

@ -76,7 +76,7 @@ type PackageVersionMetadata struct {
Dist Dist `json:"dist"` Dist Dist `json:"dist"`
} }
// Dist contains package download informations // Dist contains package download information
type Dist struct { type Dist struct {
Type string `json:"type"` Type string `json:"type"`
URL string `json:"url"` URL string `json:"url"`

View File

@ -429,14 +429,14 @@ func uploadFile(ctx *context.Context, fileFilter stringSet, fileKey string) {
ctx.Status(http.StatusCreated) ctx.Status(http.StatusCreated)
} }
// DownloadRecipeFile serves the conent of the requested recipe file // DownloadRecipeFile serves the content of the requested recipe file
func DownloadRecipeFile(ctx *context.Context) { func DownloadRecipeFile(ctx *context.Context) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference)
downloadFile(ctx, recipeFileList, rref.AsKey()) downloadFile(ctx, recipeFileList, rref.AsKey())
} }
// DownloadPackageFile serves the conent of the requested package file // DownloadPackageFile serves the content of the requested package file
func DownloadPackageFile(ctx *context.Context) { func DownloadPackageFile(ctx *context.Context) {
pref := ctx.Data[packageReferenceKey].(*conan_module.PackageReference) pref := ctx.Data[packageReferenceKey].(*conan_module.PackageReference)

View File

@ -37,7 +37,7 @@ func EnumeratePackages(ctx *context.Context) {
enumeratePackages(ctx, "specs.4.8", packages) enumeratePackages(ctx, "specs.4.8", packages)
} }
// EnumeratePackagesLatest serves the list of the lastest version of every package // EnumeratePackagesLatest serves the list of the latest version of every package
func EnumeratePackagesLatest(ctx *context.Context) { func EnumeratePackagesLatest(ctx *context.Context) {
pvs, _, err := packages_model.SearchLatestVersions(ctx, &packages_model.PackageSearchOptions{ pvs, _, err := packages_model.SearchLatestVersions(ctx, &packages_model.PackageSearchOptions{
OwnerID: ctx.Package.Owner.ID, OwnerID: ctx.Package.Owner.ID,

View File

@ -1017,7 +1017,7 @@ func Routes() *web.Route {
}, mustAllowPulls, reqRepoReader(unit.TypeCode), context.ReferencesGitRepo()) }, mustAllowPulls, reqRepoReader(unit.TypeCode), context.ReferencesGitRepo())
m.Group("/statuses", func() { m.Group("/statuses", func() {
m.Combo("/{sha}").Get(repo.GetCommitStatuses). m.Combo("/{sha}").Get(repo.GetCommitStatuses).
Post(reqToken(), bind(api.CreateStatusOption{}), repo.NewCommitStatus) Post(reqToken(), reqRepoWriter(unit.TypeCode), bind(api.CreateStatusOption{}), repo.NewCommitStatus)
}, reqRepoReader(unit.TypeCode)) }, reqRepoReader(unit.TypeCode))
m.Group("/commits", func() { m.Group("/commits", func() {
m.Get("", context.ReferencesGitRepo(), repo.GetAllCommits) m.Get("", context.ReferencesGitRepo(), repo.GetAllCommits)

View File

@ -100,7 +100,7 @@ func GetHook(ctx *context.APIContext) {
// CreateHook create a hook for an organization // CreateHook create a hook for an organization
func CreateHook(ctx *context.APIContext) { func CreateHook(ctx *context.APIContext) {
// swagger:operation POST /orgs/{org}/hooks/ organization orgCreateHook // swagger:operation POST /orgs/{org}/hooks organization orgCreateHook
// --- // ---
// summary: Create a hook // summary: Create a hook
// consumes: // consumes:

View File

@ -107,9 +107,6 @@ type swaggerParameterBodies struct {
// in:body // in:body
EditUserOption api.EditUserOption EditUserOption api.EditUserOption
// in:body
MigrateRepoForm forms.MigrateRepoForm
// in:body // in:body
EditAttachmentOptions api.EditAttachmentOptions EditAttachmentOptions api.EditAttachmentOptions

View File

@ -1440,7 +1440,7 @@ func UpdatePullRequestTarget(ctx *context.Context) {
err := err.(issues_model.ErrPullRequestAlreadyExists) err := err.(issues_model.ErrPullRequestAlreadyExists)
RepoRelPath := ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name RepoRelPath := ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name
errorMessage := ctx.Tr("repo.pulls.has_pull_request", html.EscapeString(ctx.Repo.RepoLink+"/pulls/"+strconv.FormatInt(err.IssueID, 10)), html.EscapeString(RepoRelPath), err.IssueID) // FIXME: Creates url insidde locale string errorMessage := ctx.Tr("repo.pulls.has_pull_request", html.EscapeString(ctx.Repo.RepoLink+"/pulls/"+strconv.FormatInt(err.IssueID, 10)), html.EscapeString(RepoRelPath), err.IssueID) // FIXME: Creates url inside locale string
ctx.Flash.Error(errorMessage) ctx.Flash.Error(errorMessage)
ctx.JSON(http.StatusConflict, map[string]interface{}{ ctx.JSON(http.StatusConflict, map[string]interface{}{

View File

@ -98,8 +98,8 @@ func releasesOrTags(ctx *context.Context, isTagList bool) {
listOptions.PageSize = setting.API.MaxResponseItems listOptions.PageSize = setting.API.MaxResponseItems
} }
// TODO(20073) tags are used for compare feature witch needs all tags // TODO(20073) tags are used for compare feature which needs all tags
// filtering is doen at the client side atm // filtering is done on the client-side atm
tagListStart, tagListEnd := 0, 0 tagListStart, tagListEnd := 0, 0
if isTagList { if isTagList {
tagListStart, tagListEnd = listOptions.GetStartEnd() tagListStart, tagListEnd = listOptions.GetStartEnd()
@ -514,12 +514,12 @@ func EditReleasePost(ctx *context.Context) {
ctx.Redirect(ctx.Repo.RepoLink + "/releases") ctx.Redirect(ctx.Repo.RepoLink + "/releases")
} }
// DeleteRelease delete a release // DeleteRelease deletes a release
func DeleteRelease(ctx *context.Context) { func DeleteRelease(ctx *context.Context) {
deleteReleaseOrTag(ctx, false) deleteReleaseOrTag(ctx, false)
} }
// DeleteTag delete a tag // DeleteTag deletes a tag
func DeleteTag(ctx *context.Context) { func DeleteTag(ctx *context.Context) {
deleteReleaseOrTag(ctx, true) deleteReleaseOrTag(ctx, true)
} }

View File

@ -85,7 +85,7 @@ func CorsHandler() func(next http.Handler) http.Handler {
// for users that have already signed in. // for users that have already signed in.
func buildAuthGroup() *auth_service.Group { func buildAuthGroup() *auth_service.Group {
group := auth_service.NewGroup( group := auth_service.NewGroup(
&auth_service.OAuth2{}, // FIXME: this should be removed and only applied in download and oauth realted routers &auth_service.OAuth2{}, // FIXME: this should be removed and only applied in download and oauth related routers
&auth_service.Basic{}, // FIXME: this should be removed and only applied in download and git/lfs routers &auth_service.Basic{}, // FIXME: this should be removed and only applied in download and git/lfs routers
&auth_service.Session{}, &auth_service.Session{},
) )

View File

@ -33,7 +33,7 @@ type webfingerLink struct {
Properties map[string]interface{} `json:"properties,omitempty"` Properties map[string]interface{} `json:"properties,omitempty"`
} }
// WebfingerQuery returns informations about a resource // WebfingerQuery returns information about a resource
// https://datatracker.ietf.org/doc/html/rfc7565 // https://datatracker.ietf.org/doc/html/rfc7565
func WebfingerQuery(ctx *context.Context) { func WebfingerQuery(ctx *context.Context) {
appURL, _ := url.Parse(setting.AppURL) appURL, _ := url.Parse(setting.AppURL)

View File

@ -35,7 +35,7 @@ type GothProvider interface {
GothProviderCreator GothProviderCreator
} }
// ImagedProvider provide an overrided image setting for the provider // ImagedProvider provide an overridden image setting for the provider
type ImagedProvider struct { type ImagedProvider struct {
GothProvider GothProvider
image string image string

View File

@ -7,7 +7,6 @@ package migrations
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"io" "io"
"os" "os"
@ -281,7 +280,7 @@ func (g *GiteaLocalUploader) CreateReleases(releases ...*base.Release) error {
// calc NumCommits if possible // calc NumCommits if possible
if rel.TagName != "" { if rel.TagName != "" {
commit, err := g.gitRepo.GetTagCommit(rel.TagName) commit, err := g.gitRepo.GetTagCommit(rel.TagName)
if !errors.Is(err, git.ErrNotExist{}) { if !git.IsErrNotExist(err) {
if err != nil { if err != nil {
return fmt.Errorf("GetTagCommit[%v]: %v", rel.TagName, err) return fmt.Errorf("GetTagCommit[%v]: %v", rel.TagName, err)
} }

View File

@ -84,7 +84,10 @@ func IsMigrateURLAllowed(remoteURL string, doer *user_model.User) error {
// some users only use proxy, there is no DNS resolver. it's safe to ignore the LookupIP error // some users only use proxy, there is no DNS resolver. it's safe to ignore the LookupIP error
addrList, _ := net.LookupIP(hostName) addrList, _ := net.LookupIP(hostName)
return checkByAllowBlockList(hostName, addrList)
}
func checkByAllowBlockList(hostName string, addrList []net.IP) error {
var ipAllowed bool var ipAllowed bool
var ipBlocked bool var ipBlocked bool
for _, addr := range addrList { for _, addr := range addrList {
@ -93,12 +96,12 @@ func IsMigrateURLAllowed(remoteURL string, doer *user_model.User) error {
} }
var blockedError error var blockedError error
if blockList.MatchHostName(hostName) || ipBlocked { if blockList.MatchHostName(hostName) || ipBlocked {
blockedError = &models.ErrInvalidCloneAddr{Host: u.Host, IsPermissionDenied: true} blockedError = &models.ErrInvalidCloneAddr{Host: hostName, IsPermissionDenied: true}
} }
// if we have an allow-list, check the allow-list first // if we have an allow-list, check the allow-list before return to get the more accurate error
if !allowList.IsEmpty() { if !allowList.IsEmpty() {
if !allowList.MatchHostName(hostName) && !ipAllowed { if !allowList.MatchHostName(hostName) && !ipAllowed {
return &models.ErrInvalidCloneAddr{Host: u.Host, IsPermissionDenied: true} return &models.ErrInvalidCloneAddr{Host: hostName, IsPermissionDenied: true}
} }
} }
// otherwise, we always follow the blocked list // otherwise, we always follow the blocked list
@ -474,5 +477,7 @@ func Init() error {
allowList.AppendBuiltin(hostmatcher.MatchBuiltinPrivate) allowList.AppendBuiltin(hostmatcher.MatchBuiltinPrivate)
allowList.AppendBuiltin(hostmatcher.MatchBuiltinLoopback) allowList.AppendBuiltin(hostmatcher.MatchBuiltinLoopback)
} }
// TODO: at the moment, if ALLOW_LOCALNETWORKS=false, ALLOWED_DOMAINS=domain.com, and domain.com has IP 127.0.0.1, then it's still allowed.
// if we want to block such case, the private&loopback should be added to the blockList when ALLOW_LOCALNETWORKS=false
return nil return nil
} }

View File

@ -5,6 +5,7 @@
package migrations package migrations
import ( import (
"net"
"path/filepath" "path/filepath"
"testing" "testing"
@ -74,3 +75,42 @@ func TestMigrateWhiteBlocklist(t *testing.T) {
setting.ImportLocalPaths = old setting.ImportLocalPaths = old
} }
func TestAllowBlockList(t *testing.T) {
init := func(allow, block string, local bool) {
setting.Migrations.AllowedDomains = allow
setting.Migrations.BlockedDomains = block
setting.Migrations.AllowLocalNetworks = local
assert.NoError(t, Init())
}
// default, allow all external, block none, no local networks
init("", "", false)
assert.NoError(t, checkByAllowBlockList("domain.com", []net.IP{net.ParseIP("1.2.3.4")}))
assert.Error(t, checkByAllowBlockList("domain.com", []net.IP{net.ParseIP("127.0.0.1")}))
// allow all including local networks (it could lead to SSRF in production)
init("", "", true)
assert.NoError(t, checkByAllowBlockList("domain.com", []net.IP{net.ParseIP("1.2.3.4")}))
assert.NoError(t, checkByAllowBlockList("domain.com", []net.IP{net.ParseIP("127.0.0.1")}))
// allow wildcard, block some subdomains. if the domain name is allowed, then the local network check is skipped
init("*.domain.com", "blocked.domain.com", false)
assert.NoError(t, checkByAllowBlockList("sub.domain.com", []net.IP{net.ParseIP("1.2.3.4")}))
assert.NoError(t, checkByAllowBlockList("sub.domain.com", []net.IP{net.ParseIP("127.0.0.1")}))
assert.Error(t, checkByAllowBlockList("blocked.domain.com", []net.IP{net.ParseIP("1.2.3.4")}))
assert.Error(t, checkByAllowBlockList("sub.other.com", []net.IP{net.ParseIP("1.2.3.4")}))
// allow wildcard (it could lead to SSRF in production)
init("*", "", false)
assert.NoError(t, checkByAllowBlockList("domain.com", []net.IP{net.ParseIP("1.2.3.4")}))
assert.NoError(t, checkByAllowBlockList("domain.com", []net.IP{net.ParseIP("127.0.0.1")}))
// local network can still be blocked
init("*", "127.0.0.*", false)
assert.NoError(t, checkByAllowBlockList("domain.com", []net.IP{net.ParseIP("1.2.3.4")}))
assert.Error(t, checkByAllowBlockList("domain.com", []net.IP{net.ParseIP("127.0.0.1")}))
// reset
init("", "", false)
}

View File

@ -254,7 +254,7 @@
{{$notAllOverridableChecksOk := or .IsBlockedByApprovals .IsBlockedByRejection .IsBlockedByOfficialReviewRequests .IsBlockedByOutdatedBranch .IsBlockedByChangedProtectedFiles (and .EnableStatusCheck (not .RequiredStatusCheckState.IsSuccess))}} {{$notAllOverridableChecksOk := or .IsBlockedByApprovals .IsBlockedByRejection .IsBlockedByOfficialReviewRequests .IsBlockedByOutdatedBranch .IsBlockedByChangedProtectedFiles (and .EnableStatusCheck (not .RequiredStatusCheckState.IsSuccess))}}
{{/* admin can merge without checks, writer can merge when checkes succeed */}} {{/* admin can merge without checks, writer can merge when checks succeed */}}
{{$canMergeNow := and (or $.IsRepoAdmin (not $notAllOverridableChecksOk)) (or (not .AllowMerge) (not .RequireSigned) .WillSign)}} {{$canMergeNow := and (or $.IsRepoAdmin (not $notAllOverridableChecksOk)) (or (not .AllowMerge) (not .RequireSigned) .WillSign)}}
{{/* admin and writer both can make an auto merge schedule */}} {{/* admin and writer both can make an auto merge schedule */}}

View File

@ -3,7 +3,7 @@
<label>{{.locale.Tr "repo.migrate_options"}}</label> <label>{{.locale.Tr "repo.migrate_options"}}</label>
<div class="ui checkbox"> <div class="ui checkbox">
<input id="mirror" name="mirror" type="checkbox" {{if .mirror}} checked{{end}}> <input id="mirror" name="mirror" type="checkbox" {{if .mirror}} checked{{end}}>
<label>{{.locale.Tr "repo.migrate_options_mirror_helper" | Safe}}</label> <label>{{.locale.Tr "repo.migrate_options_mirror_helper"}}</label>
</div> </div>
</div> </div>
{{end}} {{end}}

View File

@ -1131,9 +1131,7 @@
"$ref": "#/responses/HookList" "$ref": "#/responses/HookList"
} }
} }
} },
},
"/orgs/{org}/hooks/": {
"post": { "post": {
"consumes": [ "consumes": [
"application/json" "application/json"
@ -16078,12 +16076,6 @@
}, },
"x-go-package": "code.gitea.io/gitea/modules/structs" "x-go-package": "code.gitea.io/gitea/modules/structs"
}, },
"GitServiceType": {
"description": "GitServiceType represents a git service",
"type": "integer",
"format": "int64",
"x-go-package": "code.gitea.io/gitea/modules/structs"
},
"GitTreeResponse": { "GitTreeResponse": {
"description": "GitTreeResponse returns a git tree", "description": "GitTreeResponse returns a git tree",
"type": "object", "type": "object",
@ -16473,94 +16465,6 @@
"x-go-name": "MergePullRequestForm", "x-go-name": "MergePullRequestForm",
"x-go-package": "code.gitea.io/gitea/services/forms" "x-go-package": "code.gitea.io/gitea/services/forms"
}, },
"MigrateRepoForm": {
"description": "MigrateRepoForm form for migrating repository\nthis is used to interact with web ui",
"type": "object",
"required": [
"clone_addr",
"uid",
"repo_name"
],
"properties": {
"auth_password": {
"type": "string",
"x-go-name": "AuthPassword"
},
"auth_token": {
"type": "string",
"x-go-name": "AuthToken"
},
"auth_username": {
"type": "string",
"x-go-name": "AuthUsername"
},
"clone_addr": {
"type": "string",
"x-go-name": "CloneAddr"
},
"description": {
"type": "string",
"x-go-name": "Description"
},
"issues": {
"type": "boolean",
"x-go-name": "Issues"
},
"labels": {
"type": "boolean",
"x-go-name": "Labels"
},
"lfs": {
"type": "boolean",
"x-go-name": "LFS"
},
"lfs_endpoint": {
"type": "string",
"x-go-name": "LFSEndpoint"
},
"milestones": {
"type": "boolean",
"x-go-name": "Milestones"
},
"mirror": {
"type": "boolean",
"x-go-name": "Mirror"
},
"mirror_interval": {
"type": "string",
"x-go-name": "MirrorInterval"
},
"private": {
"type": "boolean",
"x-go-name": "Private"
},
"pull_requests": {
"type": "boolean",
"x-go-name": "PullRequests"
},
"releases": {
"type": "boolean",
"x-go-name": "Releases"
},
"repo_name": {
"type": "string",
"x-go-name": "RepoName"
},
"service": {
"$ref": "#/definitions/GitServiceType"
},
"uid": {
"type": "integer",
"format": "int64",
"x-go-name": "UID"
},
"wiki": {
"type": "boolean",
"x-go-name": "Wiki"
}
},
"x-go-package": "code.gitea.io/gitea/services/forms"
},
"MigrateRepoOptions": { "MigrateRepoOptions": {
"description": "MigrateRepoOptions options for migrating repository's\nthis is used to interact with api v1", "description": "MigrateRepoOptions options for migrating repository's\nthis is used to interact with api v1",
"type": "object", "type": "object",

View File

@ -192,7 +192,7 @@ function setLabelColor(label, color) {
} }
/** /**
* Inspired by W3C recommandation https://www.w3.org/TR/WCAG20/#relativeluminancedef * Inspired by W3C recommendation https://www.w3.org/TR/WCAG20/#relativeluminancedef
*/ */
function getRelativeColor(color) { function getRelativeColor(color) {
color /= 255; color /= 255;

View File

@ -68,7 +68,7 @@
.dashboard-repos, .dashboard-repos,
.dashboard-orgs { .dashboard-orgs {
margin: 0 1px; /* Accomodate for Semantic's 1px hacks on .attached elements */ margin: 0 1px; /* Accommodate for Semantic's 1px hacks on .attached elements */
} }
.dashboard-navbar { .dashboard-navbar {