diff --git a/.air.toml b/.air.toml index 061008830317..069a88924388 100644 --- a/.air.toml +++ b/.air.toml @@ -5,6 +5,6 @@ tmp_dir = ".air" cmd = "make backend" bin = "gitea" include_ext = ["go", "tmpl"] -exclude_dir = ["modules/git/tests", "services/gitdiff/testdata", "modules/avatar/testdata"] -include_dir = ["cmd", "models", "modules", "options", "routers", "services", "templates"] +exclude_dir = ["modules/git/tests", "services/gitdiff/testdata", "modules/avatar/testdata", "models/fixtures", "models/migrations/fixtures", "modules/migration/file_format_testdata", "modules/avatar/identicon/testdata"] +include_dir = ["cmd", "models", "modules", "options", "routers", "services"] exclude_regex = ["_test.go$", "_gen.go$"] diff --git a/CHANGELOG.md b/CHANGELOG.md index e9ba23b4c493..e82430e2ce5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,203 @@ 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 been added to each release, please refer to the [blog](https://blog.gitea.io). -## [1.17.4](https://github.com/go-gitea/gitea/releases/tag/1.17.4) - 2022-12-21 +## [1.18.0](https://github.com/go-gitea/gitea/releases/tag/v1.18.0) - 2022-12-29 + +* SECURITY + * Remove ReverseProxy authentication from the API (#22219) (#22251) + * Support Go Vulnerability Management (#21139) + * Forbid HTML string tooltips (#20935) +* BREAKING + * Rework mailer settings (#18982) + * Remove U2F support (#20141) + * Refactor `i18n` to `locale` (#20153) + * Enable contenthash in filename for dynamic assets (#20813) +* FEATURES + * Add color previews in markdown (#21474) + * Allow package version sorting (#21453) + * Add support for Chocolatey/NuGet v2 API (#21393) + * Add API endpoint to get changed files of a PR (#21177) + * Add filetree on left of diff view (#21012) + * Support Issue forms and PR forms (#20987) + * Add support for Vagrant packages (#20930) + * Add support for `npm unpublish` (#20688) + * Add badge capabilities to users (#20607) + * Add issue filter for Author (#20578) + * Add KaTeX rendering to Markdown. (#20571) + * Add support for Pub packages (#20560) + * Support localized README (#20508) + * Add support mCaptcha as captcha provider (#20458) + * Add team member invite by email (#20307) + * Added email notification option to receive all own messages (#20179) + * Switch Unicode Escaping to a VSCode-like system (#19990) + * Add user/organization code search (#19977) + * Only show relevant repositories on explore page (#19361) + * User keypairs and HTTP signatures for ActivityPub federation using go-ap (#19133) + * Add sitemap support (#18407) + * Allow creation of OAuth2 applications for orgs (#18084) + * Add system setting table with cache and also add cache supports for user setting (#18058) + * Add pages to view watched repos and subscribed issues/PRs (#17156) + * Support Proxy protocol (#12527) + * Implement sync push mirror on commit (#19411) +* API + * Allow empty assignees on pull request edit (#22150) (#22214) + * Make external issue tracker regexp configurable via API (#21338) + * Add name field for org api (#21270) + * Show teams with no members if user is admin (#21204) + * Add latest commit's SHA to content response (#20398) + * Add allow_rebase_update, default_delete_branch_after_merge to repository api response (#20079) + * Add new endpoints for push mirrors management (#19841) +* ENHANCEMENTS + * Add setting to disable the git apply step in test patch (#22130) (#22170) + * Multiple improvements for comment edit diff (#21990) (#22007) + * Fix button in branch list, avoid unexpected page jump before restore branch actually done (#21562) (#21928) + * Fix flex layout for repo list icons (#21896) (#21920) + * Fix vertical align of committer avatar rendered by email address (#21884) (#21918) + * Fix setting HTTP headers after write (#21833) (#21877) + * Color and Style enhancements (#21784, #21799) (#21868) + * Ignore line anchor links with leading zeroes (#21728) (#21776) + * Quick fixes monaco-editor error: "vs.editor.nullLanguage" (#21734) (#21738) + * Use CSS color-scheme instead of invert (#21616) (#21623) + * Respect user's locale when rendering the date range in the repo activity page (#21410) + * Change `commits-table` column width (#21564) + * Refactor git command arguments and make all arguments to be safe to be used (#21535) + * CSS color enhancements (#21534) + * Add link to user profile in markdown mention only if user exists (#21533, #21554) + * Add option to skip index dirs (#21501) + * Diff file tree tweaks (#21446) + * Localize all timestamps (#21440) + * Add `code` highlighting in issue titles (#21432) + * Use Name instead of DisplayName in LFS Lock (#21415) + * Consolidate more CSS colors into variables (#21402) + * Redirect to new repository owner (#21398) + * Use ISO date format instead of hard-coded English date format for date range in repo activity page (#21396) + * Use weighted algorithm for string matching when finding files in repo (#21370) + * Show private data in feeds (#21369) + * Refactor parseTreeEntries, speed up tree list (#21368) + * Add GET and DELETE endpoints for Docker blob uploads (#21367) + * Add nicer error handling on template compile errors (#21350) + * Add `stat` to `ToCommit` function for speed (#21337) + * Support instance-wide OAuth2 applications (#21335) + * Record OAuth client type at registration (#21316) + * Add new CSS variables --color-accent and --color-small-accent (#21305) + * Improve error descriptions for unauthorized_client (#21292) + * Case-insensitive "find files in repo" (#21269) + * Consolidate more CSS rules, fix inline code on arc-green (#21260) + * Log real ip of requests from ssh (#21216) + * Save files in local storage as group readable (#21198) + * Enable fluid page layout on medium size viewports (#21178) + * File header tweaks (#21175) + * Added missing headers on user packages page (#21172) + * Display image digest for container packages (#21170) + * Skip dirty check for team forms (#21154) + * Keep path when creating a new branch (#21153) + * Remove fomantic image module (#21145) + * Make labels clickable in the comments section. (#21137) + * Sort branches and tags by date descending (#21136) + * Better repo API unit checks (#21130) + * Improve commit status icons (#21124) + * Limit length of repo description and repo url input fields (#21119) + * Show .editorconfig errors in frontend (#21088) + * Allow poster to choose reviewers (#21084) + * Remove black labels and CSS cleanup (#21003) + * Make e-mail sanity check more precise (#20991) + * Use native inputs in whitespace dropdown (#20980) + * Enhance package date display (#20928) + * Display total blob size of a package version (#20927) + * Show language name on hover (#20923) + * Show instructions for all generic package files (#20917) + * Refactor AssertExistsAndLoadBean to use generics (#20797) + * Move the official website link at the footer of gitea (#20777) + * Add support for full name in reverse proxy auth (#20776) + * Remove useless JS operation for relative time tooltips (#20756) + * Replace some icons with SVG (#20741) + * Change commit status icons to SVG (#20736) + * Improve single repo action for issue and pull requests (#20730) + * Allow multiple files in generic packages (#20661) + * Add option to create new issue from /issues page (#20650) + * Background color of private list-items updated (#20630) + * Added search input field to issue filter (#20623) + * Increase default item listing size `ISSUE_PAGING_NUM` to 20 (#20547) + * Modify milestone search keywords to be case insensitive again (#20513) + * Show hint to link package to repo when viewing empty repo package list (#20504) + * Add Tar ZSTD support (#20493) + * Make code review checkboxes clickable (#20481) + * Add "X-Gitea-Object-Type" header for GET `/raw/` & `/media/` API (#20438) + * Display project in issue list (#20434) + * Prepend commit message to template content when opening a new PR (#20429) + * Replace fomantic popup module with tippy.js (#20428) + * Allow to specify colors for text in markup (#20363) + * Allow access to the Public Organization Member lists with minimal permissions (#20330) + * Use default values when provided values are empty (#20318) + * Vertical align navbar avatar at middle (#20302) + * Delete cancel button in repo creation page (#21381) + * Include login_name in adminCreateUser response (#20283) + * fix: icon margin in user/settings/repos (#20281) + * Remove blue text on migrate page (#20273) + * Modify milestone search keywords to be case insensitive (#20266) + * Move some files into models' sub packages (#20262) + * Add tooltip to repo icons in explore page (#20241) + * Remove deprecated licenses (#20222) + * Webhook for Wiki changes (#20219) + * Share HTML template renderers and create a watcher framework (#20218) + * Allow enable LDAP source and disable user sync via CLI (#20206) + * Adds a checkbox to select all issues/PRs (#20177) + * Refactor `i18n` to `locale` (#20153) + * Disable status checks in template if none found (#20088) + * Allow manager logging to set SQL (#20064) + * Add order by for assignee no sort issue (#20053) + * Take a stab at porting existing components to Vue3 (#20044) + * Add doctor command to write commit-graphs (#20007) + * Add support for authentication based on reverse proxy email (#19949) + * Enable spellcheck for EasyMDE, use contenteditable mode (#19776) + * Allow specifying SECRET_KEY_URI, similar to INTERNAL_TOKEN_URI (#19663) + * Rework mailer settings (#18982) + * Add option to purge users (#18064) + * Add author search input (#21246) + * Make rss/atom identifier globally unique (#21550) +* BUGFIXES + * Auth interface return error when verify failure (#22119) (#22259) + * Use complete SHA to create and query commit status (#22244) (#22257) + * Update bleve and zapx to fix unaligned atomic (#22031) (#22218) + * Prevent panic in doctor command when running default checks (#21791) (#21807) + * Load GitRepo in API before deleting issue (#21720) (#21796) + * Ignore line anchor links with leading zeroes (#21728) (#21776) + * Set last login when activating account (#21731) (#21755) + * Fix UI language switching bug (#21597) (#21749) + * Quick fixes monaco-editor error: "vs.editor.nullLanguage" (#21734) (#21738) + * Allow local package identifiers for PyPI packages (#21690) (#21727) + * Deal with markdown template without metadata (#21639) (#21654) + * Fix opaque background on mermaid diagrams (#21642) (#21652) + * Fix repository adoption on Windows (#21646) (#21650) + * Sync git hooks when config file path changed (#21619) (#21626) + * Fix 500 on PR files API (#21602) (#21607) + * Fix `Timestamp.IsZero` (#21593) (#21603) + * Fix viewing user subscriptions (#21482) + * Fix mermaid-related bugs (#21431) + * Fix branch dropdown shifting on page load (#21428) + * Fix default theme-auto selector when nologin (#21346) + * Fix and improve incorrect error messages (#21342) + * Fix formatted link for PR review notifications to matrix (#21319) + * Center-aligning content of WebAuthN page (#21127) + * Remove follow from commits by file (#20765) + * Fix commit status popup (#20737) + * Fix init mail render logic (#20704) + * Use correct page size for link header pagination (#20546) + * Preserve unix socket file (#20499) + * Use tippy.js for context popup (#20393) + * Add missing parameter for error in log message (#20144) + * Do not allow organisation owners add themselves as collaborator (#20043) + * Rework file highlight rendering and fix yaml copy-paste (#19967) + * Improve code diff highlight, fix incorrect rendered diff result (#19958) +* TESTING + * Improve OAuth integration tests (#21390) + * Add playwright tests (#20123) +* BUILD + * Switch to building with go1.19 (#20695) + * Update JS dependencies, adjust eslint (#20659) + * Add more linters to improve code readability (#19989) + +## [1.17.4](https://github.com/go-gitea/gitea/releases/tag/v1.17.4) - 2022-12-21 * SECURITY * Do not allow Ghost access to limited visible user/org (#21849) (#21875) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bd5672643a67..fbf2a331dd48 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -441,7 +441,7 @@ be reviewed by two maintainers and must pass the automatic tests. Code that you contribute should use the standard copyright header: ``` -// Copyright 2022 The Gitea Authors. All rights reserved. +// Copyright The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT ``` diff --git a/Makefile b/Makefile index d1122984a7d8..06a0d1c18e22 100644 --- a/Makefile +++ b/Makefile @@ -359,7 +359,7 @@ watch-frontend: node-check node_modules .PHONY: watch-backend watch-backend: go-check - $(GO) run $(AIR_PACKAGE) -c .air.toml + GITEA_RUN_MODE=dev $(GO) run $(AIR_PACKAGE) -c .air.toml .PHONY: test test: test-frontend test-backend diff --git a/cmd/dump_repo.go b/cmd/dump_repo.go index 2e78877afed2..b7b9b3ccc734 100644 --- a/cmd/dump_repo.go +++ b/cmd/dump_repo.go @@ -10,13 +10,13 @@ import ( "os" "strings" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" base "code.gitea.io/gitea/modules/migration" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/migrations" "github.com/urfave/cli" diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index 754eab452ff9..cec5e8cf0382 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -957,6 +957,9 @@ ROUTER = console ;; Don't allow download source archive files from UI ;DISABLE_DOWNLOAD_SOURCE_ARCHIVES = false +;; Allow fork repositories without maximum number limit +;ALLOW_FORK_WITHOUT_MAXIMUM_LIMIT = true + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;[repository.editor] diff --git a/docs/config.yaml b/docs/config.yaml index b80602cb61c3..fbd7d8d81004 100644 --- a/docs/config.yaml +++ b/docs/config.yaml @@ -18,10 +18,10 @@ params: description: Git with a cup of tea author: The Gitea Authors website: https://docs.gitea.io - version: 1.17.4 + version: 1.18.0 minGoVersion: 1.18 goVersion: 1.19 - minNodeVersion: 14 + minNodeVersion: 16 search: nav repo: "https://github.com/go-gitea/gitea" docContentPath: "docs/content" diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md index 0268938187de..3ccef3130cac 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md +++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md @@ -112,6 +112,7 @@ In addition there is _`StaticRootPath`_ which can be set as a built-in at build - `ALLOW_ADOPTION_OF_UNADOPTED_REPOSITORIES`: **false**: Allow non-admin users to adopt unadopted repositories - `ALLOW_DELETION_OF_UNADOPTED_REPOSITORIES`: **false**: Allow non-admin users to delete unadopted repositories - `DISABLE_DOWNLOAD_SOURCE_ARCHIVES`: **false**: Don't allow download source archive files from UI +- `ALLOW_FORK_WITHOUT_MAXIMUM_LIMIT`: **true**: Allow fork repositories without maximum number limit ### Repository - Editor (`repository.editor`) @@ -239,6 +240,10 @@ The following configuration set `Content-Type: application/vnd.android.package-a - `NOTICE_PAGING_NUM`: **25**: Number of notices that are shown in one page. - `ORG_PAGING_NUM`: **50**: Number of organizations that are shown in one page. +### UI - User (`ui.user`) + +- `REPO_PAGING_NUM`: **15**: Number of repos that are shown in one page. + ### UI - Metadata (`ui.meta`) - `AUTHOR`: **Gitea - Git with a cup of tea**: Author meta tag of the homepage. @@ -1145,7 +1150,7 @@ in this mapping or the filetype using heuristics. ## Time (`time`) - `FORMAT`: Time format to display on UI. i.e. RFC1123 or 2006-01-02 15:04:05 -- `DEFAULT_UI_LOCATION`: Default location of time on the UI, so that we can display correct user's time on UI. i.e. Shanghai/Asia +- `DEFAULT_UI_LOCATION`: Default location of time on the UI, so that we can display correct user's time on UI. i.e. Asia/Shanghai ## Task (`task`) diff --git a/docs/content/doc/installation/from-package.en-us.md b/docs/content/doc/installation/from-package.en-us.md index 3f75f26a53d0..c9df0d21be5f 100644 --- a/docs/content/doc/installation/from-package.en-us.md +++ b/docs/content/doc/installation/from-package.en-us.md @@ -43,6 +43,14 @@ Arch Linux ARM provides packages for [aarch64](https://archlinuxarm.org/packages pacman -S gitea ``` +## Gentoo Linux + +The rolling release distribution has [Gitea](https://packages.gentoo.org/packages/www-apps/gitea) in their official community repository and package updates are provided with new Gitea releases. + +```sh +emerge gitea -va +``` + ## Canonical Snap There is a [Gitea Snap](https://snapcraft.io/gitea) package which follows the latest stable version. diff --git a/models/activities/action.go b/models/activities/action.go index 1ac1be7135d8..4baedbfe124b 100644 --- a/models/activities/action.go +++ b/models/activities/action.go @@ -272,7 +272,7 @@ func (a *Action) GetRefLink() string { return a.GetRepoLink() + "/src/branch/" + util.PathEscapeSegments(strings.TrimPrefix(a.RefName, git.BranchPrefix)) case strings.HasPrefix(a.RefName, git.TagPrefix): return a.GetRepoLink() + "/src/tag/" + util.PathEscapeSegments(strings.TrimPrefix(a.RefName, git.TagPrefix)) - case len(a.RefName) == 40 && git.IsValidSHAPattern(a.RefName): + case len(a.RefName) == git.SHAFullLength && git.IsValidSHAPattern(a.RefName): return a.GetRepoLink() + "/src/commit/" + a.RefName default: // FIXME: we will just assume it's a branch - this was the old way - at some point we may want to enforce that there is always a ref here. diff --git a/models/asymkey/gpg_key.go b/models/asymkey/gpg_key.go index ecd9041e6561..be019184eb5b 100644 --- a/models/asymkey/gpg_key.go +++ b/models/asymkey/gpg_key.go @@ -64,11 +64,16 @@ func (key *GPGKey) AfterLoad(session *xorm.Session) { // PaddedKeyID show KeyID padded to 16 characters func (key *GPGKey) PaddedKeyID() string { - if len(key.KeyID) > 15 { - return key.KeyID + return PaddedKeyID(key.KeyID) +} + +// PaddedKeyID show KeyID padded to 16 characters +func PaddedKeyID(keyID string) string { + if len(keyID) > 15 { + return keyID } zeros := "0000000000000000" - return zeros[0:16-len(key.KeyID)] + key.KeyID + return zeros[0:16-len(keyID)] + keyID } // ListGPGKeys returns a list of public keys belongs to given user. diff --git a/models/asymkey/ssh_key_fingerprint.go b/models/asymkey/ssh_key_fingerprint.go index ca0334cc0b1a..8a8d4fce153d 100644 --- a/models/asymkey/ssh_key_fingerprint.go +++ b/models/asymkey/ssh_key_fingerprint.go @@ -5,7 +5,6 @@ package asymkey import ( "context" - "errors" "fmt" "strings" @@ -59,9 +58,9 @@ func calcFingerprintSSHKeygen(publicKeyContent string) (string, error) { if strings.Contains(stderr, "is not a public key file") { return "", ErrKeyUnableVerify{stderr} } - return "", fmt.Errorf("'ssh-keygen -lf %s' failed with error '%s': %s", tmpPath, err, stderr) + return "", util.NewInvalidArgumentErrorf("'ssh-keygen -lf %s' failed with error '%s': %s", tmpPath, err, stderr) } else if len(stdout) < 2 { - return "", errors.New("not enough output for calculating fingerprint: " + stdout) + return "", util.NewInvalidArgumentErrorf("not enough output for calculating fingerprint: %s", stdout) } return strings.Split(stdout, " ")[1], nil } diff --git a/models/asymkey/ssh_key_parse.go b/models/asymkey/ssh_key_parse.go index b3eecb2c9bfe..1df6db6fa721 100644 --- a/models/asymkey/ssh_key_parse.go +++ b/models/asymkey/ssh_key_parse.go @@ -10,7 +10,6 @@ import ( "encoding/base64" "encoding/binary" "encoding/pem" - "errors" "fmt" "math/big" "os" @@ -122,7 +121,7 @@ func parseKeyString(content string) (string, error) { parts := strings.SplitN(content, " ", 3) switch len(parts) { case 0: - return "", errors.New("empty key") + return "", util.NewInvalidArgumentErrorf("empty key") case 1: keyContent = parts[0] case 2: @@ -167,7 +166,7 @@ func CheckPublicKeyString(content string) (_ string, err error) { content = strings.TrimRight(content, "\n\r") if strings.ContainsAny(content, "\n\r") { - return "", errors.New("only a single line with a single key please") + return "", util.NewInvalidArgumentErrorf("only a single line with a single key please") } // remove any unnecessary whitespace now diff --git a/models/asymkey/ssh_key_principals.go b/models/asymkey/ssh_key_principals.go index f00c3f3e9e67..6d43437ec106 100644 --- a/models/asymkey/ssh_key_principals.go +++ b/models/asymkey/ssh_key_principals.go @@ -4,7 +4,6 @@ package asymkey import ( - "errors" "fmt" "strings" @@ -12,6 +11,7 @@ import ( "code.gitea.io/gitea/models/perm" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/util" ) // __________ .__ .__ .__ @@ -70,7 +70,7 @@ func CheckPrincipalKeyString(user *user_model.User, content string) (_ string, e content = strings.TrimSpace(content) if strings.ContainsAny(content, "\r\n") { - return "", errors.New("only a single line with a single principal please") + return "", util.NewInvalidArgumentErrorf("only a single line with a single principal please") } // check all the allowed principals, email, username or anything diff --git a/models/db/context.go b/models/db/context.go index c8ad0c1aa273..3db8b16528da 100644 --- a/models/db/context.go +++ b/models/db/context.go @@ -188,7 +188,10 @@ func EstimateCount(ctx context.Context, bean interface{}) (int64, error) { case schemas.MYSQL: _, err = e.Context(ctx).SQL("SELECT table_rows FROM information_schema.tables WHERE tables.table_name = ? AND tables.table_schema = ?;", tablename, x.Dialect().URI().DBName).Get(&rows) case schemas.POSTGRES: - _, err = e.Context(ctx).SQL("SELECT reltuples AS estimate FROM pg_class WHERE relname = ?;", tablename).Get(&rows) + // the table can live in multiple schemas of a postgres database + // See https://wiki.postgresql.org/wiki/Count_estimate + tablename = x.TableName(bean, true) + _, err = e.Context(ctx).SQL("SELECT reltuples::bigint AS estimate FROM pg_class WHERE oid = ?::regclass;", tablename).Get(&rows) case schemas.MSSQL: _, err = e.Context(ctx).SQL("sp_spaceused ?;", tablename).Get(&rows) default: diff --git a/models/git/commit_status.go b/models/git/commit_status.go index 0fb0bc66af9a..07e0b9fb73b4 100644 --- a/models/git/commit_status.go +++ b/models/git/commit_status.go @@ -279,6 +279,10 @@ func NewCommitStatus(opts NewCommitStatusOptions) error { return fmt.Errorf("NewCommitStatus[%s, %s]: no user specified", repoPath, opts.SHA) } + if _, err := git.NewIDFromString(opts.SHA); err != nil { + return fmt.Errorf("NewCommitStatus[%s, %s]: invalid sha: %w", repoPath, opts.SHA, err) + } + ctx, committer, err := db.TxContext(db.DefaultContext) if err != nil { return fmt.Errorf("NewCommitStatus[repo_id: %d, user_id: %d, sha: %s]: %w", opts.Repo.ID, opts.Creator.ID, opts.SHA, err) diff --git a/models/org_team.go b/models/org_team.go index a5a2575eec18..b3ee842c1f29 100644 --- a/models/org_team.go +++ b/models/org_team.go @@ -6,7 +6,6 @@ package models import ( "context" - "errors" "fmt" "strings" @@ -235,7 +234,7 @@ func RemoveRepository(t *organization.Team, repoID int64) error { // It's caller's responsibility to assign organization ID. func NewTeam(t *organization.Team) (err error) { if len(t.Name) == 0 { - return errors.New("empty team name") + return util.NewInvalidArgumentErrorf("empty team name") } if err = organization.IsUsableTeamName(t.Name); err != nil { @@ -300,7 +299,7 @@ func NewTeam(t *organization.Team) (err error) { // UpdateTeam updates information of team. func UpdateTeam(t *organization.Team, authChanged, includeAllChanged bool) (err error) { if len(t.Name) == 0 { - return errors.New("empty team name") + return util.NewInvalidArgumentErrorf("empty team name") } if len(t.Description) > 255 { diff --git a/models/packages/conan/references.go b/models/packages/conan/references.go index 06e828e8fa47..0d888a1ec88c 100644 --- a/models/packages/conan/references.go +++ b/models/packages/conan/references.go @@ -5,7 +5,6 @@ package conan import ( "context" - "errors" "strconv" "strings" @@ -13,13 +12,14 @@ import ( "code.gitea.io/gitea/models/packages" conan_module "code.gitea.io/gitea/modules/packages/conan" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/util" "xorm.io/builder" ) var ( - ErrRecipeReferenceNotExist = errors.New("Recipe reference does not exist") - ErrPackageReferenceNotExist = errors.New("Package reference does not exist") + ErrRecipeReferenceNotExist = util.NewNotExistErrorf("recipe reference does not exist") + ErrPackageReferenceNotExist = util.NewNotExistErrorf("package reference does not exist") ) // RecipeExists checks if a recipe exists diff --git a/models/packages/container/search.go b/models/packages/container/search.go index dfd5e244ba28..2e35c44766ae 100644 --- a/models/packages/container/search.go +++ b/models/packages/container/search.go @@ -5,7 +5,6 @@ package container import ( "context" - "errors" "strings" "time" @@ -13,11 +12,12 @@ import ( "code.gitea.io/gitea/models/packages" user_model "code.gitea.io/gitea/models/user" container_module "code.gitea.io/gitea/modules/packages/container" + "code.gitea.io/gitea/modules/util" "xorm.io/builder" ) -var ErrContainerBlobNotExist = errors.New("Container blob does not exist") +var ErrContainerBlobNotExist = util.NewNotExistErrorf("container blob does not exist") type BlobSearchOptions struct { OwnerID int64 diff --git a/models/packages/package.go b/models/packages/package.go index 5c4837d98b0c..a804f35de352 100644 --- a/models/packages/package.go +++ b/models/packages/package.go @@ -5,11 +5,11 @@ package packages import ( "context" - "errors" "fmt" "strings" "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/modules/util" "xorm.io/builder" ) @@ -20,9 +20,9 @@ func init() { var ( // ErrDuplicatePackage indicates a duplicated package error - ErrDuplicatePackage = errors.New("Package does exist already") + ErrDuplicatePackage = util.NewAlreadyExistErrorf("package already exists") // ErrPackageNotExist indicates a package not exist error - ErrPackageNotExist = errors.New("Package does not exist") + ErrPackageNotExist = util.NewNotExistErrorf("package does not exist") ) // Type of a package diff --git a/models/packages/package_blob.go b/models/packages/package_blob.go index 36ad745312d2..3b4a1ecf1859 100644 --- a/models/packages/package_blob.go +++ b/models/packages/package_blob.go @@ -5,15 +5,15 @@ package packages import ( "context" - "errors" "time" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/util" ) // ErrPackageBlobNotExist indicates a package blob not exist error -var ErrPackageBlobNotExist = errors.New("Package blob does not exist") +var ErrPackageBlobNotExist = util.NewNotExistErrorf("package blob does not exist") func init() { db.RegisterModel(new(PackageBlob)) diff --git a/models/packages/package_blob_upload.go b/models/packages/package_blob_upload.go index 64d1f9d473db..4b0e789221bd 100644 --- a/models/packages/package_blob_upload.go +++ b/models/packages/package_blob_upload.go @@ -5,7 +5,6 @@ package packages import ( "context" - "errors" "strings" "time" @@ -15,7 +14,7 @@ import ( ) // ErrPackageBlobUploadNotExist indicates a package blob upload not exist error -var ErrPackageBlobUploadNotExist = errors.New("Package blob upload does not exist") +var ErrPackageBlobUploadNotExist = util.NewNotExistErrorf("package blob upload does not exist") func init() { db.RegisterModel(new(PackageBlobUpload)) diff --git a/models/packages/package_cleanup_rule.go b/models/packages/package_cleanup_rule.go index 9bd512755de5..fa12dec40602 100644 --- a/models/packages/package_cleanup_rule.go +++ b/models/packages/package_cleanup_rule.go @@ -5,17 +5,17 @@ package packages import ( "context" - "errors" "fmt" "regexp" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/util" "xorm.io/builder" ) -var ErrPackageCleanupRuleNotExist = errors.New("Package blob does not exist") +var ErrPackageCleanupRuleNotExist = util.NewNotExistErrorf("package blob does not exist") func init() { db.RegisterModel(new(PackageCleanupRule)) diff --git a/models/packages/package_file.go b/models/packages/package_file.go index 6d0fd185a04e..7f794836dc94 100644 --- a/models/packages/package_file.go +++ b/models/packages/package_file.go @@ -5,13 +5,13 @@ package packages import ( "context" - "errors" "strconv" "strings" "time" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/util" "xorm.io/builder" ) @@ -22,9 +22,9 @@ func init() { var ( // ErrDuplicatePackageFile indicates a duplicated package file error - ErrDuplicatePackageFile = errors.New("Package file does exist already") + ErrDuplicatePackageFile = util.NewAlreadyExistErrorf("package file already exists") // ErrPackageFileNotExist indicates a package file not exist error - ErrPackageFileNotExist = errors.New("Package file does not exist") + ErrPackageFileNotExist = util.NewNotExistErrorf("package file does not exist") ) // EmptyFileKey is a named constant for an empty file key diff --git a/models/packages/package_version.go b/models/packages/package_version.go index 928f9d47d6cd..759c20abed22 100644 --- a/models/packages/package_version.go +++ b/models/packages/package_version.go @@ -5,7 +5,6 @@ package packages import ( "context" - "errors" "strconv" "strings" @@ -17,7 +16,7 @@ import ( ) // ErrDuplicatePackageVersion indicates a duplicated package version error -var ErrDuplicatePackageVersion = errors.New("Package version already exists") +var ErrDuplicatePackageVersion = util.NewAlreadyExistErrorf("package version already exists") func init() { db.RegisterModel(new(PackageVersion)) diff --git a/models/project/project.go b/models/project/project.go index bcf1166408f8..0a07cfe22ad1 100644 --- a/models/project/project.go +++ b/models/project/project.go @@ -5,7 +5,6 @@ package project import ( "context" - "errors" "fmt" "code.gitea.io/gitea/models/db" @@ -176,7 +175,7 @@ func NewProject(p *Project) error { } if !IsTypeValid(p.Type) { - return errors.New("project type is not valid") + return util.NewInvalidArgumentErrorf("project type is not valid") } ctx, committer, err := db.TxContext(db.DefaultContext) diff --git a/models/repo/mirror.go b/models/repo/mirror.go index 2f59b85331d0..c1d24a488637 100644 --- a/models/repo/mirror.go +++ b/models/repo/mirror.go @@ -6,16 +6,16 @@ package repo import ( "context" - "errors" "time" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/util" ) // ErrMirrorNotExist mirror does not exist error -var ErrMirrorNotExist = errors.New("Mirror does not exist") +var ErrMirrorNotExist = util.NewNotExistErrorf("Mirror does not exist") // Mirror represents mirror information of a repository. type Mirror struct { diff --git a/models/repo/pushmirror.go b/models/repo/pushmirror.go index f79ce59ee227..642020bb5e6d 100644 --- a/models/repo/pushmirror.go +++ b/models/repo/pushmirror.go @@ -5,18 +5,18 @@ package repo import ( "context" - "errors" "time" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/util" "xorm.io/builder" ) // ErrPushMirrorNotExist mirror does not exist error -var ErrPushMirrorNotExist = errors.New("PushMirror does not exist") +var ErrPushMirrorNotExist = util.NewNotExistErrorf("PushMirror does not exist") // PushMirror represents mirror information of a repository. type PushMirror struct { @@ -90,7 +90,7 @@ func DeletePushMirrors(ctx context.Context, opts PushMirrorOptions) error { _, err := db.GetEngine(ctx).Where(opts.toConds()).Delete(&PushMirror{}) return err } - return errors.New("repoID required and must be set") + return util.NewInvalidArgumentErrorf("repoID required and must be set") } func GetPushMirror(ctx context.Context, opts PushMirrorOptions) (*PushMirror, error) { diff --git a/models/repo/release.go b/models/repo/release.go index 25eba10e05df..08b429f5e1ec 100644 --- a/models/repo/release.go +++ b/models/repo/release.go @@ -6,7 +6,6 @@ package repo import ( "context" - "errors" "fmt" "sort" "strconv" @@ -156,7 +155,7 @@ func AddReleaseAttachments(ctx context.Context, releaseID int64, attachmentUUIDs for i := range attachments { if attachments[i].ReleaseID != 0 { - return errors.New("release permission denied") + return util.NewPermissionDeniedErrorf("release permission denied") } attachments[i].ReleaseID = releaseID // No assign value could be 0, so ignore AllCols(). diff --git a/models/repo/repo_list.go b/models/repo/repo_list.go index 6d9dd9ec65ac..9922ff25a2f0 100644 --- a/models/repo/repo_list.go +++ b/models/repo/repo_list.go @@ -5,7 +5,6 @@ package repo import ( "context" - "errors" "fmt" "strings" @@ -708,7 +707,7 @@ func GetUserRepositories(opts *SearchRepoOptions) (RepositoryList, int64, error) cond := builder.NewCond() if opts.Actor == nil { - return nil, 0, errors.New("GetUserRepositories: Actor is needed but not given") + return nil, 0, util.NewInvalidArgumentErrorf("GetUserRepositories: Actor is needed but not given") } cond = cond.And(builder.Eq{"owner_id": opts.Actor.ID}) if !opts.Private { diff --git a/models/unittest/fscopy.go b/models/unittest/fscopy.go index 631da49f2d5b..74b12d505779 100644 --- a/models/unittest/fscopy.go +++ b/models/unittest/fscopy.go @@ -64,7 +64,7 @@ func Copy(src, dest string) error { func CopyDir(srcPath, destPath string, filters ...func(filePath string) bool) error { // Check if target directory exists. if _, err := os.Stat(destPath); !errors.Is(err, os.ErrNotExist) { - return errors.New("file or directory already exists: " + destPath) + return util.NewAlreadyExistErrorf("file or directory already exists: %s", destPath) } err := os.MkdirAll(destPath, os.ModePerm) diff --git a/models/user/email_address.go b/models/user/email_address.go index 69e94f8bb6be..e310858f92ee 100644 --- a/models/user/email_address.go +++ b/models/user/email_address.go @@ -6,7 +6,6 @@ package user import ( "context" - "errors" "fmt" "net/mail" "regexp" @@ -22,7 +21,7 @@ import ( ) // ErrEmailNotActivated e-mail address has not been activated error -var ErrEmailNotActivated = errors.New("e-mail address has not been activated") +var ErrEmailNotActivated = util.NewInvalidArgumentErrorf("e-mail address has not been activated") // ErrEmailCharIsNotSupported e-mail address contains unsupported character type ErrEmailCharIsNotSupported struct { diff --git a/models/user/openid.go b/models/user/openid.go index 194670504896..596ff182bc75 100644 --- a/models/user/openid.go +++ b/models/user/openid.go @@ -5,7 +5,6 @@ package user import ( "context" - "errors" "fmt" "code.gitea.io/gitea/models/db" @@ -13,7 +12,7 @@ import ( ) // ErrOpenIDNotExist openid is not known -var ErrOpenIDNotExist = errors.New("OpenID is unknown") +var ErrOpenIDNotExist = util.NewNotExistErrorf("OpenID is unknown") // UserOpenID is the list of all OpenID identities of a user. // Since this is a middle table, name it OpenID is not suitable, so we ignore the lint here diff --git a/models/user/user.go b/models/user/user.go index 71b036b06f10..825223201b67 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -275,6 +275,15 @@ func (u *User) CanEditGitHook() bool { return !setting.DisableGitHooks && (u.IsAdmin || u.AllowGitHook) } +// CanForkRepo returns if user login can fork a repository +// It checks especially that the user can create repos, and potentially more +func (u *User) CanForkRepo() bool { + if setting.Repository.AllowForkWithoutMaximumLimit { + return true + } + return u.CanCreateRepo() +} + // CanImportLocal returns true if user can migrate repository by local path. func (u *User) CanImportLocal() bool { if !setting.ImportLocalPaths || u == nil { diff --git a/modules/context/api.go b/modules/context/api.go index f49997a7875f..3f52c54d4cfd 100644 --- a/modules/context/api.go +++ b/modules/context/api.go @@ -219,7 +219,13 @@ func (ctx *APIContext) CheckForOTP() { func APIAuth(authMethod auth_service.Method) func(*APIContext) { return func(ctx *APIContext) { // Get user from session if logged in. - ctx.Doer = authMethod.Verify(ctx.Req, ctx.Resp, ctx, ctx.Session) + var err error + ctx.Doer, err = authMethod.Verify(ctx.Req, ctx.Resp, ctx, ctx.Session) + if err != nil { + ctx.Error(http.StatusUnauthorized, "APIAuth", err) + return + } + if ctx.Doer != nil { if ctx.Locale.Language() != ctx.Doer.Language { ctx.Locale = middleware.Locale(ctx.Resp, ctx.Req) @@ -387,7 +393,7 @@ func RepoRefForAPI(next http.Handler) http.Handler { return } ctx.Repo.CommitID = ctx.Repo.Commit.ID.String() - } else if len(refName) == 40 { + } else if len(refName) == git.SHAFullLength { ctx.Repo.CommitID = refName ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refName) if err != nil { diff --git a/modules/context/context.go b/modules/context/context.go index 0fe00bf787e3..6273093060a1 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -662,7 +662,13 @@ func getCsrfOpts() CsrfOptions { // Auth converts auth.Auth as a middleware func Auth(authMethod auth.Method) func(*Context) { return func(ctx *Context) { - ctx.Doer = authMethod.Verify(ctx.Req, ctx.Resp, ctx, ctx.Session) + var err error + ctx.Doer, err = authMethod.Verify(ctx.Req, ctx.Resp, ctx, ctx.Session) + if err != nil { + log.Error("Failed to verify user %v: %v", ctx.Req.RemoteAddr, err) + ctx.Error(http.StatusUnauthorized, "Verify") + return + } if ctx.Doer != nil { if ctx.Locale.Language() != ctx.Doer.Language { ctx.Locale = middleware.Locale(ctx.Resp, ctx.Req) diff --git a/modules/context/repo.go b/modules/context/repo.go index 71a2b3c0c6ef..d15d28cab783 100644 --- a/modules/context/repo.go +++ b/modules/context/repo.go @@ -817,7 +817,7 @@ func getRefName(ctx *Context, pathType RepoRefType) string { } // For legacy and API support only full commit sha parts := strings.Split(path, "/") - if len(parts) > 0 && len(parts[0]) == 40 { + if len(parts) > 0 && len(parts[0]) == git.SHAFullLength { ctx.Repo.TreePath = strings.Join(parts[1:], "/") return parts[0] } @@ -853,7 +853,7 @@ func getRefName(ctx *Context, pathType RepoRefType) string { return getRefNameFromPath(ctx, path, ctx.Repo.GitRepo.IsTagExist) case RepoRefCommit: parts := strings.Split(path, "/") - if len(parts) > 0 && len(parts[0]) >= 7 && len(parts[0]) <= 40 { + if len(parts) > 0 && len(parts[0]) >= 7 && len(parts[0]) <= git.SHAFullLength { ctx.Repo.TreePath = strings.Join(parts[1:], "/") return parts[0] } @@ -962,7 +962,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context return } ctx.Repo.CommitID = ctx.Repo.Commit.ID.String() - } else if len(refName) >= 7 && len(refName) <= 40 { + } else if len(refName) >= 7 && len(refName) <= git.SHAFullLength { ctx.Repo.IsViewCommit = true ctx.Repo.CommitID = refName @@ -972,7 +972,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context return } // If short commit ID add canonical link header - if len(refName) < 40 { + if len(refName) < git.SHAFullLength { ctx.RespHeader().Set("Link", fmt.Sprintf("<%s>; rel=\"canonical\"", util.URLJoin(setting.AppURL, strings.Replace(ctx.Req.URL.RequestURI(), util.PathEscapeSegments(refName), url.PathEscape(ctx.Repo.Commit.ID.String()), 1)))) } diff --git a/modules/eventsource/manager_run.go b/modules/eventsource/manager_run.go index 97d08aa8a87e..35dfc62f1ed9 100644 --- a/modules/eventsource/manager_run.go +++ b/modules/eventsource/manager_run.go @@ -9,13 +9,13 @@ import ( activities_model "code.gitea.io/gitea/models/activities" issues_model "code.gitea.io/gitea/models/issues" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/services/convert" ) // Init starts this eventsource diff --git a/modules/git/repo_attribute.go b/modules/git/repo_attribute.go index d3a3dc8c837c..404d9e502c04 100644 --- a/modules/git/repo_attribute.go +++ b/modules/git/repo_attribute.go @@ -9,8 +9,6 @@ import ( "fmt" "io" "os" - "strconv" - "strings" "code.gitea.io/gitea/modules/log" ) @@ -288,102 +286,6 @@ func (wr *nulSeparatedAttributeWriter) Close() error { return nil } -type lineSeparatedAttributeWriter struct { - tmp []byte - attributes chan attributeTriple - closed chan struct{} -} - -func (wr *lineSeparatedAttributeWriter) Write(p []byte) (n int, err error) { - l := len(p) - - nlIdx := bytes.IndexByte(p, '\n') - for nlIdx >= 0 { - wr.tmp = append(wr.tmp, p[:nlIdx]...) - - if len(wr.tmp) == 0 { - // This should not happen - if len(p) > nlIdx+1 { - wr.tmp = wr.tmp[:0] - p = p[nlIdx+1:] - nlIdx = bytes.IndexByte(p, '\n') - continue - } else { - return l, nil - } - } - - working := attributeTriple{} - if wr.tmp[0] == '"' { - sb := new(strings.Builder) - remaining := string(wr.tmp[1:]) - for len(remaining) > 0 { - rn, _, tail, err := strconv.UnquoteChar(remaining, '"') - if err != nil { - if len(remaining) > 2 && remaining[0] == '"' && remaining[1] == ':' && remaining[2] == ' ' { - working.Filename = sb.String() - wr.tmp = []byte(remaining[3:]) - break - } - return l, fmt.Errorf("unexpected tail %s", remaining) - } - _, _ = sb.WriteRune(rn) - remaining = tail - } - } else { - idx := bytes.IndexByte(wr.tmp, ':') - if idx < 0 { - return l, fmt.Errorf("unexpected input %s", string(wr.tmp)) - } - working.Filename = string(wr.tmp[:idx]) - if len(wr.tmp) < idx+2 { - return l, fmt.Errorf("unexpected input %s", string(wr.tmp)) - } - wr.tmp = wr.tmp[idx+2:] - } - - idx := bytes.IndexByte(wr.tmp, ':') - if idx < 0 { - return l, fmt.Errorf("unexpected input %s", string(wr.tmp)) - } - - working.Attribute = string(wr.tmp[:idx]) - if len(wr.tmp) < idx+2 { - return l, fmt.Errorf("unexpected input %s", string(wr.tmp)) - } - - working.Value = string(wr.tmp[idx+2:]) - - wr.attributes <- working - wr.tmp = wr.tmp[:0] - if len(p) > nlIdx+1 { - p = p[nlIdx+1:] - nlIdx = bytes.IndexByte(p, '\n') - continue - } else { - return l, nil - } - } - - wr.tmp = append(wr.tmp, p...) - return l, nil -} - -func (wr *lineSeparatedAttributeWriter) ReadAttribute() <-chan attributeTriple { - return wr.attributes -} - -func (wr *lineSeparatedAttributeWriter) Close() error { - select { - case <-wr.closed: - return nil - default: - } - close(wr.attributes) - close(wr.closed) - return nil -} - // Create a check attribute reader for the current repository and provided commit ID func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeReader, context.CancelFunc) { indexFilename, worktree, deleteTemporaryFile, err := repo.ReadTreeToTemporaryIndex(commitID) diff --git a/modules/git/repo_attribute_test.go b/modules/git/repo_attribute_test.go index 6882874d2dc7..f88ae9540786 100644 --- a/modules/git/repo_attribute_test.go +++ b/modules/git/repo_attribute_test.go @@ -95,64 +95,3 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) { Value: "unspecified", }, attr) } - -func Test_lineSeparatedAttributeWriter_ReadAttribute(t *testing.T) { - wr := &lineSeparatedAttributeWriter{ - attributes: make(chan attributeTriple, 5), - } - - testStr := `".gitignore\"\n": linguist-vendored: unspecified -` - n, err := wr.Write([]byte(testStr)) - - assert.Equal(t, n, len(testStr)) - assert.NoError(t, err) - - select { - case attr := <-wr.ReadAttribute(): - assert.Equal(t, ".gitignore\"\n", attr.Filename) - assert.Equal(t, "linguist-vendored", attr.Attribute) - assert.Equal(t, "unspecified", attr.Value) - case <-time.After(100 * time.Millisecond): - assert.Fail(t, "took too long to read an attribute from the list") - } - - // Write a second attribute again - n, err = wr.Write([]byte(testStr)) - - assert.Equal(t, n, len(testStr)) - assert.NoError(t, err) - - select { - case attr := <-wr.ReadAttribute(): - assert.Equal(t, ".gitignore\"\n", attr.Filename) - assert.Equal(t, "linguist-vendored", attr.Attribute) - assert.Equal(t, "unspecified", attr.Value) - case <-time.After(100 * time.Millisecond): - assert.Fail(t, "took too long to read an attribute from the list") - } - - // Write a partial attribute - _, err = wr.Write([]byte("incomplete-file")) - assert.NoError(t, err) - _, err = wr.Write([]byte("name: ")) - assert.NoError(t, err) - select { - case <-wr.ReadAttribute(): - assert.Fail(t, "There should not be an attribute ready to read") - case <-time.After(100 * time.Millisecond): - } - _, err = wr.Write([]byte("attribute: ")) - assert.NoError(t, err) - select { - case <-wr.ReadAttribute(): - assert.Fail(t, "There should not be an attribute ready to read") - case <-time.After(100 * time.Millisecond): - } - _, err = wr.Write([]byte("value\n")) - assert.NoError(t, err) - attr := <-wr.ReadAttribute() - assert.Equal(t, "incomplete-filename", attr.Filename) - assert.Equal(t, "attribute", attr.Attribute) - assert.Equal(t, "value", attr.Value) -} diff --git a/modules/git/repo_commit_gogit.go b/modules/git/repo_commit_gogit.go index b6c42a802f0d..72de158e6e11 100644 --- a/modules/git/repo_commit_gogit.go +++ b/modules/git/repo_commit_gogit.go @@ -41,7 +41,7 @@ func (repo *Repository) RemoveReference(name string) error { // ConvertToSHA1 returns a Hash object from a potential ID string func (repo *Repository) ConvertToSHA1(commitID string) (SHA1, error) { - if len(commitID) == 40 { + if len(commitID) == SHAFullLength { sha1, err := NewIDFromString(commitID) if err == nil { return sha1, nil diff --git a/modules/git/repo_commit_nogogit.go b/modules/git/repo_commit_nogogit.go index 35a705fea30f..7373d01c8efb 100644 --- a/modules/git/repo_commit_nogogit.go +++ b/modules/git/repo_commit_nogogit.go @@ -137,7 +137,7 @@ func (repo *Repository) getCommitFromBatchReader(rd *bufio.Reader, id SHA1) (*Co // ConvertToSHA1 returns a Hash object from a potential ID string func (repo *Repository) ConvertToSHA1(commitID string) (SHA1, error) { - if len(commitID) == 40 && IsValidSHAPattern(commitID) { + if len(commitID) == SHAFullLength && IsValidSHAPattern(commitID) { sha1, err := NewIDFromString(commitID) if err == nil { return sha1, nil diff --git a/modules/git/repo_index.go b/modules/git/repo_index.go index 99eb2b540b1a..5ff2a2e4fc9d 100644 --- a/modules/git/repo_index.go +++ b/modules/git/repo_index.go @@ -16,7 +16,7 @@ import ( // ReadTreeToIndex reads a treeish to the index func (repo *Repository) ReadTreeToIndex(treeish string, indexFilename ...string) error { - if len(treeish) != 40 { + if len(treeish) != SHAFullLength { res, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify").AddDynamicArguments(treeish).RunStdString(&RunOpts{Dir: repo.Path}) if err != nil { return err diff --git a/modules/git/repo_tree_gogit.go b/modules/git/repo_tree_gogit.go index e0e5e73fa335..a7b1081b15f1 100644 --- a/modules/git/repo_tree_gogit.go +++ b/modules/git/repo_tree_gogit.go @@ -19,7 +19,7 @@ func (repo *Repository) getTree(id SHA1) (*Tree, error) { // GetTree find the tree object in the repository. func (repo *Repository) GetTree(idStr string) (*Tree, error) { - if len(idStr) != 40 { + if len(idStr) != SHAFullLength { res, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify").AddDynamicArguments(idStr).RunStdString(&RunOpts{Dir: repo.Path}) if err != nil { return nil, err diff --git a/modules/git/repo_tree_nogogit.go b/modules/git/repo_tree_nogogit.go index 16ea6bbd8a31..4fd77df2b824 100644 --- a/modules/git/repo_tree_nogogit.go +++ b/modules/git/repo_tree_nogogit.go @@ -66,7 +66,7 @@ func (repo *Repository) getTree(id SHA1) (*Tree, error) { // GetTree find the tree object in the repository. func (repo *Repository) GetTree(idStr string) (*Tree, error) { - if len(idStr) != 40 { + if len(idStr) != SHAFullLength { res, err := repo.GetRefCommitID(idStr) if err != nil { return nil, err diff --git a/modules/git/sha1.go b/modules/git/sha1.go index 3a02484bc23b..4d69653e09ac 100644 --- a/modules/git/sha1.go +++ b/modules/git/sha1.go @@ -17,6 +17,9 @@ const EmptySHA = "0000000000000000000000000000000000000000" // EmptyTreeSHA is the SHA of an empty tree const EmptyTreeSHA = "4b825dc642cb6eb9a060e54bf8d69288fbee4904" +// SHAFullLength is the full length of a git SHA +const SHAFullLength = 40 + // SHAPattern can be used to determine if a string is an valid sha var shaPattern = regexp.MustCompile(`^[0-9a-f]{4,40}$`) @@ -50,7 +53,7 @@ func MustIDFromString(s string) SHA1 { func NewIDFromString(s string) (SHA1, error) { var id SHA1 s = strings.TrimSpace(s) - if len(s) != 40 { + if len(s) != SHAFullLength { return id, fmt.Errorf("Length must be 40: %s", s) } b, err := hex.DecodeString(s) diff --git a/modules/markup/markdown/markdown.go b/modules/markup/markdown/markdown.go index 1e5c4707585e..f1ffea887246 100644 --- a/modules/markup/markdown/markdown.go +++ b/modules/markup/markdown/markdown.go @@ -289,9 +289,3 @@ func RenderRawString(ctx *markup.RenderContext, content string) (string, error) } return buf.String(), nil } - -// IsMarkdownFile reports whether name looks like a Markdown file -// based on its extension. -func IsMarkdownFile(name string) bool { - return markup.IsMarkupFile(name, MarkupName) -} diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go index bb2c47f18e99..cc683dc5b7c7 100644 --- a/modules/markup/markdown/markdown_test.go +++ b/modules/markup/markdown/markdown_test.go @@ -74,28 +74,6 @@ func TestRender_StandardLinks(t *testing.T) { `

WikiPage

`) } -func TestMisc_IsMarkdownFile(t *testing.T) { - setting.Markdown.FileExtensions = []string{".md", ".markdown", ".mdown", ".mkd"} - trueTestCases := []string{ - "test.md", - "wow.MARKDOWN", - "LOL.mDoWn", - } - falseTestCases := []string{ - "test", - "abcdefg", - "abcdefghijklmnopqrstuvwxyz", - "test.md.test", - } - - for _, testCase := range trueTestCases { - assert.True(t, IsMarkdownFile(testCase)) - } - for _, testCase := range falseTestCases { - assert.False(t, IsMarkdownFile(testCase)) - } -} - func TestRender_Images(t *testing.T) { setting.AppURL = AppURL setting.AppSubURL = AppSubURL diff --git a/modules/notification/webhook/webhook.go b/modules/notification/webhook/webhook.go index cf056f54c138..97d5e04340d9 100644 --- a/modules/notification/webhook/webhook.go +++ b/modules/notification/webhook/webhook.go @@ -14,13 +14,13 @@ import ( "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/models/webhook" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/notification/base" "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/services/convert" webhook_services "code.gitea.io/gitea/services/webhook" ) diff --git a/modules/packages/composer/metadata.go b/modules/packages/composer/metadata.go index b98294001c28..36b0b8e42197 100644 --- a/modules/packages/composer/metadata.go +++ b/modules/packages/composer/metadata.go @@ -5,12 +5,12 @@ package composer import ( "archive/zip" - "errors" "io" "regexp" "strings" "code.gitea.io/gitea/modules/json" + "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/validation" "github.com/hashicorp/go-version" @@ -21,11 +21,11 @@ const TypeProperty = "composer.type" var ( // ErrMissingComposerFile indicates a missing composer.json file - ErrMissingComposerFile = errors.New("composer.json file is missing") + ErrMissingComposerFile = util.NewInvalidArgumentErrorf("composer.json file is missing") // ErrInvalidName indicates an invalid package name - ErrInvalidName = errors.New("package name is invalid") + ErrInvalidName = util.NewInvalidArgumentErrorf("package name is invalid") // ErrInvalidVersion indicates an invalid package version - ErrInvalidVersion = errors.New("package version is invalid") + ErrInvalidVersion = util.NewInvalidArgumentErrorf("package version is invalid") ) // Package represents a Composer package diff --git a/modules/packages/conan/conaninfo_parser.go b/modules/packages/conan/conaninfo_parser.go index 5bb3fb8930c9..de11dbee45bf 100644 --- a/modules/packages/conan/conaninfo_parser.go +++ b/modules/packages/conan/conaninfo_parser.go @@ -5,9 +5,10 @@ package conan import ( "bufio" - "errors" "io" "strings" + + "code.gitea.io/gitea/modules/util" ) // Conaninfo represents infos of a Conan package @@ -79,7 +80,7 @@ func readSections(r io.Reader) (map[string][]string, error) { continue } if line != "" { - return nil, errors.New("Invalid conaninfo.txt") + return nil, util.NewInvalidArgumentErrorf("invalid conaninfo.txt") } } if err := scanner.Err(); err != nil { diff --git a/modules/packages/conan/reference.go b/modules/packages/conan/reference.go index 37a5170dd3b8..58f268bd4827 100644 --- a/modules/packages/conan/reference.go +++ b/modules/packages/conan/reference.go @@ -4,12 +4,12 @@ package conan import ( - "errors" "fmt" "regexp" "strings" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/util" ) const ( @@ -25,7 +25,7 @@ var ( namePattern = regexp.MustCompile(fmt.Sprintf(`^[a-zA-Z0-9_][a-zA-Z0-9_\+\.-]{%d,%d}$`, minChars-1, maxChars-1)) revisionPattern = regexp.MustCompile(fmt.Sprintf(`^[a-zA-Z0-9]{1,%d}$`, maxChars)) - ErrValidation = errors.New("Could not validate one or more reference fields") + ErrValidation = util.NewInvalidArgumentErrorf("could not validate one or more reference fields") ) // RecipeReference represents a recipe /@/# diff --git a/modules/packages/helm/metadata.go b/modules/packages/helm/metadata.go index 98b5919a73f2..fdbd9003b84c 100644 --- a/modules/packages/helm/metadata.go +++ b/modules/packages/helm/metadata.go @@ -6,10 +6,10 @@ package helm import ( "archive/tar" "compress/gzip" - "errors" "io" "strings" + "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/validation" "github.com/hashicorp/go-version" @@ -18,13 +18,13 @@ import ( var ( // ErrMissingChartFile indicates a missing Chart.yaml file - ErrMissingChartFile = errors.New("Chart.yaml file is missing") + ErrMissingChartFile = util.NewInvalidArgumentErrorf("Chart.yaml file is missing") // ErrInvalidName indicates an invalid package name - ErrInvalidName = errors.New("package name is invalid") + ErrInvalidName = util.NewInvalidArgumentErrorf("package name is invalid") // ErrInvalidVersion indicates an invalid package version - ErrInvalidVersion = errors.New("package version is invalid") + ErrInvalidVersion = util.NewInvalidArgumentErrorf("package version is invalid") // ErrInvalidChart indicates an invalid chart - ErrInvalidChart = errors.New("chart is invalid") + ErrInvalidChart = util.NewInvalidArgumentErrorf("chart is invalid") ) // Metadata for a Chart file. This models the structure of a Chart.yaml file. diff --git a/modules/packages/npm/creator.go b/modules/packages/npm/creator.go index 02f67248129d..548d7ed9e56f 100644 --- a/modules/packages/npm/creator.go +++ b/modules/packages/npm/creator.go @@ -8,7 +8,6 @@ import ( "crypto/sha1" "crypto/sha512" "encoding/base64" - "errors" "fmt" "io" "regexp" @@ -16,6 +15,7 @@ import ( "time" "code.gitea.io/gitea/modules/json" + "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/validation" "github.com/hashicorp/go-version" @@ -23,15 +23,15 @@ import ( var ( // ErrInvalidPackage indicates an invalid package - ErrInvalidPackage = errors.New("The package is invalid") + ErrInvalidPackage = util.NewInvalidArgumentErrorf("package is invalid") // ErrInvalidPackageName indicates an invalid name - ErrInvalidPackageName = errors.New("The package name is invalid") + ErrInvalidPackageName = util.NewInvalidArgumentErrorf("package name is invalid") // ErrInvalidPackageVersion indicates an invalid version - ErrInvalidPackageVersion = errors.New("The package version is invalid") + ErrInvalidPackageVersion = util.NewInvalidArgumentErrorf("package version is invalid") // ErrInvalidAttachment indicates a invalid attachment - ErrInvalidAttachment = errors.New("The package attachment is invalid") + ErrInvalidAttachment = util.NewInvalidArgumentErrorf("package attachment is invalid") // ErrInvalidIntegrity indicates an integrity validation error - ErrInvalidIntegrity = errors.New("Failed to validate integrity") + ErrInvalidIntegrity = util.NewInvalidArgumentErrorf("failed to validate integrity") ) var nameMatch = regexp.MustCompile(`\A((@[^\s\/~'!\(\)\*]+?)[\/])?([^_.][^\s\/~'!\(\)\*]+)\z`) diff --git a/modules/packages/nuget/metadata.go b/modules/packages/nuget/metadata.go index 033421af96a8..3c478b1c0288 100644 --- a/modules/packages/nuget/metadata.go +++ b/modules/packages/nuget/metadata.go @@ -7,13 +7,13 @@ import ( "archive/zip" "bytes" "encoding/xml" - "errors" "fmt" "io" "path/filepath" "regexp" "strings" + "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/validation" "github.com/hashicorp/go-version" @@ -21,13 +21,13 @@ import ( var ( // ErrMissingNuspecFile indicates a missing Nuspec file - ErrMissingNuspecFile = errors.New("Nuspec file is missing") + ErrMissingNuspecFile = util.NewInvalidArgumentErrorf("Nuspec file is missing") // ErrNuspecFileTooLarge indicates a Nuspec file which is too large - ErrNuspecFileTooLarge = errors.New("Nuspec file is too large") + ErrNuspecFileTooLarge = util.NewInvalidArgumentErrorf("Nuspec file is too large") // ErrNuspecInvalidID indicates an invalid id in the Nuspec file - ErrNuspecInvalidID = errors.New("Nuspec file contains an invalid id") + ErrNuspecInvalidID = util.NewInvalidArgumentErrorf("Nuspec file contains an invalid id") // ErrNuspecInvalidVersion indicates an invalid version in the Nuspec file - ErrNuspecInvalidVersion = errors.New("Nuspec file contains an invalid version") + ErrNuspecInvalidVersion = util.NewInvalidArgumentErrorf("Nuspec file contains an invalid version") ) // PackageType specifies the package type the metadata describes diff --git a/modules/packages/nuget/symbol_extractor.go b/modules/packages/nuget/symbol_extractor.go index 634bbb17e621..b709eac4c196 100644 --- a/modules/packages/nuget/symbol_extractor.go +++ b/modules/packages/nuget/symbol_extractor.go @@ -7,7 +7,6 @@ import ( "archive/zip" "bytes" "encoding/binary" - "errors" "fmt" "io" "path" @@ -15,13 +14,14 @@ import ( "strings" "code.gitea.io/gitea/modules/packages" + "code.gitea.io/gitea/modules/util" ) var ( - ErrMissingPdbFiles = errors.New("Package does not contain PDB files") - ErrInvalidFiles = errors.New("Package contains invalid files") - ErrInvalidPdbMagicNumber = errors.New("Invalid Portable PDB magic number") - ErrMissingPdbStream = errors.New("Missing PDB stream") + ErrMissingPdbFiles = util.NewInvalidArgumentErrorf("package does not contain PDB files") + ErrInvalidFiles = util.NewInvalidArgumentErrorf("package contains invalid files") + ErrInvalidPdbMagicNumber = util.NewInvalidArgumentErrorf("invalid Portable PDB magic number") + ErrMissingPdbStream = util.NewInvalidArgumentErrorf("missing PDB stream") ) type PortablePdb struct { diff --git a/modules/packages/pub/metadata.go b/modules/packages/pub/metadata.go index 36fe66570769..13a066afacc9 100644 --- a/modules/packages/pub/metadata.go +++ b/modules/packages/pub/metadata.go @@ -6,11 +6,11 @@ package pub import ( "archive/tar" "compress/gzip" - "errors" "io" "regexp" "strings" + "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/validation" "github.com/hashicorp/go-version" @@ -18,10 +18,10 @@ import ( ) var ( - ErrMissingPubspecFile = errors.New("Pubspec file is missing") - ErrPubspecFileTooLarge = errors.New("Pubspec file is too large") - ErrInvalidName = errors.New("Package name is invalid") - ErrInvalidVersion = errors.New("Package version is invalid") + ErrMissingPubspecFile = util.NewInvalidArgumentErrorf("Pubspec file is missing") + ErrPubspecFileTooLarge = util.NewInvalidArgumentErrorf("Pubspec file is too large") + ErrInvalidName = util.NewInvalidArgumentErrorf("package name is invalid") + ErrInvalidVersion = util.NewInvalidArgumentErrorf("package version is invalid") ) var namePattern = regexp.MustCompile(`\A[a-zA-Z_][a-zA-Z0-9_]*\z`) diff --git a/modules/packages/rubygems/marshal.go b/modules/packages/rubygems/marshal.go index 14fb755606e9..efb2ba34a492 100644 --- a/modules/packages/rubygems/marshal.go +++ b/modules/packages/rubygems/marshal.go @@ -6,9 +6,10 @@ package rubygems import ( "bufio" "bytes" - "errors" "io" "reflect" + + "code.gitea.io/gitea/modules/util" ) const ( @@ -31,9 +32,9 @@ const ( var ( // ErrUnsupportedType indicates an unsupported type - ErrUnsupportedType = errors.New("Type is unsupported") + ErrUnsupportedType = util.NewInvalidArgumentErrorf("type is unsupported") // ErrInvalidIntRange indicates an invalid number range - ErrInvalidIntRange = errors.New("Number is not in valid range") + ErrInvalidIntRange = util.NewInvalidArgumentErrorf("number is not in valid range") ) // RubyUserMarshal is a Ruby object that has a marshal_load function. diff --git a/modules/packages/rubygems/metadata.go b/modules/packages/rubygems/metadata.go index e2c73c8f3a0d..adc1c0580874 100644 --- a/modules/packages/rubygems/metadata.go +++ b/modules/packages/rubygems/metadata.go @@ -6,11 +6,11 @@ package rubygems import ( "archive/tar" "compress/gzip" - "errors" "io" "regexp" "strings" + "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/validation" "gopkg.in/yaml.v3" @@ -18,11 +18,11 @@ import ( var ( // ErrMissingMetadataFile indicates a missing metadata.gz file - ErrMissingMetadataFile = errors.New("Metadata file is missing") + ErrMissingMetadataFile = util.NewInvalidArgumentErrorf("metadata.gz file is missing") // ErrInvalidName indicates an invalid id in the metadata.gz file - ErrInvalidName = errors.New("Metadata file contains an invalid name") + ErrInvalidName = util.NewInvalidArgumentErrorf("package name is invalid") // ErrInvalidVersion indicates an invalid version in the metadata.gz file - ErrInvalidVersion = errors.New("Metadata file contains an invalid version") + ErrInvalidVersion = util.NewInvalidArgumentErrorf("package version is invalid") ) var versionMatcher = regexp.MustCompile(`\A[0-9]+(?:\.[0-9a-zA-Z]+)*(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?\z`) diff --git a/modules/queue/queue_channel.go b/modules/queue/queue_channel.go index 431f48390c8b..6f75b8357eab 100644 --- a/modules/queue/queue_channel.go +++ b/modules/queue/queue_channel.go @@ -109,32 +109,6 @@ func (q *ChannelQueue) Flush(timeout time.Duration) error { return q.FlushWithContext(ctx) } -// FlushWithContext is very similar to CleanUp but it will return as soon as the dataChan is empty -func (q *ChannelQueue) FlushWithContext(ctx context.Context) error { - log.Trace("ChannelQueue: %d Flush", q.qid) - paused, _ := q.IsPausedIsResumed() - for { - select { - case <-paused: - return nil - case data, ok := <-q.dataChan: - if !ok { - return nil - } - if unhandled := q.handle(data); unhandled != nil { - log.Error("Unhandled Data whilst flushing queue %d", q.qid) - } - atomic.AddInt64(&q.numInQueue, -1) - case <-q.baseCtx.Done(): - return q.baseCtx.Err() - case <-ctx.Done(): - return ctx.Err() - default: - return nil - } - } -} - // Shutdown processing from this queue func (q *ChannelQueue) Shutdown() { q.lock.Lock() diff --git a/modules/queue/unique_queue_channel.go b/modules/queue/unique_queue_channel.go index f2d3dbdc970f..c43bd1db3f7d 100644 --- a/modules/queue/unique_queue_channel.go +++ b/modules/queue/unique_queue_channel.go @@ -8,7 +8,6 @@ import ( "fmt" "runtime/pprof" "sync" - "sync/atomic" "time" "code.gitea.io/gitea/modules/container" @@ -167,35 +166,6 @@ func (q *ChannelUniqueQueue) Flush(timeout time.Duration) error { return q.FlushWithContext(ctx) } -// FlushWithContext is very similar to CleanUp but it will return as soon as the dataChan is empty -func (q *ChannelUniqueQueue) FlushWithContext(ctx context.Context) error { - log.Trace("ChannelUniqueQueue: %d Flush", q.qid) - paused, _ := q.IsPausedIsResumed() - for { - select { - case <-paused: - return nil - default: - } - select { - case data, ok := <-q.dataChan: - if !ok { - return nil - } - if unhandled := q.handle(data); unhandled != nil { - log.Error("Unhandled Data whilst flushing queue %d", q.qid) - } - atomic.AddInt64(&q.numInQueue, -1) - case <-q.baseCtx.Done(): - return q.baseCtx.Err() - case <-ctx.Done(): - return ctx.Err() - default: - return nil - } - } -} - // Shutdown processing from this queue func (q *ChannelUniqueQueue) Shutdown() { log.Trace("ChannelUniqueQueue: %s Shutting down", q.name) diff --git a/modules/queue/workerpool.go b/modules/queue/workerpool.go index 244927880e92..b32128cb8214 100644 --- a/modules/queue/workerpool.go +++ b/modules/queue/workerpool.go @@ -463,13 +463,43 @@ func (p *WorkerPool) IsEmpty() bool { return atomic.LoadInt64(&p.numInQueue) == 0 } +// contextError returns either ctx.Done(), the base context's error or nil +func (p *WorkerPool) contextError(ctx context.Context) error { + select { + case <-p.baseCtx.Done(): + return p.baseCtx.Err() + case <-ctx.Done(): + return ctx.Err() + default: + return nil + } +} + // FlushWithContext is very similar to CleanUp but it will return as soon as the dataChan is empty // NB: The worker will not be registered with the manager. func (p *WorkerPool) FlushWithContext(ctx context.Context) error { log.Trace("WorkerPool: %d Flush", p.qid) + paused, _ := p.IsPausedIsResumed() for { + // Because select will return any case that is satisified at random we precheck here before looking at dataChan. + select { + case <-paused: + // Ensure that even if paused that the cancelled error is still sent + return p.contextError(ctx) + case <-p.baseCtx.Done(): + return p.baseCtx.Err() + case <-ctx.Done(): + return ctx.Err() + default: + } + select { - case data := <-p.dataChan: + case <-paused: + return p.contextError(ctx) + case data, ok := <-p.dataChan: + if !ok { + return nil + } if unhandled := p.handle(data); unhandled != nil { log.Error("Unhandled Data whilst flushing queue %d", p.qid) } @@ -495,6 +525,7 @@ func (p *WorkerPool) doWork(ctx context.Context) { paused, _ := p.IsPausedIsResumed() data := make([]Data, 0, p.batchLength) for { + // Because select will return any case that is satisified at random we precheck here before looking at dataChan. select { case <-paused: log.Trace("Worker for Queue %d Pausing", p.qid) @@ -515,8 +546,19 @@ func (p *WorkerPool) doWork(ctx context.Context) { log.Trace("Worker shutting down") return } + case <-ctx.Done(): + if len(data) > 0 { + log.Trace("Handling: %d data, %v", len(data), data) + if unhandled := p.handle(data...); unhandled != nil { + log.Error("Unhandled Data in queue %d", p.qid) + } + atomic.AddInt64(&p.numInQueue, -1*int64(len(data))) + } + log.Trace("Worker shutting down") + return default: } + select { case <-paused: // go back around diff --git a/modules/setting/repository.go b/modules/setting/repository.go index ea288d2ed29d..d78b63a1f3f7 100644 --- a/modules/setting/repository.go +++ b/modules/setting/repository.go @@ -48,6 +48,7 @@ var ( AllowAdoptionOfUnadoptedRepositories bool AllowDeleteOfUnadoptedRepositories bool DisableDownloadSourceArchives bool + AllowForkWithoutMaximumLimit bool // Repository editor settings Editor struct { @@ -160,6 +161,7 @@ var ( DisableMigrations: false, DisableStars: false, DefaultBranch: "main", + AllowForkWithoutMaximumLimit: true, // Repository editor settings Editor: struct { diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 47e0ae2cda1f..07290fbfeb9f 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -1043,7 +1043,10 @@ func loadFromConf(allowEmpty bool, extraConfig string) { // The following is a purposefully undocumented option. Please do not run Gitea as root. It will only cause future headaches. // Please don't use root as a bandaid to "fix" something that is broken, instead the broken thing should instead be fixed properly. unsafeAllowRunAsRoot := Cfg.Section("").Key("I_AM_BEING_UNSAFE_RUNNING_AS_ROOT").MustBool(false) - RunMode = Cfg.Section("").Key("RUN_MODE").MustString("prod") + RunMode = os.Getenv("GITEA_RUN_MODE") + if RunMode == "" { + RunMode = Cfg.Section("").Key("RUN_MODE").MustString("prod") + } IsProd = strings.EqualFold(RunMode, "prod") // Does not check run user when the install lock is off. if InstallLock { diff --git a/modules/sitemap/sitemap.go b/modules/sitemap/sitemap.go index ceb65c1c8d24..280ca1d71007 100644 --- a/modules/sitemap/sitemap.go +++ b/modules/sitemap/sitemap.go @@ -11,48 +11,62 @@ import ( "time" ) -// sitemapFileLimit contains the maximum size of a sitemap file -const sitemapFileLimit = 50 * 1024 * 1024 +const ( + sitemapFileLimit = 50 * 1024 * 1024 // the maximum size of a sitemap file + urlsLimit = 50000 -// Url represents a single sitemap entry + schemaURL = "http://www.sitemaps.org/schemas/sitemap/0.9" + urlsetName = "urlset" + sitemapindexName = "sitemapindex" +) + +// URL represents a single sitemap entry type URL struct { URL string `xml:"loc"` LastMod *time.Time `xml:"lastmod,omitempty"` } -// SitemapUrl represents a sitemap +// Sitemap represents a sitemap type Sitemap struct { XMLName xml.Name Namespace string `xml:"xmlns,attr"` - URLs []URL `xml:"url"` + URLs []URL `xml:"url"` + Sitemaps []URL `xml:"sitemap"` } // NewSitemap creates a sitemap func NewSitemap() *Sitemap { return &Sitemap{ - XMLName: xml.Name{Local: "urlset"}, - Namespace: "http://www.sitemaps.org/schemas/sitemap/0.9", + XMLName: xml.Name{Local: urlsetName}, + Namespace: schemaURL, } } -// NewSitemap creates a sitemap index. +// NewSitemapIndex creates a sitemap index. func NewSitemapIndex() *Sitemap { return &Sitemap{ - XMLName: xml.Name{Local: "sitemapindex"}, - Namespace: "http://www.sitemaps.org/schemas/sitemap/0.9", + XMLName: xml.Name{Local: sitemapindexName}, + Namespace: schemaURL, } } // Add adds a URL to the sitemap func (s *Sitemap) Add(u URL) { - s.URLs = append(s.URLs, u) + if s.XMLName.Local == sitemapindexName { + s.Sitemaps = append(s.Sitemaps, u) + } else { + s.URLs = append(s.URLs, u) + } } -// Write writes the sitemap to a response +// WriteTo writes the sitemap to a response func (s *Sitemap) WriteTo(w io.Writer) (int64, error) { - if len(s.URLs) > 50000 { - return 0, fmt.Errorf("The sitemap contains too many URLs: %d", len(s.URLs)) + if l := len(s.URLs); l > urlsLimit { + return 0, fmt.Errorf("The sitemap contains %d URLs, but only %d are allowed", l, urlsLimit) + } + if l := len(s.Sitemaps); l > urlsLimit { + return 0, fmt.Errorf("The sitemap contains %d sub-sitemaps, but only %d are allowed", l, urlsLimit) } buf := bytes.NewBufferString(xml.Header) if err := xml.NewEncoder(buf).Encode(s); err != nil { @@ -62,7 +76,7 @@ func (s *Sitemap) WriteTo(w io.Writer) (int64, error) { return 0, err } if buf.Len() > sitemapFileLimit { - return 0, fmt.Errorf("The sitemap is too big: %d", buf.Len()) + return 0, fmt.Errorf("The sitemap has %d bytes, but only %d are allowed", buf.Len(), sitemapFileLimit) } return buf.WriteTo(w) } diff --git a/modules/sitemap/sitemap_test.go b/modules/sitemap/sitemap_test.go index ab879b272e70..1180463cd79e 100644 --- a/modules/sitemap/sitemap_test.go +++ b/modules/sitemap/sitemap_test.go @@ -6,7 +6,6 @@ package sitemap import ( "bytes" "encoding/xml" - "fmt" "strings" "testing" "time" @@ -14,63 +13,154 @@ import ( "github.com/stretchr/testify/assert" ) -func TestOk(t *testing.T) { - testReal := func(s *Sitemap, name string, urls []URL, expected string) { - for _, url := range urls { - s.Add(url) - } - buf := &bytes.Buffer{} - _, err := s.WriteTo(buf) - assert.NoError(t, nil, err) - assert.Equal(t, xml.Header+"<"+name+" xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">"+expected+"\n", buf.String()) +func TestNewSitemap(t *testing.T) { + ts := time.Unix(1651322008, 0).UTC() + + tests := []struct { + name string + urls []URL + want string + wantErr string + }{ + { + name: "empty", + urls: []URL{}, + want: xml.Header + `` + + "" + + "\n", + }, + { + name: "regular", + urls: []URL{ + {URL: "https://gitea.io/test1", LastMod: &ts}, + }, + want: xml.Header + `` + + "https://gitea.io/test12022-04-30T12:33:28Z" + + "\n", + }, + { + name: "without lastmod", + urls: []URL{ + {URL: "https://gitea.io/test1"}, + }, + want: xml.Header + `` + + "https://gitea.io/test1" + + "\n", + }, + { + name: "multiple", + urls: []URL{ + {URL: "https://gitea.io/test1", LastMod: &ts}, + {URL: "https://gitea.io/test2", LastMod: nil}, + }, + want: xml.Header + `` + + "https://gitea.io/test12022-04-30T12:33:28Z" + + "https://gitea.io/test2" + + "\n", + }, + { + name: "too many urls", + urls: make([]URL, 50001), + wantErr: "The sitemap contains 50001 URLs, but only 50000 are allowed", + }, + { + name: "too big file", + urls: []URL{ + {URL: strings.Repeat("b", 50*1024*1024+1)}, + }, + wantErr: "The sitemap has 52428932 bytes, but only 52428800 are allowed", + }, } - test := func(urls []URL, expected string) { - testReal(NewSitemap(), "urlset", urls, expected) - testReal(NewSitemapIndex(), "sitemapindex", urls, expected) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := NewSitemap() + for _, url := range tt.urls { + s.Add(url) + } + buf := &bytes.Buffer{} + _, err := s.WriteTo(buf) + if tt.wantErr != "" { + assert.EqualError(t, err, tt.wantErr) + } else { + assert.NoError(t, err) + assert.Equalf(t, tt.want, buf.String(), "NewSitemap()") + } + }) } +} +func TestNewSitemapIndex(t *testing.T) { ts := time.Unix(1651322008, 0).UTC() - test( - []URL{}, - "", - ) - test( - []URL{ - {URL: "https://gitea.io/test1", LastMod: &ts}, + tests := []struct { + name string + urls []URL + want string + wantErr string + }{ + { + name: "empty", + urls: []URL{}, + want: xml.Header + `` + + "" + + "\n", }, - "https://gitea.io/test12022-04-30T12:33:28Z", - ) - test( - []URL{ - {URL: "https://gitea.io/test2", LastMod: nil}, + { + name: "regular", + urls: []URL{ + {URL: "https://gitea.io/test1", LastMod: &ts}, + }, + want: xml.Header + `` + + "https://gitea.io/test12022-04-30T12:33:28Z" + + "\n", }, - "https://gitea.io/test2", - ) - test( - []URL{ - {URL: "https://gitea.io/test1", LastMod: &ts}, - {URL: "https://gitea.io/test2", LastMod: nil}, + { + name: "without lastmod", + urls: []URL{ + {URL: "https://gitea.io/test1"}, + }, + want: xml.Header + `` + + "https://gitea.io/test1" + + "\n", + }, + { + name: "multiple", + urls: []URL{ + {URL: "https://gitea.io/test1", LastMod: &ts}, + {URL: "https://gitea.io/test2", LastMod: nil}, + }, + want: xml.Header + `` + + "https://gitea.io/test12022-04-30T12:33:28Z" + + "https://gitea.io/test2" + + "\n", + }, + { + name: "too many sitemaps", + urls: make([]URL, 50001), + wantErr: "The sitemap contains 50001 sub-sitemaps, but only 50000 are allowed", + }, + { + name: "too big file", + urls: []URL{ + {URL: strings.Repeat("b", 50*1024*1024+1)}, + }, + wantErr: "The sitemap has 52428952 bytes, but only 52428800 are allowed", }, - "https://gitea.io/test12022-04-30T12:33:28Z"+ - "https://gitea.io/test2", - ) -} - -func TestTooManyURLs(t *testing.T) { - s := NewSitemap() - for i := 0; i < 50001; i++ { - s.Add(URL{URL: fmt.Sprintf("https://gitea.io/test%d", i)}) } - buf := &bytes.Buffer{} - _, err := s.WriteTo(buf) - assert.EqualError(t, err, "The sitemap contains too many URLs: 50001") -} - -func TestSitemapTooBig(t *testing.T) { - s := NewSitemap() - s.Add(URL{URL: strings.Repeat("b", sitemapFileLimit)}) - buf := &bytes.Buffer{} - _, err := s.WriteTo(buf) - assert.EqualError(t, err, "The sitemap is too big: 52428931") + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := NewSitemapIndex() + for _, url := range tt.urls { + s.Add(url) + } + buf := &bytes.Buffer{} + _, err := s.WriteTo(buf) + if tt.wantErr != "" { + assert.EqualError(t, err, tt.wantErr) + } else { + assert.NoError(t, err) + assert.Equalf(t, tt.want, buf.String(), "NewSitemapIndex()") + } + }) + } } diff --git a/modules/structs/mirror.go b/modules/structs/mirror.go index 21e7751f765e..55cd133a4fc7 100644 --- a/modules/structs/mirror.go +++ b/modules/structs/mirror.go @@ -9,6 +9,7 @@ type CreatePushMirrorOption struct { RemoteUsername string `json:"remote_username"` RemotePassword string `json:"remote_password"` Interval string `json:"interval"` + SyncOnCommit bool `json:"sync_on_commit"` } // PushMirror represents information of a push mirror @@ -21,4 +22,5 @@ type PushMirror struct { LastUpdateUnix string `json:"last_update"` LastError string `json:"last_error"` Interval string `json:"interval"` + SyncOnCommit bool `json:"sync_on_commit"` } diff --git a/modules/util/error.go b/modules/util/error.go index 63bd447bf3e6..e67b9977f080 100644 --- a/modules/util/error.go +++ b/modules/util/error.go @@ -5,6 +5,7 @@ package util import ( "errors" + "fmt" ) // Common Errors forming the base of our error system @@ -34,3 +35,31 @@ func (w SilentWrap) Error() string { func (w SilentWrap) Unwrap() error { return w.Err } + +// NewSilentWrapErrorf returns an error that formats as the given text but unwraps as the provided error +func NewSilentWrapErrorf(unwrap error, message string, args ...interface{}) error { + if len(args) == 0 { + return SilentWrap{Message: message, Err: unwrap} + } + return SilentWrap{Message: fmt.Sprintf(message, args...), Err: unwrap} +} + +// NewInvalidArgumentErrorf returns an error that formats as the given text but unwraps as an ErrInvalidArgument +func NewInvalidArgumentErrorf(message string, args ...interface{}) error { + return NewSilentWrapErrorf(ErrInvalidArgument, message, args...) +} + +// NewPermissionDeniedErrorf returns an error that formats as the given text but unwraps as an ErrPermissionDenied +func NewPermissionDeniedErrorf(message string, args ...interface{}) error { + return NewSilentWrapErrorf(ErrPermissionDenied, message, args...) +} + +// NewAlreadyExistErrorf returns an error that formats as the given text but unwraps as an ErrAlreadyExist +func NewAlreadyExistErrorf(message string, args ...interface{}) error { + return NewSilentWrapErrorf(ErrAlreadyExist, message, args...) +} + +// NewNotExistErrorf returns an error that formats as the given text but unwraps as an ErrNotExist +func NewNotExistErrorf(message string, args ...interface{}) error { + return NewSilentWrapErrorf(ErrNotExist, message, args...) +} diff --git a/options/gitignore/Godot b/options/gitignore/Godot index 4f48ad79f8fb..d9aac213e776 100644 --- a/options/gitignore/Godot +++ b/options/gitignore/Godot @@ -1,3 +1,6 @@ +# Godot 4+ specific ignores +.godot/ + # Godot-specific ignores .import/ export.cfg @@ -9,3 +12,4 @@ export_presets.cfg # Mono-specific ignores .mono/ data_*/ +mono_crash.*.json diff --git a/options/license/Bitstream-Charter b/options/license/Bitstream-Charter new file mode 100644 index 000000000000..7a0cf97a0c98 --- /dev/null +++ b/options/license/Bitstream-Charter @@ -0,0 +1,9 @@ +(c) Copyright 1989-1992, Bitstream Inc., Cambridge, MA. + +You are hereby granted permission under all Bitstream propriety rights +to use, copy, modify, sublicense, sell, and redistribute the 4 Bitstream +Charter (r) Type 1 outline fonts and the 4 Courier Type 1 outline fonts for +any purpose and without restriction; provided, that this notice is left +intact on all copies of such fonts and that Bitstream's trademark is acknowledged +as shown below on all unmodified copies of the 4 Charter Type 1 fonts. +BITSTREAM CHARTER is a registered trademark of Bitstream Inc. diff --git a/options/license/Graphics-Gems b/options/license/Graphics-Gems new file mode 100644 index 000000000000..ec28c4656361 --- /dev/null +++ b/options/license/Graphics-Gems @@ -0,0 +1,5 @@ +LICENSE + +This code repository predates the concept of Open Source, and predates most licenses along such lines. As such, the official license truly is: + +EULA: The Graphics Gems code is copyright-protected. In other words, you cannot claim the text of the code as your own and resell it. Using the code is permitted in any program, product, or library, non-commercial or commercial. Giving credit is not required, though is a nice gesture. The code comes as-is, and if there are any flaws or problems with any Gems code, nobody involved with Gems - authors, editors, publishers, or webmasters - are to be held responsible. Basically, don't be a jerk, and remember that anything free comes with no guarantee. diff --git a/options/license/HPND-export-US b/options/license/HPND-export-US new file mode 100644 index 000000000000..b0cd39396978 --- /dev/null +++ b/options/license/HPND-export-US @@ -0,0 +1,5 @@ +Copyright (C) 1990 by the Massachusetts Institute of Technology + +Export of this software from the United States of America may require a specific license from the United States Government. It is the responsibility of any person or organization contemplating export to obtain such a license before exporting. + +WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of M.I.T. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. M.I.T. makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. diff --git a/options/license/IJG-short b/options/license/IJG-short new file mode 100644 index 000000000000..bbb0859d804d --- /dev/null +++ b/options/license/IJG-short @@ -0,0 +1,35 @@ +The authors make NO WARRANTY or representation, either express or +implied, with respect to this software, its quality, accuracy, +merchantability, or fitness for a particular purpose. This software is +provided "AS IS", and you, its user, assume the entire risk as to its +quality and accuracy. + +This software is copyright (C) 1991, 1992, Thomas G. Lane. All Rights +Reserved except as specified below. + +Permission is hereby granted to use, copy, modify, and distribute this +software (or portions thereof) for any purpose, without fee, subject to +these conditions: + +(1) If any part of the source code for this software +is distributed, then this README file must be included, with this +copyright and no-warranty notice unaltered; and any additions, +deletions, or changes to the original files must be clearly indicated +in accompanying documentation. + +(2) If only executable code is +distributed, then the accompanying documentation must state that "this +software is based in part on the work of the Independent JPEG Group". + +(3) Permission for use of this software is granted only if the user +accepts full responsibility for any undesirable consequences; the +authors accept NO LIABILITY for damages of any kind. + +Permission is NOT granted for the use of any IJG author's name or +company name in advertising or publicity relating to this software or +products derived from it. This software may be referred to only as +"the Independent JPEG Group's software". + +We specifically permit and encourage the use of this software as the +basis of commercial products, provided that all warranty or liability +claims are assumed by the product vendor. diff --git a/options/license/MIT-Wu b/options/license/MIT-Wu new file mode 100644 index 000000000000..86eec3c517a9 --- /dev/null +++ b/options/license/MIT-Wu @@ -0,0 +1,28 @@ +Copyright (c) 2003-2005 Tom Wu +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, +EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY +WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER +RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF +THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +In addition, the following condition applies: + +All redistributions must retain an intact copy of this copyright notice +and disclaimer. diff --git a/options/license/TPDL b/options/license/TPDL new file mode 100644 index 000000000000..d950f8f19e59 --- /dev/null +++ b/options/license/TPDL @@ -0,0 +1,2 @@ +Copyright (C) 1996-2010 David Muir Sharnoff. Copyright (C) 2011 Google, Inc. +License hereby granted for anyone to use, modify or redistribute this module at their own risk. Please feed useful changes back to cpan@dave.sharnoff.org. diff --git a/options/license/TTWL b/options/license/TTWL new file mode 100644 index 000000000000..c13d3fbe04a4 --- /dev/null +++ b/options/license/TTWL @@ -0,0 +1,8 @@ +Copyright (C) 1996-2002,2005,2006 David Muir Sharnoff. +Copyright (C) 2005 Aristotle Pagaltzis +Copyright (C) 2012-2013 Google, Inc. + +This module may be modified, used, copied, and redistributed at your own risk. +Although allowed by the preceding license, please do not publicly +redistribute modified versions of this code with the name "Text::Tabs" +unless it passes the unmodified Text::Tabs test suite. diff --git a/routers/api/packages/api.go b/routers/api/packages/api.go index b523725c4895..78eb5e860be2 100644 --- a/routers/api/packages/api.go +++ b/routers/api/packages/api.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/packages/composer" @@ -58,7 +59,13 @@ func CommonRoutes(ctx gocontext.Context) *web.Route { authGroup := auth.NewGroup(authMethods...) r.Use(func(ctx *context.Context) { - ctx.Doer = authGroup.Verify(ctx.Req, ctx.Resp, ctx, ctx.Session) + var err error + ctx.Doer, err = authGroup.Verify(ctx.Req, ctx.Resp, ctx, ctx.Session) + if err != nil { + log.Error("Verify: %v", err) + ctx.Error(http.StatusUnauthorized, "authGroup.Verify") + return + } ctx.IsSigned = ctx.Doer != nil }) @@ -321,7 +328,13 @@ func ContainerRoutes(ctx gocontext.Context) *web.Route { authGroup := auth.NewGroup(authMethods...) r.Use(func(ctx *context.Context) { - ctx.Doer = authGroup.Verify(ctx.Req, ctx.Resp, ctx, ctx.Session) + var err error + ctx.Doer, err = authGroup.Verify(ctx.Req, ctx.Resp, ctx, ctx.Session) + if err != nil { + log.Error("Failed to verify user: %v", err) + ctx.Error(http.StatusUnauthorized, "Verify") + return + } ctx.IsSigned = ctx.Doer != nil }) diff --git a/routers/api/packages/composer/composer.go b/routers/api/packages/composer/composer.go index c6e0593b42f5..a623952aa738 100644 --- a/routers/api/packages/composer/composer.go +++ b/routers/api/packages/composer/composer.go @@ -4,6 +4,7 @@ package composer import ( + "errors" "fmt" "io" "net/http" @@ -14,12 +15,12 @@ import ( "code.gitea.io/gitea/models/db" packages_model "code.gitea.io/gitea/models/packages" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" packages_module "code.gitea.io/gitea/modules/packages" composer_module "code.gitea.io/gitea/modules/packages/composer" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/routers/api/packages/helper" + "code.gitea.io/gitea/services/convert" packages_service "code.gitea.io/gitea/services/packages" "github.com/hashicorp/go-version" @@ -200,7 +201,11 @@ func UploadPackage(ctx *context.Context) { cp, err := composer_module.ParsePackage(buf, buf.Size()) if err != nil { - apiError(ctx, http.StatusBadRequest, err) + if errors.Is(err, util.ErrInvalidArgument) { + apiError(ctx, http.StatusBadRequest, err) + } else { + apiError(ctx, http.StatusInternalServerError, err) + } return } diff --git a/routers/api/packages/conan/auth.go b/routers/api/packages/conan/auth.go index f3adaf7beee6..ca02d61e7615 100644 --- a/routers/api/packages/conan/auth.go +++ b/routers/api/packages/conan/auth.go @@ -19,22 +19,22 @@ func (a *Auth) Name() string { } // Verify extracts the user from the Bearer token -func (a *Auth) Verify(req *http.Request, w http.ResponseWriter, store auth.DataStore, sess auth.SessionStore) *user_model.User { +func (a *Auth) Verify(req *http.Request, w http.ResponseWriter, store auth.DataStore, sess auth.SessionStore) (*user_model.User, error) { uid, err := packages.ParseAuthorizationToken(req) if err != nil { log.Trace("ParseAuthorizationToken: %v", err) - return nil + return nil, err } if uid == 0 { - return nil + return nil, nil } u, err := user_model.GetUserByID(req.Context(), uid) if err != nil { log.Error("GetUserByID: %v", err) - return nil + return nil, err } - return u + return u, nil } diff --git a/routers/api/packages/container/auth.go b/routers/api/packages/container/auth.go index e134f74c8f27..33f439ec3e58 100644 --- a/routers/api/packages/container/auth.go +++ b/routers/api/packages/container/auth.go @@ -20,25 +20,25 @@ func (a *Auth) Name() string { // Verify extracts the user from the Bearer token // If it's an anonymous session a ghost user is returned -func (a *Auth) Verify(req *http.Request, w http.ResponseWriter, store auth.DataStore, sess auth.SessionStore) *user_model.User { +func (a *Auth) Verify(req *http.Request, w http.ResponseWriter, store auth.DataStore, sess auth.SessionStore) (*user_model.User, error) { uid, err := packages.ParseAuthorizationToken(req) if err != nil { log.Trace("ParseAuthorizationToken: %v", err) - return nil + return nil, err } if uid == 0 { - return nil + return nil, nil } if uid == -1 { - return user_model.NewGhostUser() + return user_model.NewGhostUser(), nil } u, err := user_model.GetUserByID(req.Context(), uid) if err != nil { log.Error("GetUserByID: %v", err) - return nil + return nil, err } - return u + return u, nil } diff --git a/routers/api/packages/helm/helm.go b/routers/api/packages/helm/helm.go index af863bc4b91d..3bcce6bdf585 100644 --- a/routers/api/packages/helm/helm.go +++ b/routers/api/packages/helm/helm.go @@ -4,6 +4,7 @@ package helm import ( + "errors" "fmt" "io" "net/http" @@ -163,7 +164,11 @@ func UploadPackage(ctx *context.Context) { metadata, err := helm_module.ParseChartArchive(buf) if err != nil { - apiError(ctx, http.StatusBadRequest, err) + if errors.Is(err, util.ErrInvalidArgument) { + apiError(ctx, http.StatusBadRequest, err) + } else { + apiError(ctx, http.StatusInternalServerError, err) + } return } diff --git a/routers/api/packages/npm/npm.go b/routers/api/packages/npm/npm.go index 1a09cb6f3663..0d25f173e922 100644 --- a/routers/api/packages/npm/npm.go +++ b/routers/api/packages/npm/npm.go @@ -158,7 +158,11 @@ func DownloadPackageFileByName(ctx *context.Context) { func UploadPackage(ctx *context.Context) { npmPackage, err := npm_module.ParsePackage(ctx.Req.Body) if err != nil { - apiError(ctx, http.StatusBadRequest, err) + if errors.Is(err, util.ErrInvalidArgument) { + apiError(ctx, http.StatusBadRequest, err) + } else { + apiError(ctx, http.StatusInternalServerError, err) + } return } diff --git a/routers/api/packages/nuget/auth.go b/routers/api/packages/nuget/auth.go index 890c93018409..54b33d89c0a8 100644 --- a/routers/api/packages/nuget/auth.go +++ b/routers/api/packages/nuget/auth.go @@ -20,19 +20,20 @@ func (a *Auth) Name() string { } // https://docs.microsoft.com/en-us/nuget/api/package-publish-resource#request-parameters -func (a *Auth) Verify(req *http.Request, w http.ResponseWriter, store auth.DataStore, sess auth.SessionStore) *user_model.User { +func (a *Auth) Verify(req *http.Request, w http.ResponseWriter, store auth.DataStore, sess auth.SessionStore) (*user_model.User, error) { token, err := auth_model.GetAccessTokenBySHA(req.Header.Get("X-NuGet-ApiKey")) if err != nil { if !(auth_model.IsErrAccessTokenNotExist(err) || auth_model.IsErrAccessTokenEmpty(err)) { log.Error("GetAccessTokenBySHA: %v", err) + return nil, err } - return nil + return nil, nil } u, err := user_model.GetUserByID(req.Context(), token.UID) if err != nil { log.Error("GetUserByID: %v", err) - return nil + return nil, err } token.UpdatedUnix = timeutil.TimeStampNow() @@ -40,5 +41,5 @@ func (a *Auth) Verify(req *http.Request, w http.ResponseWriter, store auth.DataS log.Error("UpdateAccessToken: %v", err) } - return u + return u, nil } diff --git a/routers/api/packages/nuget/nuget.go b/routers/api/packages/nuget/nuget.go index d6f7d1d7f66c..6423db7d3a21 100644 --- a/routers/api/packages/nuget/nuget.go +++ b/routers/api/packages/nuget/nuget.go @@ -411,7 +411,11 @@ func UploadSymbolPackage(ctx *context.Context) { pdbs, err := nuget_module.ExtractPortablePdb(buf, buf.Size()) if err != nil { - apiError(ctx, http.StatusBadRequest, err) + if errors.Is(err, util.ErrInvalidArgument) { + apiError(ctx, http.StatusBadRequest, err) + } else { + apiError(ctx, http.StatusInternalServerError, err) + } return } defer pdbs.Close() @@ -507,7 +511,7 @@ func processUploadedFile(ctx *context.Context, expectedType nuget_module.Package np, err := nuget_module.ParsePackageMetaData(buf, buf.Size()) if err != nil { - if err == nuget_module.ErrMissingNuspecFile || err == nuget_module.ErrNuspecFileTooLarge || err == nuget_module.ErrNuspecInvalidID || err == nuget_module.ErrNuspecInvalidVersion { + if errors.Is(err, util.ErrInvalidArgument) { apiError(ctx, http.StatusBadRequest, err) } else { apiError(ctx, http.StatusInternalServerError, err) diff --git a/routers/api/packages/pub/pub.go b/routers/api/packages/pub/pub.go index 247950a214ae..1ece4e18ed6d 100644 --- a/routers/api/packages/pub/pub.go +++ b/routers/api/packages/pub/pub.go @@ -4,6 +4,7 @@ package pub import ( + "errors" "fmt" "io" "net/http" @@ -19,6 +20,7 @@ import ( packages_module "code.gitea.io/gitea/modules/packages" pub_module "code.gitea.io/gitea/modules/packages/pub" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/routers/api/packages/helper" packages_service "code.gitea.io/gitea/services/packages" ) @@ -173,7 +175,11 @@ func UploadPackageFile(ctx *context.Context) { pck, err := pub_module.ParsePackage(buf) if err != nil { - apiError(ctx, http.StatusInternalServerError, err) + if errors.Is(err, util.ErrInvalidArgument) { + apiError(ctx, http.StatusBadRequest, err) + } else { + apiError(ctx, http.StatusInternalServerError, err) + } return } diff --git a/routers/api/packages/rubygems/rubygems.go b/routers/api/packages/rubygems/rubygems.go index c1a10b5e78f3..af358fb82fba 100644 --- a/routers/api/packages/rubygems/rubygems.go +++ b/routers/api/packages/rubygems/rubygems.go @@ -6,6 +6,7 @@ package rubygems import ( "compress/gzip" "compress/zlib" + "errors" "fmt" "io" "net/http" @@ -217,7 +218,11 @@ func UploadPackageFile(ctx *context.Context) { rp, err := rubygems_module.ParsePackageMetaData(buf) if err != nil { - apiError(ctx, http.StatusInternalServerError, err) + if errors.Is(err, util.ErrInvalidArgument) { + apiError(ctx, http.StatusBadRequest, err) + } else { + apiError(ctx, http.StatusInternalServerError, err) + } return } if _, err := buf.Seek(0, io.SeekStart); err != nil { diff --git a/routers/api/v1/admin/org.go b/routers/api/v1/admin/org.go index 9d0725e3e85d..ff6624418442 100644 --- a/routers/api/v1/admin/org.go +++ b/routers/api/v1/admin/org.go @@ -11,10 +11,10 @@ import ( "code.gitea.io/gitea/models/organization" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // CreateOrg api for create organization diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index 183ade8a0a5e..6b48ce4a9d4d 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -16,7 +16,6 @@ import ( "code.gitea.io/gitea/models/db" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/password" "code.gitea.io/gitea/modules/setting" @@ -26,6 +25,7 @@ import ( "code.gitea.io/gitea/routers/api/v1/user" "code.gitea.io/gitea/routers/api/v1/utils" asymkey_service "code.gitea.io/gitea/services/asymkey" + "code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/mailer" user_service "code.gitea.io/gitea/services/user" ) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 82ff7ae0befc..c12ceacdd3b1 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -230,13 +230,10 @@ func reqExploreSignIn() func(ctx *context.APIContext) { } } -func reqBasicOrRevProxyAuth() func(ctx *context.APIContext) { +func reqBasicAuth() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { - if ctx.IsSigned && setting.Service.EnableReverseProxyAuth && ctx.Data["AuthedMethod"].(string) == auth.ReverseProxyMethodName { - return - } if !ctx.Context.IsBasicAuth { - ctx.Error(http.StatusUnauthorized, "reqBasicOrRevProxyAuth", "auth required") + ctx.Error(http.StatusUnauthorized, "reqBasicAuth", "auth required") return } ctx.CheckForOTP() @@ -598,9 +595,6 @@ func buildAuthGroup() *auth.Group { &auth.HTTPSign{}, &auth.Basic{}, // FIXME: this should be removed once we don't allow basic auth in API ) - if setting.Service.EnableReverseProxyAuth { - group.Add(&auth.ReverseProxy{}) - } specialAdd(group) return group @@ -690,7 +684,7 @@ func Routes(ctx gocontext.Context) *web.Route { m.Combo("").Get(user.ListAccessTokens). Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken) m.Combo("/{id}").Delete(user.DeleteAccessToken) - }, reqBasicOrRevProxyAuth()) + }, reqBasicAuth()) }, context_service.UserAssignmentAPI()) }) diff --git a/routers/api/v1/notify/repo.go b/routers/api/v1/notify/repo.go index a2e72cb48de0..bd3b86a6f152 100644 --- a/routers/api/v1/notify/repo.go +++ b/routers/api/v1/notify/repo.go @@ -10,9 +10,9 @@ import ( activities_model "code.gitea.io/gitea/models/activities" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/services/convert" ) func statusStringToNotificationStatus(status string) activities_model.NotificationStatus { diff --git a/routers/api/v1/notify/threads.go b/routers/api/v1/notify/threads.go index 47d0e4972143..6a1bce4de41a 100644 --- a/routers/api/v1/notify/threads.go +++ b/routers/api/v1/notify/threads.go @@ -11,7 +11,7 @@ import ( "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" + "code.gitea.io/gitea/services/convert" ) // GetThread get notification by ID diff --git a/routers/api/v1/notify/user.go b/routers/api/v1/notify/user.go index 725eeff017fc..2261610c0923 100644 --- a/routers/api/v1/notify/user.go +++ b/routers/api/v1/notify/user.go @@ -9,8 +9,8 @@ import ( activities_model "code.gitea.io/gitea/models/activities" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/services/convert" ) // ListNotifications list users's notification threads diff --git a/routers/api/v1/org/hook.go b/routers/api/v1/org/hook.go index 2e9d7c656a76..ef08a08be0e4 100644 --- a/routers/api/v1/org/hook.go +++ b/routers/api/v1/org/hook.go @@ -8,10 +8,10 @@ import ( "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // ListHooks list an organziation's webhooks diff --git a/routers/api/v1/org/label.go b/routers/api/v1/org/label.go index c95a6be3d20a..5d0455cdd4f4 100644 --- a/routers/api/v1/org/label.go +++ b/routers/api/v1/org/label.go @@ -11,10 +11,10 @@ import ( issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // ListLabels list all the labels of an organization diff --git a/routers/api/v1/org/member.go b/routers/api/v1/org/member.go index fe071439588e..33c994497803 100644 --- a/routers/api/v1/org/member.go +++ b/routers/api/v1/org/member.go @@ -10,11 +10,11 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/routers/api/v1/user" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // listMembers list an organization's members diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index cf985d44fbb0..a1b071d4887a 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -12,11 +12,11 @@ import ( "code.gitea.io/gitea/models/perm" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/user" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/org" ) diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 798b792e71e5..8f87e8276485 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -15,12 +15,12 @@ import ( repo_model "code.gitea.io/gitea/models/repo" unit_model "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/log" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/user" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" org_service "code.gitea.io/gitea/services/org" ) diff --git a/routers/api/v1/packages/package.go b/routers/api/v1/packages/package.go index 433a79939cc7..6f9083ba327b 100644 --- a/routers/api/v1/packages/package.go +++ b/routers/api/v1/packages/package.go @@ -8,10 +8,10 @@ import ( "code.gitea.io/gitea/models/packages" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" packages_service "code.gitea.io/gitea/services/packages" ) diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index 3060cf24064d..46fcc2fcd366 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -14,11 +14,11 @@ import ( "code.gitea.io/gitea/models/organization" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" pull_service "code.gitea.io/gitea/services/pull" repo_service "code.gitea.io/gitea/services/repository" ) diff --git a/routers/api/v1/repo/collaborators.go b/routers/api/v1/repo/collaborators.go index 202418bd2bec..293778420bc2 100644 --- a/routers/api/v1/repo/collaborators.go +++ b/routers/api/v1/repo/collaborators.go @@ -14,11 +14,11 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" repo_module "code.gitea.io/gitea/modules/repository" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // ListCollaborators list a repository's collaborators diff --git a/routers/api/v1/repo/commits.go b/routers/api/v1/repo/commits.go index 682044407dfe..68a92ca2a840 100644 --- a/routers/api/v1/repo/commits.go +++ b/routers/api/v1/repo/commits.go @@ -12,11 +12,11 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // GetSingleCommit get a commit via sha diff --git a/routers/api/v1/repo/fork.go b/routers/api/v1/repo/fork.go index f2cd10e711af..e4c7eb70414a 100644 --- a/routers/api/v1/repo/fork.go +++ b/routers/api/v1/repo/fork.go @@ -14,10 +14,10 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" repo_service "code.gitea.io/gitea/services/repository" ) @@ -141,7 +141,7 @@ func CreateFork(ctx *context.APIContext) { Description: repo.Description, }) if err != nil { - if repo_model.IsErrRepoAlreadyExist(err) { + if repo_model.IsErrReachLimitOfRepo(err) || repo_model.IsErrRepoAlreadyExist(err) { ctx.Error(http.StatusConflict, "ForkRepository", err) } else { ctx.Error(http.StatusInternalServerError, "ForkRepository", err) diff --git a/routers/api/v1/repo/git_hook.go b/routers/api/v1/repo/git_hook.go index 963cbc719f42..40bd35542888 100644 --- a/routers/api/v1/repo/git_hook.go +++ b/routers/api/v1/repo/git_hook.go @@ -7,10 +7,10 @@ import ( "net/http" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/services/convert" ) // ListGitHooks list all Git hooks of a repository diff --git a/routers/api/v1/repo/hook.go b/routers/api/v1/repo/hook.go index 0c3d59a41938..757ae7247bf7 100644 --- a/routers/api/v1/repo/hook.go +++ b/routers/api/v1/repo/hook.go @@ -10,12 +10,12 @@ import ( "code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" webhook_service "code.gitea.io/gitea/services/webhook" ) diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index 30dc7a68326c..fecb601dd533 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -19,7 +19,6 @@ import ( "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" issue_indexer "code.gitea.io/gitea/modules/indexer/issues" "code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/setting" @@ -28,6 +27,7 @@ import ( "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" issue_service "code.gitea.io/gitea/services/issue" ) diff --git a/routers/api/v1/repo/issue_attachment.go b/routers/api/v1/repo/issue_attachment.go index 4cf108b41378..8cbd2e11b699 100644 --- a/routers/api/v1/repo/issue_attachment.go +++ b/routers/api/v1/repo/issue_attachment.go @@ -9,12 +9,12 @@ import ( issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/services/attachment" + "code.gitea.io/gitea/services/convert" issue_service "code.gitea.io/gitea/services/issue" ) diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go index 9097004186f4..40c92998d19c 100644 --- a/routers/api/v1/repo/issue_comment.go +++ b/routers/api/v1/repo/issue_comment.go @@ -14,10 +14,10 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" issue_service "code.gitea.io/gitea/services/issue" ) diff --git a/routers/api/v1/repo/issue_comment_attachment.go b/routers/api/v1/repo/issue_comment_attachment.go index 2198a6a33d51..4c8452380f03 100644 --- a/routers/api/v1/repo/issue_comment_attachment.go +++ b/routers/api/v1/repo/issue_comment_attachment.go @@ -9,12 +9,12 @@ import ( issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/services/attachment" + "code.gitea.io/gitea/services/convert" issue_service "code.gitea.io/gitea/services/issue" ) diff --git a/routers/api/v1/repo/issue_label.go b/routers/api/v1/repo/issue_label.go index 04d70913c7a6..1f0d21141bcc 100644 --- a/routers/api/v1/repo/issue_label.go +++ b/routers/api/v1/repo/issue_label.go @@ -9,9 +9,9 @@ import ( issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/services/convert" issue_service "code.gitea.io/gitea/services/issue" ) diff --git a/routers/api/v1/repo/issue_reaction.go b/routers/api/v1/repo/issue_reaction.go index dcfe7967b58e..1b998a535424 100644 --- a/routers/api/v1/repo/issue_reaction.go +++ b/routers/api/v1/repo/issue_reaction.go @@ -9,10 +9,10 @@ import ( issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // GetIssueCommentReactions list reactions of a comment from an issue diff --git a/routers/api/v1/repo/issue_stopwatch.go b/routers/api/v1/repo/issue_stopwatch.go index 110139cc36b6..9ab3c61deb4f 100644 --- a/routers/api/v1/repo/issue_stopwatch.go +++ b/routers/api/v1/repo/issue_stopwatch.go @@ -9,8 +9,8 @@ import ( issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // StartIssueStopwatch creates a stopwatch for the given issue. diff --git a/routers/api/v1/repo/issue_subscription.go b/routers/api/v1/repo/issue_subscription.go index 32832d83f79a..6d22c82652ef 100644 --- a/routers/api/v1/repo/issue_subscription.go +++ b/routers/api/v1/repo/issue_subscription.go @@ -10,9 +10,9 @@ import ( issues_model "code.gitea.io/gitea/models/issues" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // AddIssueSubscription Subscribe user to issue diff --git a/routers/api/v1/repo/issue_tracked_time.go b/routers/api/v1/repo/issue_tracked_time.go index ede60a2ed810..16bb8cb73d6c 100644 --- a/routers/api/v1/repo/issue_tracked_time.go +++ b/routers/api/v1/repo/issue_tracked_time.go @@ -13,10 +13,10 @@ import ( "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // ListTrackedTimes list all the tracked times of an issue diff --git a/routers/api/v1/repo/key.go b/routers/api/v1/repo/key.go index 54313e8e764f..d496c4a73c11 100644 --- a/routers/api/v1/repo/key.go +++ b/routers/api/v1/repo/key.go @@ -15,12 +15,12 @@ import ( "code.gitea.io/gitea/models/perm" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" asymkey_service "code.gitea.io/gitea/services/asymkey" + "code.gitea.io/gitea/services/convert" ) // appendPrivateInformation appends the owner and key type information to api.PublicKey diff --git a/routers/api/v1/repo/label.go b/routers/api/v1/repo/label.go index 8b49becd37bb..411c0274e6c7 100644 --- a/routers/api/v1/repo/label.go +++ b/routers/api/v1/repo/label.go @@ -12,10 +12,10 @@ import ( issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // ListLabels list all the labels of a repository diff --git a/routers/api/v1/repo/migrate.go b/routers/api/v1/repo/migrate.go index 35516ff58f36..09e857b5fcfe 100644 --- a/routers/api/v1/repo/migrate.go +++ b/routers/api/v1/repo/migrate.go @@ -17,7 +17,6 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" @@ -28,6 +27,7 @@ import ( api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/forms" "code.gitea.io/gitea/services/migrations" ) diff --git a/routers/api/v1/repo/milestone.go b/routers/api/v1/repo/milestone.go index 2b80b4df7345..b77fe8aca8a9 100644 --- a/routers/api/v1/repo/milestone.go +++ b/routers/api/v1/repo/milestone.go @@ -11,11 +11,11 @@ import ( issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // ListMilestones list milestones for a repository diff --git a/routers/api/v1/repo/mirror.go b/routers/api/v1/repo/mirror.go index b693c0e7db46..06bfabe3d2d2 100644 --- a/routers/api/v1/repo/mirror.go +++ b/routers/api/v1/repo/mirror.go @@ -14,13 +14,13 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" mirror_module "code.gitea.io/gitea/modules/mirror" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/forms" "code.gitea.io/gitea/services/migrations" mirror_service "code.gitea.io/gitea/services/mirror" @@ -345,10 +345,11 @@ func CreatePushMirror(ctx *context.APIContext, mirrorOption *api.CreatePushMirro } pushMirror := &repo_model.PushMirror{ - RepoID: repo.ID, - Repo: repo, - RemoteName: fmt.Sprintf("remote_mirror_%s", remoteSuffix), - Interval: interval, + RepoID: repo.ID, + Repo: repo, + RemoteName: fmt.Sprintf("remote_mirror_%s", remoteSuffix), + Interval: interval, + SyncOnCommit: mirrorOption.SyncOnCommit, } if err = repo_model.InsertPushMirror(ctx, pushMirror); err != nil { diff --git a/routers/api/v1/repo/notes.go b/routers/api/v1/repo/notes.go index 91eebb4c724d..8eaa503ff7cc 100644 --- a/routers/api/v1/repo/notes.go +++ b/routers/api/v1/repo/notes.go @@ -8,9 +8,9 @@ import ( "net/http" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/services/convert" ) // GetNote Get a note corresponding to a single commit from a repository diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index ed23b267f287..1b1aba17d929 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -21,7 +21,6 @@ import ( "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/notification" @@ -32,6 +31,7 @@ import ( "code.gitea.io/gitea/routers/api/v1/utils" asymkey_service "code.gitea.io/gitea/services/asymkey" "code.gitea.io/gitea/services/automerge" + "code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/forms" "code.gitea.io/gitea/services/gitdiff" issue_service "code.gitea.io/gitea/services/issue" @@ -815,7 +815,7 @@ func MergePullRequest(ctx *context.APIContext) { message := strings.TrimSpace(form.MergeTitleField) if len(message) == 0 { - message, err = pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pr, repo_model.MergeStyle(form.Do)) + message, _, err = pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pr, repo_model.MergeStyle(form.Do)) if err != nil { ctx.Error(http.StatusInternalServerError, "GetDefaultMergeMessage", err) return diff --git a/routers/api/v1/repo/pull_review.go b/routers/api/v1/repo/pull_review.go index 2f357afb79f7..96dc1fc2dee1 100644 --- a/routers/api/v1/repo/pull_review.go +++ b/routers/api/v1/repo/pull_review.go @@ -13,11 +13,11 @@ import ( access_model "code.gitea.io/gitea/models/perm/access" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" issue_service "code.gitea.io/gitea/services/issue" pull_service "code.gitea.io/gitea/services/pull" ) diff --git a/routers/api/v1/repo/release.go b/routers/api/v1/repo/release.go index 4e1927ea3d92..d0b20102f7a4 100644 --- a/routers/api/v1/repo/release.go +++ b/routers/api/v1/repo/release.go @@ -11,10 +11,10 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" release_service "code.gitea.io/gitea/services/release" ) diff --git a/routers/api/v1/repo/release_attachment.go b/routers/api/v1/repo/release_attachment.go index e7dbb42c7411..5aaea693c03b 100644 --- a/routers/api/v1/repo/release_attachment.go +++ b/routers/api/v1/repo/release_attachment.go @@ -8,13 +8,13 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/upload" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/services/attachment" + "code.gitea.io/gitea/services/convert" ) // GetReleaseAttachment gets a single attachment of the release diff --git a/routers/api/v1/repo/release_tags.go b/routers/api/v1/repo/release_tags.go index 5e1f1860ae77..7cc846fdc443 100644 --- a/routers/api/v1/repo/release_tags.go +++ b/routers/api/v1/repo/release_tags.go @@ -9,7 +9,7 @@ import ( "code.gitea.io/gitea/models" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" + "code.gitea.io/gitea/services/convert" releaseservice "code.gitea.io/gitea/services/release" ) diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 349040507810..e0cae5f82c7a 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -18,7 +18,6 @@ import ( unit_model "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" @@ -28,6 +27,7 @@ import ( "code.gitea.io/gitea/modules/validation" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" repo_service "code.gitea.io/gitea/services/repository" ) diff --git a/routers/api/v1/repo/star.go b/routers/api/v1/repo/star.go index a3d110587390..c7b2eb01ff65 100644 --- a/routers/api/v1/repo/star.go +++ b/routers/api/v1/repo/star.go @@ -8,9 +8,9 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // ListStargazers list a repository's stargazers diff --git a/routers/api/v1/repo/status.go b/routers/api/v1/repo/status.go index 0b196d162c27..19f57b1cea98 100644 --- a/routers/api/v1/repo/status.go +++ b/routers/api/v1/repo/status.go @@ -9,10 +9,10 @@ import ( git_model "code.gitea.io/gitea/models/git" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" files_service "code.gitea.io/gitea/services/repository/files" ) @@ -183,6 +183,7 @@ func getCommitStatuses(ctx *context.APIContext, sha string) { ctx.Error(http.StatusBadRequest, "ref/sha not given", nil) return } + sha = utils.MustConvertToSHA1(ctx.Context, sha) repo := ctx.Repo.Repository listOptions := utils.GetListOptions(ctx) diff --git a/routers/api/v1/repo/subscriber.go b/routers/api/v1/repo/subscriber.go index 5cc94abd487f..6cd369898eba 100644 --- a/routers/api/v1/repo/subscriber.go +++ b/routers/api/v1/repo/subscriber.go @@ -8,9 +8,9 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // ListSubscribers list a repo's subscribers (i.e. watchers) diff --git a/routers/api/v1/repo/tag.go b/routers/api/v1/repo/tag.go index 6b38a08c2f7b..cb65e2b651b0 100644 --- a/routers/api/v1/repo/tag.go +++ b/routers/api/v1/repo/tag.go @@ -11,10 +11,10 @@ import ( "code.gitea.io/gitea/models" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" releaseservice "code.gitea.io/gitea/services/release" ) diff --git a/routers/api/v1/repo/teams.go b/routers/api/v1/repo/teams.go index 1ea3ae0008a8..eafe4236ec3a 100644 --- a/routers/api/v1/repo/teams.go +++ b/routers/api/v1/repo/teams.go @@ -10,7 +10,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" + "code.gitea.io/gitea/services/convert" org_service "code.gitea.io/gitea/services/org" ) diff --git a/routers/api/v1/repo/topic.go b/routers/api/v1/repo/topic.go index 316b19025986..7d27fe7d25a0 100644 --- a/routers/api/v1/repo/topic.go +++ b/routers/api/v1/repo/topic.go @@ -9,11 +9,11 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/log" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // ListTopics returns list of current topics for repo diff --git a/routers/api/v1/repo/transfer.go b/routers/api/v1/repo/transfer.go index 5154c5afa3cb..aec398da7a41 100644 --- a/routers/api/v1/repo/transfer.go +++ b/routers/api/v1/repo/transfer.go @@ -13,10 +13,10 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/log" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/services/convert" repo_service "code.gitea.io/gitea/services/repository" ) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 0b55a9b2818f..764530a671e6 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -11,13 +11,13 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/services/convert" wiki_service "code.gitea.io/gitea/services/wiki" ) diff --git a/routers/api/v1/user/app.go b/routers/api/v1/user/app.go index 6cb7b812b233..7b2f0d8c30d2 100644 --- a/routers/api/v1/user/app.go +++ b/routers/api/v1/user/app.go @@ -12,10 +12,10 @@ import ( auth_model "code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // ListAccessTokens list all the access tokens diff --git a/routers/api/v1/user/email.go b/routers/api/v1/user/email.go index 84823aaed207..fc74c8d14846 100644 --- a/routers/api/v1/user/email.go +++ b/routers/api/v1/user/email.go @@ -9,10 +9,10 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/services/convert" ) // ListEmails list all of the authenticated user's email addresses diff --git a/routers/api/v1/user/follower.go b/routers/api/v1/user/follower.go index 38ddf990c47e..e9d4ae478b3d 100644 --- a/routers/api/v1/user/follower.go +++ b/routers/api/v1/user/follower.go @@ -9,9 +9,9 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) func responseAPIUsers(ctx *context.APIContext, users []*user_model.User) { diff --git a/routers/api/v1/user/gpg_key.go b/routers/api/v1/user/gpg_key.go index 7c91d2ac6563..84327cc92a43 100644 --- a/routers/api/v1/user/gpg_key.go +++ b/routers/api/v1/user/gpg_key.go @@ -11,10 +11,10 @@ import ( asymkey_model "code.gitea.io/gitea/models/asymkey" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) func listGPGKeys(ctx *context.APIContext, uid int64, listOptions db.ListOptions) { diff --git a/routers/api/v1/user/key.go b/routers/api/v1/user/key.go index 25bda0444a54..8aad69884fd8 100644 --- a/routers/api/v1/user/key.go +++ b/routers/api/v1/user/key.go @@ -11,13 +11,13 @@ import ( "code.gitea.io/gitea/models/perm" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/repo" "code.gitea.io/gitea/routers/api/v1/utils" asymkey_service "code.gitea.io/gitea/services/asymkey" + "code.gitea.io/gitea/services/convert" ) // appendPrivateInformation appends the owner and key type information to api.PublicKey diff --git a/routers/api/v1/user/repo.go b/routers/api/v1/user/repo.go index e79a9d8f8b1d..d566c072fba7 100644 --- a/routers/api/v1/user/repo.go +++ b/routers/api/v1/user/repo.go @@ -11,9 +11,9 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // listUserRepos - List the repositories owned by the given user. diff --git a/routers/api/v1/user/settings.go b/routers/api/v1/user/settings.go index 89bfd83efc15..53794c82f838 100644 --- a/routers/api/v1/user/settings.go +++ b/routers/api/v1/user/settings.go @@ -8,9 +8,9 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/services/convert" ) // GetUserSettings returns user settings diff --git a/routers/api/v1/user/star.go b/routers/api/v1/user/star.go index 0475489640ec..ad5a8bee33be 100644 --- a/routers/api/v1/user/star.go +++ b/routers/api/v1/user/star.go @@ -13,9 +13,9 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // getStarredRepos returns the repos that the user with the specified userID has diff --git a/routers/api/v1/user/user.go b/routers/api/v1/user/user.go index 8a21c2c7cacd..55f3df40b9cc 100644 --- a/routers/api/v1/user/user.go +++ b/routers/api/v1/user/user.go @@ -10,8 +10,8 @@ import ( activities_model "code.gitea.io/gitea/models/activities" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // Search search users diff --git a/routers/api/v1/user/watch.go b/routers/api/v1/user/watch.go index 707e5da0903b..211f36459a83 100644 --- a/routers/api/v1/user/watch.go +++ b/routers/api/v1/user/watch.go @@ -12,9 +12,9 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" ) // getWatchedRepos returns the repos that the user with the specified userID is watching diff --git a/routers/api/v1/utils/git.go b/routers/api/v1/utils/git.go index 2801dee8babe..eaf0f5fd37fc 100644 --- a/routers/api/v1/utils/git.go +++ b/routers/api/v1/utils/git.go @@ -33,6 +33,8 @@ func ResolveRefOrSha(ctx *context.APIContext, ref string) string { } } + sha = MustConvertToSHA1(ctx.Context, sha) + if ctx.Repo.GitRepo != nil { err := ctx.Repo.GitRepo.AddLastCommitCache(ctx.Repo.Repository.GetCommitsCountCacheKey(ref, ref != sha), ctx.Repo.Repository.FullName(), sha) if err != nil { @@ -65,3 +67,30 @@ func searchRefCommitByType(ctx *context.APIContext, refType, filter string) (str } return "", "", nil } + +// ConvertToSHA1 returns a full-length SHA1 from a potential ID string +func ConvertToSHA1(ctx *context.Context, commitID string) (git.SHA1, error) { + if len(commitID) == git.SHAFullLength && git.IsValidSHAPattern(commitID) { + sha1, err := git.NewIDFromString(commitID) + if err == nil { + return sha1, nil + } + } + + gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, ctx.Repo.Repository.RepoPath()) + if err != nil { + return git.SHA1{}, fmt.Errorf("RepositoryFromContextOrOpen: %w", err) + } + defer closer.Close() + + return gitRepo.ConvertToSHA1(commitID) +} + +// MustConvertToSHA1 returns a full-length SHA1 string from a potential ID string, or returns origin input if it can't convert to SHA1 +func MustConvertToSHA1(ctx *context.Context, commitID string) string { + sha, err := ConvertToSHA1(ctx, commitID) + if err != nil { + return commitID + } + return sha.String() +} diff --git a/routers/api/v1/utils/hook.go b/routers/api/v1/utils/hook.go index 7faf609ae813..1a27ececfe1c 100644 --- a/routers/api/v1/utils/hook.go +++ b/routers/api/v1/utils/hook.go @@ -10,10 +10,10 @@ import ( "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/json" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/services/convert" webhook_service "code.gitea.io/gitea/services/webhook" ) diff --git a/routers/api/v1/utils/page.go b/routers/api/v1/utils/page.go index ef5806fa9218..6910b8293196 100644 --- a/routers/api/v1/utils/page.go +++ b/routers/api/v1/utils/page.go @@ -6,7 +6,7 @@ package utils import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" + "code.gitea.io/gitea/services/convert" ) // GetListOptions returns list options using the page and limit parameters diff --git a/routers/web/admin/packages.go b/routers/web/admin/packages.go index 80cec51275cf..7c6d1ed840f5 100644 --- a/routers/web/admin/packages.go +++ b/routers/web/admin/packages.go @@ -62,6 +62,7 @@ func Packages(ctx *context.Context) { ctx.Data["PageIsAdminPackages"] = true ctx.Data["Query"] = query ctx.Data["PackageType"] = packageType + ctx.Data["AvailableTypes"] = packages_model.TypeList ctx.Data["SortType"] = sort ctx.Data["PackageDescriptors"] = pds ctx.Data["Total"] = total diff --git a/routers/web/explore/topic.go b/routers/web/explore/topic.go index 50df9d1113e2..e172d9e04d01 100644 --- a/routers/web/explore/topic.go +++ b/routers/web/explore/topic.go @@ -9,8 +9,8 @@ import ( "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/services/convert" ) // TopicSearch search for creating topic diff --git a/routers/web/org/teams.go b/routers/web/org/teams.go index 5dd86fdf117f..d9754633bfd9 100644 --- a/routers/web/org/teams.go +++ b/routers/web/org/teams.go @@ -20,11 +20,11 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/utils" + "code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/forms" org_service "code.gitea.io/gitea/services/org" ) diff --git a/routers/web/repo/commit.go b/routers/web/repo/commit.go index efc216661cae..6eda3fca10b3 100644 --- a/routers/web/repo/commit.go +++ b/routers/web/repo/commit.go @@ -283,7 +283,7 @@ func Diff(ctx *context.Context) { } return } - if len(commitID) != 40 { + if len(commitID) != git.SHAFullLength { commitID = commit.ID.String() } diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index d315525dac87..100e343de49b 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -31,7 +31,6 @@ import ( "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" issue_indexer "code.gitea.io/gitea/modules/indexer/issues" issue_template "code.gitea.io/gitea/modules/issue/template" @@ -47,6 +46,7 @@ import ( "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/utils" asymkey_service "code.gitea.io/gitea/services/asymkey" + "code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/forms" issue_service "code.gitea.io/gitea/services/issue" pull_service "code.gitea.io/gitea/services/pull" @@ -1664,19 +1664,21 @@ func ViewIssue(ctx *context.Context) { ctx.Data["MergeStyle"] = mergeStyle - defaultMergeMessage, err := pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pull, mergeStyle) + defaultMergeMessage, defaultMergeBody, err := pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pull, mergeStyle) if err != nil { ctx.ServerError("GetDefaultMergeMessage", err) return } ctx.Data["DefaultMergeMessage"] = defaultMergeMessage + ctx.Data["DefaultMergeBody"] = defaultMergeBody - defaultSquashMergeMessage, err := pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pull, repo_model.MergeStyleSquash) + defaultSquashMergeMessage, defaultSquashMergeBody, err := pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pull, repo_model.MergeStyleSquash) if err != nil { ctx.ServerError("GetDefaultSquashMergeMessage", err) return } ctx.Data["DefaultSquashMergeMessage"] = defaultSquashMergeMessage + ctx.Data["DefaultSquashMergeBody"] = defaultSquashMergeBody if err = pull.LoadProtectedBranch(ctx); err != nil { ctx.ServerError("LoadProtectedBranch", err) diff --git a/routers/web/repo/packages.go b/routers/web/repo/packages.go index 83324711da72..6ad2f71b5c2d 100644 --- a/routers/web/repo/packages.go +++ b/routers/web/repo/packages.go @@ -61,6 +61,7 @@ func Packages(ctx *context.Context) { ctx.Data["ContextUser"] = ctx.ContextUser ctx.Data["Query"] = query ctx.Data["PackageType"] = packageType + ctx.Data["AvailableTypes"] = packages.TypeList ctx.Data["HasPackages"] = hasPackages if ctx.Repo != nil { ctx.Data["CanWritePackages"] = ctx.IsUserRepoWriter([]unit.Type{unit.TypePackages}) || ctx.IsUserSiteAdmin() diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index bea6bfe433c1..a18f9f6a56a5 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -182,6 +182,15 @@ func getForkRepository(ctx *context.Context) *repo_model.Repository { func Fork(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("new_fork") + if ctx.Doer.CanForkRepo() { + ctx.Data["CanForkRepo"] = true + } else { + maxCreationLimit := ctx.Doer.MaxCreationLimit() + msg := ctx.TrN(maxCreationLimit, "repo.form.reach_limit_of_creation_1", "repo.form.reach_limit_of_creation_n", maxCreationLimit) + ctx.Data["Flash"] = ctx.Flash + ctx.Flash.Error(msg) + } + getForkRepository(ctx) if ctx.Written() { return @@ -254,6 +263,10 @@ func ForkPost(ctx *context.Context) { if err != nil { ctx.Data["Err_RepoName"] = true switch { + case repo_model.IsErrReachLimitOfRepo(err): + maxCreationLimit := ctxUser.MaxCreationLimit() + msg := ctx.TrN(maxCreationLimit, "repo.form.reach_limit_of_creation_1", "repo.form.reach_limit_of_creation_n", maxCreationLimit) + ctx.RenderWithErr(msg, tplFork, &form) case repo_model.IsErrRepoAlreadyExist(err): ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplFork, &form) case db.IsErrNameReserved(err): @@ -973,7 +986,7 @@ func MergePullRequest(ctx *context.Context) { message := strings.TrimSpace(form.MergeTitleField) if len(message) == 0 { var err error - message, err = pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pr, repo_model.MergeStyle(form.Do)) + message, _, err = pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pr, repo_model.MergeStyle(form.Do)) if err != nil { ctx.ServerError("GetDefaultMergeMessage", err) return diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go index 8856ee662684..f9c67f170bec 100644 --- a/routers/web/repo/repo.go +++ b/routers/web/repo/repo.go @@ -19,7 +19,6 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" @@ -27,6 +26,7 @@ import ( api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/forms" repo_service "code.gitea.io/gitea/services/repository" archiver_service "code.gitea.io/gitea/services/repository/archiver" diff --git a/routers/web/repo/webhook.go b/routers/web/repo/webhook.go index 18d71c6435a5..2b6f107fafd1 100644 --- a/routers/web/repo/webhook.go +++ b/routers/web/repo/webhook.go @@ -17,13 +17,13 @@ import ( "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/forms" webhook_service "code.gitea.io/gitea/services/webhook" ) diff --git a/routers/web/user/package.go b/routers/web/user/package.go index 3782f46b4242..c0aba7583fc0 100644 --- a/routers/web/user/package.go +++ b/routers/web/user/package.go @@ -89,6 +89,7 @@ func ListPackages(ctx *context.Context) { ctx.Data["ContextUser"] = ctx.ContextUser ctx.Data["Query"] = query ctx.Data["PackageType"] = packageType + ctx.Data["AvailableTypes"] = packages_model.TypeList ctx.Data["HasPackages"] = hasPackages ctx.Data["PackageDescriptors"] = pds ctx.Data["Total"] = total diff --git a/routers/web/user/search.go b/routers/web/user/search.go index 093de406a978..f9b0e0735864 100644 --- a/routers/web/user/search.go +++ b/routers/web/user/search.go @@ -9,7 +9,7 @@ import ( "code.gitea.io/gitea/models/db" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" + "code.gitea.io/gitea/services/convert" ) // Search search users diff --git a/routers/web/user/setting/keys.go b/routers/web/user/setting/keys.go index 89be795599bd..ec50eef9c18d 100644 --- a/routers/web/user/setting/keys.go +++ b/routers/web/user/setting/keys.go @@ -99,14 +99,18 @@ func KeysPost(ctx *context.Context) { loadKeysData(ctx) ctx.Data["Err_Content"] = true ctx.Data["Err_Signature"] = true - ctx.Data["KeyID"] = err.(asymkey_model.ErrGPGInvalidTokenSignature).ID + keyID := err.(asymkey_model.ErrGPGInvalidTokenSignature).ID + ctx.Data["KeyID"] = keyID + ctx.Data["PaddedKeyID"] = asymkey_model.PaddedKeyID(keyID) ctx.RenderWithErr(ctx.Tr("settings.gpg_invalid_token_signature"), tplSettingsKeys, &form) case asymkey_model.IsErrGPGNoEmailFound(err): loadKeysData(ctx) ctx.Data["Err_Content"] = true ctx.Data["Err_Signature"] = true - ctx.Data["KeyID"] = err.(asymkey_model.ErrGPGNoEmailFound).ID + keyID := err.(asymkey_model.ErrGPGNoEmailFound).ID + ctx.Data["KeyID"] = keyID + ctx.Data["PaddedKeyID"] = asymkey_model.PaddedKeyID(keyID) ctx.RenderWithErr(ctx.Tr("settings.gpg_no_key_email_found"), tplSettingsKeys, &form) default: ctx.ServerError("AddPublicKey", err) @@ -138,7 +142,9 @@ func KeysPost(ctx *context.Context) { loadKeysData(ctx) ctx.Data["VerifyingID"] = form.KeyID ctx.Data["Err_Signature"] = true - ctx.Data["KeyID"] = err.(asymkey_model.ErrGPGInvalidTokenSignature).ID + keyID := err.(asymkey_model.ErrGPGInvalidTokenSignature).ID + ctx.Data["KeyID"] = keyID + ctx.Data["PaddedKeyID"] = asymkey_model.PaddedKeyID(keyID) ctx.RenderWithErr(ctx.Tr("settings.gpg_invalid_token_signature"), tplSettingsKeys, &form) default: ctx.ServerError("VerifyGPG", err) diff --git a/routers/web/user/stop_watch.go b/routers/web/user/stop_watch.go index 26c7558c115e..d262c777c30f 100644 --- a/routers/web/user/stop_watch.go +++ b/routers/web/user/stop_watch.go @@ -9,7 +9,7 @@ import ( "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" + "code.gitea.io/gitea/services/convert" ) // GetStopwatches get all stopwatches diff --git a/services/auth/basic.go b/services/auth/basic.go index 839aaa7a4ed6..5fb80703ab5a 100644 --- a/services/auth/basic.go +++ b/services/auth/basic.go @@ -40,20 +40,20 @@ func (b *Basic) Name() string { // "Authorization" header of the request and returns the corresponding user object for that // name/token on successful validation. // Returns nil if header is empty or validation fails. -func (b *Basic) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *user_model.User { +func (b *Basic) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) (*user_model.User, error) { // Basic authentication should only fire on API, Download or on Git or LFSPaths if !middleware.IsAPIPath(req) && !isContainerPath(req) && !isAttachmentDownload(req) && !isGitRawReleaseOrLFSPath(req) { - return nil + return nil, nil } baHead := req.Header.Get("Authorization") if len(baHead) == 0 { - return nil + return nil, nil } auths := strings.SplitN(baHead, " ", 2) if len(auths) != 2 || (strings.ToLower(auths[0]) != "basic") { - return nil + return nil, nil } uname, passwd, _ := base.BasicAuthDecode(auths[1]) @@ -77,11 +77,11 @@ func (b *Basic) Verify(req *http.Request, w http.ResponseWriter, store DataStore u, err := user_model.GetUserByID(req.Context(), uid) if err != nil { log.Error("GetUserByID: %v", err) - return nil + return nil, err } store.GetData()["IsApiToken"] = true - return u + return u, nil } token, err := auth_model.GetAccessTokenBySHA(authToken) @@ -90,7 +90,7 @@ func (b *Basic) Verify(req *http.Request, w http.ResponseWriter, store DataStore u, err := user_model.GetUserByID(req.Context(), token.UID) if err != nil { log.Error("GetUserByID: %v", err) - return nil + return nil, err } token.UpdatedUnix = timeutil.TimeStampNow() @@ -99,13 +99,13 @@ func (b *Basic) Verify(req *http.Request, w http.ResponseWriter, store DataStore } store.GetData()["IsApiToken"] = true - return u + return u, nil } else if !auth_model.IsErrAccessTokenNotExist(err) && !auth_model.IsErrAccessTokenEmpty(err) { log.Error("GetAccessTokenBySha: %v", err) } if !setting.Service.EnableBasicAuth { - return nil + return nil, nil } log.Trace("Basic Authorization: Attempting SignIn for %s", uname) @@ -114,7 +114,7 @@ func (b *Basic) Verify(req *http.Request, w http.ResponseWriter, store DataStore if !user_model.IsErrUserNotExist(err) { log.Error("UserSignIn: %v", err) } - return nil + return nil, err } if skipper, ok := source.Cfg.(LocalTwoFASkipper); ok && skipper.IsSkipLocalTwoFA() { @@ -123,5 +123,5 @@ func (b *Basic) Verify(req *http.Request, w http.ResponseWriter, store DataStore log.Trace("Basic Authorization: Logged in user %-v", u) - return u + return u, nil } diff --git a/services/auth/group.go b/services/auth/group.go index a9112029c54c..0a0330b3aa95 100644 --- a/services/auth/group.go +++ b/services/auth/group.go @@ -9,7 +9,6 @@ import ( "reflect" "strings" - "code.gitea.io/gitea/models/db" user_model "code.gitea.io/gitea/models/user" ) @@ -80,23 +79,23 @@ func (b *Group) Free() error { } // Verify extracts and validates -func (b *Group) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *user_model.User { - if !db.HasEngine { - return nil - } - +func (b *Group) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) (*user_model.User, error) { // Try to sign in with each of the enabled plugins for _, ssoMethod := range b.methods { - user := ssoMethod.Verify(req, w, store, sess) + user, err := ssoMethod.Verify(req, w, store, sess) + if err != nil { + return nil, err + } + if user != nil { if store.GetData()["AuthedMethod"] == nil { if named, ok := ssoMethod.(Named); ok { store.GetData()["AuthedMethod"] = named.Name() } } - return user + return user, nil } } - return nil + return nil, nil } diff --git a/services/auth/httpsign.go b/services/auth/httpsign.go index e73db4f24807..4d52315381c3 100644 --- a/services/auth/httpsign.go +++ b/services/auth/httpsign.go @@ -39,10 +39,10 @@ func (h *HTTPSign) Name() string { // Verify extracts and validates HTTPsign from the Signature header of the request and returns // the corresponding user object on successful validation. // Returns nil if header is empty or validation fails. -func (h *HTTPSign) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *user_model.User { +func (h *HTTPSign) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) (*user_model.User, error) { sigHead := req.Header.Get("Signature") if len(sigHead) == 0 { - return nil + return nil, nil } var ( @@ -53,14 +53,14 @@ func (h *HTTPSign) Verify(req *http.Request, w http.ResponseWriter, store DataSt if len(req.Header.Get("X-Ssh-Certificate")) != 0 { // Handle Signature signed by SSH certificates if len(setting.SSH.TrustedUserCAKeys) == 0 { - return nil + return nil, nil } publicKey, err = VerifyCert(req) if err != nil { log.Debug("VerifyCert on request from %s: failed: %v", req.RemoteAddr, err) log.Warn("Failed authentication attempt from %s", req.RemoteAddr) - return nil + return nil, nil } } else { // Handle Signature signed by Public Key @@ -68,21 +68,21 @@ func (h *HTTPSign) Verify(req *http.Request, w http.ResponseWriter, store DataSt if err != nil { log.Debug("VerifyPubKey on request from %s: failed: %v", req.RemoteAddr, err) log.Warn("Failed authentication attempt from %s", req.RemoteAddr) - return nil + return nil, nil } } u, err := user_model.GetUserByID(req.Context(), publicKey.OwnerID) if err != nil { log.Error("GetUserByID: %v", err) - return nil + return nil, err } store.GetData()["IsApiToken"] = true log.Trace("HTTP Sign: Logged in user %-v", u) - return u + return u, nil } func VerifyPubKey(r *http.Request) (*asymkey_model.PublicKey, error) { diff --git a/services/auth/interface.go b/services/auth/interface.go index d238a408560b..f2f1aaf39cb0 100644 --- a/services/auth/interface.go +++ b/services/auth/interface.go @@ -24,8 +24,9 @@ type Method interface { // If verification is successful returns either an existing user object (with id > 0) // or a new user object (with id = 0) populated with the information that was found // in the authentication data (username or email). - // Returns nil if verification fails. - Verify(http *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *user_model.User + // Second argument returns err if verification fails, otherwise + // First return argument returns nil if no matched verification condition + Verify(http *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) (*user_model.User, error) } // Initializable represents a structure that requires initialization diff --git a/services/auth/oauth2.go b/services/auth/oauth2.go index 7aea3eadf36d..c0a8250e9547 100644 --- a/services/auth/oauth2.go +++ b/services/auth/oauth2.go @@ -108,18 +108,14 @@ func (o *OAuth2) userIDFromToken(req *http.Request, store DataStore) int64 { // or the "Authorization" header and returns the corresponding user object for that ID. // If verification is successful returns an existing user object. // Returns nil if verification fails. -func (o *OAuth2) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *user_model.User { - if !db.HasEngine { - return nil - } - +func (o *OAuth2) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) (*user_model.User, error) { if !middleware.IsAPIPath(req) && !isAttachmentDownload(req) && !isAuthenticatedTokenRequest(req) { - return nil + return nil, nil } id := o.userIDFromToken(req, store) if id <= 0 { - return nil + return nil, nil } log.Trace("OAuth2 Authorization: Found token for user[%d]", id) @@ -128,11 +124,11 @@ func (o *OAuth2) Verify(req *http.Request, w http.ResponseWriter, store DataStor if !user_model.IsErrUserNotExist(err) { log.Error("GetUserByName: %v", err) } - return nil + return nil, err } log.Trace("OAuth2 Authorization: Logged in user %-v", user) - return user + return user, nil } func isAuthenticatedTokenRequest(req *http.Request) bool { diff --git a/services/auth/reverseproxy.go b/services/auth/reverseproxy.go index 2d5b6611b58c..0206ccdf667d 100644 --- a/services/auth/reverseproxy.go +++ b/services/auth/reverseproxy.go @@ -51,10 +51,10 @@ func (r *ReverseProxy) Name() string { // If a username is available in the "setting.ReverseProxyAuthUser" header an existing // user object is returned (populated with username or email found in header). // Returns nil if header is empty. -func (r *ReverseProxy) getUserFromAuthUser(req *http.Request) *user_model.User { +func (r *ReverseProxy) getUserFromAuthUser(req *http.Request) (*user_model.User, error) { username := r.getUserName(req) if len(username) == 0 { - return nil + return nil, nil } log.Trace("ReverseProxy Authorization: Found username: %s", username) @@ -62,11 +62,11 @@ func (r *ReverseProxy) getUserFromAuthUser(req *http.Request) *user_model.User { if err != nil { if !user_model.IsErrUserNotExist(err) || !r.isAutoRegisterAllowed() { log.Error("GetUserByName: %v", err) - return nil + return nil, err } user = r.newUser(req) } - return user + return user, nil } // getEmail extracts the email from the "setting.ReverseProxyAuthEmail" header @@ -106,12 +106,15 @@ func (r *ReverseProxy) getUserFromAuthEmail(req *http.Request) *user_model.User // First it will attempt to load it based on the username (see docs for getUserFromAuthUser), // and failing that it will attempt to load it based on the email (see docs for getUserFromAuthEmail). // Returns nil if the headers are empty or the user is not found. -func (r *ReverseProxy) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *user_model.User { - user := r.getUserFromAuthUser(req) +func (r *ReverseProxy) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) (*user_model.User, error) { + user, err := r.getUserFromAuthUser(req) + if err != nil { + return nil, err + } if user == nil { user = r.getUserFromAuthEmail(req) if user == nil { - return nil + return nil, nil } } @@ -124,7 +127,7 @@ func (r *ReverseProxy) Verify(req *http.Request, w http.ResponseWriter, store Da store.GetData()["IsReverseProxy"] = true log.Trace("ReverseProxy Authorization: Logged in user %-v", user) - return user + return user, nil } // isAutoRegisterAllowed checks if EnableReverseProxyAutoRegister setting is true diff --git a/services/auth/session.go b/services/auth/session.go index ef2c35d58a19..c75113573810 100644 --- a/services/auth/session.go +++ b/services/auth/session.go @@ -29,12 +29,12 @@ func (s *Session) Name() string { // Verify checks if there is a user uid stored in the session and returns the user // object for that uid. // Returns nil if there is no user uid stored in the session. -func (s *Session) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *user_model.User { +func (s *Session) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) (*user_model.User, error) { user := SessionUser(sess) if user != nil { - return user + return user, nil } - return nil + return nil, nil } // SessionUser returns the user object corresponding to the "uid" session variable. diff --git a/services/auth/sspi_windows.go b/services/auth/sspi_windows.go index 988afb473034..045834b6911a 100644 --- a/services/auth/sspi_windows.go +++ b/services/auth/sspi_windows.go @@ -77,15 +77,15 @@ func (s *SSPI) Free() error { // If authentication is successful, returns the corresponding user object. // If negotiation should continue or authentication fails, immediately returns a 401 HTTP // response code, as required by the SPNEGO protocol. -func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *user_model.User { +func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) (*user_model.User, error) { if !s.shouldAuthenticate(req) { - return nil + return nil, nil } cfg, err := s.getConfig() if err != nil { log.Error("could not get SSPI config: %v", err) - return nil + return nil, err } log.Trace("SSPI Authorization: Attempting to authenticate") @@ -108,7 +108,7 @@ func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore, log.Error("%v", err) } - return nil + return nil, err } if outToken != "" { sspiAuth.AppendAuthenticateHeader(w, outToken) @@ -116,7 +116,7 @@ func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore, username := sanitizeUsername(userInfo.Username, cfg) if len(username) == 0 { - return nil + return nil, nil } log.Info("Authenticated as %s\n", username) @@ -124,16 +124,16 @@ func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore, if err != nil { if !user_model.IsErrUserNotExist(err) { log.Error("GetUserByName: %v", err) - return nil + return nil, err } if !cfg.AutoCreateUsers { log.Error("User '%s' not found", username) - return nil + return nil, nil } user, err = s.newUser(username, cfg) if err != nil { log.Error("CreateUser: %v", err) - return nil + return nil, err } } @@ -143,7 +143,7 @@ func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore, } log.Trace("SSPI Authorization: Logged in user %-v", user) - return user + return user, nil } // getConfig retrieves the SSPI configuration from login sources diff --git a/modules/convert/attachment.go b/services/convert/attachment.go similarity index 100% rename from modules/convert/attachment.go rename to services/convert/attachment.go diff --git a/modules/convert/convert.go b/services/convert/convert.go similarity index 100% rename from modules/convert/convert.go rename to services/convert/convert.go diff --git a/modules/convert/git_commit.go b/services/convert/git_commit.go similarity index 100% rename from modules/convert/git_commit.go rename to services/convert/git_commit.go diff --git a/modules/convert/git_commit_test.go b/services/convert/git_commit_test.go similarity index 100% rename from modules/convert/git_commit_test.go rename to services/convert/git_commit_test.go diff --git a/modules/convert/issue.go b/services/convert/issue.go similarity index 100% rename from modules/convert/issue.go rename to services/convert/issue.go diff --git a/modules/convert/issue_comment.go b/services/convert/issue_comment.go similarity index 100% rename from modules/convert/issue_comment.go rename to services/convert/issue_comment.go diff --git a/modules/convert/issue_test.go b/services/convert/issue_test.go similarity index 100% rename from modules/convert/issue_test.go rename to services/convert/issue_test.go diff --git a/modules/convert/main_test.go b/services/convert/main_test.go similarity index 100% rename from modules/convert/main_test.go rename to services/convert/main_test.go diff --git a/modules/convert/mirror.go b/services/convert/mirror.go similarity index 100% rename from modules/convert/mirror.go rename to services/convert/mirror.go diff --git a/modules/convert/notification.go b/services/convert/notification.go similarity index 100% rename from modules/convert/notification.go rename to services/convert/notification.go diff --git a/modules/convert/package.go b/services/convert/package.go similarity index 100% rename from modules/convert/package.go rename to services/convert/package.go diff --git a/modules/convert/pull.go b/services/convert/pull.go similarity index 100% rename from modules/convert/pull.go rename to services/convert/pull.go diff --git a/modules/convert/pull_review.go b/services/convert/pull_review.go similarity index 100% rename from modules/convert/pull_review.go rename to services/convert/pull_review.go diff --git a/modules/convert/pull_test.go b/services/convert/pull_test.go similarity index 100% rename from modules/convert/pull_test.go rename to services/convert/pull_test.go diff --git a/modules/convert/release.go b/services/convert/release.go similarity index 100% rename from modules/convert/release.go rename to services/convert/release.go diff --git a/modules/convert/repository.go b/services/convert/repository.go similarity index 100% rename from modules/convert/repository.go rename to services/convert/repository.go diff --git a/modules/convert/status.go b/services/convert/status.go similarity index 100% rename from modules/convert/status.go rename to services/convert/status.go diff --git a/modules/convert/user.go b/services/convert/user.go similarity index 100% rename from modules/convert/user.go rename to services/convert/user.go diff --git a/modules/convert/user_test.go b/services/convert/user_test.go similarity index 100% rename from modules/convert/user_test.go rename to services/convert/user_test.go diff --git a/modules/convert/utils.go b/services/convert/utils.go similarity index 100% rename from modules/convert/utils.go rename to services/convert/utils.go diff --git a/modules/convert/utils_test.go b/services/convert/utils_test.go similarity index 100% rename from modules/convert/utils_test.go rename to services/convert/utils_test.go diff --git a/modules/convert/wiki.go b/services/convert/wiki.go similarity index 100% rename from modules/convert/wiki.go rename to services/convert/wiki.go diff --git a/services/lfs/locks.go b/services/lfs/locks.go index 0dc51f063c8f..d5fe3f4e314c 100644 --- a/services/lfs/locks.go +++ b/services/lfs/locks.go @@ -11,12 +11,12 @@ import ( git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/json" lfs_module "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/services/convert" ) func handleLockListOut(ctx *context.Context, repo *repo_model.Repository, lock *git_model.LFSLock, err error) { diff --git a/services/packages/auth.go b/services/packages/auth.go index 9b84ac79a6c3..a7acdaf1c3a9 100644 --- a/services/packages/auth.go +++ b/services/packages/auth.go @@ -10,6 +10,7 @@ import ( "time" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "github.com/golang-jwt/jwt/v4" @@ -41,9 +42,15 @@ func CreateAuthorizationToken(u *user_model.User) (string, error) { } func ParseAuthorizationToken(req *http.Request) (int64, error) { - parts := strings.SplitN(req.Header.Get("Authorization"), " ", 2) + h := req.Header.Get("Authorization") + if h == "" { + return 0, nil + } + + parts := strings.SplitN(h, " ", 2) if len(parts) != 2 { - return 0, fmt.Errorf("no token") + log.Error("split token failed: %s", h) + return 0, fmt.Errorf("split token failed") } token, err := jwt.ParseWithClaims(parts[1], &packageClaims{}, func(t *jwt.Token) (interface{}, error) { diff --git a/services/pull/check.go b/services/pull/check.go index ed4b18107caf..86460cd49cad 100644 --- a/services/pull/check.go +++ b/services/pull/check.go @@ -199,19 +199,19 @@ func getMergeCommit(ctx context.Context, pr *issues_model.PullRequest) (*git.Com return nil, fmt.Errorf("ReadFile(%s): %w", headFile, err) } commitID := string(commitIDBytes) - if len(commitID) < 40 { + if len(commitID) < git.SHAFullLength { return nil, fmt.Errorf(`ReadFile(%s): invalid commit-ID "%s"`, headFile, commitID) } - cmd := commitID[:40] + ".." + pr.BaseBranch + cmd := commitID[:git.SHAFullLength] + ".." + pr.BaseBranch // Get the commit from BaseBranch where the pull request got merged mergeCommit, _, err := git.NewCommand(ctx, "rev-list", "--ancestry-path", "--merges", "--reverse").AddDynamicArguments(cmd). RunStdString(&git.RunOpts{Dir: "", Env: []string{"GIT_INDEX_FILE=" + indexTmpPath, "GIT_DIR=" + pr.BaseRepo.RepoPath()}}) if err != nil { return nil, fmt.Errorf("git rev-list --ancestry-path --merges --reverse: %w", err) - } else if len(mergeCommit) < 40 { + } else if len(mergeCommit) < git.SHAFullLength { // PR was maybe fast-forwarded, so just use last commit of PR - mergeCommit = commitID[:40] + mergeCommit = commitID[:git.SHAFullLength] } gitRepo, err := git.OpenRepository(ctx, pr.BaseRepo.RepoPath()) @@ -220,9 +220,9 @@ func getMergeCommit(ctx context.Context, pr *issues_model.PullRequest) (*git.Com } defer gitRepo.Close() - commit, err := gitRepo.GetCommit(mergeCommit[:40]) + commit, err := gitRepo.GetCommit(mergeCommit[:git.SHAFullLength]) if err != nil { - return nil, fmt.Errorf("GetMergeCommit[%v]: %w", mergeCommit[:40], err) + return nil, fmt.Errorf("GetMergeCommit[%v]: %w", mergeCommit[:git.SHAFullLength], err) } return commit, nil diff --git a/services/pull/merge.go b/services/pull/merge.go index 1c42c1c17b8b..7a936163f1fe 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -39,19 +39,19 @@ import ( ) // GetDefaultMergeMessage returns default message used when merging pull request -func GetDefaultMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr *issues_model.PullRequest, mergeStyle repo_model.MergeStyle) (string, error) { +func GetDefaultMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr *issues_model.PullRequest, mergeStyle repo_model.MergeStyle) (message, body string, err error) { if err := pr.LoadHeadRepo(ctx); err != nil { - return "", err + return "", "", err } if err := pr.LoadBaseRepo(ctx); err != nil { - return "", err + return "", "", err } if pr.BaseRepo == nil { - return "", repo_model.ErrRepoNotExist{ID: pr.BaseRepoID} + return "", "", repo_model.ErrRepoNotExist{ID: pr.BaseRepoID} } if err := pr.LoadIssue(ctx); err != nil { - return "", err + return "", "", err } isExternalTracker := pr.BaseRepo.UnitEnabled(ctx, unit.TypeExternalTracker) @@ -64,12 +64,12 @@ func GetDefaultMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr templateFilepath := fmt.Sprintf(".gitea/default_merge_message/%s_TEMPLATE.md", strings.ToUpper(string(mergeStyle))) commit, err := baseGitRepo.GetBranchCommit(pr.BaseRepo.DefaultBranch) if err != nil { - return "", err + return "", "", err } templateContent, err := commit.GetFileContent(templateFilepath, setting.Repository.PullRequest.DefaultMergeMessageSize) if err != nil { if !git.IsErrNotExist(err) { - return "", err + return "", "", err } } else { vars := map[string]string{ @@ -107,27 +107,35 @@ func GetDefaultMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr vars["ClosingIssues"] = "" } } - - return os.Expand(templateContent, func(s string) string { - return vars[s] - }), nil + message, body = expandDefaultMergeMessage(templateContent, vars) + return message, body, nil } } // Squash merge has a different from other styles. if mergeStyle == repo_model.MergeStyleSquash { - return fmt.Sprintf("%s (%s%d)", pr.Issue.Title, issueReference, pr.Issue.Index), nil + return fmt.Sprintf("%s (%s%d)", pr.Issue.Title, issueReference, pr.Issue.Index), "", nil } if pr.BaseRepoID == pr.HeadRepoID { - return fmt.Sprintf("Merge pull request '%s' (%s%d) from %s into %s", pr.Issue.Title, issueReference, pr.Issue.Index, pr.HeadBranch, pr.BaseBranch), nil + return fmt.Sprintf("Merge pull request '%s' (%s%d) from %s into %s", pr.Issue.Title, issueReference, pr.Issue.Index, pr.HeadBranch, pr.BaseBranch), "", nil } if pr.HeadRepo == nil { - return fmt.Sprintf("Merge pull request '%s' (%s%d) from :%s into %s", pr.Issue.Title, issueReference, pr.Issue.Index, pr.HeadBranch, pr.BaseBranch), nil + return fmt.Sprintf("Merge pull request '%s' (%s%d) from :%s into %s", pr.Issue.Title, issueReference, pr.Issue.Index, pr.HeadBranch, pr.BaseBranch), "", nil } - return fmt.Sprintf("Merge pull request '%s' (%s%d) from %s:%s into %s", pr.Issue.Title, issueReference, pr.Issue.Index, pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseBranch), nil + return fmt.Sprintf("Merge pull request '%s' (%s%d) from %s:%s into %s", pr.Issue.Title, issueReference, pr.Issue.Index, pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseBranch), "", nil +} + +func expandDefaultMergeMessage(template string, vars map[string]string) (message, body string) { + message = strings.TrimSpace(template) + if splits := strings.SplitN(message, "\n", 2); len(splits) == 2 { + message = splits[0] + body = strings.TrimSpace(splits[1]) + } + mapping := func(s string) string { return vars[s] } + return os.Expand(message, mapping), os.Expand(body, mapping) } // Merge merges pull request to base repository. @@ -839,7 +847,7 @@ func MergedManually(pr *issues_model.PullRequest, doer *user_model.User, baseGit return models.ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: repo_model.MergeStyleManuallyMerged} } - if len(commitID) < 40 { + if len(commitID) < git.SHAFullLength { return fmt.Errorf("Wrong commit ID") } diff --git a/services/pull/merge_test.go b/services/pull/merge_test.go new file mode 100644 index 000000000000..6df6f55d4611 --- /dev/null +++ b/services/pull/merge_test.go @@ -0,0 +1,67 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package pull + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_expandDefaultMergeMessage(t *testing.T) { + type args struct { + template string + vars map[string]string + } + tests := []struct { + name string + args args + want string + wantBody string + }{ + { + name: "single line", + args: args{ + template: "Merge ${PullRequestTitle}", + vars: map[string]string{ + "PullRequestTitle": "PullRequestTitle", + "PullRequestDescription": "Pull\nRequest\nDescription\n", + }, + }, + want: "Merge PullRequestTitle", + wantBody: "", + }, + { + name: "multiple lines", + args: args{ + template: "Merge ${PullRequestTitle}\nDescription:\n\n${PullRequestDescription}\n", + vars: map[string]string{ + "PullRequestTitle": "PullRequestTitle", + "PullRequestDescription": "Pull\nRequest\nDescription\n", + }, + }, + want: "Merge PullRequestTitle", + wantBody: "Description:\n\nPull\nRequest\nDescription\n", + }, + { + name: "leading newlines", + args: args{ + template: "\n\n\nMerge ${PullRequestTitle}\n\n\nDescription:\n\n${PullRequestDescription}\n", + vars: map[string]string{ + "PullRequestTitle": "PullRequestTitle", + "PullRequestDescription": "Pull\nRequest\nDescription\n", + }, + }, + want: "Merge PullRequestTitle", + wantBody: "Description:\n\nPull\nRequest\nDescription\n", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, got1 := expandDefaultMergeMessage(tt.args.template, tt.args.vars) + assert.Equalf(t, tt.want, got, "expandDefaultMergeMessage(%v, %v)", tt.args.template, tt.args.vars) + assert.Equalf(t, tt.wantBody, got1, "expandDefaultMergeMessage(%v, %v)", tt.args.template, tt.args.vars) + }) + } +} diff --git a/services/pull/pull_test.go b/services/pull/pull_test.go index cbbdccce9c07..d63227a7d5e9 100644 --- a/services/pull/pull_test.go +++ b/services/pull/pull_test.go @@ -45,13 +45,13 @@ func TestPullRequest_GetDefaultMergeMessage_InternalTracker(t *testing.T) { assert.NoError(t, err) defer gitRepo.Close() - mergeMessage, err := GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") + mergeMessage, _, err := GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") assert.NoError(t, err) assert.Equal(t, "Merge pull request 'issue3' (#3) from branch2 into master", mergeMessage) pr.BaseRepoID = 1 pr.HeadRepoID = 2 - mergeMessage, err = GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") + mergeMessage, _, err = GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") assert.NoError(t, err) assert.Equal(t, "Merge pull request 'issue3' (#3) from user2/repo1:branch2 into master", mergeMessage) } @@ -75,7 +75,7 @@ func TestPullRequest_GetDefaultMergeMessage_ExternalTracker(t *testing.T) { assert.NoError(t, err) defer gitRepo.Close() - mergeMessage, err := GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") + mergeMessage, _, err := GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") assert.NoError(t, err) assert.Equal(t, "Merge pull request 'issue3' (!3) from branch2 into master", mergeMessage) @@ -84,7 +84,7 @@ func TestPullRequest_GetDefaultMergeMessage_ExternalTracker(t *testing.T) { pr.HeadRepoID = 2 pr.BaseRepo = nil pr.HeadRepo = nil - mergeMessage, err = GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") + mergeMessage, _, err = GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") assert.NoError(t, err) assert.Equal(t, "Merge pull request 'issue3' (#3) from user2/repo2:branch2 into master", mergeMessage) diff --git a/services/pull/temp_repo.go b/services/pull/temp_repo.go index 842719467f36..d49a15cea00a 100644 --- a/services/pull/temp_repo.go +++ b/services/pull/temp_repo.go @@ -166,7 +166,7 @@ func createTemporaryRepo(ctx context.Context, pr *issues_model.PullRequest) (str var headBranch string if pr.Flow == issues_model.PullRequestFlowGithub { headBranch = git.BranchPrefix + pr.HeadBranch - } else if len(pr.HeadCommitID) == 40 { // for not created pull request + } else if len(pr.HeadCommitID) == git.SHAFullLength { // for not created pull request headBranch = pr.HeadCommitID } else { headBranch = pr.GetGitRefName() diff --git a/services/repository/files/commit.go b/services/repository/files/commit.go index c49b03d60854..74f9eb868d00 100644 --- a/services/repository/files/commit.go +++ b/services/repository/files/commit.go @@ -29,9 +29,12 @@ func CreateCommitStatus(ctx context.Context, repo *repo_model.Repository, creato } defer closer.Close() - if _, err := gitRepo.GetCommit(sha); err != nil { + if commit, err := gitRepo.GetCommit(sha); err != nil { gitRepo.Close() return fmt.Errorf("GetCommit[%s]: %w", sha, err) + } else if len(sha) != git.SHAFullLength { + // use complete commit sha + sha = commit.ID.String() } gitRepo.Close() diff --git a/services/repository/files/tree.go b/services/repository/files/tree.go index 1aa6d0df36de..f4304ea6306e 100644 --- a/services/repository/files/tree.go +++ b/services/repository/files/tree.go @@ -49,7 +49,7 @@ func GetTreeBySHA(ctx context.Context, repo *repo_model.Repository, gitRepo *git copy(treeURL[apiURLLen:], "/git/trees/") // 40 is the size of the sha1 hash in hexadecimal format. - copyPos := len(treeURL) - 40 + copyPos := len(treeURL) - git.SHAFullLength if perPage <= 0 || perPage > setting.API.DefaultGitTreesPerPage { perPage = setting.API.DefaultGitTreesPerPage diff --git a/services/repository/fork.go b/services/repository/fork.go index 3ed0f4ffa516..ad534be887f1 100644 --- a/services/repository/fork.go +++ b/services/repository/fork.go @@ -51,6 +51,13 @@ type ForkRepoOptions struct { // ForkRepository forks a repository func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts ForkRepoOptions) (*repo_model.Repository, error) { + // Fork is prohibited, if user has reached maximum limit of repositories + if !owner.CanForkRepo() { + return nil, repo_model.ErrReachLimitOfRepo{ + Limit: owner.MaxRepoCreation, + } + } + forkedRepo, err := repo_model.GetUserFork(ctx, opts.BaseRepo.ID, owner.ID) if err != nil { return nil, err diff --git a/services/repository/fork_test.go b/services/repository/fork_test.go index c809ed4529ce..452798b25b49 100644 --- a/services/repository/fork_test.go +++ b/services/repository/fork_test.go @@ -10,6 +10,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/setting" "github.com/stretchr/testify/assert" ) @@ -29,4 +30,19 @@ func TestForkRepository(t *testing.T) { assert.Nil(t, fork) assert.Error(t, err) assert.True(t, IsErrForkAlreadyExist(err)) + + // user not reached maximum limit of repositories + assert.False(t, repo_model.IsErrReachLimitOfRepo(err)) + + // change AllowForkWithoutMaximumLimit to false for the test + setting.Repository.AllowForkWithoutMaximumLimit = false + // user has reached maximum limit of repositories + user.MaxRepoCreation = 0 + fork2, err := ForkRepository(git.DefaultContext, user, user, ForkRepoOptions{ + BaseRepo: repo, + Name: "test", + Description: "test", + }) + assert.Nil(t, fork2) + assert.True(t, repo_model.IsErrReachLimitOfRepo(err)) } diff --git a/templates/admin/packages/list.tmpl b/templates/admin/packages/list.tmpl index 3aab2873c6b7..c39f5fc12881 100644 --- a/templates/admin/packages/list.tmpl +++ b/templates/admin/packages/list.tmpl @@ -13,18 +13,9 @@ diff --git a/templates/package/shared/list.tmpl b/templates/package/shared/list.tmpl index 37c47cef335d..ec2e88c8541d 100644 --- a/templates/package/shared/list.tmpl +++ b/templates/package/shared/list.tmpl @@ -6,18 +6,9 @@ diff --git a/templates/repo/issue/view_content/pull.tmpl b/templates/repo/issue/view_content/pull.tmpl index d68f3e541439..665f78205386 100644 --- a/templates/repo/issue/view_content/pull.tmpl +++ b/templates/repo/issue/view_content/pull.tmpl @@ -343,7 +343,8 @@ (() => { const defaultMergeTitle = {{.DefaultMergeMessage}}; const defaultSquashMergeTitle = {{.DefaultSquashMergeMessage}}; - const defaultMergeMessage = 'Reviewed-on: ' + {{$.Issue.HTMLURL}} + '\n' + {{$approvers}}; + const defaultMergeMessage = {{if .DefaultMergeBody}}{{.DefaultMergeBody}}{{else}}'Reviewed-on: ' + {{$.Issue.HTMLURL}} + '\n' + {{$approvers}}{{end}}; + const defaultSquashMergeMessage = {{if .DefaultSquashMergeBody}}{{.DefaultSquashMergeBody}}{{else}}'Reviewed-on: ' + {{$.Issue.HTMLURL}} + '\n' + {{$approvers}}{{end}}; const mergeForm = { 'baseLink': {{.Link}}, 'textCancel': {{$.locale.Tr "cancel"}}, @@ -398,7 +399,7 @@ 'allowed': {{$prUnit.PullRequestsConfig.AllowSquash}}, 'textDoMerge': {{$.locale.Tr "repo.pulls.squash_merge_pull_request"}}, 'mergeTitleFieldText': defaultSquashMergeTitle, - 'mergeMessageFieldText': {{.GetCommitMessages}} + defaultMergeMessage, + 'mergeMessageFieldText': {{.GetCommitMessages}} + defaultSquashMergeMessage, 'hideAutoMerge': generalHideAutoMerge, }, { diff --git a/templates/repo/pulls/fork.tmpl b/templates/repo/pulls/fork.tmpl index 28ba8e2e2527..4e20642cf612 100644 --- a/templates/repo/pulls/fork.tmpl +++ b/templates/repo/pulls/fork.tmpl @@ -58,7 +58,7 @@
-
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index c86c6744deec..c2232825966d 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -15376,6 +15376,10 @@ "remote_username": { "type": "string", "x-go-name": "RemoteUsername" + }, + "sync_on_commit": { + "type": "boolean", + "x-go-name": "SyncOnCommit" } }, "x-go-package": "code.gitea.io/gitea/modules/structs" @@ -18576,6 +18580,10 @@ "repo_name": { "type": "string", "x-go-name": "RepoName" + }, + "sync_on_commit": { + "type": "boolean", + "x-go-name": "SyncOnCommit" } }, "x-go-package": "code.gitea.io/gitea/modules/structs" diff --git a/templates/user/settings/keys_gpg.tmpl b/templates/user/settings/keys_gpg.tmpl index fe6c0bbeb1f7..0968069c3a0a 100644 --- a/templates/user/settings/keys_gpg.tmpl +++ b/templates/user/settings/keys_gpg.tmpl @@ -18,7 +18,7 @@

{{.locale.Tr "settings.gpg_token_required"}}

-