diff --git a/contrib/environment-to-ini/environment-to-ini.go b/contrib/environment-to-ini/environment-to-ini.go index 230ed58269..e472384a95 100644 --- a/contrib/environment-to-ini/environment-to-ini.go +++ b/contrib/environment-to-ini/environment-to-ini.go @@ -5,7 +5,6 @@ package main import ( "os" - "strings" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -13,9 +12,6 @@ import ( "github.com/urfave/cli" ) -// EnvironmentPrefix environment variables prefixed with this represent ini values to write -const EnvironmentPrefix = "GITEA" - func main() { app := cli.NewApp() app.Name = "environment-to-ini" @@ -70,15 +66,6 @@ func main() { Value: "", Usage: "Destination file to write to", }, - cli.BoolFlag{ - Name: "clear", - Usage: "Clears the matched variables from the environment", - }, - cli.StringFlag{ - Name: "prefix, p", - Value: EnvironmentPrefix, - Usage: "Environment prefix to look for - will be suffixed by __ (2 underscores)", - }, } app.Action = runEnvironmentToIni err := app.Run(os.Args) @@ -99,9 +86,7 @@ func runEnvironmentToIni(c *cli.Context) error { log.Fatal("Failed to load custom conf '%s': %v", setting.CustomConf, err) } - prefixGitea := c.String("prefix") + "__" - suffixFile := "__FILE" - changed := setting.EnvironmentToConfig(cfg, prefixGitea, suffixFile, os.Environ()) + changed := setting.EnvironmentToConfig(cfg, os.Environ()) // try to save the config file destination := c.String("out") @@ -116,19 +101,5 @@ func runEnvironmentToIni(c *cli.Context) error { } } - // clear Gitea's specific environment variables if requested - if c.Bool("clear") { - for _, kv := range os.Environ() { - idx := strings.IndexByte(kv, '=') - if idx < 0 { - continue - } - eKey := kv[:idx] - if strings.HasPrefix(eKey, prefixGitea) { - _ = os.Unsetenv(eKey) - } - } - } - return nil } diff --git a/docker/root/usr/local/bin/gitea b/docker/root/usr/local/bin/gitea index 24d3f91eb1..3f78d65abd 100644 --- a/docker/root/usr/local/bin/gitea +++ b/docker/root/usr/local/bin/gitea @@ -8,7 +8,7 @@ # # And place the original in /usr/lib/gitea with working files in /data/gitea GITEA="/app/gitea/gitea" -WORK_DIR="/app/gitea" +WORK_DIR="/data/gitea" CUSTOM_PATH="/data/gitea" # Provide docker defaults diff --git a/docs/content/doc/installation/with-docker-rootless.en-us.md b/docs/content/doc/installation/with-docker-rootless.en-us.md index b8b40fcbd7..5aa4e46e12 100644 --- a/docs/content/doc/installation/with-docker-rootless.en-us.md +++ b/docs/content/doc/installation/with-docker-rootless.en-us.md @@ -288,7 +288,7 @@ docker-compose up -d In addition to the environment variables above, any settings in `app.ini` can be set or overridden with an environment variable of the form: `GITEA__SECTION_NAME__KEY_NAME`. -These settings are applied each time the docker container starts. +These settings are applied each time the docker container starts, and won't be passed into Gitea's sub-processes. Full information [here](https://github.com/go-gitea/gitea/tree/main/contrib/environment-to-ini). These environment variables can be passed to the docker container in `docker-compose.yml`. diff --git a/docs/content/doc/installation/with-docker.en-us.md b/docs/content/doc/installation/with-docker.en-us.md index e70a6ab133..a7a575293d 100644 --- a/docs/content/doc/installation/with-docker.en-us.md +++ b/docs/content/doc/installation/with-docker.en-us.md @@ -289,7 +289,7 @@ docker-compose up -d In addition to the environment variables above, any settings in `app.ini` can be set or overridden with an environment variable of the form: `GITEA__SECTION_NAME__KEY_NAME`. -These settings are applied each time the docker container starts. +These settings are applied each time the docker container starts, and won't be passed into Gitea's sub-processes. Full information [here](https://github.com/go-gitea/gitea/tree/master/contrib/environment-to-ini). These environment variables can be passed to the docker container in `docker-compose.yml`. diff --git a/models/fixtures/org_user.yml b/models/fixtures/org_user.yml index d08f695799..8d58169a32 100644 --- a/models/fixtures/org_user.yml +++ b/models/fixtures/org_user.yml @@ -81,3 +81,21 @@ uid: 5 org_id: 23 is_public: false + +- + id: 15 + uid: 1 + org_id: 35 + is_public: true + +- + id: 16 + uid: 1 + org_id: 36 + is_public: true + +- + id: 17 + uid: 5 + org_id: 36 + is_public: true diff --git a/models/fixtures/team.yml b/models/fixtures/team.yml index aa3b36e644..65326eedbf 100644 --- a/models/fixtures/team.yml +++ b/models/fixtures/team.yml @@ -184,3 +184,36 @@ num_members: 1 includes_all_repositories: false can_create_org_repo: true + +- + id: 18 + org_id: 35 + lower_name: owners + name: Owners + authorize: 4 # owner + num_repos: 0 + num_members: 1 + includes_all_repositories: false + can_create_org_repo: true + +- + id: 19 + org_id: 36 + lower_name: owners + name: Owners + authorize: 4 # owner + num_repos: 0 + num_members: 1 + includes_all_repositories: false + can_create_org_repo: true + +- + id: 20 + org_id: 36 + lower_name: team20writepackage + name: team20writepackage + authorize: 1 + num_repos: 0 + num_members: 1 + includes_all_repositories: false + can_create_org_repo: true diff --git a/models/fixtures/team_unit.yml b/models/fixtures/team_unit.yml index 5257d2c385..5d2ba2fb6c 100644 --- a/models/fixtures/team_unit.yml +++ b/models/fixtures/team_unit.yml @@ -273,4 +273,10 @@ id: 46 team_id: 17 type: 9 # package - access_mode: 0 + access_mode: 2 + +- + id: 47 + team_id: 20 + type: 9 # package + access_mode: 2 diff --git a/models/fixtures/team_user.yml b/models/fixtures/team_user.yml index b95f76c723..feace5f2a5 100644 --- a/models/fixtures/team_user.yml +++ b/models/fixtures/team_user.yml @@ -105,3 +105,21 @@ org_id: 23 team_id: 17 uid: 5 + +- + id: 19 + org_id: 35 + team_id: 18 + uid: 1 + +- + id: 20 + org_id: 36 + team_id: 19 + uid: 1 + +- + id: 21 + org_id: 36 + team_id: 20 + uid: 5 diff --git a/models/fixtures/user.yml b/models/fixtures/user.yml index eba33a7c36..26bb7a9f4b 100644 --- a/models/fixtures/user.yml +++ b/models/fixtures/user.yml @@ -1258,3 +1258,77 @@ repo_admin_change_team_access: false theme: "" keep_activity_private: false + +- + id: 35 + lower_name: private_org35 + name: private_org35 + full_name: Private Org 35 + email: private_org35@example.com + keep_email_private: false + email_notifications_preference: enabled + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy + must_change_password: false + login_source: 0 + login_name: private_org35 + type: 1 + salt: ZogKvWdyEx + max_repo_creation: -1 + is_active: true + is_admin: false + is_restricted: false + allow_git_hook: false + allow_import_local: false + allow_create_organization: true + prohibit_login: false + avatar: avatar35 + avatar_email: private_org35@example.com + use_custom_avatar: false + num_followers: 0 + num_following: 0 + num_stars: 0 + num_repos: 0 + num_teams: 1 + num_members: 1 + visibility: 2 + repo_admin_change_team_access: false + theme: "" + keep_activity_private: false + +- + id: 36 + lower_name: limited_org36 + name: limited_org36 + full_name: Limited Org 36 + email: limited_org36@example.com + keep_email_private: false + email_notifications_preference: enabled + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy + must_change_password: false + login_source: 0 + login_name: limited_org36 + type: 1 + salt: ZogKvWdyEx + max_repo_creation: -1 + is_active: true + is_admin: false + is_restricted: false + allow_git_hook: false + allow_import_local: false + allow_create_organization: true + prohibit_login: false + avatar: avatar22 + avatar_email: limited_org36@example.com + use_custom_avatar: false + num_followers: 0 + num_following: 0 + num_stars: 0 + num_repos: 0 + num_teams: 2 + num_members: 2 + visibility: 1 + repo_admin_change_team_access: false + theme: "" + keep_activity_private: false diff --git a/models/git/branch.go b/models/git/branch.go index 97891f01eb..d57b72719c 100644 --- a/models/git/branch.go +++ b/models/git/branch.go @@ -382,7 +382,8 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to str } // FindRecentlyPushedNewBranches return at most 2 new branches pushed by the user in 6 hours which has no opened PRs created -func FindRecentlyPushedNewBranches(ctx context.Context, repoID, userID int64) (BranchList, error) { +// except the indicate branch +func FindRecentlyPushedNewBranches(ctx context.Context, repoID, userID int64, excludeBranchName string) (BranchList, error) { branches := make(BranchList, 0, 2) subQuery := builder.Select("head_branch").From("pull_request"). InnerJoin("issue", "issue.id = pull_request.issue_id"). @@ -392,6 +393,7 @@ func FindRecentlyPushedNewBranches(ctx context.Context, repoID, userID int64) (B }) err := db.GetEngine(ctx). Where("pusher_id=? AND is_deleted=?", userID, false). + And("name <> ?", excludeBranchName). And("updated_unix >= ?", time.Now().Add(-time.Hour*6).Unix()). NotIn("name", subQuery). OrderBy("branch.updated_unix DESC"). diff --git a/models/repo/attachment.go b/models/repo/attachment.go index 93b83aae8a..df3b9cd213 100644 --- a/models/repo/attachment.go +++ b/models/repo/attachment.go @@ -65,13 +65,6 @@ func (a *Attachment) DownloadURL() string { return setting.AppURL + "attachments/" + url.PathEscape(a.UUID) } -// _____ __ __ .__ __ -// / _ \_/ |__/ |______ ____ | |__ _____ ____ _____/ |_ -// / /_\ \ __\ __\__ \ _/ ___\| | \ / \_/ __ \ / \ __\ -// / | \ | | | / __ \\ \___| Y \ Y Y \ ___/| | \ | -// \____|__ /__| |__| (____ /\___ >___| /__|_| /\___ >___| /__| -// \/ \/ \/ \/ \/ \/ \/ - // ErrAttachmentNotExist represents a "AttachmentNotExist" kind of error. type ErrAttachmentNotExist struct { ID int64 diff --git a/models/repo/git.go b/models/repo/git.go index 7ae88058dc..c1af7ee960 100644 --- a/models/repo/git.go +++ b/models/repo/git.go @@ -11,7 +11,7 @@ type MergeStyle string const ( // MergeStyleMerge create merge commit MergeStyleMerge MergeStyle = "merge" - // MergeStyleRebase rebase before merging + // MergeStyleRebase rebase before merging, and fast-forward MergeStyleRebase MergeStyle = "rebase" // MergeStyleRebaseMerge rebase before merging with merge commit (--no-ff) MergeStyleRebaseMerge MergeStyle = "rebase-merge" diff --git a/modules/assetfs/layered.go b/modules/assetfs/layered.go index d032160a6f..e18a13e4aa 100644 --- a/modules/assetfs/layered.go +++ b/modules/assetfs/layered.go @@ -215,6 +215,7 @@ func (l *LayeredFS) WatchLocalChanges(ctx context.Context, callback func()) { log.Error("Unable to list directories for asset local file-system %q: %v", layer.localPath, err) continue } + layerDirs = append(layerDirs, ".") for _, dir := range layerDirs { if err = watcher.Add(util.FilePathJoinAbs(layer.localPath, dir)); err != nil { log.Error("Unable to watch directory %s: %v", dir, err) diff --git a/modules/context/package.go b/modules/context/package.go index 8e80fa66ec..be50e0a991 100644 --- a/modules/context/package.go +++ b/modules/context/package.go @@ -108,18 +108,28 @@ func determineAccessMode(ctx *Base, pkg *Package, doer *user_model.User) (perm.A if doer != nil && !doer.IsGhost() { // 1. If user is logged in, check all team packages permissions - teams, err := organization.GetUserOrgTeams(ctx, org.ID, doer.ID) + var err error + accessMode, err = org.GetOrgUserMaxAuthorizeLevel(doer.ID) if err != nil { return accessMode, err } - for _, t := range teams { - perm := t.UnitAccessMode(ctx, unit.TypePackages) - if accessMode < perm { - accessMode = perm + // If access mode is less than write check every team for more permissions + // The minimum possible access mode is read for org members + if accessMode < perm.AccessModeWrite { + teams, err := organization.GetUserOrgTeams(ctx, org.ID, doer.ID) + if err != nil { + return accessMode, err + } + for _, t := range teams { + perm := t.UnitAccessMode(ctx, unit.TypePackages) + if accessMode < perm { + accessMode = perm + } } } - } else if organization.HasOrgOrUserVisible(ctx, pkg.Owner, doer) { - // 2. If user is non-login, check if org is visible to non-login user + } + if accessMode == perm.AccessModeNone && organization.HasOrgOrUserVisible(ctx, pkg.Owner, doer) { + // 2. If user is unauthorized or no org member, check if org is visible accessMode = perm.AccessModeRead } } else { diff --git a/modules/setting/config_env.go b/modules/setting/config_env.go index 6348803705..e23b64557f 100644 --- a/modules/setting/config_env.go +++ b/modules/setting/config_env.go @@ -12,10 +12,31 @@ import ( "code.gitea.io/gitea/modules/log" ) +const ( + EnvConfigKeyPrefixGitea = "GITEA__" + EnvConfigKeySuffixFile = "__FILE" +) + const escapeRegexpString = "_0[xX](([0-9a-fA-F][0-9a-fA-F])+)_" var escapeRegex = regexp.MustCompile(escapeRegexpString) +func CollectEnvConfigKeys() (keys []string) { + for _, env := range os.Environ() { + if strings.HasPrefix(env, EnvConfigKeyPrefixGitea) { + k, _, _ := strings.Cut(env, "=") + keys = append(keys, k) + } + } + return keys +} + +func ClearEnvConfigKeys() { + for _, k := range CollectEnvConfigKeys() { + _ = os.Unsetenv(k) + } +} + // decodeEnvSectionKey will decode a portable string encoded Section__Key pair // Portable strings are considered to be of the form [A-Z0-9_]* // We will encode a disallowed value as the UTF8 byte string preceded by _0X and @@ -87,7 +108,7 @@ func decodeEnvironmentKey(prefixGitea, suffixFile, envKey string) (ok bool, sect return ok, section, key, useFileValue } -func EnvironmentToConfig(cfg ConfigProvider, prefixGitea, suffixFile string, envs []string) (changed bool) { +func EnvironmentToConfig(cfg ConfigProvider, envs []string) (changed bool) { for _, kv := range envs { idx := strings.IndexByte(kv, '=') if idx < 0 { @@ -97,7 +118,7 @@ func EnvironmentToConfig(cfg ConfigProvider, prefixGitea, suffixFile string, env // parse the environment variable to config section name and key name envKey := kv[:idx] envValue := kv[idx+1:] - ok, sectionName, keyName, useFileValue := decodeEnvironmentKey(prefixGitea, suffixFile, envKey) + ok, sectionName, keyName, useFileValue := decodeEnvironmentKey(EnvConfigKeyPrefixGitea, EnvConfigKeySuffixFile, envKey) if !ok { continue } diff --git a/modules/setting/config_env_test.go b/modules/setting/config_env_test.go index d574554bcc..2c1dd2f5c7 100644 --- a/modules/setting/config_env_test.go +++ b/modules/setting/config_env_test.go @@ -72,7 +72,7 @@ func TestDecodeEnvironmentKey(t *testing.T) { func TestEnvironmentToConfig(t *testing.T) { cfg, _ := NewConfigProviderFromData("") - changed := EnvironmentToConfig(cfg, "GITEA__", "__FILE", nil) + changed := EnvironmentToConfig(cfg, nil) assert.False(t, changed) cfg, err := NewConfigProviderFromData(` @@ -81,16 +81,16 @@ key = old `) assert.NoError(t, err) - changed = EnvironmentToConfig(cfg, "GITEA__", "__FILE", []string{"GITEA__sec__key=new"}) + changed = EnvironmentToConfig(cfg, []string{"GITEA__sec__key=new"}) assert.True(t, changed) assert.Equal(t, "new", cfg.Section("sec").Key("key").String()) - changed = EnvironmentToConfig(cfg, "GITEA__", "__FILE", []string{"GITEA__sec__key=new"}) + changed = EnvironmentToConfig(cfg, []string{"GITEA__sec__key=new"}) assert.False(t, changed) tmpFile := t.TempDir() + "/the-file" _ = os.WriteFile(tmpFile, []byte("value-from-file"), 0o644) - changed = EnvironmentToConfig(cfg, "GITEA__", "__FILE", []string{"GITEA__sec__key__FILE=" + tmpFile}) + changed = EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile}) assert.True(t, changed) assert.Equal(t, "value-from-file", cfg.Section("sec").Key("key").String()) } diff --git a/modules/setting/path.go b/modules/setting/path.go index 163f1d1590..32ed8d81fa 100644 --- a/modules/setting/path.go +++ b/modules/setting/path.go @@ -171,6 +171,9 @@ func InitWorkPathAndCfgProvider(getEnvFn func(name string) string, args ArgWorkP // only read the config but do not load/init anything more, because the AppWorkPath and CustomPath are not ready InitCfgProvider(tmpCustomConf.Value) + if HasInstallLock(CfgProvider) { + ClearEnvConfigKeys() // if the instance has been installed, do not pass the environment variables to sub-processes + } configWorkPath := ConfigSectionKeyString(CfgProvider.Section(""), "WORK_PATH") if configWorkPath != "" { if !filepath.IsAbs(configWorkPath) { diff --git a/modules/setting/security.go b/modules/setting/security.go index 5f1f9f4ade..7064d7a008 100644 --- a/modules/setting/security.go +++ b/modules/setting/security.go @@ -102,7 +102,7 @@ func generateSaveInternalToken(rootCfg ConfigProvider) { func loadSecurityFrom(rootCfg ConfigProvider) { sec := rootCfg.Section("security") - InstallLock = sec.Key("INSTALL_LOCK").MustBool(false) + InstallLock = HasInstallLock(rootCfg) LogInRememberDays = sec.Key("LOGIN_REMEMBER_DAYS").MustInt(7) CookieUserName = sec.Key("COOKIE_USERNAME").MustString("gitea_awesome") SecretKey = loadSecret(sec, "SECRET_KEY_URI", "SECRET_KEY") diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 0d69847dbe..d444d9a017 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -183,10 +183,14 @@ func loadRunModeFrom(rootCfg ConfigProvider) { } } +// HasInstallLock checks the install-lock in ConfigProvider directly, because sometimes the config file is not loaded into setting variables yet. +func HasInstallLock(rootCfg ConfigProvider) bool { + return rootCfg.Section("security").Key("INSTALL_LOCK").MustBool(false) +} + func mustCurrentRunUserMatch(rootCfg ConfigProvider) { // Does not check run user when the "InstallLock" is off. - installLock := rootCfg.Section("security").Key("INSTALL_LOCK").MustBool(false) - if installLock { + if HasInstallLock(rootCfg) { currentUser, match := IsRunUserMatchCurrentUser(RunUser) if !match { log.Fatal("Expect user '%s' but current user is: %s", RunUser, currentUser) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 99cf004538..ccf22f5d3a 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -296,6 +296,8 @@ invalid_password_algorithm = Invalid password hash algorithm password_algorithm_helper = Set the password hashing algorithm. Algorithms have differing requirements and strength. The argon2 algorithm is rather secure but uses a lot of memory and may be inappropriate for small systems. enable_update_checker = Enable Update Checker enable_update_checker_helper = Checks for new version releases periodically by connecting to gitea.io. +env_config_keys = Environment Configuration +env_config_keys_prompt = The following environment variables will also be applied to your configuration file: [home] uname_holder = Username or Email Address diff --git a/pyproject.toml b/pyproject.toml index 7a30f59140..43c6b050bb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,4 +12,4 @@ djlint = "1.31.1" [tool.djlint] profile="golang" -ignore="H005,H006,H008,H013,H014,H016,H020,H021,H023,H026,H030,H031,T027" +ignore="H005,H006,H008,H013,H016,H020,H021,H026,H030,H031,T027" diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 0e28bde683..eee97cbc20 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1034,7 +1034,7 @@ func Routes() *web.Route { m.Group("/assets", func() { m.Combo("").Get(repo.ListReleaseAttachments). Post(reqToken(), reqRepoWriter(unit.TypeReleases), repo.CreateReleaseAttachment) - m.Combo("/{asset}").Get(repo.GetReleaseAttachment). + m.Combo("/{attachment_id}").Get(repo.GetReleaseAttachment). Patch(reqToken(), reqRepoWriter(unit.TypeReleases), bind(api.EditAttachmentOptions{}), repo.EditReleaseAttachment). Delete(reqToken(), reqRepoWriter(unit.TypeReleases), repo.DeleteReleaseAttachment) }) @@ -1179,7 +1179,7 @@ func Routes() *web.Route { m.Combo(""). Get(repo.ListIssueCommentAttachments). Post(reqToken(), mustNotBeArchived, repo.CreateIssueCommentAttachment) - m.Combo("/{asset}"). + m.Combo("/{attachment_id}"). Get(repo.GetIssueCommentAttachment). Patch(reqToken(), mustNotBeArchived, bind(api.EditAttachmentOptions{}), repo.EditIssueCommentAttachment). Delete(reqToken(), mustNotBeArchived, repo.DeleteIssueCommentAttachment) @@ -1231,7 +1231,7 @@ func Routes() *web.Route { m.Combo(""). Get(repo.ListIssueAttachments). Post(reqToken(), mustNotBeArchived, repo.CreateIssueAttachment) - m.Combo("/{asset}"). + m.Combo("/{attachment_id}"). Get(repo.GetIssueAttachment). Patch(reqToken(), mustNotBeArchived, bind(api.EditAttachmentOptions{}), repo.EditIssueAttachment). Delete(reqToken(), mustNotBeArchived, repo.DeleteIssueAttachment) diff --git a/routers/api/v1/repo/issue_attachment.go b/routers/api/v1/repo/issue_attachment.go index 92e1138688..779da9fd7f 100644 --- a/routers/api/v1/repo/issue_attachment.go +++ b/routers/api/v1/repo/issue_attachment.go @@ -64,7 +64,7 @@ func GetIssueAttachment(ctx *context.APIContext) { return } - ctx.JSON(http.StatusOK, convert.ToAttachment(attach)) + ctx.JSON(http.StatusOK, convert.ToAPIAttachment(ctx.Repo.Repository, attach)) } // ListIssueAttachments lists all attachments of the issue @@ -194,7 +194,7 @@ func CreateIssueAttachment(ctx *context.APIContext) { return } - ctx.JSON(http.StatusCreated, convert.ToAttachment(attachment)) + ctx.JSON(http.StatusCreated, convert.ToAPIAttachment(ctx.Repo.Repository, attachment)) } // EditIssueAttachment updates the given attachment @@ -254,7 +254,7 @@ func EditIssueAttachment(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "UpdateAttachment", err) } - ctx.JSON(http.StatusCreated, convert.ToAttachment(attachment)) + ctx.JSON(http.StatusCreated, convert.ToAPIAttachment(ctx.Repo.Repository, attachment)) } // DeleteIssueAttachment delete a given attachment @@ -332,7 +332,7 @@ func getIssueAttachmentSafeWrite(ctx *context.APIContext) *repo_model.Attachment } func getIssueAttachmentSafeRead(ctx *context.APIContext, issue *issues_model.Issue) *repo_model.Attachment { - attachment, err := repo_model.GetAttachmentByID(ctx, ctx.ParamsInt64("asset")) + attachment, err := repo_model.GetAttachmentByID(ctx, ctx.ParamsInt64("attachment_id")) if err != nil { ctx.NotFoundOrServerError("GetAttachmentByID", repo_model.IsErrAttachmentNotExist, err) return nil diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go index 5616e255ad..c2392126db 100644 --- a/routers/api/v1/repo/issue_comment.go +++ b/routers/api/v1/repo/issue_comment.go @@ -103,7 +103,7 @@ func ListIssueComments(ctx *context.APIContext) { apiComments := make([]*api.Comment, len(comments)) for i, comment := range comments { comment.Issue = issue - apiComments[i] = convert.ToComment(ctx, comments[i]) + apiComments[i] = convert.ToAPIComment(ctx, ctx.Repo.Repository, comments[i]) } ctx.SetTotalCountHeader(totalCount) @@ -191,7 +191,7 @@ func ListIssueCommentsAndTimeline(ctx *context.APIContext) { for _, comment := range comments { if comment.Type != issues_model.CommentTypeCode && isXRefCommentAccessible(ctx, ctx.Doer, comment, issue.RepoID) { comment.Issue = issue - apiComments = append(apiComments, convert.ToTimelineComment(ctx, comment, ctx.Doer)) + apiComments = append(apiComments, convert.ToTimelineComment(ctx, issue.Repo, comment, ctx.Doer)) } } @@ -308,7 +308,7 @@ func ListRepoIssueComments(ctx *context.APIContext) { return } for i := range comments { - apiComments[i] = convert.ToComment(ctx, comments[i]) + apiComments[i] = convert.ToAPIComment(ctx, ctx.Repo.Repository, comments[i]) } ctx.SetTotalCountHeader(totalCount) @@ -368,7 +368,7 @@ func CreateIssueComment(ctx *context.APIContext) { return } - ctx.JSON(http.StatusCreated, convert.ToComment(ctx, comment)) + ctx.JSON(http.StatusCreated, convert.ToAPIComment(ctx, ctx.Repo.Repository, comment)) } // GetIssueComment Get a comment by ID @@ -436,7 +436,7 @@ func GetIssueComment(ctx *context.APIContext) { return } - ctx.JSON(http.StatusOK, convert.ToComment(ctx, comment)) + ctx.JSON(http.StatusOK, convert.ToAPIComment(ctx, ctx.Repo.Repository, comment)) } // EditIssueComment modify a comment of an issue @@ -561,7 +561,7 @@ func editIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption) return } - ctx.JSON(http.StatusOK, convert.ToComment(ctx, comment)) + ctx.JSON(http.StatusOK, convert.ToAPIComment(ctx, ctx.Repo.Repository, comment)) } // DeleteIssueComment delete a comment from an issue diff --git a/routers/api/v1/repo/issue_comment_attachment.go b/routers/api/v1/repo/issue_comment_attachment.go index 6fe4dbc977..121e3f10e0 100644 --- a/routers/api/v1/repo/issue_comment_attachment.go +++ b/routers/api/v1/repo/issue_comment_attachment.go @@ -68,7 +68,7 @@ func GetIssueCommentAttachment(ctx *context.APIContext) { return } - ctx.JSON(http.StatusOK, convert.ToAttachment(attachment)) + ctx.JSON(http.StatusOK, convert.ToAPIAttachment(ctx.Repo.Repository, attachment)) } // ListIssueCommentAttachments lists all attachments of the comment @@ -110,7 +110,7 @@ func ListIssueCommentAttachments(ctx *context.APIContext) { return } - ctx.JSON(http.StatusOK, convert.ToAttachments(comment.Attachments)) + ctx.JSON(http.StatusOK, convert.ToAPIAttachments(ctx.Repo.Repository, comment.Attachments)) } // CreateIssueCommentAttachment creates an attachment and saves the given file @@ -201,7 +201,7 @@ func CreateIssueCommentAttachment(ctx *context.APIContext) { return } - ctx.JSON(http.StatusCreated, convert.ToAttachment(attachment)) + ctx.JSON(http.StatusCreated, convert.ToAPIAttachment(ctx.Repo.Repository, attachment)) } // EditIssueCommentAttachment updates the given attachment @@ -259,7 +259,7 @@ func EditIssueCommentAttachment(ctx *context.APIContext) { if err := repo_model.UpdateAttachment(ctx, attach); err != nil { ctx.Error(http.StatusInternalServerError, "UpdateAttachment", attach) } - ctx.JSON(http.StatusCreated, convert.ToAttachment(attach)) + ctx.JSON(http.StatusCreated, convert.ToAPIAttachment(ctx.Repo.Repository, attach)) } // DeleteIssueCommentAttachment delete a given attachment @@ -352,7 +352,7 @@ func canUserWriteIssueCommentAttachment(ctx *context.APIContext, comment *issues } func getIssueCommentAttachmentSafeRead(ctx *context.APIContext, comment *issues_model.Comment) *repo_model.Attachment { - attachment, err := repo_model.GetAttachmentByID(ctx, ctx.ParamsInt64("asset")) + attachment, err := repo_model.GetAttachmentByID(ctx, ctx.ParamsInt64("attachment_id")) if err != nil { ctx.NotFoundOrServerError("GetAttachmentByID", repo_model.IsErrAttachmentNotExist, err) return nil diff --git a/routers/api/v1/repo/release.go b/routers/api/v1/repo/release.go index e9693dd053..af7199d1d6 100644 --- a/routers/api/v1/repo/release.go +++ b/routers/api/v1/repo/release.go @@ -64,7 +64,7 @@ func GetRelease(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } - ctx.JSON(http.StatusOK, convert.ToRelease(ctx, release)) + ctx.JSON(http.StatusOK, convert.ToAPIRelease(ctx, ctx.Repo.Repository, release)) } // GetLatestRelease gets the most recent non-prerelease, non-draft release of a repository, sorted by created_at @@ -105,7 +105,7 @@ func GetLatestRelease(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } - ctx.JSON(http.StatusOK, convert.ToRelease(ctx, release)) + ctx.JSON(http.StatusOK, convert.ToAPIRelease(ctx, ctx.Repo.Repository, release)) } // ListReleases list a repository's releases @@ -174,7 +174,7 @@ func ListReleases(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } - rels[i] = convert.ToRelease(ctx, release) + rels[i] = convert.ToAPIRelease(ctx, ctx.Repo.Repository, release) } filteredCount, err := repo_model.CountReleasesByRepoID(ctx.Repo.Repository.ID, opts) @@ -272,7 +272,7 @@ func CreateRelease(ctx *context.APIContext) { return } } - ctx.JSON(http.StatusCreated, convert.ToRelease(ctx, rel)) + ctx.JSON(http.StatusCreated, convert.ToAPIRelease(ctx, ctx.Repo.Repository, rel)) } // EditRelease edit a release @@ -357,7 +357,7 @@ func EditRelease(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } - ctx.JSON(http.StatusOK, convert.ToRelease(ctx, rel)) + ctx.JSON(http.StatusOK, convert.ToAPIRelease(ctx, ctx.Repo.Repository, rel)) } // DeleteRelease delete a release from a repository diff --git a/routers/api/v1/repo/release_attachment.go b/routers/api/v1/repo/release_attachment.go index 305b2808df..a7d73acceb 100644 --- a/routers/api/v1/repo/release_attachment.go +++ b/routers/api/v1/repo/release_attachment.go @@ -52,7 +52,7 @@ func GetReleaseAttachment(ctx *context.APIContext) { // "$ref": "#/responses/Attachment" releaseID := ctx.ParamsInt64(":id") - attachID := ctx.ParamsInt64(":asset") + attachID := ctx.ParamsInt64(":attachment_id") attach, err := repo_model.GetAttachmentByID(ctx, attachID) if err != nil { if repo_model.IsErrAttachmentNotExist(err) { @@ -68,7 +68,7 @@ func GetReleaseAttachment(ctx *context.APIContext) { return } // FIXME Should prove the existence of the given repo, but results in unnecessary database requests - ctx.JSON(http.StatusOK, convert.ToAttachment(attach)) + ctx.JSON(http.StatusOK, convert.ToAPIAttachment(ctx.Repo.Repository, attach)) } // ListReleaseAttachments lists all attachments of the release @@ -117,7 +117,7 @@ func ListReleaseAttachments(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } - ctx.JSON(http.StatusOK, convert.ToRelease(ctx, release).Attachments) + ctx.JSON(http.StatusOK, convert.ToAPIRelease(ctx, ctx.Repo.Repository, release).Attachments) } // CreateReleaseAttachment creates an attachment and saves the given file @@ -209,7 +209,7 @@ func CreateReleaseAttachment(ctx *context.APIContext) { return } - ctx.JSON(http.StatusCreated, convert.ToAttachment(attach)) + ctx.JSON(http.StatusCreated, convert.ToAPIAttachment(ctx.Repo.Repository, attach)) } // EditReleaseAttachment updates the given attachment @@ -256,7 +256,7 @@ func EditReleaseAttachment(ctx *context.APIContext) { // Check if release exists an load release releaseID := ctx.ParamsInt64(":id") - attachID := ctx.ParamsInt64(":asset") + attachID := ctx.ParamsInt64(":attachment_id") attach, err := repo_model.GetAttachmentByID(ctx, attachID) if err != nil { if repo_model.IsErrAttachmentNotExist(err) { @@ -279,7 +279,7 @@ func EditReleaseAttachment(ctx *context.APIContext) { if err := repo_model.UpdateAttachment(ctx, attach); err != nil { ctx.Error(http.StatusInternalServerError, "UpdateAttachment", attach) } - ctx.JSON(http.StatusCreated, convert.ToAttachment(attach)) + ctx.JSON(http.StatusCreated, convert.ToAPIAttachment(ctx.Repo.Repository, attach)) } // DeleteReleaseAttachment delete a given attachment @@ -318,7 +318,7 @@ func DeleteReleaseAttachment(ctx *context.APIContext) { // Check if release exists an load release releaseID := ctx.ParamsInt64(":id") - attachID := ctx.ParamsInt64(":asset") + attachID := ctx.ParamsInt64(":attachment_id") attach, err := repo_model.GetAttachmentByID(ctx, attachID) if err != nil { if repo_model.IsErrAttachmentNotExist(err) { diff --git a/routers/api/v1/repo/release_tags.go b/routers/api/v1/repo/release_tags.go index 051ee8f22e..a03edfafcf 100644 --- a/routers/api/v1/repo/release_tags.go +++ b/routers/api/v1/repo/release_tags.go @@ -63,7 +63,7 @@ func GetReleaseByTag(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } - ctx.JSON(http.StatusOK, convert.ToRelease(ctx, release)) + ctx.JSON(http.StatusOK, convert.ToAPIRelease(ctx, ctx.Repo.Repository, release)) } // DeleteReleaseByTag delete a release from a repository by tag name diff --git a/routers/install/install.go b/routers/install/install.go index f121f31376..a2e89d3dac 100644 --- a/routers/install/install.go +++ b/routers/install/install.go @@ -56,6 +56,7 @@ func getSupportedDbTypeNames() (dbTypeNames []map[string]string) { func Contexter() func(next http.Handler) http.Handler { rnd := templates.HTMLRenderer() dbTypeNames := getSupportedDbTypeNames() + envConfigKeys := setting.CollectEnvConfigKeys() return func(next http.Handler) http.Handler { return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { base, baseCleanUp := context.NewBaseContext(resp, req) @@ -70,11 +71,13 @@ func Contexter() func(next http.Handler) http.Handler { ctx.AppendContextValue(context.WebContextKey, ctx) ctx.Data.MergeFrom(middleware.CommonTemplateContextData()) ctx.Data.MergeFrom(middleware.ContextData{ - "locale": ctx.Locale, - "Title": ctx.Locale.Tr("install.install"), - "PageIsInstall": true, - "DbTypeNames": dbTypeNames, - "AllLangs": translation.AllLangs(), + "locale": ctx.Locale, + "Title": ctx.Locale.Tr("install.install"), + "PageIsInstall": true, + "DbTypeNames": dbTypeNames, + "EnvConfigKeys": envConfigKeys, + "CustomConfFile": setting.CustomConf, + "AllLangs": translation.AllLangs(), "PasswordHashAlgorithms": hash.RecommendedHashAlgorithms, }) @@ -218,7 +221,7 @@ func checkDatabase(ctx *context.Context, form *forms.InstallForm) bool { return false } - log.Info("User confirmed reinstallation of Gitea into a pre-existing database") + log.Info("User confirmed re-installation of Gitea into a pre-existing database") } if hasPostInstallationUser || dbMigrationVersion > 0 { @@ -502,6 +505,8 @@ func SubmitInstall(ctx *context.Context) { return } + setting.EnvironmentToConfig(cfg, os.Environ()) + if err = cfg.SaveTo(setting.CustomConf); err != nil { ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form) return @@ -568,6 +573,7 @@ func SubmitInstall(ctx *context.Context) { } } + setting.ClearEnvConfigKeys() log.Info("First-time run install finished!") InstallDone(ctx) diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 317f762fb1..31bcbd7c21 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -2058,7 +2058,7 @@ func GetIssueInfo(ctx *context.Context) { } } - ctx.JSON(http.StatusOK, convert.ToAPIIssue(ctx, issue)) + ctx.JSON(http.StatusOK, convert.ToIssue(ctx, issue)) } // UpdateIssueTitle change issue's title @@ -2563,7 +2563,7 @@ func SearchIssues(ctx *context.Context) { } ctx.SetTotalCountHeader(filteredCount) - ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues)) + ctx.JSON(http.StatusOK, convert.ToIssueList(ctx, issues)) } func getUserIDForFilter(ctx *context.Context, queryName string) int64 { @@ -2724,7 +2724,7 @@ func ListIssues(ctx *context.Context) { } ctx.SetTotalCountHeader(filteredCount) - ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues)) + ctx.JSON(http.StatusOK, convert.ToIssueList(ctx, issues)) } func BatchDeleteIssues(ctx *context.Context) { @@ -3290,7 +3290,7 @@ func GetIssueAttachments(ctx *context.Context) { } attachments := make([]*api.Attachment, len(issue.Attachments)) for i := 0; i < len(issue.Attachments); i++ { - attachments[i] = convert.ToAttachment(issue.Attachments[i]) + attachments[i] = convert.ToAttachment(ctx.Repo.Repository, issue.Attachments[i]) } ctx.JSON(http.StatusOK, attachments) } @@ -3314,7 +3314,7 @@ func GetCommentAttachments(ctx *context.Context) { return } for i := 0; i < len(comment.Attachments); i++ { - attachments = append(attachments, convert.ToAttachment(comment.Attachments[i])) + attachments = append(attachments, convert.ToAttachment(ctx.Repo.Repository, comment.Attachments[i])) } ctx.JSON(http.StatusOK, attachments) } diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index e0a618bf59..1b68ef352a 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -723,6 +723,9 @@ func ViewPullCommits(ctx *context.Context) { ctx.Data["Commits"] = commits ctx.Data["CommitCount"] = len(commits) + ctx.Data["HasIssuesOrPullsWritePermission"] = ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) + ctx.Data["IsIssuePoster"] = ctx.IsSigned && issue.IsPoster(ctx.Doer.ID) + getBranchData(ctx, issue) ctx.HTML(http.StatusOK, tplPullCommits) } diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index acea08d629..ece2ec5416 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -982,7 +982,7 @@ func renderCode(ctx *context.Context) { ctx.ServerError("GetBaseRepo", err) return } - ctx.Data["RecentlyPushedNewBranches"], err = git_model.FindRecentlyPushedNewBranches(ctx, ctx.Repo.Repository.ID, ctx.Doer.ID) + ctx.Data["RecentlyPushedNewBranches"], err = git_model.FindRecentlyPushedNewBranches(ctx, ctx.Repo.Repository.ID, ctx.Doer.ID, ctx.Repo.Repository.DefaultBranch) if err != nil { ctx.ServerError("GetRecentlyPushedBranches", err) return diff --git a/routers/web/user/notification.go b/routers/web/user/notification.go index e0aa92879f..cae12f4126 100644 --- a/routers/web/user/notification.go +++ b/routers/web/user/notification.go @@ -186,7 +186,7 @@ func NotificationStatusPost(ctx *context.Context) { if ctx.Written() { return } - ctx.Data["Link"] = setting.AppURL + "notifications" + ctx.Data["Link"] = setting.AppSubURL + "/notifications" ctx.Data["SequenceNumber"] = ctx.Req.PostFormValue("sequence-number") ctx.HTML(http.StatusOK, tplNotificationDiv) diff --git a/services/actions/notifier.go b/services/actions/notifier.go index 507eeaacf6..cfe2e284da 100644 --- a/services/actions/notifier.go +++ b/services/actions/notifier.go @@ -171,7 +171,7 @@ func (n *actionsNotifier) NotifyCreateIssueComment(ctx context.Context, doer *us WithPayload(&api.IssueCommentPayload{ Action: api.HookIssueCommentCreated, Issue: convert.ToAPIIssue(ctx, issue), - Comment: convert.ToComment(ctx, comment), + Comment: convert.ToAPIComment(ctx, repo, comment), Repository: convert.ToRepo(ctx, repo, permission), Sender: convert.ToUser(ctx, doer, nil), IsPull: true, @@ -185,7 +185,7 @@ func (n *actionsNotifier) NotifyCreateIssueComment(ctx context.Context, doer *us WithPayload(&api.IssueCommentPayload{ Action: api.HookIssueCommentCreated, Issue: convert.ToAPIIssue(ctx, issue), - Comment: convert.ToComment(ctx, comment), + Comment: convert.ToAPIComment(ctx, repo, comment), Repository: convert.ToRepo(ctx, repo, permission), Sender: convert.ToUser(ctx, doer, nil), IsPull: false, diff --git a/services/actions/notifier_helper.go b/services/actions/notifier_helper.go index c4c2a0df29..90ad3001ba 100644 --- a/services/actions/notifier_helper.go +++ b/services/actions/notifier_helper.go @@ -260,7 +260,7 @@ func notifyRelease(ctx context.Context, doer *user_model.User, rel *repo_model.R WithRef(git.RefNameFromTag(rel.TagName).String()). WithPayload(&api.ReleasePayload{ Action: action, - Release: convert.ToRelease(ctx, rel), + Release: convert.ToAPIRelease(ctx, rel.Repo, rel), Repository: convert.ToRepo(ctx, rel.Repo, permission), Sender: convert.ToUser(ctx, doer, nil), }). diff --git a/services/convert/activity.go b/services/convert/activity.go index 71a2722a49..01fef73e58 100644 --- a/services/convert/activity.go +++ b/services/convert/activity.go @@ -37,7 +37,7 @@ func ToActivity(ctx context.Context, ac *activities_model.Action, doer *user_mod if ac.Comment != nil { result.CommentID = ac.CommentID - result.Comment = ToComment(ctx, ac.Comment) + result.Comment = ToAPIComment(ctx, ac.Repo, ac.Comment) } return result diff --git a/services/convert/attachment.go b/services/convert/attachment.go index ddba181a12..ab36a1c577 100644 --- a/services/convert/attachment.go +++ b/services/convert/attachment.go @@ -4,12 +4,38 @@ package convert import ( + "strconv" + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" ) -// ToAttachment converts models.Attachment to api.Attachment -func ToAttachment(a *repo_model.Attachment) *api.Attachment { +func WebAssetDownloadURL(repo *repo_model.Repository, attach *repo_model.Attachment) string { + return attach.DownloadURL() +} + +func APIAssetDownloadURL(repo *repo_model.Repository, attach *repo_model.Attachment) string { + if attach.CustomDownloadURL != "" { + return attach.CustomDownloadURL + } + + // /repos/{owner}/{repo}/releases/{id}/assets/{attachment_id} + return setting.AppURL + "api/repos/" + repo.FullName() + "/releases/" + strconv.FormatInt(attach.ReleaseID, 10) + "/assets/" + strconv.FormatInt(attach.ID, 10) +} + +// ToAttachment converts models.Attachment to api.Attachment for API usage +func ToAttachment(repo *repo_model.Repository, a *repo_model.Attachment) *api.Attachment { + return toAttachment(repo, a, WebAssetDownloadURL) +} + +// ToAPIAttachment converts models.Attachment to api.Attachment for API usage +func ToAPIAttachment(repo *repo_model.Repository, a *repo_model.Attachment) *api.Attachment { + return toAttachment(repo, a, APIAssetDownloadURL) +} + +// toAttachment converts models.Attachment to api.Attachment for API usage +func toAttachment(repo *repo_model.Repository, a *repo_model.Attachment, getDownloadURL func(repo *repo_model.Repository, attach *repo_model.Attachment) string) *api.Attachment { return &api.Attachment{ ID: a.ID, Name: a.Name, @@ -17,14 +43,18 @@ func ToAttachment(a *repo_model.Attachment) *api.Attachment { DownloadCount: a.DownloadCount, Size: a.Size, UUID: a.UUID, - DownloadURL: a.DownloadURL(), + DownloadURL: getDownloadURL(repo, a), // for web request json and api request json, return different download urls } } -func ToAttachments(attachments []*repo_model.Attachment) []*api.Attachment { +func ToAPIAttachments(repo *repo_model.Repository, attachments []*repo_model.Attachment) []*api.Attachment { + return toAttachments(repo, attachments, APIAssetDownloadURL) +} + +func toAttachments(repo *repo_model.Repository, attachments []*repo_model.Attachment, getDownloadURL func(repo *repo_model.Repository, attach *repo_model.Attachment) string) []*api.Attachment { converted := make([]*api.Attachment, 0, len(attachments)) for _, attachment := range attachments { - converted = append(converted, ToAttachment(attachment)) + converted = append(converted, toAttachment(repo, attachment, getDownloadURL)) } return converted } diff --git a/services/convert/issue.go b/services/convert/issue.go index bcb1618e8f..d81840f025 100644 --- a/services/convert/issue.go +++ b/services/convert/issue.go @@ -19,11 +19,19 @@ import ( api "code.gitea.io/gitea/modules/structs" ) +func ToIssue(ctx context.Context, issue *issues_model.Issue) *api.Issue { + return toIssue(ctx, issue, WebAssetDownloadURL) +} + // ToAPIIssue converts an Issue to API format // it assumes some fields assigned with values: // Required - Poster, Labels, // Optional - Milestone, Assignee, PullRequest func ToAPIIssue(ctx context.Context, issue *issues_model.Issue) *api.Issue { + return toIssue(ctx, issue, APIAssetDownloadURL) +} + +func toIssue(ctx context.Context, issue *issues_model.Issue, getDownloadURL func(repo *repo_model.Repository, attach *repo_model.Attachment) string) *api.Issue { if err := issue.LoadLabels(ctx); err != nil { return &api.Issue{} } @@ -40,7 +48,7 @@ func ToAPIIssue(ctx context.Context, issue *issues_model.Issue) *api.Issue { Poster: ToUser(ctx, issue.Poster, nil), Title: issue.Title, Body: issue.Content, - Attachments: ToAttachments(issue.Attachments), + Attachments: toAttachments(issue.Repo, issue.Attachments, getDownloadURL), Ref: issue.Ref, State: issue.State(), IsLocked: issue.IsLocked, @@ -105,6 +113,15 @@ func ToAPIIssue(ctx context.Context, issue *issues_model.Issue) *api.Issue { return apiIssue } +// ToIssueList converts an IssueList to API format +func ToIssueList(ctx context.Context, il issues_model.IssueList) []*api.Issue { + result := make([]*api.Issue, len(il)) + for i := range il { + result[i] = ToIssue(ctx, il[i]) + } + return result +} + // ToAPIIssueList converts an IssueList to API format func ToAPIIssueList(ctx context.Context, il issues_model.IssueList) []*api.Issue { result := make([]*api.Issue, len(il)) diff --git a/services/convert/issue_comment.go b/services/convert/issue_comment.go index db48faa69e..b0145c38e6 100644 --- a/services/convert/issue_comment.go +++ b/services/convert/issue_comment.go @@ -14,8 +14,8 @@ import ( "code.gitea.io/gitea/modules/util" ) -// ToComment converts a issues_model.Comment to the api.Comment format -func ToComment(ctx context.Context, c *issues_model.Comment) *api.Comment { +// ToAPIComment converts a issues_model.Comment to the api.Comment format for API usage +func ToAPIComment(ctx context.Context, repo *repo_model.Repository, c *issues_model.Comment) *api.Comment { return &api.Comment{ ID: c.ID, Poster: ToUser(ctx, c.Poster, nil), @@ -23,14 +23,14 @@ func ToComment(ctx context.Context, c *issues_model.Comment) *api.Comment { IssueURL: c.IssueURL(), PRURL: c.PRURL(), Body: c.Content, - Attachments: ToAttachments(c.Attachments), + Attachments: ToAPIAttachments(repo, c.Attachments), Created: c.CreatedUnix.AsTime(), Updated: c.UpdatedUnix.AsTime(), } } // ToTimelineComment converts a issues_model.Comment to the api.TimelineComment format -func ToTimelineComment(ctx context.Context, c *issues_model.Comment, doer *user_model.User) *api.TimelineComment { +func ToTimelineComment(ctx context.Context, repo *repo_model.Repository, c *issues_model.Comment, doer *user_model.User) *api.TimelineComment { err := c.LoadMilestone(ctx) if err != nil { log.Error("LoadMilestone: %v", err) @@ -143,7 +143,7 @@ func ToTimelineComment(ctx context.Context, c *issues_model.Comment, doer *user_ log.Error("LoadPoster: %v", err) return nil } - comment.RefComment = ToComment(ctx, com) + comment.RefComment = ToAPIComment(ctx, repo, com) } if c.Label != nil { diff --git a/services/convert/release.go b/services/convert/release.go index ca28aa0d6b..d8aa46d432 100644 --- a/services/convert/release.go +++ b/services/convert/release.go @@ -10,8 +10,8 @@ import ( api "code.gitea.io/gitea/modules/structs" ) -// ToRelease convert a repo_model.Release to api.Release -func ToRelease(ctx context.Context, r *repo_model.Release) *api.Release { +// ToAPIRelease convert a repo_model.Release to api.Release +func ToAPIRelease(ctx context.Context, repo *repo_model.Repository, r *repo_model.Release) *api.Release { return &api.Release{ ID: r.ID, TagName: r.TagName, @@ -27,6 +27,6 @@ func ToRelease(ctx context.Context, r *repo_model.Release) *api.Release { CreatedAt: r.CreatedUnix.AsTime(), PublishedAt: r.CreatedUnix.AsTime(), Publisher: ToUser(ctx, r.Publisher, nil), - Attachments: ToAttachments(r.Attachments), + Attachments: ToAPIAttachments(repo, r.Attachments), } } diff --git a/services/pull/merge.go b/services/pull/merge.go index 85bb90b853..416c744463 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -110,6 +110,11 @@ func getMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr *issue } } + if mergeStyle == repo_model.MergeStyleRebase { + // for fast-forward rebase, do not amend the last commit if there is no template + return "", "", 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 diff --git a/services/webhook/notifier.go b/services/webhook/notifier.go index 3332d5d4aa..23080a5a35 100644 --- a/services/webhook/notifier.go +++ b/services/webhook/notifier.go @@ -386,7 +386,7 @@ func (m *webhookNotifier) NotifyUpdateComment(ctx context.Context, doer *user_mo if err := PrepareWebhooks(ctx, EventSource{Repository: c.Issue.Repo}, eventType, &api.IssueCommentPayload{ Action: api.HookIssueCommentEdited, Issue: convert.ToAPIIssue(ctx, c.Issue), - Comment: convert.ToComment(ctx, c), + Comment: convert.ToAPIComment(ctx, c.Issue.Repo, c), Changes: &api.ChangesPayload{ Body: &api.ChangesFromPayload{ From: oldContent, @@ -414,7 +414,7 @@ func (m *webhookNotifier) NotifyCreateIssueComment(ctx context.Context, doer *us if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, eventType, &api.IssueCommentPayload{ Action: api.HookIssueCommentCreated, Issue: convert.ToAPIIssue(ctx, issue), - Comment: convert.ToComment(ctx, comment), + Comment: convert.ToAPIComment(ctx, repo, comment), Repository: convert.ToRepo(ctx, repo, permission), Sender: convert.ToUser(ctx, doer, nil), IsPull: issue.IsPull, @@ -451,7 +451,7 @@ func (m *webhookNotifier) NotifyDeleteComment(ctx context.Context, doer *user_mo if err := PrepareWebhooks(ctx, EventSource{Repository: comment.Issue.Repo}, eventType, &api.IssueCommentPayload{ Action: api.HookIssueCommentDeleted, Issue: convert.ToAPIIssue(ctx, comment.Issue), - Comment: convert.ToComment(ctx, comment), + Comment: convert.ToAPIComment(ctx, comment.Issue.Repo, comment), Repository: convert.ToRepo(ctx, comment.Issue.Repo, permission), Sender: convert.ToUser(ctx, doer, nil), IsPull: comment.Issue.IsPull, @@ -808,7 +808,7 @@ func sendReleaseHook(ctx context.Context, doer *user_model.User, rel *repo_model permission, _ := access_model.GetUserRepoPermission(ctx, rel.Repo, doer) if err := PrepareWebhooks(ctx, EventSource{Repository: rel.Repo}, webhook_module.HookEventRelease, &api.ReleasePayload{ Action: action, - Release: convert.ToRelease(ctx, rel), + Release: convert.ToAPIRelease(ctx, rel.Repo, rel), Repository: convert.ToRepo(ctx, rel.Repo, permission), Sender: convert.ToUser(ctx, doer, nil), }); err != nil { diff --git a/templates/admin/auth/edit.tmpl b/templates/admin/auth/edit.tmpl index 801cf9e7b4..6dfa86d9dd 100644 --- a/templates/admin/auth/edit.tmpl +++ b/templates/admin/auth/edit.tmpl @@ -106,7 +106,6 @@ -
{{.locale.Tr "install.admin_setting_desc"}}
@@ -321,10 +320,27 @@