From 69d98f83f9a62a7e70976b5d973f293f73e42266 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 8 Nov 2023 21:50:20 +0800 Subject: [PATCH 01/81] Fix format error (#27963) --- modules/context/repo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/context/repo.go b/modules/context/repo.go index 9efa2ab3c08..41683a69388 100644 --- a/modules/context/repo.go +++ b/modules/context/repo.go @@ -850,7 +850,7 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string { return getRefNameFromPath(ctx, repo, path, func(s string) bool { b, exist, err := git_model.FindRenamedBranch(ctx, repo.Repository.ID, s) if err != nil { - log.Error("FindRenamedBranch", err) + log.Error("FindRenamedBranch: %v", err) return false } From 16ba16dbe951763cfc026b7351e26009d1a25fdc Mon Sep 17 00:00:00 2001 From: 6543 Date: Thu, 9 Nov 2023 11:11:45 +0100 Subject: [PATCH 02/81] Allow to set explore page default sort (#27951) as title --- *Sponsored by Kithara Software GmbH* --- custom/conf/app.example.ini | 4 ++++ .../administration/config-cheat-sheet.en-us.md | 3 ++- modules/setting/ui.go | 1 + routers/web/admin/orgs.go | 2 +- routers/web/admin/users.go | 5 ++++- routers/web/explore/org.go | 2 +- routers/web/explore/repo.go | 9 +++++++-- routers/web/explore/user.go | 17 ++++++++--------- 8 files changed, 28 insertions(+), 15 deletions(-) diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index a4e777fa128..329dd34d7be 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -1238,6 +1238,10 @@ LEVEL = Info ;; Whether to only show relevant repos on the explore page when no keyword is specified and default sorting is used. ;; A repo is considered irrelevant if it's a fork or if it has no metadata (no description, no icon, no topic). ;ONLY_SHOW_RELEVANT_REPOS = false +;; +;; Change the sort type of the explore pages. +;; Default is "recentupdate", but you also have "alphabetically", "reverselastlogin", "newest", "oldest". +;EXPLORE_PAGING_DEFAULT_SORT = recentupdate ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/docs/content/administration/config-cheat-sheet.en-us.md b/docs/content/administration/config-cheat-sheet.en-us.md index 401da352c12..2da6bd3ff53 100644 --- a/docs/content/administration/config-cheat-sheet.en-us.md +++ b/docs/content/administration/config-cheat-sheet.en-us.md @@ -229,8 +229,9 @@ The following configuration set `Content-Type: application/vnd.android.package-a add it to this config. - `DEFAULT_SHOW_FULL_NAME`: **false**: Whether the full name of the users should be shown where possible. If the full name isn't set, the username will be used. - `SEARCH_REPO_DESCRIPTION`: **true**: Whether to search within description at repository search on explore page. -- `ONLY_SHOW_RELEVANT_REPOS`: **false** Whether to only show relevant repos on the explore page when no keyword is specified and default sorting is used. +- `ONLY_SHOW_RELEVANT_REPOS`: **false**: Whether to only show relevant repos on the explore page when no keyword is specified and default sorting is used. A repo is considered irrelevant if it's a fork or if it has no metadata (no description, no icon, no topic). +- `EXPLORE_PAGING_DEFAULT_SORT`: **recentupdate**: Change the sort type of the explore pages. Valid values are "recentupdate", "alphabetically", "reverselastlogin", "newest" and "oldest" ### UI - Admin (`ui.admin`) diff --git a/modules/setting/ui.go b/modules/setting/ui.go index 231698bf605..31042d3ee0d 100644 --- a/modules/setting/ui.go +++ b/modules/setting/ui.go @@ -33,6 +33,7 @@ var UI = struct { CustomEmojisMap map[string]string `ini:"-"` SearchRepoDescription bool OnlyShowRelevantRepos bool + ExploreDefaultSort string `ini:"EXPLORE_PAGING_DEFAULT_SORT"` Notification struct { MinTimeout time.Duration diff --git a/routers/web/admin/orgs.go b/routers/web/admin/orgs.go index ab44f8048bf..00131c9e2f7 100644 --- a/routers/web/admin/orgs.go +++ b/routers/web/admin/orgs.go @@ -24,7 +24,7 @@ func Organizations(ctx *context.Context) { ctx.Data["PageIsAdminOrganizations"] = true if ctx.FormString("sort") == "" { - ctx.SetFormString("sort", explore.UserSearchDefaultAdminSort) + ctx.SetFormString("sort", UserSearchDefaultAdminSort) } explore.RenderUserSearch(ctx, &user_model.SearchUserOptions{ diff --git a/routers/web/admin/users.go b/routers/web/admin/users.go index 630d739836b..58120818b0b 100644 --- a/routers/web/admin/users.go +++ b/routers/web/admin/users.go @@ -37,6 +37,9 @@ const ( tplUserEdit base.TplName = "admin/user/edit" ) +// UserSearchDefaultAdminSort is the default sort type for admin view +const UserSearchDefaultAdminSort = "alphabetically" + // Users show all the users func Users(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.users") @@ -56,7 +59,7 @@ func Users(ctx *context.Context) { sortType := ctx.FormString("sort") if sortType == "" { - sortType = explore.UserSearchDefaultAdminSort + sortType = UserSearchDefaultAdminSort ctx.SetFormString("sort", sortType) } ctx.PageData["adminUserListSearchForm"] = map[string]any{ diff --git a/routers/web/explore/org.go b/routers/web/explore/org.go index e37bce6b40e..dc1318beefe 100644 --- a/routers/web/explore/org.go +++ b/routers/web/explore/org.go @@ -25,7 +25,7 @@ func Organizations(ctx *context.Context) { } if ctx.FormString("sort") == "" { - ctx.SetFormString("sort", UserSearchDefaultSortType) + ctx.SetFormString("sort", setting.UI.ExploreDefaultSort) } RenderUserSearch(ctx, &user_model.SearchUserOptions{ diff --git a/routers/web/explore/repo.go b/routers/web/explore/repo.go index e5f7977abd0..0446edebe69 100644 --- a/routers/web/explore/repo.go +++ b/routers/web/explore/repo.go @@ -57,8 +57,13 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { orderBy db.SearchOrderBy ) - ctx.Data["SortType"] = ctx.FormString("sort") - switch ctx.FormString("sort") { + sortOrder := ctx.FormString("sort") + if sortOrder == "" { + sortOrder = setting.UI.ExploreDefaultSort + } + ctx.Data["SortType"] = sortOrder + + switch sortOrder { case "newest": orderBy = db.SearchOrderByNewest case "oldest": diff --git a/routers/web/explore/user.go b/routers/web/explore/user.go index c760004088e..09d31f95ef4 100644 --- a/routers/web/explore/user.go +++ b/routers/web/explore/user.go @@ -23,12 +23,6 @@ const ( tplExploreUsers base.TplName = "explore/users" ) -// UserSearchDefaultSortType is the default sort type for user search -const ( - UserSearchDefaultSortType = "recentupdate" - UserSearchDefaultAdminSort = "alphabetically" -) - var nullByte = []byte{0x00} func isKeywordValid(keyword string) bool { @@ -60,8 +54,13 @@ func RenderUserSearch(ctx *context.Context, opts *user_model.SearchUserOptions, // we can not set orderBy to `models.SearchOrderByXxx`, because there may be a JOIN in the statement, different tables may have the same name columns - ctx.Data["SortType"] = ctx.FormString("sort") - switch ctx.FormString("sort") { + sortOrder := ctx.FormString("sort") + if sortOrder == "" { + sortOrder = setting.UI.ExploreDefaultSort + } + ctx.Data["SortType"] = sortOrder + + switch sortOrder { case "newest": orderBy = "`user`.id DESC" case "oldest": @@ -134,7 +133,7 @@ func Users(ctx *context.Context) { ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled if ctx.FormString("sort") == "" { - ctx.SetFormString("sort", UserSearchDefaultSortType) + ctx.SetFormString("sort", setting.UI.ExploreDefaultSort) } RenderUserSearch(ctx, &user_model.SearchUserOptions{ From 603573366a203efae06f818a0b220be964cdac21 Mon Sep 17 00:00:00 2001 From: 6543 Date: Thu, 9 Nov 2023 15:05:52 +0100 Subject: [PATCH 03/81] Add Profile Readme for Organisations (#27955) https://blog.gitea.com/release-of-1.20.0/#-user-profile-readme-23260 (#23260) did introduce Profile Readme for Users. This makes it usable for Organisations: ![image](https://github.com/go-gitea/gitea/assets/24977596/464ab58b-a952-414b-8a34-6deaeb4f7d35) --- *Sponsored by Kithara Software GmbH* --------- Co-authored-by: silverwind Co-authored-by: KN4CK3R --- docs/content/usage/profile-readme.en-us.md | 3 ++- routers/web/org/home.go | 26 ++++++++++++++++++++++ templates/org/home.tmpl | 3 +++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/docs/content/usage/profile-readme.en-us.md b/docs/content/usage/profile-readme.en-us.md index 045d33d1c17..339176f7d4a 100644 --- a/docs/content/usage/profile-readme.en-us.md +++ b/docs/content/usage/profile-readme.en-us.md @@ -15,6 +15,7 @@ menu: # Profile READMEs -To display a Markdown file in your Gitea profile page, simply create a repository named `.profile` and add a new file called `README.md`. Gitea will automatically display the contents of the file on your profile, above your repositories. +To display a Markdown file in your Gitea user or organization profile page, create a repository named `.profile` and add a new file named `README.md` to it. +Gitea will automatically display the contents of the file on your profile, in a new "Overview" above your repositories. Making the `.profile` repository private will hide the Profile README. diff --git a/routers/web/org/home.go b/routers/web/org/home.go index ec866eb6b3b..4a8ebb670a7 100644 --- a/routers/web/org/home.go +++ b/routers/web/org/home.go @@ -13,6 +13,8 @@ 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/git" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/setting" @@ -155,5 +157,29 @@ func Home(ctx *context.Context) { ctx.Data["ShowMemberAndTeamTab"] = ctx.Org.IsMember || len(members) > 0 + profileGitRepo, profileReadmeBlob, profileClose := shared_user.FindUserProfileReadme(ctx) + defer profileClose() + prepareOrgProfileReadme(ctx, profileGitRepo, profileReadmeBlob) + ctx.HTML(http.StatusOK, tplOrgHome) } + +func prepareOrgProfileReadme(ctx *context.Context, profileGitRepo *git.Repository, profileReadme *git.Blob) { + if profileGitRepo == nil || profileReadme == nil { + return + } + + if bytes, err := profileReadme.GetBlobContent(setting.UI.MaxDisplayFileSize); err != nil { + log.Error("failed to GetBlobContent: %v", err) + } else { + if profileContent, err := markdown.RenderString(&markup.RenderContext{ + Ctx: ctx, + GitRepo: profileGitRepo, + Metas: map[string]string{"mode": "document"}, + }, bytes); err != nil { + log.Error("failed to RenderString: %v", err) + } else { + ctx.Data["ProfileReadme"] = profileContent + } + } +} diff --git a/templates/org/home.tmpl b/templates/org/home.tmpl index ee3237d45b0..2bebcc0f87d 100644 --- a/templates/org/home.tmpl +++ b/templates/org/home.tmpl @@ -38,6 +38,9 @@
+ {{if .ProfileReadme}} +
{{.ProfileReadme | Str2html}}
+ {{end}} {{template "explore/repo_search" .}} {{template "explore/repo_list" .}} {{template "base/paginate" .}} From 481e738e7f3ee22a5a8280d155a1b7d1ff09bc7f Mon Sep 17 00:00:00 2001 From: KN4CK3R Date: Fri, 10 Nov 2023 02:45:13 +0100 Subject: [PATCH 04/81] Remove `title` from elements on Org mode (#27968) The Org mode rendering has some problems: 1. `[[https://example.com][pre https://example.com/example.mp4 post]]` renders as `

https://example.com/example.mp4 post">pre post

` As you can see, the `title` attribute contains the inner html in unescaped form. I removed the `title` attribute because it is of little value. 3. The `title` attribute on `img` and `video` is of little value. 4. The inner elements of `video` are different depending on the `if`. --- modules/markup/orgmode/orgmode.go | 8 ++++---- modules/markup/orgmode/orgmode_test.go | 18 +++++++++++------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/modules/markup/orgmode/orgmode.go b/modules/markup/orgmode/orgmode.go index 9b6175649f1..c1e01441993 100644 --- a/modules/markup/orgmode/orgmode.go +++ b/modules/markup/orgmode/orgmode.go @@ -158,7 +158,7 @@ func (r *Writer) WriteRegularLink(l org.RegularLink) { case "image": if l.Description == nil { imageSrc := getMediaURL(link) - fmt.Fprintf(r, `%s`, imageSrc, link, link) + fmt.Fprintf(r, `%s`, imageSrc, link) } else { description := strings.TrimPrefix(org.String(l.Description...), "file:") imageSrc := getMediaURL([]byte(description)) @@ -167,18 +167,18 @@ func (r *Writer) WriteRegularLink(l org.RegularLink) { case "video": if l.Description == nil { imageSrc := getMediaURL(link) - fmt.Fprintf(r, ``, imageSrc, link, link) + fmt.Fprintf(r, ``, imageSrc, link) } else { description := strings.TrimPrefix(org.String(l.Description...), "file:") videoSrc := getMediaURL([]byte(description)) - fmt.Fprintf(r, ``, link, videoSrc, videoSrc) + fmt.Fprintf(r, ``, link, videoSrc, videoSrc) } default: description := string(link) if l.Description != nil { description = r.WriteNodesAsString(l.Description...) } - fmt.Fprintf(r, `%s`, link, description, description) + fmt.Fprintf(r, `%s`, link, description) } } diff --git a/modules/markup/orgmode/orgmode_test.go b/modules/markup/orgmode/orgmode_test.go index 8f454e99558..88ae14ebcf5 100644 --- a/modules/markup/orgmode/orgmode_test.go +++ b/modules/markup/orgmode/orgmode_test.go @@ -34,12 +34,12 @@ func TestRender_StandardLinks(t *testing.T) { assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer)) } - googleRendered := "

https://google.com/

" - test("[[https://google.com/]]", googleRendered) + test("[[https://google.com/]]", + `

https://google.com/

`) lnk := util.URLJoin(AppSubURL, "WikiPage") test("[[WikiPage][WikiPage]]", - "

WikiPage

") + `

WikiPage

`) } func TestRender_Media(t *testing.T) { @@ -59,19 +59,23 @@ func TestRender_Media(t *testing.T) { result := util.URLJoin(AppSubURL, url) test("[[file:"+url+"]]", - "

\""+result+"\"

") + `

`+result+`

`) // With description. test("[[https://example.com][https://example.com/example.svg]]", `

https://example.com/example.svg

`) + test("[[https://example.com][pre https://example.com/example.svg post]]", + `

pre https://example.com/example.svg post

`) test("[[https://example.com][https://example.com/example.mp4]]", - `

`) + `

`) + test("[[https://example.com][pre https://example.com/example.mp4 post]]", + `

pre post

`) // Without description. test("[[https://example.com/example.svg]]", - `

https://example.com/example.svg

`) + `

https://example.com/example.svg

`) test("[[https://example.com/example.mp4]]", - `

`) + `

`) } func TestRender_Source(t *testing.T) { From 6c9e196e5457b30716f3939f258dca07567a2637 Mon Sep 17 00:00:00 2001 From: Nanguan Lin <70063547+lng2020@users.noreply.github.com> Date: Fri, 10 Nov 2023 19:43:18 +0800 Subject: [PATCH 05/81] Show error toast when file size exceeds the limits (#27985) As title. Before that, there was no alert at all. After: ![error_toast](https://github.com/go-gitea/gitea/assets/70063547/c54ffeed-76f8-4c3a-b5dc-b9b3e0f8fc76) --- web_src/js/features/common-global.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/web_src/js/features/common-global.js b/web_src/js/features/common-global.js index c00c06c0cc3..c2e0111849b 100644 --- a/web_src/js/features/common-global.js +++ b/web_src/js/features/common-global.js @@ -247,6 +247,10 @@ export function initGlobalDropzone() { }); } }); + this.on('error', function (file, message) { + showErrorToast(message); + this.removeFile(file); + }); }, }); } From 1c0566f66dcb35b33b0b308356e1b16a26ea906b Mon Sep 17 00:00:00 2001 From: Yarden Shoham Date: Sat, 11 Nov 2023 06:08:19 +0200 Subject: [PATCH 06/81] Render email addresses as such if followed by punctuation (#27987) Added the following characters to the regular expression for the email: - , - ; - ? - ! Also added a test case. - Fixes #27616 # Before ![image](https://github.com/go-gitea/gitea/assets/20454870/c57eac26-f281-43ef-a51d-9c9a81b63efa) # After ![image](https://github.com/go-gitea/gitea/assets/20454870/fc7d5c08-4350-4af0-a7f0-d1444d2d75af) Signed-off-by: Yarden Shoham --- modules/markup/html.go | 2 +- modules/markup/html_test.go | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/modules/markup/html.go b/modules/markup/html.go index e53ccc6a794..774cbe1557e 100644 --- a/modules/markup/html.go +++ b/modules/markup/html.go @@ -66,7 +66,7 @@ var ( // well as the HTML5 spec: // http://spec.commonmark.org/0.28/#email-address // https://html.spec.whatwg.org/multipage/input.html#e-mail-state-(type%3Demail) - emailRegex = regexp.MustCompile("(?:\\s|^|\\(|\\[)([a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9]{2,}(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+)(?:\\s|$|\\)|\\]|\\.(\\s|$))") + emailRegex = regexp.MustCompile("(?:\\s|^|\\(|\\[)([a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9]{2,}(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+)(?:\\s|$|\\)|\\]|;|,|\\?|!|\\.(\\s|$))") // blackfriday extensions create IDs like fn:user-content-footnote blackfridayExtRegex = regexp.MustCompile(`[^:]*:user-content-`) diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go index 21bfc8314a8..d1f4e9e8a35 100644 --- a/modules/markup/html_test.go +++ b/modules/markup/html_test.go @@ -264,6 +264,18 @@ func TestRender_email(t *testing.T) { "send email to info@gitea.co.uk.", `

send email to info@gitea.co.uk.

`) + test( + `j.doe@example.com, + j.doe@example.com. + j.doe@example.com; + j.doe@example.com? + j.doe@example.com!`, + `

j.doe@example.com,
+j.doe@example.com.
+j.doe@example.com;
+j.doe@example.com?
+j.doe@example.com!

`) + // Test that should *not* be turned into email links test( "\"info@gitea.com\"", From 61ff91f9603806df2505907614b9006bf721b9c8 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 11 Nov 2023 18:27:02 +0800 Subject: [PATCH 07/81] Fix the wrong oauth2 name (#27993) Fix #27989 Regression #27798 --- templates/user/auth/signin_inner.tmpl | 2 +- templates/user/auth/signup_inner.tmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/user/auth/signin_inner.tmpl b/templates/user/auth/signin_inner.tmpl index 7f744b24d87..40e54ec8fa9 100644 --- a/templates/user/auth/signin_inner.tmpl +++ b/templates/user/auth/signin_inner.tmpl @@ -60,7 +60,7 @@
{{range $provider := .OAuth2Providers}} - diff --git a/templates/user/auth/signup_inner.tmpl b/templates/user/auth/signup_inner.tmpl index c75e33a18a0..e930bd3d158 100644 --- a/templates/user/auth/signup_inner.tmpl +++ b/templates/user/auth/signup_inner.tmpl @@ -64,7 +64,7 @@
{{range $provider := .OAuth2Providers}} - From f860fe31d96a7331b429e11ac96d2f166cc5dca0 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Sun, 12 Nov 2023 15:15:00 +0800 Subject: [PATCH 08/81] Move some JS code from `fomantic.js` to standalone files (#27994) To improve maintainability, this PR: 1. Rename `web_src/js/modules/aria` to `web_src/js/modules/fomantic` (the code there are all for aria of fomantic) 2. Move api/transition related code to `web_src/js/modules/fomantic/api.js` and `web_src/js/modules/fomantic/transition.js` No logic is changed. --- web_src/js/modules/fomantic.js | 99 ++----------------- web_src/js/modules/fomantic/api.js | 40 ++++++++ web_src/js/modules/{aria => fomantic}/aria.md | 0 web_src/js/modules/{aria => fomantic}/base.js | 0 .../js/modules/{aria => fomantic}/checkbox.js | 0 .../js/modules/{aria => fomantic}/dropdown.js | 0 .../js/modules/{aria => fomantic}/modal.js | 0 web_src/js/modules/fomantic/transition.js | 54 ++++++++++ 8 files changed, 100 insertions(+), 93 deletions(-) create mode 100644 web_src/js/modules/fomantic/api.js rename web_src/js/modules/{aria => fomantic}/aria.md (100%) rename web_src/js/modules/{aria => fomantic}/base.js (100%) rename web_src/js/modules/{aria => fomantic}/checkbox.js (100%) rename web_src/js/modules/{aria => fomantic}/dropdown.js (100%) rename web_src/js/modules/{aria => fomantic}/modal.js (100%) create mode 100644 web_src/js/modules/fomantic/transition.js diff --git a/web_src/js/modules/fomantic.js b/web_src/js/modules/fomantic.js index da693e9a933..0c7a7ae6412 100644 --- a/web_src/js/modules/fomantic.js +++ b/web_src/js/modules/fomantic.js @@ -1,7 +1,9 @@ import $ from 'jquery'; -import {initAriaCheckboxPatch} from './aria/checkbox.js'; -import {initAriaDropdownPatch} from './aria/dropdown.js'; -import {initAriaModalPatch} from './aria/modal.js'; +import {initFomanticApiPatch} from './fomantic/api.js'; +import {initAriaCheckboxPatch} from './fomantic/checkbox.js'; +import {initAriaDropdownPatch} from './fomantic/dropdown.js'; +import {initAriaModalPatch} from './fomantic/modal.js'; +import {initFomanticTransition} from './fomantic/transition.js'; import {svg} from '../svg.js'; export const fomanticMobileScreen = window.matchMedia('only screen and (max-width: 767.98px)'); @@ -22,57 +24,7 @@ export function initGiteaFomantic() { return escape(text, preserveHTML) + svg('octicon-x', 16, `${className.delete} icon`); }; - const transitionNopBehaviors = new Set([ - 'clear queue', 'stop', 'stop all', 'destroy', - 'force repaint', 'repaint', 'reset', - 'looping', 'remove looping', 'disable', 'enable', - 'set duration', 'save conditions', 'restore conditions', - ]); - // stand-in for removed transition module - $.fn.transition = function (arg0, arg1, arg2) { - if (arg0 === 'is supported') return true; - if (arg0 === 'is animating') return false; - if (arg0 === 'is inward') return false; - if (arg0 === 'is outward') return false; - - let argObj; - if (typeof arg0 === 'string') { - // many behaviors are no-op now. https://fomantic-ui.com/modules/transition.html#/usage - if (transitionNopBehaviors.has(arg0)) return this; - // now, the arg0 is an animation name, the syntax: (animation, duration, complete) - argObj = {animation: arg0, ...(arg1 && {duration: arg1}), ...(arg2 && {onComplete: arg2})}; - } else if (typeof arg0 === 'object') { - argObj = arg0; - } else { - throw new Error(`invalid argument: ${arg0}`); - } - - const isAnimationIn = argObj.animation?.startsWith('show') || argObj.animation?.endsWith(' in'); - const isAnimationOut = argObj.animation?.startsWith('hide') || argObj.animation?.endsWith(' out'); - this.each((_, el) => { - let toShow = isAnimationIn; - if (!isAnimationIn && !isAnimationOut) { - // If the animation is not in/out, then it must be a toggle animation. - // Fomantic uses computed styles to check "visibility", but to avoid unnecessary arguments, here it only checks the class. - toShow = this.hasClass('hidden'); // maybe it could also check "!this.hasClass('visible')", leave it to the future until there is a real problem. - } - argObj.onStart?.call(el); - if (toShow) { - el.classList.remove('hidden'); - el.classList.add('visible', 'transition'); - if (argObj.displayType) el.style.setProperty('display', argObj.displayType, 'important'); - argObj.onShow?.call(el); - } else { - el.classList.add('hidden'); - el.classList.remove('visible'); // don't remove the transition class because the Fomantic animation style is `.hidden.transition`. - el.style.removeProperty('display'); - argObj.onHidden?.call(el); - } - argObj.onComplete?.call(el); - }); - return this; - }; - + initFomanticTransition(); initFomanticApiPatch(); // Use the patches to improve accessibility, these patches are designed to be as independent as possible, make it easy to modify or remove in the future. @@ -80,42 +32,3 @@ export function initGiteaFomantic() { initAriaDropdownPatch(); initAriaModalPatch(); } - -function initFomanticApiPatch() { - // - // Fomantic API module has some very buggy behaviors: - // - // If encodeParameters=true, it calls `urlEncodedValue` to encode the parameter. - // However, `urlEncodedValue` just tries to "guess" whether the parameter is already encoded, by decoding the parameter and encoding it again. - // - // There are 2 problems: - // 1. It may guess wrong, and skip encoding a parameter which looks like encoded. - // 2. If the parameter can't be decoded, `decodeURIComponent` will throw an error, and the whole request will fail. - // - // This patch only fixes the second error behavior at the moment. - // - const patchKey = '_giteaFomanticApiPatch'; - const oldApi = $.api; - $.api = $.fn.api = function(...args) { - const apiCall = oldApi.bind(this); - const ret = oldApi.apply(this, args); - - if (typeof args[0] !== 'string') { - const internalGet = apiCall('internal', 'get'); - if (!internalGet.urlEncodedValue[patchKey]) { - const oldUrlEncodedValue = internalGet.urlEncodedValue; - internalGet.urlEncodedValue = function (value) { - try { - return oldUrlEncodedValue(value); - } catch { - // if Fomantic API module's `urlEncodedValue` throws an error, we encode it by ourselves. - return encodeURIComponent(value); - } - }; - internalGet.urlEncodedValue[patchKey] = true; - } - } - return ret; - }; - $.api.settings = oldApi.settings; -} diff --git a/web_src/js/modules/fomantic/api.js b/web_src/js/modules/fomantic/api.js new file mode 100644 index 00000000000..ca212c9fef9 --- /dev/null +++ b/web_src/js/modules/fomantic/api.js @@ -0,0 +1,40 @@ +import $ from 'jquery'; + +export function initFomanticApiPatch() { + // + // Fomantic API module has some very buggy behaviors: + // + // If encodeParameters=true, it calls `urlEncodedValue` to encode the parameter. + // However, `urlEncodedValue` just tries to "guess" whether the parameter is already encoded, by decoding the parameter and encoding it again. + // + // There are 2 problems: + // 1. It may guess wrong, and skip encoding a parameter which looks like encoded. + // 2. If the parameter can't be decoded, `decodeURIComponent` will throw an error, and the whole request will fail. + // + // This patch only fixes the second error behavior at the moment. + // + const patchKey = '_giteaFomanticApiPatch'; + const oldApi = $.api; + $.api = $.fn.api = function(...args) { + const apiCall = oldApi.bind(this); + const ret = oldApi.apply(this, args); + + if (typeof args[0] !== 'string') { + const internalGet = apiCall('internal', 'get'); + if (!internalGet.urlEncodedValue[patchKey]) { + const oldUrlEncodedValue = internalGet.urlEncodedValue; + internalGet.urlEncodedValue = function (value) { + try { + return oldUrlEncodedValue(value); + } catch { + // if Fomantic API module's `urlEncodedValue` throws an error, we encode it by ourselves. + return encodeURIComponent(value); + } + }; + internalGet.urlEncodedValue[patchKey] = true; + } + } + return ret; + }; + $.api.settings = oldApi.settings; +} diff --git a/web_src/js/modules/aria/aria.md b/web_src/js/modules/fomantic/aria.md similarity index 100% rename from web_src/js/modules/aria/aria.md rename to web_src/js/modules/fomantic/aria.md diff --git a/web_src/js/modules/aria/base.js b/web_src/js/modules/fomantic/base.js similarity index 100% rename from web_src/js/modules/aria/base.js rename to web_src/js/modules/fomantic/base.js diff --git a/web_src/js/modules/aria/checkbox.js b/web_src/js/modules/fomantic/checkbox.js similarity index 100% rename from web_src/js/modules/aria/checkbox.js rename to web_src/js/modules/fomantic/checkbox.js diff --git a/web_src/js/modules/aria/dropdown.js b/web_src/js/modules/fomantic/dropdown.js similarity index 100% rename from web_src/js/modules/aria/dropdown.js rename to web_src/js/modules/fomantic/dropdown.js diff --git a/web_src/js/modules/aria/modal.js b/web_src/js/modules/fomantic/modal.js similarity index 100% rename from web_src/js/modules/aria/modal.js rename to web_src/js/modules/fomantic/modal.js diff --git a/web_src/js/modules/fomantic/transition.js b/web_src/js/modules/fomantic/transition.js new file mode 100644 index 00000000000..78aa0538b02 --- /dev/null +++ b/web_src/js/modules/fomantic/transition.js @@ -0,0 +1,54 @@ +import $ from 'jquery'; + +export function initFomanticTransition() { + const transitionNopBehaviors = new Set([ + 'clear queue', 'stop', 'stop all', 'destroy', + 'force repaint', 'repaint', 'reset', + 'looping', 'remove looping', 'disable', 'enable', + 'set duration', 'save conditions', 'restore conditions', + ]); + // stand-in for removed transition module + $.fn.transition = function (arg0, arg1, arg2) { + if (arg0 === 'is supported') return true; + if (arg0 === 'is animating') return false; + if (arg0 === 'is inward') return false; + if (arg0 === 'is outward') return false; + + let argObj; + if (typeof arg0 === 'string') { + // many behaviors are no-op now. https://fomantic-ui.com/modules/transition.html#/usage + if (transitionNopBehaviors.has(arg0)) return this; + // now, the arg0 is an animation name, the syntax: (animation, duration, complete) + argObj = {animation: arg0, ...(arg1 && {duration: arg1}), ...(arg2 && {onComplete: arg2})}; + } else if (typeof arg0 === 'object') { + argObj = arg0; + } else { + throw new Error(`invalid argument: ${arg0}`); + } + + const isAnimationIn = argObj.animation?.startsWith('show') || argObj.animation?.endsWith(' in'); + const isAnimationOut = argObj.animation?.startsWith('hide') || argObj.animation?.endsWith(' out'); + this.each((_, el) => { + let toShow = isAnimationIn; + if (!isAnimationIn && !isAnimationOut) { + // If the animation is not in/out, then it must be a toggle animation. + // Fomantic uses computed styles to check "visibility", but to avoid unnecessary arguments, here it only checks the class. + toShow = this.hasClass('hidden'); // maybe it could also check "!this.hasClass('visible')", leave it to the future until there is a real problem. + } + argObj.onStart?.call(el); + if (toShow) { + el.classList.remove('hidden'); + el.classList.add('visible', 'transition'); + if (argObj.displayType) el.style.setProperty('display', argObj.displayType, 'important'); + argObj.onShow?.call(el); + } else { + el.classList.add('hidden'); + el.classList.remove('visible'); // don't remove the transition class because the Fomantic animation style is `.hidden.transition`. + el.style.removeProperty('display'); + argObj.onHidden?.call(el); + } + argObj.onComplete?.call(el); + }); + return this; + }; +} From d95102d650673165785a05d1cd07a75a3f8763cb Mon Sep 17 00:00:00 2001 From: Nanguan Lin <70063547+lng2020@users.noreply.github.com> Date: Sun, 12 Nov 2023 15:38:45 +0800 Subject: [PATCH 09/81] Fix wrong xorm Delete usage (#27995) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Bug in Gitea I ran into this bug when I accidentally used the wrong redirect URL for the oauth2 provider when using mssql. But the oauth2 provider still got added. Most of the time, we use `Delete(&some{id: some.id})` or `In(condition).Delete(&some{})`, which specify the conditions. But the function uses `Delete(source)` when `source.Cfg` is a `TEXT` field and not empty. This will cause xorm `Delete` function not working in mssql. https://github.com/go-gitea/gitea/blob/61ff91f9603806df2505907614b9006bf721b9c8/models/auth/source.go#L234-L240 ## Reason Because the `TEXT` field can not be compared in mssql, xorm doesn't support it according to [this PR](https://gitea.com/xorm/xorm/pulls/2062) [related code](https://gitea.com/xorm/xorm/src/commit/b23798dc987af776bec867f4537ca129fd66328e/internal/statements/statement.go#L552-L558) in xorm ```go if statement.dialect.URI().DBType == schemas.MSSQL && (col.SQLType.Name == schemas.Text ||   col.SQLType.IsBlob() || col.SQLType.Name == schemas.TimeStampz) {   if utils.IsValueZero(fieldValue) {   continue   }   return nil, fmt.Errorf("column %s is a TEXT type with data %#v which cannot be as compare condition", col.Name, fieldValue.Interface())   } } ``` When using the `Delete` function in xorm, the non-empty fields will auto-set as conditions(perhaps some special fields are not?). If `TEXT` field is not empty, xorm will return an error. I only found this usage after searching, but maybe there is something I missing. --------- Co-authored-by: delvh --- models/auth/source.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/auth/source.go b/models/auth/source.go index b3f3262cc20..5f2781c808f 100644 --- a/models/auth/source.go +++ b/models/auth/source.go @@ -234,7 +234,7 @@ func CreateSource(ctx context.Context, source *Source) error { err = registerableSource.RegisterSource() if err != nil { // remove the AuthSource in case of errors while registering configuration - if _, err := db.GetEngine(ctx).Delete(source); err != nil { + if _, err := db.GetEngine(ctx).ID(source.ID).Delete(new(Source)); err != nil { log.Error("CreateSource: Error while wrapOpenIDConnectInitializeError: %v", err) } } From 024fe11cd31361740095a2f29b400e1a152454a7 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Mon, 13 Nov 2023 00:24:40 +0000 Subject: [PATCH 10/81] [skip ci] Updated licenses and gitignores --- options/license/AML-glslang | 41 +++++ options/license/Adobe-Display-PostScript | 30 +++ options/license/DEC-3-Clause | 28 +++ options/license/DRL-1.1 | 17 ++ options/license/GCR-docs | 30 +++ .../license/HPND-sell-MIT-disclaimer-xserver | 12 ++ options/license/Pixar | 174 ++++++++++++++++++ options/license/hdparm | 9 + 8 files changed, 341 insertions(+) create mode 100644 options/license/AML-glslang create mode 100644 options/license/Adobe-Display-PostScript create mode 100644 options/license/DEC-3-Clause create mode 100644 options/license/DRL-1.1 create mode 100644 options/license/GCR-docs create mode 100644 options/license/HPND-sell-MIT-disclaimer-xserver create mode 100644 options/license/Pixar create mode 100644 options/license/hdparm diff --git a/options/license/AML-glslang b/options/license/AML-glslang new file mode 100644 index 00000000000..2a24aeac224 --- /dev/null +++ b/options/license/AML-glslang @@ -0,0 +1,41 @@ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/options/license/Adobe-Display-PostScript b/options/license/Adobe-Display-PostScript new file mode 100644 index 00000000000..6df57d3c80e --- /dev/null +++ b/options/license/Adobe-Display-PostScript @@ -0,0 +1,30 @@ +(c)Copyright 1988,1991 Adobe Systems Incorporated. +All rights reserved. + +Permission to use, copy, modify, distribute, and sublicense this software and its +documentation for any purpose and without fee is hereby granted, provided that +the above copyright notices appear in all copies and that both those copyright +notices and this permission notice appear in supporting documentation and that +the name of Adobe Systems Incorporated not be used in advertising or publicity +pertaining to distribution of the software without specific, written prior +permission. No trademark license to use the Adobe trademarks is hereby +granted. If the Adobe trademark "Display PostScript"(tm) is used to describe +this software, its functionality or for any other purpose, such use shall be +limited to a statement that this software works in conjunction with the Display +PostScript system. Proper trademark attribution to reflect Adobe's ownership +of the trademark shall be given whenever any such reference to the Display +PostScript system is made. + +ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY +PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. ADOBE +DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON- +INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE TO YOU +OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,NEGLIGENCE, STRICT +LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT PROVIDE ANY TRAINING OR OTHER +SUPPORT FOR THE SOFTWARE. + +Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems +Incorporated which may be registered in certain jurisdictions. diff --git a/options/license/DEC-3-Clause b/options/license/DEC-3-Clause new file mode 100644 index 00000000000..112edaa70d5 --- /dev/null +++ b/options/license/DEC-3-Clause @@ -0,0 +1,28 @@ +Copyright 1997 Digital Equipment Corporation. +All rights reserved. + +This software is furnished under license and may be used and copied only in +accordance with the following terms and conditions. Subject to these +conditions, you may download, copy, install, use, modify and distribute +this software in source and/or binary form. No title or ownership is +transferred hereby. + +1) Any source code used, modified or distributed must reproduce and retain + this copyright notice and list of conditions as they appear in the + source file. + +2) No right is granted to use any trade name, trademark, or logo of Digital + Equipment Corporation. Neither the "Digital Equipment Corporation" + name nor any trademark or logo of Digital Equipment Corporation may be + used to endorse or promote products derived from this software without + the prior written permission of Digital Equipment Corporation. + +3) This software is provided "AS-IS" and any express or implied warranties, + including but not limited to, any implied warranties of merchantability, + fitness for a particular purpose, or non-infringement are disclaimed. + In no event shall DIGITAL be liable for any damages whatsoever, and in + particular, DIGITAL shall not be liable for special, indirect, + consequential, or incidental damages or damages for lost profits, loss + of revenue or loss of use, whether such damages arise in contract, + negligence, tort, under statute, in equity, at law or otherwise, even + if advised of the possibility of such damage. diff --git a/options/license/DRL-1.1 b/options/license/DRL-1.1 new file mode 100644 index 00000000000..a6445601ff4 --- /dev/null +++ b/options/license/DRL-1.1 @@ -0,0 +1,17 @@ +Detection Rule License (DRL) 1.1 + +Permission is hereby granted, free of charge, to any person obtaining a copy of this rule set and associated documentation files (the "Rules"), to deal in the Rules without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Rules, and to permit persons to whom the Rules are furnished to do so, subject to the following conditions: + +If you share the Rules (including in modified form), you must retain the following if it is supplied within the Rules: + +identification of the authors(s) ("author" field) of the Rule and any others designated to receive attribution, in any reasonable manner requested by the Rule author (including by pseudonym if designated). + +a URI or hyperlink to the Rule set or explicit Rule to the extent reasonably practicable + +indicate the Rules are licensed under this Detection Rule License, and include the text of, or the URI or hyperlink to, this Detection Rule License to the extent reasonably practicable + +If you use the Rules (including in modified form) on data, messages based on matches with the Rules must retain the following if it is supplied within the Rules: + +identification of the authors(s) ("author" field) of the Rule and any others designated to receive attribution, in any reasonable manner requested by the Rule author (including by pseudonym if designated). + +THE RULES ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE RULES OR THE USE OR OTHER DEALINGS IN THE RULES. diff --git a/options/license/GCR-docs b/options/license/GCR-docs new file mode 100644 index 00000000000..d5c1293c965 --- /dev/null +++ b/options/license/GCR-docs @@ -0,0 +1,30 @@ +This work may be reproduced and distributed in whole or in part, in +any medium, physical or electronic, so as long as this copyright +notice remains intact and unchanged on all copies. Commercial +redistribution is permitted and encouraged, but you may not +redistribute, in whole or in part, under terms more restrictive than +those under which you received it. If you redistribute a modified or +translated version of this work, you must also make the source code to +the modified or translated version available in electronic form +without charge. However, mere aggregation as part of a larger work +shall not count as a modification for this purpose. + +All code examples in this work are placed into the public domain, +and may be used, modified and redistributed without restriction. + +BECAUSE THIS WORK IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE WORK, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE WORK "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. SHOULD THE WORK PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY REPAIR OR CORRECTION. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE WORK AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +WORK, EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. diff --git a/options/license/HPND-sell-MIT-disclaimer-xserver b/options/license/HPND-sell-MIT-disclaimer-xserver new file mode 100644 index 00000000000..e7bea21d16e --- /dev/null +++ b/options/license/HPND-sell-MIT-disclaimer-xserver @@ -0,0 +1,12 @@ +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +this permission notice appear in supporting documentation. This permission +notice shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/options/license/Pixar b/options/license/Pixar new file mode 100644 index 00000000000..c7533090bbe --- /dev/null +++ b/options/license/Pixar @@ -0,0 +1,174 @@ + + Modified Apache 2.0 License + + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor + and its affiliates, except as required to comply with Section 4(c) of + the License and to reproduce the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/options/license/hdparm b/options/license/hdparm new file mode 100644 index 00000000000..280a1c07974 --- /dev/null +++ b/options/license/hdparm @@ -0,0 +1,9 @@ +BSD-Style Open Source License: + +You may freely use, modify, and redistribute the hdparm program, +as either binary or source, or both. + +The only condition is that my name and copyright notice +remain in the source code as-is. + +Mark Lord (mlord@pobox.com) From 3081e7e1536356346f73fb4a0d00101863b2cf05 Mon Sep 17 00:00:00 2001 From: KN4CK3R Date: Mon, 13 Nov 2023 04:20:34 +0100 Subject: [PATCH 11/81] Fix missing mail reply address (#27997) Fixes https://codeberg.org/forgejo/forgejo/issues/1458 Some mails such as issue creation mails are missing the reply-to-comment address. This PR fixes that and specifies which comment types should get a reply-possibility. --- models/issues/comment.go | 8 ++++++++ services/mailer/mail.go | 8 +++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/models/issues/comment.go b/models/issues/comment.go index 8e06838f73a..f2a3cb7b026 100644 --- a/models/issues/comment.go +++ b/models/issues/comment.go @@ -183,6 +183,14 @@ func (t CommentType) HasAttachmentSupport() bool { return false } +func (t CommentType) HasMailReplySupport() bool { + switch t { + case CommentTypeComment, CommentTypeCode, CommentTypeReview, CommentTypeDismissReview, CommentTypeReopen, CommentTypeClose, CommentTypeMergePull, CommentTypeAssignees: + return true + } + return false +} + // RoleInRepo presents the user's participation in the repo type RoleInRepo string diff --git a/services/mailer/mail.go b/services/mailer/mail.go index 1f139d233ff..b597dd0487c 100644 --- a/services/mailer/mail.go +++ b/services/mailer/mail.go @@ -290,8 +290,10 @@ func composeIssueCommentMessages(ctx *mailCommentContext, lang string, recipient reference := createReference(ctx.Issue, nil, activities_model.ActionType(0)) var replyPayload []byte - if ctx.Comment != nil && ctx.Comment.Type == issues_model.CommentTypeCode { - replyPayload, err = incoming_payload.CreateReferencePayload(ctx.Comment) + if ctx.Comment != nil { + if ctx.Comment.Type.HasMailReplySupport() { + replyPayload, err = incoming_payload.CreateReferencePayload(ctx.Comment) + } } else { replyPayload, err = incoming_payload.CreateReferencePayload(ctx.Issue) } @@ -316,7 +318,7 @@ func composeIssueCommentMessages(ctx *mailCommentContext, lang string, recipient listUnsubscribe := []string{"<" + ctx.Issue.HTMLURL() + ">"} if setting.IncomingEmail.Enabled { - if ctx.Comment != nil { + if replyPayload != nil { token, err := token.CreateToken(token.ReplyHandlerType, recipient, replyPayload) if err != nil { log.Error("CreateToken failed: %v", err) From 0678c822653975c7fcf40371f2c39dd14254aa2a Mon Sep 17 00:00:00 2001 From: Nanguan Lin <70063547+lng2020@users.noreply.github.com> Date: Mon, 13 Nov 2023 22:19:22 +0800 Subject: [PATCH 12/81] Change default size of issue/pr attachments and repo file (#27946) As title. Some attachments and file sizes can easily be larger than these limits --- custom/conf/app.example.ini | 8 ++++---- docs/content/administration/config-cheat-sheet.en-us.md | 4 ++-- docs/content/administration/config-cheat-sheet.zh-cn.md | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index 329dd34d7be..325e31af390 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -1016,8 +1016,8 @@ LEVEL = Info ;; Comma-separated list of allowed file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types. ;ALLOWED_TYPES = ;; -;; Max size of each file in megabytes. Defaults to 3MB -;FILE_MAX_SIZE = 3 +;; Max size of each file in megabytes. Defaults to 50MB +;FILE_MAX_SIZE = 50 ;; ;; Max number of files per upload. Defaults to 5 ;MAX_FILES = 5 @@ -1821,8 +1821,8 @@ LEVEL = Info ;; Comma-separated list of allowed file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types. ;ALLOWED_TYPES = .csv,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip ;; -;; Max size of each file. Defaults to 4MB -;MAX_SIZE = 4 +;; Max size of each file. Defaults to 2048MB +;MAX_SIZE = 2048 ;; ;; Max number of files per upload. Defaults to 5 ;MAX_FILES = 5 diff --git a/docs/content/administration/config-cheat-sheet.en-us.md b/docs/content/administration/config-cheat-sheet.en-us.md index 2da6bd3ff53..385830e5d89 100644 --- a/docs/content/administration/config-cheat-sheet.en-us.md +++ b/docs/content/administration/config-cheat-sheet.en-us.md @@ -146,7 +146,7 @@ In addition, there is _`StaticRootPath`_ which can be set as a built-in at build - `ENABLED`: **true**: Whether repository file uploads are enabled - `TEMP_PATH`: **data/tmp/uploads**: Path for uploads (content gets deleted on Gitea restart) - `ALLOWED_TYPES`: **_empty_**: Comma-separated list of allowed file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types. -- `FILE_MAX_SIZE`: **3**: Max size of each file in megabytes. +- `FILE_MAX_SIZE`: **50**: Max size of each file in megabytes. - `MAX_FILES`: **5**: Max number of files per upload ### Repository - Release (`repository.release`) @@ -823,7 +823,7 @@ Default templates for project boards: - `ENABLED`: **true**: Whether issue and pull request attachments are enabled. - `ALLOWED_TYPES`: **.csv,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip**: Comma-separated list of allowed file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types. -- `MAX_SIZE`: **4**: Maximum size (MB). +- `MAX_SIZE`: **2048**: Maximum size (MB). - `MAX_FILES`: **5**: Maximum number of attachments that can be uploaded at once. - `STORAGE_TYPE`: **local**: Storage type for attachments, `local` for local disk or `minio` for s3 compatible object storage service, default is `local` or other name defined with `[storage.xxx]` - `SERVE_DIRECT`: **false**: Allows the storage driver to redirect to authenticated URLs to serve files directly. Currently, only Minio/S3 is supported via signed URLs, local does nothing. diff --git a/docs/content/administration/config-cheat-sheet.zh-cn.md b/docs/content/administration/config-cheat-sheet.zh-cn.md index d541013159f..da86660b8e1 100644 --- a/docs/content/administration/config-cheat-sheet.zh-cn.md +++ b/docs/content/administration/config-cheat-sheet.zh-cn.md @@ -145,7 +145,7 @@ menu: - `ENABLED`: **true**: 是否启用仓库文件上传。 - `TEMP_PATH`: **data/tmp/uploads**: 文件上传的临时保存路径(在Gitea重启的时候该目录会被清空)。 - `ALLOWED_TYPES`: **_empty_**: 以逗号分割的列表,代表支持上传的文件类型。(`.zip`), mime类型 (`text/plain`) or 通配符类型 (`image/*`, `audio/*`, `video/*`). 为空或者 `*/*`代表允许所有类型文件。 -- `FILE_MAX_SIZE`: **3**: 每个文件的最大大小(MB)。 +- `FILE_MAX_SIZE`: **50**: 每个文件的最大大小(MB)。 - `MAX_FILES`: **5**: 每次上传的最大文件数。 ### 仓库 - 版本发布 (`repository.release`) @@ -783,7 +783,7 @@ Gitea 创建以下非唯一队列: - `ENABLED`: **true**: 是否允许用户上传附件。 - `ALLOWED_TYPES`: **.csv,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip**: 允许的文件扩展名(`.zip`)、mime 类型(`text/plain`)或通配符类型(`image/*`、`audio/*`、`video/*`)的逗号分隔列表。空值或 `*/*` 允许所有类型。 -- `MAX_SIZE`: **4**: 附件的最大限制(MB)。 +- `MAX_SIZE`: **2048**: 附件的最大限制(MB)。 - `MAX_FILES`: **5**: 一次最多上传的附件数量。 - `STORAGE_TYPE`: **local**: 附件的存储类型,`local` 表示本地磁盘,`minio` 表示兼容 S3 的对象存储服务,如果未设置将使用默认值 `local` 或其他在 `[storage.xxx]` 中定义的名称。 - `SERVE_DIRECT`: **false**: 允许存储驱动器重定向到经过身份验证的 URL 以直接提供文件。目前,只支持 Minio/S3 通过签名 URL 提供支持,local 不会执行任何操作。 From f2ea31de36ec777a84f32dfdb242da2a3d9f1fc8 Mon Sep 17 00:00:00 2001 From: Earl Warren <109468362+earl-warren@users.noreply.github.com> Date: Mon, 13 Nov 2023 15:30:08 +0100 Subject: [PATCH 13/81] Enable system users for comment.LoadPoster (#28014) System users (Ghost, ActionsUser, etc) have a negative id and may be the author of a comment, either because it was created by a now deleted user or via an action using a transient token. The GetPossibleUserByID function has special cases related to system users and will not fail if given a negative id. Refs: https://codeberg.org/forgejo/forgejo/issues/1425 (cherry picked from commit 6a2d2fa24390116d31ae2507c0a93d423f690b7b) --- models/issues/comment.go | 2 +- tests/integration/api_comment_test.go | 37 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/models/issues/comment.go b/models/issues/comment.go index f2a3cb7b026..7fd07867dfe 100644 --- a/models/issues/comment.go +++ b/models/issues/comment.go @@ -350,7 +350,7 @@ func (c *Comment) AfterLoad(session *xorm.Session) { // LoadPoster loads comment poster func (c *Comment) LoadPoster(ctx context.Context) (err error) { - if c.PosterID <= 0 || c.Poster != nil { + if c.Poster != nil { return nil } diff --git a/tests/integration/api_comment_test.go b/tests/integration/api_comment_test.go index ee648210e5e..0be4896105b 100644 --- a/tests/integration/api_comment_test.go +++ b/tests/integration/api_comment_test.go @@ -136,6 +136,43 @@ func TestAPIGetComment(t *testing.T) { assert.Equal(t, expect.Created.Unix(), apiComment.Created.Unix()) } +func TestAPIGetSystemUserComment(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{}) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID}) + repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) + + for _, systemUser := range []*user_model.User{ + user_model.NewGhostUser(), + user_model.NewActionsUser(), + } { + body := fmt.Sprintf("Hello %s", systemUser.Name) + comment, err := issues_model.CreateComment(db.DefaultContext, &issues_model.CreateCommentOptions{ + Type: issues_model.CommentTypeComment, + Doer: systemUser, + Repo: repo, + Issue: issue, + Content: body, + }) + assert.NoError(t, err) + + req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/comments/%d", repoOwner.Name, repo.Name, comment.ID) + resp := MakeRequest(t, req, http.StatusOK) + + var apiComment api.Comment + DecodeJSON(t, resp, &apiComment) + + if assert.NotNil(t, apiComment.Poster) { + if assert.Equal(t, systemUser.ID, apiComment.Poster.ID) { + assert.NoError(t, comment.LoadPoster(db.DefaultContext)) + assert.Equal(t, systemUser.Name, apiComment.Poster.UserName) + } + } + assert.Equal(t, body, apiComment.Body) + } +} + func TestAPIEditComment(t *testing.T) { defer tests.PrepareTestEnv(t)() const newCommentBody = "This is the new comment body" From 340055ab6c579fccc9a370527ee2768bfb1466ba Mon Sep 17 00:00:00 2001 From: Earl Warren <109468362+earl-warren@users.noreply.github.com> Date: Mon, 13 Nov 2023 15:31:38 +0100 Subject: [PATCH 14/81] Enable system users search via the API (#28013) Refs: https://codeberg.org/forgejo/forgejo/issues/1403 (cherry picked from commit dd4d17c159eaf8b642aa9e6105b0532e25972bb7) --- routers/api/v1/user/user.go | 38 ++++++++++++++++------- tests/integration/api_user_search_test.go | 22 +++++++++++++ 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/routers/api/v1/user/user.go b/routers/api/v1/user/user.go index 63591383695..fb8f67d0722 100644 --- a/routers/api/v1/user/user.go +++ b/routers/api/v1/user/user.go @@ -54,19 +54,33 @@ func Search(ctx *context.APIContext) { listOptions := utils.GetListOptions(ctx) - users, maxResults, err := user_model.SearchUsers(ctx, &user_model.SearchUserOptions{ - Actor: ctx.Doer, - Keyword: ctx.FormTrim("q"), - UID: ctx.FormInt64("uid"), - Type: user_model.UserTypeIndividual, - ListOptions: listOptions, - }) - if err != nil { - ctx.JSON(http.StatusInternalServerError, map[string]any{ - "ok": false, - "error": err.Error(), + uid := ctx.FormInt64("uid") + var users []*user_model.User + var maxResults int64 + var err error + + switch uid { + case user_model.GhostUserID: + maxResults = 1 + users = []*user_model.User{user_model.NewGhostUser()} + case user_model.ActionsUserID: + maxResults = 1 + users = []*user_model.User{user_model.NewActionsUser()} + default: + users, maxResults, err = user_model.SearchUsers(ctx, &user_model.SearchUserOptions{ + Actor: ctx.Doer, + Keyword: ctx.FormTrim("q"), + UID: uid, + Type: user_model.UserTypeIndividual, + ListOptions: listOptions, }) - return + if err != nil { + ctx.JSON(http.StatusInternalServerError, map[string]any{ + "ok": false, + "error": err.Error(), + }) + return + } } ctx.SetLinkHeader(int(maxResults), listOptions.PageSize) diff --git a/tests/integration/api_user_search_test.go b/tests/integration/api_user_search_test.go index c5b202b3193..ddfeb25234b 100644 --- a/tests/integration/api_user_search_test.go +++ b/tests/integration/api_user_search_test.go @@ -56,6 +56,28 @@ func TestAPIUserSearchNotLoggedIn(t *testing.T) { } } +func TestAPIUserSearchSystemUsers(t *testing.T) { + defer tests.PrepareTestEnv(t)() + for _, systemUser := range []*user_model.User{ + user_model.NewGhostUser(), + user_model.NewActionsUser(), + } { + t.Run(systemUser.Name, func(t *testing.T) { + req := NewRequestf(t, "GET", "/api/v1/users/search?uid=%d", systemUser.ID) + resp := MakeRequest(t, req, http.StatusOK) + + var results SearchResults + DecodeJSON(t, resp, &results) + assert.NotEmpty(t, results.Data) + if assert.EqualValues(t, 1, len(results.Data)) { + user := results.Data[0] + assert.EqualValues(t, user.UserName, systemUser.Name) + assert.EqualValues(t, user.ID, systemUser.ID) + } + }) + } +} + func TestAPIUserSearchAdminLoggedInUserHidden(t *testing.T) { defer tests.PrepareTestEnv(t)() adminUsername := "user1" From 089ac06969030b0886d4e20bf8f7a757f785f158 Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Mon, 13 Nov 2023 23:33:22 +0900 Subject: [PATCH 15/81] Improve profile for Organizations (#27982) Fixes some problems in #27955: - autofocus of the search box before: if access the home page will jump to the search box ![image](https://github.com/go-gitea/gitea/assets/18380374/7f100e8d-2bd6-4563-85ba-d6008ffc71d7) after: will not jump to the search box ![image](https://github.com/go-gitea/gitea/assets/18380374/9aab382c-8ebe-4d18-b990-4adbb6c341ad) - incorrect display of overview tab before: ![image](https://github.com/go-gitea/gitea/assets/18380374/b24c79e8-9b79-4576-9276-43bd19172043) after: ![image](https://github.com/go-gitea/gitea/assets/18380374/7aab5827-f086-4874-bd84-39bd81b872f3) - improve the permission check to the private profile repo In #26295, we simply added access control to the private profile. But if user have access to the private profile repo , we should also display the profile. - add a button which can jump to the repo list? I agree @wxiaoguang 's opinion here: https://github.com/go-gitea/gitea/pull/27955#issuecomment-1803178239 But it seems that this feature is sponsored. So can we add a button which can quickly jump to the repo list or just move profile to the `overview` page? --------- Co-authored-by: silverwind --- routers/web/org/home.go | 2 +- routers/web/shared/user/header.go | 25 ++++++++++++++++--------- routers/web/user/profile.go | 2 +- templates/explore/repo_search.tmpl | 2 +- templates/user/overview/header.tmpl | 2 +- 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/routers/web/org/home.go b/routers/web/org/home.go index 4a8ebb670a7..a9adfdc03cd 100644 --- a/routers/web/org/home.go +++ b/routers/web/org/home.go @@ -157,7 +157,7 @@ func Home(ctx *context.Context) { ctx.Data["ShowMemberAndTeamTab"] = ctx.Org.IsMember || len(members) > 0 - profileGitRepo, profileReadmeBlob, profileClose := shared_user.FindUserProfileReadme(ctx) + profileGitRepo, profileReadmeBlob, profileClose := shared_user.FindUserProfileReadme(ctx, ctx.Doer) defer profileClose() prepareOrgProfileReadme(ctx, profileGitRepo, profileReadmeBlob) diff --git a/routers/web/shared/user/header.go b/routers/web/shared/user/header.go index 6d1901dd2bb..3a83722ef76 100644 --- a/routers/web/shared/user/header.go +++ b/routers/web/shared/user/header.go @@ -6,7 +6,9 @@ package user import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" + access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" + "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/git" @@ -84,18 +86,23 @@ func PrepareContextForProfileBigAvatar(ctx *context.Context) { } } -func FindUserProfileReadme(ctx *context.Context) (profileGitRepo *git.Repository, profileReadmeBlob *git.Blob, profileClose func()) { +func FindUserProfileReadme(ctx *context.Context, doer *user_model.User) (profileGitRepo *git.Repository, profileReadmeBlob *git.Blob, profileClose func()) { profileDbRepo, err := repo_model.GetRepositoryByName(ctx, ctx.ContextUser.ID, ".profile") - if err == nil && !profileDbRepo.IsEmpty && !profileDbRepo.IsPrivate { - if profileGitRepo, err = git.OpenRepository(ctx, profileDbRepo.RepoPath()); err != nil { - log.Error("FindUserProfileReadme failed to OpenRepository: %v", err) - } else { - if commit, err := profileGitRepo.GetBranchCommit(profileDbRepo.DefaultBranch); err != nil { - log.Error("FindUserProfileReadme failed to GetBranchCommit: %v", err) + if err == nil { + perm, err := access_model.GetUserRepoPermission(ctx, profileDbRepo, doer) + if err == nil && !profileDbRepo.IsEmpty && perm.CanRead(unit.TypeCode) { + if profileGitRepo, err = git.OpenRepository(ctx, profileDbRepo.RepoPath()); err != nil { + log.Error("FindUserProfileReadme failed to OpenRepository: %v", err) } else { - profileReadmeBlob, _ = commit.GetBlobByPath("README.md") + if commit, err := profileGitRepo.GetBranchCommit(profileDbRepo.DefaultBranch); err != nil { + log.Error("FindUserProfileReadme failed to GetBranchCommit: %v", err) + } else { + profileReadmeBlob, _ = commit.GetBlobByPath("README.md") + } } } + } else if !repo_model.IsErrRepoNotExist(err) { + log.Error("FindUserProfileReadme failed to GetRepositoryByName: %v", err) } return profileGitRepo, profileReadmeBlob, func() { if profileGitRepo != nil { @@ -107,7 +114,7 @@ func FindUserProfileReadme(ctx *context.Context) (profileGitRepo *git.Repository func RenderUserHeader(ctx *context.Context) { prepareContextForCommonProfile(ctx) - _, profileReadmeBlob, profileClose := FindUserProfileReadme(ctx) + _, profileReadmeBlob, profileClose := FindUserProfileReadme(ctx, ctx.Doer) defer profileClose() ctx.Data["HasProfileReadme"] = profileReadmeBlob != nil } diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go index 48a4b94c190..ac278e300d7 100644 --- a/routers/web/user/profile.go +++ b/routers/web/user/profile.go @@ -64,7 +64,7 @@ func userProfile(ctx *context.Context) { ctx.Data["HeatmapTotalContributions"] = activities_model.GetTotalContributionsInHeatmap(data) } - profileGitRepo, profileReadmeBlob, profileClose := shared_user.FindUserProfileReadme(ctx) + profileGitRepo, profileReadmeBlob, profileClose := shared_user.FindUserProfileReadme(ctx, ctx.Doer) defer profileClose() showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID) diff --git a/templates/explore/repo_search.tmpl b/templates/explore/repo_search.tmpl index 136d3f8e819..71c088ef241 100644 --- a/templates/explore/repo_search.tmpl +++ b/templates/explore/repo_search.tmpl @@ -3,7 +3,7 @@
- {{template "shared/searchinput" dict "Value" .Keyword "AutoFocus" true}} + {{template "shared/searchinput" dict "Value" .Keyword "AutoFocus" (not .ProfileReadme)}} {{if .PageIsExploreRepositories}} {{else if .TabName}} diff --git a/templates/user/overview/header.tmpl b/templates/user/overview/header.tmpl index 9b6458474e5..94d06234faa 100644 --- a/templates/user/overview/header.tmpl +++ b/templates/user/overview/header.tmpl @@ -1,5 +1,5 @@
{{if and .PageIsPullFiles $.SignedUserID (not .IsArchived) (not .DiffNotAvailable)}} -
+
diff --git a/web_src/css/repo.css b/web_src/css/repo.css index d759d10c8a0..6bddbe9ba56 100644 --- a/web_src/css/repo.css +++ b/web_src/css/repo.css @@ -1506,7 +1506,6 @@ @media (max-width: 991.98px) { .repository .diff-detail-box { flex-direction: row; - height: 77px; /* this height should match sticky-2nd-row */ } } @@ -1534,13 +1533,9 @@ color: var(--color-red); } -@media (max-width: 480px) { +@media (max-width: 991.98px) { .repository .diff-detail-box .diff-detail-stats { - font-size: 0; - line-height: 1.6rem; - } - .repository .diff-detail-box .diff-detail-stats strong { - font-size: 1rem; + display: none !important; } } @@ -1735,12 +1730,6 @@ border: none; } -@media (max-width: 991.98px) { - .diff-file-box { - scroll-margin-top: 77px; /* match .repository .diff-detail-box */ - } -} - /* TODO: this can potentially be made "global" by removing the class prefix */ .diff-file-box .ui.attached.header, .diff-file-box .ui.attached.table { @@ -2826,18 +2815,6 @@ tbody.commit-list { z-index: 7; } -@media (max-width: 991.98px) { - .ui.attached.header.diff-file-header.sticky-2nd-row { - top: 77px; /* match .repository .diff-detail-box */ - } -} - -@media (max-width: 480px) { - .ui.attached.header.diff-file-header.sticky-2nd-row { - position: static; - } -} - .diff-file-name { flex: auto; min-width: 100px; From fce1d5d7dce6a16429d0fe043555eac2c083ae7b Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Thu, 16 Nov 2023 20:53:42 +0800 Subject: [PATCH 28/81] Fix system config cache expiration timing (#28072) To avoid unnecessary database access, the `cacheTime` should always be set if the revision has been checked. Fix #28057 --- models/system/setting.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/models/system/setting.go b/models/system/setting.go index 1ae6f5c6528..507d23cff6b 100644 --- a/models/system/setting.go +++ b/models/system/setting.go @@ -115,24 +115,26 @@ func (d *dbConfigCachedGetter) GetValue(ctx context.Context, key string) (v stri func (d *dbConfigCachedGetter) GetRevision(ctx context.Context) int { d.mu.RLock() - defer d.mu.RUnlock() - if time.Since(d.cacheTime) < time.Second { - return d.revision + cachedDuration := time.Since(d.cacheTime) + cachedRevision := d.revision + d.mu.RUnlock() + + if cachedDuration < time.Second { + return cachedRevision } + + d.mu.Lock() + defer d.mu.Unlock() if GetRevision(ctx) != d.revision { - d.mu.RUnlock() - d.mu.Lock() rev, set, err := GetAllSettings(ctx) if err != nil { log.Error("Unable to get all settings: %v", err) } else { - d.cacheTime = time.Now() d.revision = rev d.settings = set } - d.mu.Unlock() - d.mu.RLock() } + d.cacheTime = time.Now() return d.revision } From 17d246cdcc0bf615ee4ba97a17c0f7e2c2f5f27f Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Fri, 17 Nov 2023 10:30:57 +0800 Subject: [PATCH 29/81] Fix incorrect pgsql conn builder behavior (#28085) Fix #28083 and fix the tests --- modules/setting/database.go | 5 +++-- modules/setting/database_test.go | 15 ++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/modules/setting/database.go b/modules/setting/database.go index aa42f506bc5..761e767e8f5 100644 --- a/modules/setting/database.go +++ b/modules/setting/database.go @@ -109,7 +109,7 @@ func DBConnStr() (string, error) { connStr = fmt.Sprintf("%s:%s@%s(%s)/%s%scharset=%s&parseTime=true&tls=%s", Database.User, Database.Passwd, connType, Database.Host, Database.Name, paramSep, Database.MysqlCharset, tls) case "postgres": - connStr = getPostgreSQLConnectionString(Database.Host, Database.User, Database.Passwd, Database.Name, paramSep, Database.SSLMode) + connStr = getPostgreSQLConnectionString(Database.Host, Database.User, Database.Passwd, Database.Name, Database.SSLMode) case "mssql": host, port := ParseMSSQLHostPort(Database.Host) connStr = fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", host, port, Database.Name, Database.User, Database.Passwd) @@ -157,7 +157,8 @@ func parsePostgreSQLHostPort(info string) (host, port string) { return host, port } -func getPostgreSQLConnectionString(dbHost, dbUser, dbPasswd, dbName, dbParam, dbsslMode string) (connStr string) { +func getPostgreSQLConnectionString(dbHost, dbUser, dbPasswd, dbName, dbsslMode string) (connStr string) { + dbName, dbParam, _ := strings.Cut(dbName, "?") host, port := parsePostgreSQLHostPort(dbHost) connURL := url.URL{ Scheme: "postgres", diff --git a/modules/setting/database_test.go b/modules/setting/database_test.go index 85271c36cb3..1d5b416504b 100644 --- a/modules/setting/database_test.go +++ b/modules/setting/database_test.go @@ -59,38 +59,39 @@ func Test_parsePostgreSQLHostPort(t *testing.T) { func Test_getPostgreSQLConnectionString(t *testing.T) { tests := []struct { Host string - Port string User string Passwd string Name string - Param string SSLMode string Output string }{ { Host: "/tmp/pg.sock", - Port: "4321", User: "testuser", Passwd: "space space !#$%^^%^```-=?=", Name: "gitea", - Param: "", SSLMode: "false", Output: "postgres://testuser:space%20space%20%21%23$%25%5E%5E%25%5E%60%60%60-=%3F=@:5432/gitea?host=%2Ftmp%2Fpg.sock&sslmode=false", }, { Host: "localhost", - Port: "1234", User: "pgsqlusername", Passwd: "I love Gitea!", Name: "gitea", - Param: "", SSLMode: "true", Output: "postgres://pgsqlusername:I%20love%20Gitea%21@localhost:5432/gitea?sslmode=true", }, + { + Host: "localhost:1234", + User: "user", + Passwd: "pass", + Name: "gitea?param=1", + Output: "postgres://user:pass@localhost:1234/gitea?param=1&sslmode=", + }, } for _, test := range tests { - connStr := getPostgreSQLConnectionString(test.Host, test.User, test.Passwd, test.Name, test.Param, test.SSLMode) + connStr := getPostgreSQLConnectionString(test.Host, test.User, test.Passwd, test.Name, test.SSLMode) assert.Equal(t, test.Output, connStr) } } From 58f5fa653676fefc9b497e2cc18af976f749273c Mon Sep 17 00:00:00 2001 From: KN4CK3R Date: Fri, 17 Nov 2023 12:17:33 +0100 Subject: [PATCH 30/81] Fix Matrix and MSTeams nil dereference (#28089) Fixes #28088 Fixes #28094 Added missing tests. --------- Co-authored-by: Lunny Xiao --- services/webhook/dingtalk_test.go | 15 +++++++++++++++ services/webhook/discord_test.go | 18 ++++++++++++++++++ services/webhook/feishu_test.go | 12 ++++++++++++ services/webhook/general_test.go | 30 ++++++++++++++++++++++++++++++ services/webhook/matrix.go | 6 +++--- services/webhook/matrix_test.go | 13 +++++++++++++ services/webhook/msteams.go | 7 ++++--- services/webhook/msteams_test.go | 27 +++++++++++++++++++++++++++ services/webhook/packagist_test.go | 9 +++++++++ services/webhook/slack_test.go | 12 ++++++++++++ services/webhook/telegram_test.go | 12 ++++++++++++ 11 files changed, 155 insertions(+), 6 deletions(-) diff --git a/services/webhook/dingtalk_test.go b/services/webhook/dingtalk_test.go index 7289c751f38..a03fa46f145 100644 --- a/services/webhook/dingtalk_test.go +++ b/services/webhook/dingtalk_test.go @@ -188,6 +188,21 @@ func TestDingTalkPayload(t *testing.T) { assert.Equal(t, "http://localhost:3000/test/repo", parseRealSingleURL(pl.(*DingtalkPayload).ActionCard.SingleURL)) }) + t.Run("Package", func(t *testing.T) { + p := packageTestPayload() + + d := new(DingtalkPayload) + pl, err := d.Package(p) + require.NoError(t, err) + require.NotNil(t, pl) + require.IsType(t, &DingtalkPayload{}, pl) + + assert.Equal(t, "Package created: GiteaContainer:latest by user1", pl.(*DingtalkPayload).ActionCard.Text) + assert.Equal(t, "Package created: GiteaContainer:latest by user1", pl.(*DingtalkPayload).ActionCard.Title) + assert.Equal(t, "view package", pl.(*DingtalkPayload).ActionCard.SingleTitle) + assert.Equal(t, "http://localhost:3000/user1/-/packages/container/GiteaContainer/latest", parseRealSingleURL(pl.(*DingtalkPayload).ActionCard.SingleURL)) + }) + t.Run("Wiki", func(t *testing.T) { p := wikiTestPayload() diff --git a/services/webhook/discord_test.go b/services/webhook/discord_test.go index 6a276e9e874..b567cbc395d 100644 --- a/services/webhook/discord_test.go +++ b/services/webhook/discord_test.go @@ -211,6 +211,24 @@ func TestDiscordPayload(t *testing.T) { assert.Equal(t, p.Sender.AvatarURL, pl.(*DiscordPayload).Embeds[0].Author.IconURL) }) + t.Run("Package", func(t *testing.T) { + p := packageTestPayload() + + d := new(DiscordPayload) + pl, err := d.Package(p) + require.NoError(t, err) + require.NotNil(t, pl) + require.IsType(t, &DiscordPayload{}, pl) + + assert.Len(t, pl.(*DiscordPayload).Embeds, 1) + assert.Equal(t, "Package created: GiteaContainer:latest", pl.(*DiscordPayload).Embeds[0].Title) + assert.Empty(t, pl.(*DiscordPayload).Embeds[0].Description) + assert.Equal(t, "http://localhost:3000/user1/-/packages/container/GiteaContainer/latest", pl.(*DiscordPayload).Embeds[0].URL) + assert.Equal(t, p.Sender.UserName, pl.(*DiscordPayload).Embeds[0].Author.Name) + assert.Equal(t, setting.AppURL+p.Sender.UserName, pl.(*DiscordPayload).Embeds[0].Author.URL) + assert.Equal(t, p.Sender.AvatarURL, pl.(*DiscordPayload).Embeds[0].Author.IconURL) + }) + t.Run("Wiki", func(t *testing.T) { p := wikiTestPayload() diff --git a/services/webhook/feishu_test.go b/services/webhook/feishu_test.go index a3182e82b09..98bc50dedec 100644 --- a/services/webhook/feishu_test.go +++ b/services/webhook/feishu_test.go @@ -144,6 +144,18 @@ func TestFeishuPayload(t *testing.T) { assert.Equal(t, "[test/repo] Repository created", pl.(*FeishuPayload).Content.Text) }) + t.Run("Package", func(t *testing.T) { + p := packageTestPayload() + + d := new(FeishuPayload) + pl, err := d.Package(p) + require.NoError(t, err) + require.NotNil(t, pl) + require.IsType(t, &FeishuPayload{}, pl) + + assert.Equal(t, "Package created: GiteaContainer:latest by user1", pl.(*FeishuPayload).Content.Text) + }) + t.Run("Wiki", func(t *testing.T) { p := wikiTestPayload() diff --git a/services/webhook/general_test.go b/services/webhook/general_test.go index a9a8c6b5212..41bac3fd04d 100644 --- a/services/webhook/general_test.go +++ b/services/webhook/general_test.go @@ -303,6 +303,36 @@ func repositoryTestPayload() *api.RepositoryPayload { } } +func packageTestPayload() *api.PackagePayload { + return &api.PackagePayload{ + Action: api.HookPackageCreated, + Sender: &api.User{ + UserName: "user1", + AvatarURL: "http://localhost:3000/user1/avatar", + }, + Repository: nil, + Organization: &api.User{ + UserName: "org1", + AvatarURL: "http://localhost:3000/org1/avatar", + }, + Package: &api.Package{ + Owner: &api.User{ + UserName: "user1", + AvatarURL: "http://localhost:3000/user1/avatar", + }, + Repository: nil, + Creator: &api.User{ + UserName: "user1", + AvatarURL: "http://localhost:3000/user1/avatar", + }, + Type: "container", + Name: "GiteaContainer", + Version: "latest", + HTMLURL: "http://localhost:3000/user1/-/packages/container/GiteaContainer/latest", + }, + } +} + func TestGetIssuesPayloadInfo(t *testing.T) { p := issueTestPayload() diff --git a/services/webhook/matrix.go b/services/webhook/matrix.go index ab7e6b72c25..602d16ef39b 100644 --- a/services/webhook/matrix.go +++ b/services/webhook/matrix.go @@ -212,14 +212,14 @@ func (m *MatrixPayload) Repository(p *api.RepositoryPayload) (api.Payloader, err func (m *MatrixPayload) Package(p *api.PackagePayload) (api.Payloader, error) { senderLink := MatrixLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName) - repoLink := MatrixLinkFormatter(p.Repository.HTMLURL, p.Repository.FullName) + packageLink := MatrixLinkFormatter(p.Package.HTMLURL, p.Package.Name) var text string switch p.Action { case api.HookPackageCreated: - text = fmt.Sprintf("[%s] Package published by %s", repoLink, senderLink) + text = fmt.Sprintf("[%s] Package published by %s", packageLink, senderLink) case api.HookPackageDeleted: - text = fmt.Sprintf("[%s] Package deleted by %s", repoLink, senderLink) + text = fmt.Sprintf("[%s] Package deleted by %s", packageLink, senderLink) } return getMatrixPayload(text, nil, m.MsgType), nil diff --git a/services/webhook/matrix_test.go b/services/webhook/matrix_test.go index 8c710942280..99a22fbd7eb 100644 --- a/services/webhook/matrix_test.go +++ b/services/webhook/matrix_test.go @@ -155,6 +155,19 @@ func TestMatrixPayload(t *testing.T) { assert.Equal(t, `[test/repo] Repository created by user1`, pl.(*MatrixPayload).FormattedBody) }) + t.Run("Package", func(t *testing.T) { + p := packageTestPayload() + + d := new(MatrixPayload) + pl, err := d.Package(p) + require.NoError(t, err) + require.NotNil(t, pl) + require.IsType(t, &MatrixPayload{}, pl) + + assert.Equal(t, `[[GiteaContainer](http://localhost:3000/user1/-/packages/container/GiteaContainer/latest)] Package published by [user1](https://try.gitea.io/user1)`, pl.(*MatrixPayload).Body) + assert.Equal(t, `[GiteaContainer] Package published by user1`, pl.(*MatrixPayload).FormattedBody) + }) + t.Run("Wiki", func(t *testing.T) { p := wikiTestPayload() diff --git a/services/webhook/msteams.go b/services/webhook/msteams.go index f58da3fe1cd..37810b4cd39 100644 --- a/services/webhook/msteams.go +++ b/services/webhook/msteams.go @@ -316,11 +316,12 @@ func GetMSTeamsPayload(p api.Payloader, event webhook_module.HookEventType, _ st } func createMSTeamsPayload(r *api.Repository, s *api.User, title, text, actionTarget string, color int, fact *MSTeamsFact) *MSTeamsPayload { - facts := []MSTeamsFact{ - { + facts := make([]MSTeamsFact, 0, 2) + if r != nil { + facts = append(facts, MSTeamsFact{ Name: "Repository:", Value: r.FullName, - }, + }) } if fact != nil { facts = append(facts, *fact) diff --git a/services/webhook/msteams_test.go b/services/webhook/msteams_test.go index 990a535df5c..8d1aed60408 100644 --- a/services/webhook/msteams_test.go +++ b/services/webhook/msteams_test.go @@ -329,6 +329,33 @@ func TestMSTeamsPayload(t *testing.T) { assert.Equal(t, "http://localhost:3000/test/repo", pl.(*MSTeamsPayload).PotentialAction[0].Targets[0].URI) }) + t.Run("Package", func(t *testing.T) { + p := packageTestPayload() + + d := new(MSTeamsPayload) + pl, err := d.Package(p) + require.NoError(t, err) + require.NotNil(t, pl) + require.IsType(t, &MSTeamsPayload{}, pl) + + assert.Equal(t, "Package created: GiteaContainer:latest", pl.(*MSTeamsPayload).Title) + assert.Equal(t, "Package created: GiteaContainer:latest", pl.(*MSTeamsPayload).Summary) + assert.Len(t, pl.(*MSTeamsPayload).Sections, 1) + assert.Equal(t, "user1", pl.(*MSTeamsPayload).Sections[0].ActivitySubtitle) + assert.Empty(t, pl.(*MSTeamsPayload).Sections[0].Text) + assert.Len(t, pl.(*MSTeamsPayload).Sections[0].Facts, 1) + for _, fact := range pl.(*MSTeamsPayload).Sections[0].Facts { + if fact.Name == "Package:" { + assert.Equal(t, p.Package.Name, fact.Value) + } else { + t.Fail() + } + } + assert.Len(t, pl.(*MSTeamsPayload).PotentialAction, 1) + assert.Len(t, pl.(*MSTeamsPayload).PotentialAction[0].Targets, 1) + assert.Equal(t, "http://localhost:3000/user1/-/packages/container/GiteaContainer/latest", pl.(*MSTeamsPayload).PotentialAction[0].Targets[0].URI) + }) + t.Run("Wiki", func(t *testing.T) { p := wikiTestPayload() diff --git a/services/webhook/packagist_test.go b/services/webhook/packagist_test.go index 932b56fe9b9..26d01b0555d 100644 --- a/services/webhook/packagist_test.go +++ b/services/webhook/packagist_test.go @@ -115,6 +115,15 @@ func TestPackagistPayload(t *testing.T) { require.Nil(t, pl) }) + t.Run("Package", func(t *testing.T) { + p := packageTestPayload() + + d := new(PackagistPayload) + pl, err := d.Package(p) + require.NoError(t, err) + require.Nil(t, pl) + }) + t.Run("Wiki", func(t *testing.T) { p := wikiTestPayload() diff --git a/services/webhook/slack_test.go b/services/webhook/slack_test.go index d9828f374f0..b1340963e23 100644 --- a/services/webhook/slack_test.go +++ b/services/webhook/slack_test.go @@ -144,6 +144,18 @@ func TestSlackPayload(t *testing.T) { assert.Equal(t, "[] Repository created by ", pl.(*SlackPayload).Text) }) + t.Run("Package", func(t *testing.T) { + p := packageTestPayload() + + d := new(SlackPayload) + pl, err := d.Package(p) + require.NoError(t, err) + require.NotNil(t, pl) + require.IsType(t, &SlackPayload{}, pl) + + assert.Equal(t, "Package created: by ", pl.(*SlackPayload).Text) + }) + t.Run("Wiki", func(t *testing.T) { p := wikiTestPayload() diff --git a/services/webhook/telegram_test.go b/services/webhook/telegram_test.go index b42b0ccda88..5b9927d0571 100644 --- a/services/webhook/telegram_test.go +++ b/services/webhook/telegram_test.go @@ -144,6 +144,18 @@ func TestTelegramPayload(t *testing.T) { assert.Equal(t, `[test/repo] Repository created`, pl.(*TelegramPayload).Message) }) + t.Run("Package", func(t *testing.T) { + p := packageTestPayload() + + d := new(TelegramPayload) + pl, err := d.Package(p) + require.NoError(t, err) + require.NotNil(t, pl) + require.IsType(t, &TelegramPayload{}, pl) + + assert.Equal(t, `Package created: GiteaContainer:latest by user1`, pl.(*TelegramPayload).Message) + }) + t.Run("Wiki", func(t *testing.T) { p := wikiTestPayload() From f63b1166970705454f62059cf46f3fbc6f0c8871 Mon Sep 17 00:00:00 2001 From: Nanguan Lin <70063547+lng2020@users.noreply.github.com> Date: Fri, 17 Nov 2023 19:42:00 +0800 Subject: [PATCH 31/81] Change default size of attachments and repo files (#28100) https://github.com/go-gitea/gitea/pull/27946 forgets to change them in code. Sorry about that. --- modules/setting/attachment.go | 2 +- modules/setting/repository.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/setting/attachment.go b/modules/setting/attachment.go index 491564c9dcc..007aae9d044 100644 --- a/modules/setting/attachment.go +++ b/modules/setting/attachment.go @@ -13,7 +13,7 @@ var Attachment = struct { }{ Storage: &Storage{}, AllowedTypes: ".csv,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip", - MaxSize: 4, + MaxSize: 2048, MaxFiles: 5, Enabled: true, } diff --git a/modules/setting/repository.go b/modules/setting/repository.go index 42ffb99138a..9697a851d3b 100644 --- a/modules/setting/repository.go +++ b/modules/setting/repository.go @@ -184,7 +184,7 @@ var ( Enabled: true, TempPath: "data/tmp/uploads", AllowedTypes: "", - FileMaxSize: 3, + FileMaxSize: 50, MaxFiles: 5, }, From e31c6cfe6e30341c502302d1c0a03138f8bf5c9f Mon Sep 17 00:00:00 2001 From: sebastian-sauer Date: Fri, 17 Nov 2023 19:35:51 +0100 Subject: [PATCH 32/81] Fix Show/hide filetree button on small displays (#27881) the gt-df's display:flex !important did override the display:none on small displays --------- Co-authored-by: wxiaoguang --- templates/repo/diff/box.tmpl | 4 ++-- web_src/css/repo.css | 20 -------------------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/templates/repo/diff/box.tmpl b/templates/repo/diff/box.tmpl index e72ac1eeaef..1224bbe84c4 100644 --- a/templates/repo/diff/box.tmpl +++ b/templates/repo/diff/box.tmpl @@ -3,7 +3,7 @@
{{if $showFileTree}} -
diff --git a/templates/admin/emails/list.tmpl b/templates/admin/emails/list.tmpl index 84afc0585f6..bcd80368e66 100644 --- a/templates/admin/emails/list.tmpl +++ b/templates/admin/emails/list.tmpl @@ -7,7 +7,7 @@