diff --git a/.eslintrc.yaml b/.eslintrc.yaml index f87a4149ac36..878b74cba4dc 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -15,6 +15,7 @@ plugins: - eslint-plugin-no-jquery - eslint-plugin-sonarjs - eslint-plugin-custom-elements + - eslint-plugin-regexp env: es2022: true @@ -472,6 +473,80 @@ rules: quote-props: [0] quotes: [2, single, {avoidEscape: true, allowTemplateLiterals: true}] radix: [2, as-needed] + regexp/confusing-quantifier: [2] + regexp/control-character-escape: [2] + regexp/hexadecimal-escape: [0] + regexp/letter-case: [0] + regexp/match-any: [2] + regexp/negation: [2] + regexp/no-contradiction-with-assertion: [0] + regexp/no-control-character: [0] + regexp/no-dupe-characters-character-class: [2] + regexp/no-dupe-disjunctions: [2] + regexp/no-empty-alternative: [2] + regexp/no-empty-capturing-group: [2] + regexp/no-empty-character-class: [0] + regexp/no-empty-group: [2] + regexp/no-empty-lookarounds-assertion: [2] + regexp/no-escape-backspace: [2] + regexp/no-extra-lookaround-assertions: [0] + regexp/no-invalid-regexp: [2] + regexp/no-invisible-character: [2] + regexp/no-lazy-ends: [2] + regexp/no-legacy-features: [2] + regexp/no-misleading-capturing-group: [0] + regexp/no-misleading-unicode-character: [0] + regexp/no-missing-g-flag: [2] + regexp/no-non-standard-flag: [2] + regexp/no-obscure-range: [2] + regexp/no-octal: [2] + regexp/no-optional-assertion: [2] + regexp/no-potentially-useless-backreference: [2] + regexp/no-standalone-backslash: [2] + regexp/no-super-linear-backtracking: [0] + regexp/no-super-linear-move: [0] + regexp/no-trivially-nested-assertion: [2] + regexp/no-trivially-nested-quantifier: [2] + regexp/no-unused-capturing-group: [0] + regexp/no-useless-assertions: [2] + regexp/no-useless-backreference: [2] + regexp/no-useless-character-class: [2] + regexp/no-useless-dollar-replacements: [2] + regexp/no-useless-escape: [2] + regexp/no-useless-flag: [2] + regexp/no-useless-lazy: [2] + regexp/no-useless-non-capturing-group: [2] + regexp/no-useless-quantifier: [2] + regexp/no-useless-range: [2] + regexp/no-useless-two-nums-quantifier: [2] + regexp/no-zero-quantifier: [2] + regexp/optimal-lookaround-quantifier: [2] + regexp/optimal-quantifier-concatenation: [0] + regexp/prefer-character-class: [0] + regexp/prefer-d: [0] + regexp/prefer-escape-replacement-dollar-char: [0] + regexp/prefer-lookaround: [0] + regexp/prefer-named-backreference: [0] + regexp/prefer-named-capture-group: [0] + regexp/prefer-named-replacement: [0] + regexp/prefer-plus-quantifier: [2] + regexp/prefer-predefined-assertion: [2] + regexp/prefer-quantifier: [0] + regexp/prefer-question-quantifier: [2] + regexp/prefer-range: [2] + regexp/prefer-regexp-exec: [2] + regexp/prefer-regexp-test: [2] + regexp/prefer-result-array-groups: [0] + regexp/prefer-star-quantifier: [2] + regexp/prefer-unicode-codepoint-escapes: [2] + regexp/prefer-w: [0] + regexp/require-unicode-regexp: [0] + regexp/sort-alternatives: [0] + regexp/sort-character-class-elements: [0] + regexp/sort-flags: [0] + regexp/strict: [2] + regexp/unicode-escape: [0] + regexp/use-ignore-case: [0] require-atomic-updates: [0] require-await: [0] require-unicode-regexp: [0] diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index 29ebb4699bc1..3687e0fbd4ca 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -992,7 +992,7 @@ ROUTER = console ;; ;; List of file extensions for which lines should be wrapped in the Monaco editor ;; Separate extensions with a comma. To line wrap files without an extension, just put a comma -;LINE_WRAP_EXTENSIONS = .txt,.md,.markdown,.mdown,.mkd, +;LINE_WRAP_EXTENSIONS = .txt,.md,.markdown,.mdown,.mkd,.livemd, ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1203,10 +1203,9 @@ ROUTER = console ;; Number of line of codes shown for a code comment ;CODE_COMMENT_LINES = 4 ;; -;; Value of `theme-color` meta tag, used by Android >= 5.0 -;; An invalid color like "none" or "disable" will have the default style -;; More info: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android -;THEME_COLOR_META_TAG = `#6cc644` +;; Value of `theme-color` meta tag, used by some mobile browers for chrome and +;; out-of-viewport areas. Default is unset which uses body color. +;THEME_COLOR_META_TAG = ;; ;; Max size of files to be displayed (default is 8MiB) ;MAX_DISPLAY_FILE_SIZE = 8388608 @@ -1335,7 +1334,7 @@ ROUTER = console ;; ;; List of file extensions that should be rendered/edited as Markdown ;; Separate the extensions with a comma. To render files without any extension as markdown, just put a comma -;FILE_EXTENSIONS = .md,.markdown,.mdown,.mkd +;FILE_EXTENSIONS = .md,.markdown,.mdown,.mkd,.livemd ;; ;; Enables math inline and block detection ;ENABLE_MATH = true diff --git a/docs/assets/js/search.js b/docs/assets/js/search.js index 315a5ebd9181..f731e0b224c7 100644 --- a/docs/assets/js/search.js +++ b/docs/assets/js/search.js @@ -138,8 +138,8 @@ function populateResults(result) { function render(templateString, data) { let conditionalMatches, copy; - const conditionalPattern = /\$\{\s*isset ([a-zA-Z]*) \s*\}(.*)\$\{\s*end\s*}/g; - // since loop below depends on re.lastInxdex, we use a copy to capture any manipulations whilst inside the loop + const conditionalPattern = /\$\{\s*isset ([a-zA-Z]*) \s*\}(.*)\$\{\s*end\s*\}/g; + // since loop below depends on re.lastIndex, we use a copy to capture any manipulations whilst inside the loop copy = templateString; while ((conditionalMatches = conditionalPattern.exec(templateString)) !== null) { if (data[conditionalMatches[1]]) { diff --git a/docs/config.yaml b/docs/config.yaml index d79a91b0a4f9..90a4c808f741 100644 --- a/docs/config.yaml +++ b/docs/config.yaml @@ -10,7 +10,7 @@ enableEmoji: true permalinks: post: /:year/:month/:title/ - doc: /:slug/ + doc: /:sections[1:]/:slug/ page: /:slug/ default: /:slug/ diff --git a/docs/content/doc/administration/_index.en-us.md b/docs/content/doc/administration/_index.en-us.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/administration/_index.zh-cn.md b/docs/content/doc/administration/_index.zh-cn.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/administration/_index.zh-tw.md b/docs/content/doc/administration/_index.zh-tw.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/administration/adding-legal-pages.en-us.md b/docs/content/doc/administration/adding-legal-pages.en-us.md index 48aa21154ce5..6de145ce09ca 100644 --- a/docs/content/doc/administration/adding-legal-pages.en-us.md +++ b/docs/content/doc/administration/adding-legal-pages.en-us.md @@ -5,6 +5,8 @@ slug: adding-legal-pages weight: 110 toc: false draft: false +aliases: + - /en-us/adding-legal-pages menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/backup-and-restore.en-us.md b/docs/content/doc/administration/backup-and-restore.en-us.md index b1e5a6aee013..7dee038b5750 100644 --- a/docs/content/doc/administration/backup-and-restore.en-us.md +++ b/docs/content/doc/administration/backup-and-restore.en-us.md @@ -5,6 +5,8 @@ slug: "backup-and-restore" weight: 11 toc: false draft: false +aliases: + - /en-us/backup-and-restore menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/backup-and-restore.zh-cn.md b/docs/content/doc/administration/backup-and-restore.zh-cn.md index 602657f4194c..1a8f620a8dcd 100644 --- a/docs/content/doc/administration/backup-and-restore.zh-cn.md +++ b/docs/content/doc/administration/backup-and-restore.zh-cn.md @@ -5,6 +5,8 @@ slug: "backup-and-restore" weight: 11 toc: false draft: false +aliases: + - /zh-cn/backup-and-restore menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/backup-and-restore.zh-tw.md b/docs/content/doc/administration/backup-and-restore.zh-tw.md index cab95217a38b..07b9b0726b4d 100644 --- a/docs/content/doc/administration/backup-and-restore.zh-tw.md +++ b/docs/content/doc/administration/backup-and-restore.zh-tw.md @@ -5,6 +5,8 @@ slug: "backup-and-restore" weight: 11 toc: false draft: false +aliases: + - /zh-tw/backup-and-restore menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/cmd-embedded.en-us.md b/docs/content/doc/administration/cmd-embedded.en-us.md index 229a1c01d6d9..e418138ed782 100644 --- a/docs/content/doc/administration/cmd-embedded.en-us.md +++ b/docs/content/doc/administration/cmd-embedded.en-us.md @@ -5,6 +5,8 @@ slug: "cmd-embedded" weight: 20 toc: false draft: false +aliases: + - /en-us/cmd-embedded menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/command-line.en-us.md b/docs/content/doc/administration/command-line.en-us.md index 4d01d6e640ef..bf4578afec5c 100644 --- a/docs/content/doc/administration/command-line.en-us.md +++ b/docs/content/doc/administration/command-line.en-us.md @@ -5,6 +5,8 @@ slug: "command-line" weight: 1 toc: false draft: false +aliases: + - /en-us/command-line menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/config-cheat-sheet.en-us.md b/docs/content/doc/administration/config-cheat-sheet.en-us.md index 772e0535e91e..03cd93f91eba 100644 --- a/docs/content/doc/administration/config-cheat-sheet.en-us.md +++ b/docs/content/doc/administration/config-cheat-sheet.en-us.md @@ -5,6 +5,8 @@ slug: "config-cheat-sheet" weight: 30 toc: false draft: false +aliases: + - /en-us/config-cheat-sheet menu: sidebar: parent: "administration" @@ -117,7 +119,7 @@ In addition there is _`StaticRootPath`_ which can be set as a built-in at build ### Repository - Editor (`repository.editor`) -- `LINE_WRAP_EXTENSIONS`: **.txt,.md,.markdown,.mdown,.mkd,**: List of file extensions for which lines should be wrapped in the Monaco editor. Separate extensions with a comma. To line wrap files without an extension, just put a comma +- `LINE_WRAP_EXTENSIONS`: **.txt,.md,.markdown,.mdown,.mkd,.livemd,**: List of file extensions for which lines should be wrapped in the Monaco editor. Separate extensions with a comma. To line wrap files without an extension, just put a comma - `PREVIEWABLE_FILE_MODES`: **markdown**: Valid file modes that have a preview API associated with them, such as `api/v1/markdown`. Separate the values by commas. The preview tab in edit mode won't be displayed if the file extension doesn't match. ### Repository - Pull Request (`repository.pull-request`) @@ -220,7 +222,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a - `SHOW_USER_EMAIL`: **true**: Whether the email of the user should be shown in the Explore Users page. - `THEMES`: **auto,gitea,arc-green**: All available themes. Allow users select personalized themes. regardless of the value of `DEFAULT_THEME`. -- `THEME_COLOR_META_TAG`: **#6cc644**: Value of `theme-color` meta tag, used by Android >= 5.0. An invalid color like "none" or "disable" will have the default style. More info: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android +- `THEME_COLOR_META_TAG`: **\**: Value of `theme-color` meta tag, used by some mobile browers for chrome and out-of-viewport areas. Default is unset which uses body color. - `MAX_DISPLAY_FILE_SIZE`: **8388608**: Max size of files to be displayed (default is 8MiB) - `REACTIONS`: All available reactions users can choose on issues/prs and comments Values can be emoji alias (:smile:) or a unicode emoji. @@ -277,6 +279,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a - `CUSTOM_URL_SCHEMES`: Use a comma separated list (ftp,git,svn) to indicate additional URL hyperlinks to be rendered in Markdown. URLs beginning in http and https are always displayed +- `FILE_EXTENSIONS`: **.md,.markdown,.mdown,.mkd,.livemd**: List of file extensions that should be rendered/edited as Markdown. Separate the extensions with a comma. To render files without any extension as markdown, just put a comma. - `ENABLE_MATH`: **true**: Enables detection of `\(...\)`, `\[...\]`, `$...$` and `$$...$$` blocks as math blocks. ## Server (`server`) diff --git a/docs/content/doc/administration/config-cheat-sheet.zh-cn.md b/docs/content/doc/administration/config-cheat-sheet.zh-cn.md index 485d10623469..eb015908bbcd 100644 --- a/docs/content/doc/administration/config-cheat-sheet.zh-cn.md +++ b/docs/content/doc/administration/config-cheat-sheet.zh-cn.md @@ -5,6 +5,8 @@ slug: "config-cheat-sheet" weight: 30 toc: false draft: false +aliases: + - /zh-cn/config-cheat-sheet menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/customizing-gitea.en-us.md b/docs/content/doc/administration/customizing-gitea.en-us.md index db31dc949b7d..54ce2a715f94 100644 --- a/docs/content/doc/administration/customizing-gitea.en-us.md +++ b/docs/content/doc/administration/customizing-gitea.en-us.md @@ -5,6 +5,8 @@ slug: "customizing-gitea" weight: 100 toc: false draft: false +aliases: + - /en-us/customizing-gitea menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/customizing-gitea.zh-cn.md b/docs/content/doc/administration/customizing-gitea.zh-cn.md index 38729153f50a..47230ddeb225 100644 --- a/docs/content/doc/administration/customizing-gitea.zh-cn.md +++ b/docs/content/doc/administration/customizing-gitea.zh-cn.md @@ -5,6 +5,8 @@ slug: "customizing-gitea" weight: 100 toc: false draft: false +aliases: + - /zh-cn/customizing-gitea menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/email-setup.en-us.md b/docs/content/doc/administration/email-setup.en-us.md index b8a3324f1644..92ec95cce424 100644 --- a/docs/content/doc/administration/email-setup.en-us.md +++ b/docs/content/doc/administration/email-setup.en-us.md @@ -5,6 +5,8 @@ slug: "email-setup" weight: 12 toc: false draft: false +aliases: + - /en-us/email-setup menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/environment-variables.en-us.md b/docs/content/doc/administration/environment-variables.en-us.md index 83ff6f359aa2..92dbeb80c649 100644 --- a/docs/content/doc/administration/environment-variables.en-us.md +++ b/docs/content/doc/administration/environment-variables.en-us.md @@ -5,6 +5,8 @@ slug: "environment-variables" weight: 10 toc: false draft: false +aliases: + - /en-us/environment-variables menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/environment-variables.zh-cn.md b/docs/content/doc/administration/environment-variables.zh-cn.md index e1488385811c..cbc9787c35a2 100644 --- a/docs/content/doc/administration/environment-variables.zh-cn.md +++ b/docs/content/doc/administration/environment-variables.zh-cn.md @@ -5,6 +5,8 @@ slug: "environment-variables" weight: 10 toc: false draft: false +aliases: + - /zh-cn/environment-variables menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/external-renderers.en-us.md b/docs/content/doc/administration/external-renderers.en-us.md index a62c20e32677..5e64bb847fa7 100644 --- a/docs/content/doc/administration/external-renderers.en-us.md +++ b/docs/content/doc/administration/external-renderers.en-us.md @@ -5,6 +5,8 @@ slug: "external-renderers" weight: 60 toc: false draft: false +aliases: + - /en-us/external-renderers menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/fail2ban-setup.en-us.md b/docs/content/doc/administration/fail2ban-setup.en-us.md index 420c6ae54924..1638e0dd1f9a 100644 --- a/docs/content/doc/administration/fail2ban-setup.en-us.md +++ b/docs/content/doc/administration/fail2ban-setup.en-us.md @@ -5,6 +5,8 @@ slug: "fail2ban-setup" weight: 16 toc: false draft: false +aliases: + - /en-us/fail2ban-setup menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/fail2ban-setup.zh-cn.md b/docs/content/doc/administration/fail2ban-setup.zh-cn.md index 920d3f4af2f7..f4f3cff4ca70 100644 --- a/docs/content/doc/administration/fail2ban-setup.zh-cn.md +++ b/docs/content/doc/administration/fail2ban-setup.zh-cn.md @@ -5,6 +5,8 @@ slug: "fail2ban-setup" weight: 16 toc: false draft: false +aliases: + - /zh-cn/fail2ban-setup menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/git-lfs-support.en-us.md b/docs/content/doc/administration/git-lfs-support.en-us.md index 95f4b95887f5..884b19896a51 100644 --- a/docs/content/doc/administration/git-lfs-support.en-us.md +++ b/docs/content/doc/administration/git-lfs-support.en-us.md @@ -5,6 +5,8 @@ slug: "git-lfs-setup" weight: 12 toc: false draft: false +aliases: + - /en-us/git-lfs-setup menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/https-support.en-us.md b/docs/content/doc/administration/https-support.en-us.md index f5cd28682312..d59ae2e8ee26 100644 --- a/docs/content/doc/administration/https-support.en-us.md +++ b/docs/content/doc/administration/https-support.en-us.md @@ -5,6 +5,8 @@ slug: "https-setup" weight: 12 toc: false draft: false +aliases: + - /en-us/https-setup menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/logging-documentation.en-us.md b/docs/content/doc/administration/logging-documentation.en-us.md index 029eb5de095f..3b2bf8076922 100644 --- a/docs/content/doc/administration/logging-documentation.en-us.md +++ b/docs/content/doc/administration/logging-documentation.en-us.md @@ -5,6 +5,8 @@ slug: "logging-configuration" weight: 40 toc: false draft: false +aliases: + - /en-us/logging-configuration menu: sidebar: parent: "administration" @@ -29,7 +31,7 @@ As mentioned below, there is a fully functional log output by default, so it is ## Collecting Logs for Help -To collect logs for help and issue report, see [Support Options]({{< relref "doc/help/seek-help.en-us.md" >}}). +To collect logs for help and issue report, see [Support Options]({{< relref "doc/help/support.en-us.md" >}}). ## The `[log]` section diff --git a/docs/content/doc/administration/mail-templates.en-us.md b/docs/content/doc/administration/mail-templates.en-us.md index bc4b2ead309b..0740ccaa5fa3 100644 --- a/docs/content/doc/administration/mail-templates.en-us.md +++ b/docs/content/doc/administration/mail-templates.en-us.md @@ -5,6 +5,8 @@ slug: "mail-templates" weight: 45 toc: false draft: false +aliases: + - /en-us/mail-templates menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/repo-indexer.en-us.md b/docs/content/doc/administration/repo-indexer.en-us.md index 11ce547a0d7a..81d224347670 100644 --- a/docs/content/doc/administration/repo-indexer.en-us.md +++ b/docs/content/doc/administration/repo-indexer.en-us.md @@ -5,6 +5,8 @@ slug: "repo-indexer" weight: 45 toc: false draft: false +aliases: + - /en-us/repo-indexer menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/reverse-proxies.en-us.md b/docs/content/doc/administration/reverse-proxies.en-us.md index 5132ee83f147..d11552bb9fa3 100644 --- a/docs/content/doc/administration/reverse-proxies.en-us.md +++ b/docs/content/doc/administration/reverse-proxies.en-us.md @@ -5,6 +5,8 @@ slug: "reverse-proxies" weight: 16 toc: false draft: false +aliases: + - /en-us/reverse-proxies menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/reverse-proxies.zh-cn.md b/docs/content/doc/administration/reverse-proxies.zh-cn.md index e622773df1bd..6504f7209bff 100644 --- a/docs/content/doc/administration/reverse-proxies.zh-cn.md +++ b/docs/content/doc/administration/reverse-proxies.zh-cn.md @@ -5,6 +5,8 @@ slug: "reverse-proxies" weight: 16 toc: false draft: false +aliases: + - /zh-cn/reverse-proxies menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/search-engines-indexation.en-us.md b/docs/content/doc/administration/search-engines-indexation.en-us.md index 8c7f79d4b87f..27427531ce7d 100644 --- a/docs/content/doc/administration/search-engines-indexation.en-us.md +++ b/docs/content/doc/administration/search-engines-indexation.en-us.md @@ -5,6 +5,8 @@ slug: "search-engines-indexation" weight: 60 toc: false draft: false +aliases: + - /en-us/search-engines-indexation menu: sidebar: parent: "administration" diff --git a/docs/content/doc/administration/signing.en-us.md b/docs/content/doc/administration/signing.en-us.md index 34580ab42828..de539e34b263 100644 --- a/docs/content/doc/administration/signing.en-us.md +++ b/docs/content/doc/administration/signing.en-us.md @@ -5,6 +5,8 @@ slug: "signing" weight: 50 toc: false draft: false +aliases: + - /en-us/signing menu: sidebar: parent: "administration" diff --git a/docs/content/doc/contributing/_index.de-de.md b/docs/content/doc/contributing/_index.de-de.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/contributing/_index.en-us.md b/docs/content/doc/contributing/_index.en-us.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/contributing/_index.zh-cn.md b/docs/content/doc/contributing/_index.zh-cn.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/contributing/_index.zh-tw.md b/docs/content/doc/contributing/_index.zh-tw.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/contributing/guidelines-backend.en-us.md b/docs/content/doc/contributing/guidelines-backend.en-us.md index 6ae0ba517d32..fd0f8b083079 100644 --- a/docs/content/doc/contributing/guidelines-backend.en-us.md +++ b/docs/content/doc/contributing/guidelines-backend.en-us.md @@ -5,6 +5,8 @@ slug: "guidelines-backend" weight: 20 toc: false draft: false +aliases: + - /en-us/guidelines-backend menu: sidebar: parent: "contributing" diff --git a/docs/content/doc/contributing/guidelines-frontend.en-us.md b/docs/content/doc/contributing/guidelines-frontend.en-us.md index bde7d3151074..39a70eee97d2 100644 --- a/docs/content/doc/contributing/guidelines-frontend.en-us.md +++ b/docs/content/doc/contributing/guidelines-frontend.en-us.md @@ -5,6 +5,8 @@ slug: "guidelines-frontend" weight: 20 toc: false draft: false +aliases: + - /en-us/guidelines-frontend menu: sidebar: parent: "contributing" diff --git a/docs/content/doc/contributing/guidelines-refactoring.en-us.md b/docs/content/doc/contributing/guidelines-refactoring.en-us.md index 913ce8d9bb50..c8c8ee0ee1a3 100644 --- a/docs/content/doc/contributing/guidelines-refactoring.en-us.md +++ b/docs/content/doc/contributing/guidelines-refactoring.en-us.md @@ -5,6 +5,8 @@ slug: "guidelines-refactoring" weight: 20 toc: false draft: false +aliases: + - /en-us/guidelines-refactoring menu: sidebar: parent: "contributing" diff --git a/docs/content/doc/contributing/localization.en-us.md b/docs/content/doc/contributing/localization.en-us.md index 3006ca599b50..7f78fb3fa852 100644 --- a/docs/content/doc/contributing/localization.en-us.md +++ b/docs/content/doc/contributing/localization.en-us.md @@ -5,6 +5,8 @@ slug: "localization" weight: 10 toc: false draft: false +aliases: + - /en-us/localization menu: sidebar: parent: "contributing" diff --git a/docs/content/doc/contributing/localization.zh-cn.md b/docs/content/doc/contributing/localization.zh-cn.md index c20f4d4138df..99a9f3743f5d 100644 --- a/docs/content/doc/contributing/localization.zh-cn.md +++ b/docs/content/doc/contributing/localization.zh-cn.md @@ -5,6 +5,8 @@ slug: "localization" weight: 20 toc: false draft: false +aliases: + - /zh-cn/localization menu: sidebar: parent: "contributing" diff --git a/docs/content/doc/contributing/localization.zh-tw.md b/docs/content/doc/contributing/localization.zh-tw.md index 815fbc311912..cfdc1dcb9b43 100644 --- a/docs/content/doc/contributing/localization.zh-tw.md +++ b/docs/content/doc/contributing/localization.zh-tw.md @@ -5,6 +5,8 @@ slug: "localization" weight: 20 toc: false draft: false +aliases: + - /zh-tw/localization menu: sidebar: parent: "contributing" diff --git a/docs/content/doc/development/_index.en-us.md b/docs/content/doc/development/_index.en-us.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/development/_index.zh-cn.md b/docs/content/doc/development/_index.zh-cn.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/development/_index.zh-tw.md b/docs/content/doc/development/_index.zh-tw.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/development/api-usage.en-us.md b/docs/content/doc/development/api-usage.en-us.md index 641012607bf3..fe334827c3ff 100644 --- a/docs/content/doc/development/api-usage.en-us.md +++ b/docs/content/doc/development/api-usage.en-us.md @@ -5,6 +5,8 @@ slug: "api-usage" weight: 40 toc: false draft: false +aliases: + - /en-us/api-usage menu: sidebar: parent: "development" diff --git a/docs/content/doc/development/api-usage.zh-cn.md b/docs/content/doc/development/api-usage.zh-cn.md index b0821039ffd1..ceb69b3f0efd 100644 --- a/docs/content/doc/development/api-usage.zh-cn.md +++ b/docs/content/doc/development/api-usage.zh-cn.md @@ -5,6 +5,8 @@ slug: "api-usage" weight: 40 toc: false draft: false +aliases: + - /zh-cn/api-usage menu: sidebar: parent: "development" diff --git a/docs/content/doc/development/hacking-on-gitea.en-us.md b/docs/content/doc/development/hacking-on-gitea.en-us.md index da38d238ac8e..8ac7fcc34c4c 100644 --- a/docs/content/doc/development/hacking-on-gitea.en-us.md +++ b/docs/content/doc/development/hacking-on-gitea.en-us.md @@ -5,6 +5,8 @@ slug: "hacking-on-gitea" weight: 10 toc: false draft: false +aliases: + - /en-us/hacking-on-gitea menu: sidebar: parent: "development" diff --git a/docs/content/doc/development/hacking-on-gitea.zh-cn.md b/docs/content/doc/development/hacking-on-gitea.zh-cn.md index c63d0c4685d8..3a4078dfdb62 100644 --- a/docs/content/doc/development/hacking-on-gitea.zh-cn.md +++ b/docs/content/doc/development/hacking-on-gitea.zh-cn.md @@ -5,6 +5,8 @@ slug: "hacking-on-gitea" weight: 10 toc: false draft: false +aliases: + - /zh-cn/hacking-on-gitea menu: sidebar: parent: "development" diff --git a/docs/content/doc/development/integrations.en-us.md b/docs/content/doc/development/integrations.en-us.md index dae557c9b8a7..bbb50ae71dc7 100644 --- a/docs/content/doc/development/integrations.en-us.md +++ b/docs/content/doc/development/integrations.en-us.md @@ -5,6 +5,8 @@ slug: "integrations" weight: 65 toc: false draft: false +aliases: + - /en-us/integrations menu: sidebar: parent: "development" diff --git a/docs/content/doc/development/integrations.zh-tw.md b/docs/content/doc/development/integrations.zh-tw.md index fdc210399089..278a8f41d5cf 100644 --- a/docs/content/doc/development/integrations.zh-tw.md +++ b/docs/content/doc/development/integrations.zh-tw.md @@ -5,6 +5,8 @@ slug: "integrations" weight: 65 toc: false draft: false +aliases: + - /zh-tw/integrations menu: sidebar: parent: "development" diff --git a/docs/content/doc/development/migrations.en-us.md b/docs/content/doc/development/migrations.en-us.md index 1d9103254b29..f4116341566f 100644 --- a/docs/content/doc/development/migrations.en-us.md +++ b/docs/content/doc/development/migrations.en-us.md @@ -5,6 +5,8 @@ slug: "migrations-interfaces" weight: 55 toc: false draft: false +aliases: + - /en-us/migrations-interfaces menu: sidebar: parent: "development" diff --git a/docs/content/doc/development/migrations.zh-tw.md b/docs/content/doc/development/migrations.zh-tw.md index bf995598f5fe..de4ddd788d3f 100644 --- a/docs/content/doc/development/migrations.zh-tw.md +++ b/docs/content/doc/development/migrations.zh-tw.md @@ -5,6 +5,8 @@ slug: "migrations-interfaces" weight: 55 toc: false draft: false +aliases: + - /zh-tw/migrations-interfaces menu: sidebar: parent: "development" diff --git a/docs/content/doc/development/oauth2-provider.en-us.md b/docs/content/doc/development/oauth2-provider.en-us.md index 7be7a42934e4..b279e97a6ebc 100644 --- a/docs/content/doc/development/oauth2-provider.en-us.md +++ b/docs/content/doc/development/oauth2-provider.en-us.md @@ -5,6 +5,8 @@ slug: "oauth2-provider" weight: 41 toc: false draft: false +aliases: + - /en-us/oauth2-provider menu: sidebar: parent: "development" diff --git a/docs/content/doc/development/oauth2-provider.zh-cn.md b/docs/content/doc/development/oauth2-provider.zh-cn.md index 926500d64f41..3fbf174efc96 100644 --- a/docs/content/doc/development/oauth2-provider.zh-cn.md +++ b/docs/content/doc/development/oauth2-provider.zh-cn.md @@ -5,6 +5,8 @@ slug: "oauth2-provider" weight: 41 toc: false draft: false +aliases: + - /zh-cn/oauth2-provider menu: sidebar: parent: "development" diff --git a/docs/content/doc/development/oauth2-provider.zh-tw.md b/docs/content/doc/development/oauth2-provider.zh-tw.md index b28e48d61e8d..8d62264abc5d 100644 --- a/docs/content/doc/development/oauth2-provider.zh-tw.md +++ b/docs/content/doc/development/oauth2-provider.zh-tw.md @@ -5,6 +5,8 @@ slug: "oauth2-provider" weight: 41 toc: false draft: false +aliases: + - /zh-tw/oauth2-provider menu: sidebar: parent: "development" diff --git a/docs/content/doc/help/_index.en-us.md b/docs/content/doc/help/_index.en-us.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/help/_index.zh-cn.md b/docs/content/doc/help/_index.zh-cn.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/help/_index.zh-tw.md b/docs/content/doc/help/_index.zh-tw.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/help/faq.en-us.md b/docs/content/doc/help/faq.en-us.md index 4847e8e03bef..53215e18a544 100644 --- a/docs/content/doc/help/faq.en-us.md +++ b/docs/content/doc/help/faq.en-us.md @@ -5,6 +5,8 @@ slug: "faq" weight: 5 toc: false draft: false +aliases: + - /en-us/faq menu: sidebar: parent: "help" @@ -17,7 +19,7 @@ menu: This page contains some common questions and answers. -For more help resources, check all [Support Options]({{< relref "doc/help/seek-help.en-us.md" >}}). +For more help resources, check all [Support Options]({{< relref "doc/help/support.en-us.md" >}}). **Table of Contents** @@ -408,7 +410,7 @@ Stdout on systemd goes to the journal by default. Try using `journalctl`, `journ Similarly, stdout on docker can be viewed using `docker logs `. -To collect logs for help and issue report, see [Support Options]({{< relref "doc/help/seek-help.en-us.md" >}}). +To collect logs for help and issue report, see [Support Options]({{< relref "doc/help/support.en-us.md" >}}). ## Initial logging diff --git a/docs/content/doc/help/seek-help.en-us.md b/docs/content/doc/help/support.en-us.md similarity index 97% rename from docs/content/doc/help/seek-help.en-us.md rename to docs/content/doc/help/support.en-us.md index 0e56b9a57554..c6db3d6eb344 100644 --- a/docs/content/doc/help/seek-help.en-us.md +++ b/docs/content/doc/help/support.en-us.md @@ -1,16 +1,18 @@ --- date: "2018-05-21T15:00:00+00:00" title: "Support Options" -slug: "seek-help" +slug: "support" weight: 20 toc: false draft: false +aliases: + - /en-us/seek-help menu: sidebar: parent: "help" name: "Support Options" weight: 20 - identifier: "seek-help" + identifier: "support" --- # Support Options diff --git a/docs/content/doc/help/seek-help.zh-cn.md b/docs/content/doc/help/support.zh-cn.md similarity index 89% rename from docs/content/doc/help/seek-help.zh-cn.md rename to docs/content/doc/help/support.zh-cn.md index 80febad24863..775dfe83bd7d 100644 --- a/docs/content/doc/help/seek-help.zh-cn.md +++ b/docs/content/doc/help/support.zh-cn.md @@ -1,16 +1,18 @@ --- date: "2017-01-20T15:00:00+08:00" title: "需要帮助" -slug: "seek-help" +slug: "support" weight: 20 toc: false draft: false +aliases: + - /zh-cn/seek-help menu: sidebar: parent: "help" name: "需要帮助" weight: 20 - identifier: "seek-help" + identifier: "support" --- ## 需要帮助? diff --git a/docs/content/doc/help/seek-help.zh-tw.md b/docs/content/doc/help/support.zh-tw.md similarity index 93% rename from docs/content/doc/help/seek-help.zh-tw.md rename to docs/content/doc/help/support.zh-tw.md index f87dad547aa8..a9c35eaafbba 100644 --- a/docs/content/doc/help/seek-help.zh-tw.md +++ b/docs/content/doc/help/support.zh-tw.md @@ -1,16 +1,18 @@ --- date: "2018-05-21T15:00:00+00:00" title: "取得協助" -slug: "seek-help" +slug: "support" weight: 20 toc: false draft: false +aliases: + - /zh-tw/seek-help menu: sidebar: parent: "help" name: "取得協助" weight: 20 - identifier: "seek-help" + identifier: "support" --- # 取得協助 diff --git a/docs/content/doc/installation/_index.en-us.md b/docs/content/doc/installation/_index.en-us.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/installation/_index.fr-fr.md b/docs/content/doc/installation/_index.fr-fr.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/installation/_index.zh-cn.md b/docs/content/doc/installation/_index.zh-cn.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/installation/_index.zh-tw.md b/docs/content/doc/installation/_index.zh-tw.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/installation/comparison.en-us.md b/docs/content/doc/installation/comparison.en-us.md index 082b2a85edd9..578b00c21125 100644 --- a/docs/content/doc/installation/comparison.en-us.md +++ b/docs/content/doc/installation/comparison.en-us.md @@ -5,6 +5,8 @@ slug: "comparison" weight: 5 toc: false draft: false +aliases: + - /en-us/comparison menu: sidebar: name: "Comparison" diff --git a/docs/content/doc/installation/comparison.zh-cn.md b/docs/content/doc/installation/comparison.zh-cn.md index 7dfca526ebb8..06c770caa285 100644 --- a/docs/content/doc/installation/comparison.zh-cn.md +++ b/docs/content/doc/installation/comparison.zh-cn.md @@ -5,6 +5,8 @@ slug: "comparison" weight: 5 toc: false draft: false +aliases: + - /zh-cn/comparison menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/comparison.zh-tw.md b/docs/content/doc/installation/comparison.zh-tw.md index 89190523434b..042acba8d3da 100644 --- a/docs/content/doc/installation/comparison.zh-tw.md +++ b/docs/content/doc/installation/comparison.zh-tw.md @@ -5,6 +5,8 @@ slug: "comparison" weight: 5 toc: false draft: false +aliases: + - /zh-tw/comparison menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/database-preparation.en-us.md b/docs/content/doc/installation/database-preparation.en-us.md index edad89b07cc7..4b0d1b5ba819 100644 --- a/docs/content/doc/installation/database-preparation.en-us.md +++ b/docs/content/doc/installation/database-preparation.en-us.md @@ -5,6 +5,8 @@ slug: "database-prep" weight: 10 toc: false draft: false +aliases: + - /en-us/database-prep menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/from-binary.en-us.md b/docs/content/doc/installation/from-binary.en-us.md index ce1d7e5a2c25..c7824c348025 100644 --- a/docs/content/doc/installation/from-binary.en-us.md +++ b/docs/content/doc/installation/from-binary.en-us.md @@ -5,6 +5,8 @@ slug: "install-from-binary" weight: 15 toc: false draft: false +aliases: + - /en-us/install-from-binary menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/from-binary.fr-fr.md b/docs/content/doc/installation/from-binary.fr-fr.md index 7dfbe7dd5f08..eea3819384da 100644 --- a/docs/content/doc/installation/from-binary.fr-fr.md +++ b/docs/content/doc/installation/from-binary.fr-fr.md @@ -5,6 +5,8 @@ slug: "install-from-binary" weight: 15 toc: false draft: false +aliases: + - /fr-fr/install-from-binary menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/from-binary.zh-cn.md b/docs/content/doc/installation/from-binary.zh-cn.md index 55cf6c1da2c1..abe799dc94b7 100644 --- a/docs/content/doc/installation/from-binary.zh-cn.md +++ b/docs/content/doc/installation/from-binary.zh-cn.md @@ -5,6 +5,8 @@ slug: "install-from-binary" weight: 15 toc: false draft: false +aliases: + - /zh-cn/install-from-binary menu: sidebar: parent: "installation" @@ -161,4 +163,4 @@ GITEA_WORK_DIR=/var/lib/gitea/ /usr/local/bin/gitea web -c /etc/gitea/app.ini > 更多经验总结,请参考英文版 [Troubleshooting](/en-us/install-from-binary/#troubleshooting) -如果从本页中没有找到你需要的内容,请访问 [帮助页面]({{< relref "seek-help.zh-cn.md" >}}) +如果从本页中没有找到你需要的内容,请访问 [帮助页面]({{< relref "support.zh-cn.md" >}}) diff --git a/docs/content/doc/installation/from-binary.zh-tw.md b/docs/content/doc/installation/from-binary.zh-tw.md index 3991b101ae1b..858cee2193de 100644 --- a/docs/content/doc/installation/from-binary.zh-tw.md +++ b/docs/content/doc/installation/from-binary.zh-tw.md @@ -5,6 +5,8 @@ slug: "install-from-binary" weight: 15 toc: false draft: false +aliases: + - /zh-tw/install-from-binary menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/from-package.en-us.md b/docs/content/doc/installation/from-package.en-us.md index 2615b7d27d11..15283d583786 100644 --- a/docs/content/doc/installation/from-package.en-us.md +++ b/docs/content/doc/installation/from-package.en-us.md @@ -5,6 +5,8 @@ slug: "install-from-package" weight: 20 toc: false draft: false +aliases: + - /en-us/install-from-package menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/from-package.fr-fr.md b/docs/content/doc/installation/from-package.fr-fr.md index eff74c31e53b..b7e842400d00 100644 --- a/docs/content/doc/installation/from-package.fr-fr.md +++ b/docs/content/doc/installation/from-package.fr-fr.md @@ -5,6 +5,8 @@ slug: "install-from-package" weight: 20 toc: false draft: false +aliases: + - /fr-fr/install-from-package menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/from-package.zh-cn.md b/docs/content/doc/installation/from-package.zh-cn.md index e3ed3aa37145..a8e92694f96f 100644 --- a/docs/content/doc/installation/from-package.zh-cn.md +++ b/docs/content/doc/installation/from-package.zh-cn.md @@ -5,6 +5,8 @@ slug: "install-from-package" weight: 20 toc: false draft: false +aliases: + - /zh-cn/install-from-package menu: sidebar: parent: "installation" @@ -107,4 +109,4 @@ make install clean ## 需要帮助? -如果从本页中没有找到你需要的内容,请访问 [帮助页面]({{< relref "seek-help.zh-cn.md" >}}) +如果从本页中没有找到你需要的内容,请访问 [帮助页面]({{< relref "support.zh-cn.md" >}}) diff --git a/docs/content/doc/installation/from-package.zh-tw.md b/docs/content/doc/installation/from-package.zh-tw.md index 1616ba6655e3..c5347991ec83 100644 --- a/docs/content/doc/installation/from-package.zh-tw.md +++ b/docs/content/doc/installation/from-package.zh-tw.md @@ -5,6 +5,8 @@ slug: "install-from-package" weight: 20 toc: false draft: false +aliases: + - /zh-tw/install-from-package menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/from-source.en-us.md b/docs/content/doc/installation/from-source.en-us.md index 45064a43a85d..72a3e1247265 100644 --- a/docs/content/doc/installation/from-source.en-us.md +++ b/docs/content/doc/installation/from-source.en-us.md @@ -5,6 +5,8 @@ slug: "install-from-source" weight: 30 toc: false draft: false +aliases: + - /en-us/install-from-source menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/from-source.fr-fr.md b/docs/content/doc/installation/from-source.fr-fr.md index ebb094175419..544059b573c4 100644 --- a/docs/content/doc/installation/from-source.fr-fr.md +++ b/docs/content/doc/installation/from-source.fr-fr.md @@ -5,6 +5,8 @@ slug: "install-from-source" weight: 30 toc: false draft: false +aliases: + - /fr-fr/install-from-source menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/from-source.zh-cn.md b/docs/content/doc/installation/from-source.zh-cn.md index 9d5c50cbda1b..8f3ccbe7e260 100644 --- a/docs/content/doc/installation/from-source.zh-cn.md +++ b/docs/content/doc/installation/from-source.zh-cn.md @@ -5,6 +5,8 @@ slug: "install-from-source" weight: 30 toc: false draft: false +aliases: + - /zh-cn/install-from-source menu: sidebar: parent: "installation" @@ -104,4 +106,4 @@ CC=aarch64-unknown-linux-gnu-gcc GOOS=linux GOARCH=arm64 TAGS="bindata sqlite sq ## 需要帮助? -如果从本页中没有找到你需要的内容,请访问 [帮助页面]({{< relref "seek-help.zh-cn.md" >}}) +如果从本页中没有找到你需要的内容,请访问 [帮助页面]({{< relref "support.zh-cn.md" >}}) diff --git a/docs/content/doc/installation/from-source.zh-tw.md b/docs/content/doc/installation/from-source.zh-tw.md index fc9c2dca4caf..f9e6e06effaa 100644 --- a/docs/content/doc/installation/from-source.zh-tw.md +++ b/docs/content/doc/installation/from-source.zh-tw.md @@ -5,6 +5,8 @@ slug: "install-from-source" weight: 30 toc: false draft: false +aliases: + - /zh-tw/install-from-source menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/on-cloud-provider.en-us.md b/docs/content/doc/installation/on-cloud-provider.en-us.md index 550ef3f677eb..20ca812effeb 100644 --- a/docs/content/doc/installation/on-cloud-provider.en-us.md +++ b/docs/content/doc/installation/on-cloud-provider.en-us.md @@ -5,6 +5,8 @@ slug: "install-on-cloud-provider" weight: 90 toc: false draft: false +aliases: + - /en-us/install-on-cloud-provider menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/on-kubernetes.en-us.md b/docs/content/doc/installation/on-kubernetes.en-us.md index e8f3612ea41c..b46a61df025a 100644 --- a/docs/content/doc/installation/on-kubernetes.en-us.md +++ b/docs/content/doc/installation/on-kubernetes.en-us.md @@ -5,6 +5,8 @@ slug: "install-on-kubernetes" weight: 80 toc: false draft: false +aliases: + - /en-us/install-on-kubernetes menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/on-kubernetes.zh-cn.md b/docs/content/doc/installation/on-kubernetes.zh-cn.md index 91dec2e73a29..367aef1cf31f 100644 --- a/docs/content/doc/installation/on-kubernetes.zh-cn.md +++ b/docs/content/doc/installation/on-kubernetes.zh-cn.md @@ -5,6 +5,8 @@ slug: "install-on-kubernetes" weight: 80 toc: false draft: false +aliases: + - /zh-cn/install-on-kubernetes menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/on-kubernetes.zh-tw.md b/docs/content/doc/installation/on-kubernetes.zh-tw.md index 6d31a14b05c6..51446911d599 100644 --- a/docs/content/doc/installation/on-kubernetes.zh-tw.md +++ b/docs/content/doc/installation/on-kubernetes.zh-tw.md @@ -5,6 +5,8 @@ slug: "install-on-kubernetes" weight: 80 toc: false draft: false +aliases: + - /zh-tw/install-on-kubernetes menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/run-as-service-in-ubuntu.en-us.md b/docs/content/doc/installation/run-as-service-in-ubuntu.en-us.md index 19b3be1a22a9..3587dfc01aa5 100644 --- a/docs/content/doc/installation/run-as-service-in-ubuntu.en-us.md +++ b/docs/content/doc/installation/run-as-service-in-ubuntu.en-us.md @@ -5,6 +5,8 @@ slug: "linux-service" weight: 40 toc: false draft: false +aliases: + - /en-us/linux-service menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/run-as-service-in-ubuntu.zh-cn.md b/docs/content/doc/installation/run-as-service-in-ubuntu.zh-cn.md index aa00a42aa6b4..62312c060c67 100644 --- a/docs/content/doc/installation/run-as-service-in-ubuntu.zh-cn.md +++ b/docs/content/doc/installation/run-as-service-in-ubuntu.zh-cn.md @@ -5,6 +5,8 @@ slug: "linux-service" weight: 40 toc: false draft: false +aliases: + - /zh-cn/linux-service menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/run-as-service-in-ubuntu.zh-tw.md b/docs/content/doc/installation/run-as-service-in-ubuntu.zh-tw.md index de811d73e77a..6b8a4cfce806 100644 --- a/docs/content/doc/installation/run-as-service-in-ubuntu.zh-tw.md +++ b/docs/content/doc/installation/run-as-service-in-ubuntu.zh-tw.md @@ -5,6 +5,8 @@ slug: "linux-service" weight: 40 toc: false draft: false +aliases: + - /zh-tw/linux-service menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/upgrade-from-gitea.en-us.md b/docs/content/doc/installation/upgrade-from-gitea.en-us.md index 8748573a2f4c..a6415f78618e 100644 --- a/docs/content/doc/installation/upgrade-from-gitea.en-us.md +++ b/docs/content/doc/installation/upgrade-from-gitea.en-us.md @@ -5,6 +5,8 @@ slug: "upgrade-from-gitea" weight: 100 toc: false draft: false +aliases: + - /en-us/upgrade-from-gitea menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/upgrade-from-gogs.en-us.md b/docs/content/doc/installation/upgrade-from-gogs.en-us.md index 5b08ed2f6aab..2e149c6a2bfe 100644 --- a/docs/content/doc/installation/upgrade-from-gogs.en-us.md +++ b/docs/content/doc/installation/upgrade-from-gogs.en-us.md @@ -5,6 +5,8 @@ slug: "upgrade-from-gogs" weight: 101 toc: false draft: false +aliases: + - /en-us/upgrade-from-gogs menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/upgrade-from-gogs.fr-fr.md b/docs/content/doc/installation/upgrade-from-gogs.fr-fr.md index 2ce1b4bf3d32..9a46562f066e 100644 --- a/docs/content/doc/installation/upgrade-from-gogs.fr-fr.md +++ b/docs/content/doc/installation/upgrade-from-gogs.fr-fr.md @@ -5,6 +5,8 @@ slug: "upgrade-from-gogs" weight: 101 toc: false draft: false +aliases: + - /fr-fr/upgrade-from-gogs menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/upgrade-from-gogs.zh-cn.md b/docs/content/doc/installation/upgrade-from-gogs.zh-cn.md index 048cfee79372..f537896ca1ee 100644 --- a/docs/content/doc/installation/upgrade-from-gogs.zh-cn.md +++ b/docs/content/doc/installation/upgrade-from-gogs.zh-cn.md @@ -5,6 +5,8 @@ slug: "upgrade-from-gogs" weight: 101 toc: false draft: false +aliases: + - /zh-cn/upgrade-from-gogs menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/upgrade-from-gogs.zh-tw.md b/docs/content/doc/installation/upgrade-from-gogs.zh-tw.md index 0082bf73cb28..9812efaf946f 100644 --- a/docs/content/doc/installation/upgrade-from-gogs.zh-tw.md +++ b/docs/content/doc/installation/upgrade-from-gogs.zh-tw.md @@ -5,6 +5,8 @@ slug: "upgrade-from-gogs" weight: 101 toc: false draft: false +aliases: + - /zh-tw/upgrade-from-gogs menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/windows-service.en-us.md b/docs/content/doc/installation/windows-service.en-us.md index 6efc1fd58263..d3f5a9abae0b 100644 --- a/docs/content/doc/installation/windows-service.en-us.md +++ b/docs/content/doc/installation/windows-service.en-us.md @@ -5,6 +5,8 @@ slug: "windows-service" weight: 50 toc: false draft: false +aliases: + - /en-us/windows-service menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/windows-service.fr-fr.md b/docs/content/doc/installation/windows-service.fr-fr.md index a0f8f057c03b..c4e00b04e134 100644 --- a/docs/content/doc/installation/windows-service.fr-fr.md +++ b/docs/content/doc/installation/windows-service.fr-fr.md @@ -5,6 +5,8 @@ slug: "windows-service" weight: 50 toc: false draft: false +aliases: + - /fr-fr/windows-service menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/windows-service.zh-cn.md b/docs/content/doc/installation/windows-service.zh-cn.md index 8388a057b35f..0f2a0f5869ad 100644 --- a/docs/content/doc/installation/windows-service.zh-cn.md +++ b/docs/content/doc/installation/windows-service.zh-cn.md @@ -5,6 +5,8 @@ slug: "windows-service" weight: 50 toc: false draft: false +aliases: + - /zh-cn/windows-service menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/windows-service.zh-tw.md b/docs/content/doc/installation/windows-service.zh-tw.md index a2934a52d1b6..5764d647fc2a 100644 --- a/docs/content/doc/installation/windows-service.zh-tw.md +++ b/docs/content/doc/installation/windows-service.zh-tw.md @@ -5,6 +5,8 @@ slug: "windows-service" weight: 50 toc: false draft: false +aliases: + - /zh-tw/windows-service menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/with-docker-rootless.en-us.md b/docs/content/doc/installation/with-docker-rootless.en-us.md index f33e99c58096..e1073a1d679e 100644 --- a/docs/content/doc/installation/with-docker-rootless.en-us.md +++ b/docs/content/doc/installation/with-docker-rootless.en-us.md @@ -5,6 +5,8 @@ slug: "install-with-docker-rootless" weight: 60 toc: false draft: false +aliases: + - /en-us/install-with-docker-rootless menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/with-docker.en-us.md b/docs/content/doc/installation/with-docker.en-us.md index 05764e0bc9f5..043a10c08fc5 100644 --- a/docs/content/doc/installation/with-docker.en-us.md +++ b/docs/content/doc/installation/with-docker.en-us.md @@ -5,6 +5,8 @@ slug: "install-with-docker" weight: 70 toc: false draft: false +aliases: + - /en-us/install-with-docker menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/with-docker.fr-fr.md b/docs/content/doc/installation/with-docker.fr-fr.md index 59f2b0752a0e..362aa5fc67d2 100644 --- a/docs/content/doc/installation/with-docker.fr-fr.md +++ b/docs/content/doc/installation/with-docker.fr-fr.md @@ -5,6 +5,8 @@ slug: "install-with-docker" weight: 70 toc: false draft: false +aliases: + - /fr-fr/install-with-docker menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/with-docker.zh-cn.md b/docs/content/doc/installation/with-docker.zh-cn.md index e5bb07b4951f..50acc3ffae12 100644 --- a/docs/content/doc/installation/with-docker.zh-cn.md +++ b/docs/content/doc/installation/with-docker.zh-cn.md @@ -5,6 +5,8 @@ slug: "install-with-docker" weight: 70 toc: false draft: false +aliases: + - /zh-cn/install-with-docker menu: sidebar: parent: "installation" diff --git a/docs/content/doc/installation/with-docker.zh-tw.md b/docs/content/doc/installation/with-docker.zh-tw.md index e2e47e87023a..fdf5a0101dc3 100644 --- a/docs/content/doc/installation/with-docker.zh-tw.md +++ b/docs/content/doc/installation/with-docker.zh-tw.md @@ -5,6 +5,8 @@ slug: "install-with-docker" weight: 70 toc: false draft: false +aliases: + - /zh-tw/install-with-docker menu: sidebar: parent: "installation" diff --git a/docs/content/doc/help/search.de-de.md b/docs/content/doc/search.de-de.md similarity index 93% rename from docs/content/doc/help/search.de-de.md rename to docs/content/doc/search.de-de.md index d22e9c1b2e6a..29c153171e4e 100644 --- a/docs/content/doc/help/search.de-de.md +++ b/docs/content/doc/search.de-de.md @@ -5,6 +5,8 @@ slug: "search" weight: 1 toc: false draft: false +aliases: + - /de-de/help/search sitemap: priority : 1 layout: "search" diff --git a/docs/content/doc/help/search.en-us.md b/docs/content/doc/search.en-us.md similarity index 93% rename from docs/content/doc/help/search.en-us.md rename to docs/content/doc/search.en-us.md index d22e9c1b2e6a..60a4898c4289 100644 --- a/docs/content/doc/help/search.en-us.md +++ b/docs/content/doc/search.en-us.md @@ -5,6 +5,8 @@ slug: "search" weight: 1 toc: false draft: false +aliases: + - /en-us/help/search sitemap: priority : 1 layout: "search" diff --git a/docs/content/doc/help/search.fr-fr.md b/docs/content/doc/search.fr-fr.md similarity index 93% rename from docs/content/doc/help/search.fr-fr.md rename to docs/content/doc/search.fr-fr.md index 421f7830b2aa..d3f85c966f3d 100644 --- a/docs/content/doc/help/search.fr-fr.md +++ b/docs/content/doc/search.fr-fr.md @@ -5,6 +5,8 @@ slug: "search" weight: 1 toc: false draft: false +aliases: + - /fr-fr/help/search sitemap: priority : 1 layout: "search" diff --git a/docs/content/doc/help/search.nl-nl.md b/docs/content/doc/search.nl-nl.md similarity index 93% rename from docs/content/doc/help/search.nl-nl.md rename to docs/content/doc/search.nl-nl.md index d22e9c1b2e6a..9ca7a34d489b 100644 --- a/docs/content/doc/help/search.nl-nl.md +++ b/docs/content/doc/search.nl-nl.md @@ -5,6 +5,8 @@ slug: "search" weight: 1 toc: false draft: false +aliases: + - /nl-nl/help/search sitemap: priority : 1 layout: "search" diff --git a/docs/content/doc/help/search.pt-br.md b/docs/content/doc/search.pt-br.md similarity index 93% rename from docs/content/doc/help/search.pt-br.md rename to docs/content/doc/search.pt-br.md index d22e9c1b2e6a..0a70026c23c7 100644 --- a/docs/content/doc/help/search.pt-br.md +++ b/docs/content/doc/search.pt-br.md @@ -5,6 +5,8 @@ slug: "search" weight: 1 toc: false draft: false +aliases: + - /pt-br/help/search sitemap: priority : 1 layout: "search" diff --git a/docs/content/doc/help/search.zh-cn.md b/docs/content/doc/search.zh-cn.md similarity index 93% rename from docs/content/doc/help/search.zh-cn.md rename to docs/content/doc/search.zh-cn.md index 778df0d47d55..50415c259e30 100644 --- a/docs/content/doc/help/search.zh-cn.md +++ b/docs/content/doc/search.zh-cn.md @@ -5,6 +5,8 @@ slug: "search" weight: 1 toc: false draft: false +aliases: + - /zh-cn/help/search sitemap: priority : 1 layout: "search" diff --git a/docs/content/doc/help/search.zh-tw.md b/docs/content/doc/search.zh-tw.md similarity index 93% rename from docs/content/doc/help/search.zh-tw.md rename to docs/content/doc/search.zh-tw.md index 8f2ce17ec682..746cb14c1135 100644 --- a/docs/content/doc/help/search.zh-tw.md +++ b/docs/content/doc/search.zh-tw.md @@ -5,6 +5,8 @@ slug: "search" weight: 1 toc: false draft: false +aliases: + - /zh-tw/help/search sitemap: priority : 1 layout: "search" diff --git a/docs/content/doc/usage/_index.en-us.md b/docs/content/doc/usage/_index.en-us.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/usage/_index.zh-cn.md b/docs/content/doc/usage/_index.zh-cn.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/usage/_index.zh-tw.md b/docs/content/doc/usage/_index.zh-tw.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/usage/agit-support.en-us.md b/docs/content/doc/usage/agit-support.en-us.md index b005e1bd7367..30e2879e89b6 100644 --- a/docs/content/doc/usage/agit-support.en-us.md +++ b/docs/content/doc/usage/agit-support.en-us.md @@ -5,6 +5,8 @@ slug: "agit-setup" weight: 12 toc: false draft: false +aliases: + - /en-us/agit-setup menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/authentication.en-us.md b/docs/content/doc/usage/authentication.en-us.md index 5478ee94f681..2b8cdd29642e 100644 --- a/docs/content/doc/usage/authentication.en-us.md +++ b/docs/content/doc/usage/authentication.en-us.md @@ -5,6 +5,8 @@ slug: "authentication" weight: 10 toc: false draft: false +aliases: + - /en-us/authentication menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/authentication.zh-cn.md b/docs/content/doc/usage/authentication.zh-cn.md index 403c3f43ce17..37ecc8bab1f2 100644 --- a/docs/content/doc/usage/authentication.zh-cn.md +++ b/docs/content/doc/usage/authentication.zh-cn.md @@ -5,6 +5,8 @@ slug: "authentication" weight: 10 toc: false draft: false +aliases: + - /zh-cn/authentication menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/authentication.zh-tw.md b/docs/content/doc/usage/authentication.zh-tw.md index 958c498fc6bb..75959802b1f5 100644 --- a/docs/content/doc/usage/authentication.zh-tw.md +++ b/docs/content/doc/usage/authentication.zh-tw.md @@ -5,6 +5,8 @@ slug: "authentication" weight: 10 toc: false draft: false +aliases: + - /zh-tw/authentication menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/clone-filter.en-us.md b/docs/content/doc/usage/clone-filter.en-us.md index 7d4ba2d9a876..8331c138bf5d 100644 --- a/docs/content/doc/usage/clone-filter.en-us.md +++ b/docs/content/doc/usage/clone-filter.en-us.md @@ -5,6 +5,8 @@ slug: "clone-filters" weight: 25 draft: false toc: false +aliases: + - /en-us/clone-filters menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/incoming-email.en-us.md b/docs/content/doc/usage/incoming-email.en-us.md index 867e9d8a69f3..205b3dd8ed8a 100644 --- a/docs/content/doc/usage/incoming-email.en-us.md +++ b/docs/content/doc/usage/incoming-email.en-us.md @@ -5,6 +5,8 @@ slug: "incoming-email" weight: 13 draft: false toc: false +aliases: + - /en-us/incoming-email menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/issue-pull-request-templates.en-us.md b/docs/content/doc/usage/issue-pull-request-templates.en-us.md index 107484689b9f..b48763cf8e0a 100644 --- a/docs/content/doc/usage/issue-pull-request-templates.en-us.md +++ b/docs/content/doc/usage/issue-pull-request-templates.en-us.md @@ -5,6 +5,8 @@ slug: "issue-pull-request-templates" weight: 15 toc: false draft: false +aliases: + - /en-us/issue-pull-request-templates menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/issue-pull-request-templates.zh-cn.md b/docs/content/doc/usage/issue-pull-request-templates.zh-cn.md index 866378e2ac56..135dcf8de8c1 100644 --- a/docs/content/doc/usage/issue-pull-request-templates.zh-cn.md +++ b/docs/content/doc/usage/issue-pull-request-templates.zh-cn.md @@ -5,6 +5,8 @@ slug: "issue-pull-request-templates" weight: 15 toc: true draft: false +aliases: + - /zh-cn/issue-pull-request-templates menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/labels.en-us.md b/docs/content/doc/usage/labels.en-us.md index 7c2494971fcc..bf60951d8c67 100644 --- a/docs/content/doc/usage/labels.en-us.md +++ b/docs/content/doc/usage/labels.en-us.md @@ -5,6 +5,8 @@ slug: "labels" weight: 13 toc: false draft: false +aliases: + - /en-us/labels menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/linked-references.en-us.md b/docs/content/doc/usage/linked-references.en-us.md index 335d2654e37a..8cd4ff7b1fc8 100644 --- a/docs/content/doc/usage/linked-references.en-us.md +++ b/docs/content/doc/usage/linked-references.en-us.md @@ -5,6 +5,8 @@ slug: "automatically-linked-references" weight: 15 toc: false draft: false +aliases: + - /en-us/automatically-linked-references menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/merge-message-templates.en-us.md b/docs/content/doc/usage/merge-message-templates.en-us.md index 70710b989e24..751f07e13f6e 100644 --- a/docs/content/doc/usage/merge-message-templates.en-us.md +++ b/docs/content/doc/usage/merge-message-templates.en-us.md @@ -5,6 +5,8 @@ slug: "merge-message-templates" weight: 15 toc: false draft: false +aliases: + - /en-us/merge-message-templates menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/packages/_index.en-us.md b/docs/content/doc/usage/packages/_index.en-us.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/content/doc/packages/cargo.en-us.md b/docs/content/doc/usage/packages/cargo.en-us.md similarity index 99% rename from docs/content/doc/packages/cargo.en-us.md rename to docs/content/doc/usage/packages/cargo.en-us.md index 1beeba407b6e..a74384ccefe9 100644 --- a/docs/content/doc/packages/cargo.en-us.md +++ b/docs/content/doc/usage/packages/cargo.en-us.md @@ -1,7 +1,7 @@ --- date: "2022-11-20T00:00:00+00:00" title: "Cargo Packages Repository" -slug: "usage/packages/cargo" +slug: "cargo" weight: 5 draft: false toc: false diff --git a/docs/content/doc/packages/chef.en-us.md b/docs/content/doc/usage/packages/chef.en-us.md similarity index 98% rename from docs/content/doc/packages/chef.en-us.md rename to docs/content/doc/usage/packages/chef.en-us.md index ab7150a2a207..dc5ca21e98cf 100644 --- a/docs/content/doc/packages/chef.en-us.md +++ b/docs/content/doc/usage/packages/chef.en-us.md @@ -1,7 +1,7 @@ --- date: "2023-01-20T00:00:00+00:00" title: "Chef Packages Repository" -slug: "usage/packages/chef" +slug: "chef" weight: 5 draft: false toc: false diff --git a/docs/content/doc/packages/composer.en-us.md b/docs/content/doc/usage/packages/composer.en-us.md similarity index 99% rename from docs/content/doc/packages/composer.en-us.md rename to docs/content/doc/usage/packages/composer.en-us.md index 6055ff319447..16c367eb2cf8 100644 --- a/docs/content/doc/packages/composer.en-us.md +++ b/docs/content/doc/usage/packages/composer.en-us.md @@ -1,7 +1,7 @@ --- date: "2021-07-20T00:00:00+00:00" title: "Composer Packages Repository" -slug: "usage/packages/composer" +slug: "composer" weight: 10 draft: false toc: false diff --git a/docs/content/doc/packages/conan.en-us.md b/docs/content/doc/usage/packages/conan.en-us.md similarity index 98% rename from docs/content/doc/packages/conan.en-us.md rename to docs/content/doc/usage/packages/conan.en-us.md index ff89fc153ef6..8c8fe4e262ad 100644 --- a/docs/content/doc/packages/conan.en-us.md +++ b/docs/content/doc/usage/packages/conan.en-us.md @@ -1,7 +1,7 @@ --- date: "2021-07-20T00:00:00+00:00" title: "Conan Packages Repository" -slug: "usage/packages/conan" +slug: "conan" weight: 20 draft: false toc: false diff --git a/docs/content/doc/packages/conda.en-us.md b/docs/content/doc/usage/packages/conda.en-us.md similarity index 98% rename from docs/content/doc/packages/conda.en-us.md rename to docs/content/doc/usage/packages/conda.en-us.md index 1a7cd8633450..c9a852239f9d 100644 --- a/docs/content/doc/packages/conda.en-us.md +++ b/docs/content/doc/usage/packages/conda.en-us.md @@ -1,7 +1,7 @@ --- date: "2022-12-28T00:00:00+00:00" title: "Conda Packages Repository" -slug: "usage/packages/conda" +slug: "conda" weight: 25 draft: false toc: false diff --git a/docs/content/doc/packages/container.en-us.md b/docs/content/doc/usage/packages/container.en-us.md similarity index 98% rename from docs/content/doc/packages/container.en-us.md rename to docs/content/doc/usage/packages/container.en-us.md index 5fd990b4b2fd..457e6fb1a473 100644 --- a/docs/content/doc/packages/container.en-us.md +++ b/docs/content/doc/usage/packages/container.en-us.md @@ -1,7 +1,7 @@ --- date: "2021-07-20T00:00:00+00:00" title: "Container Registry" -slug: "usage/packages/container" +slug: "container" weight: 30 draft: false toc: false diff --git a/docs/content/doc/packages/generic.en-us.md b/docs/content/doc/usage/packages/generic.en-us.md similarity index 99% rename from docs/content/doc/packages/generic.en-us.md rename to docs/content/doc/usage/packages/generic.en-us.md index 55b1868bfbc7..fbfe42d50a66 100644 --- a/docs/content/doc/packages/generic.en-us.md +++ b/docs/content/doc/usage/packages/generic.en-us.md @@ -1,7 +1,7 @@ --- date: "2021-07-20T00:00:00+00:00" title: "Generic Packages Repository" -slug: "usage/packages/generic" +slug: "generic" weight: 40 draft: false toc: false diff --git a/docs/content/doc/packages/helm.en-us.md b/docs/content/doc/usage/packages/helm.en-us.md similarity index 98% rename from docs/content/doc/packages/helm.en-us.md rename to docs/content/doc/usage/packages/helm.en-us.md index 263218b31eef..1db1e8758b28 100644 --- a/docs/content/doc/packages/helm.en-us.md +++ b/docs/content/doc/usage/packages/helm.en-us.md @@ -1,7 +1,7 @@ --- date: "2022-04-14T00:00:00+00:00" title: "Helm Chart Registry" -slug: "usage/packages/helm" +slug: "helm" weight: 50 draft: false toc: false diff --git a/docs/content/doc/packages/maven.en-us.md b/docs/content/doc/usage/packages/maven.en-us.md similarity index 99% rename from docs/content/doc/packages/maven.en-us.md rename to docs/content/doc/usage/packages/maven.en-us.md index 408a02a710be..81c3e2219740 100644 --- a/docs/content/doc/packages/maven.en-us.md +++ b/docs/content/doc/usage/packages/maven.en-us.md @@ -1,7 +1,7 @@ --- date: "2021-07-20T00:00:00+00:00" title: "Maven Packages Repository" -slug: "usage/packages/maven" +slug: "maven" weight: 60 draft: false toc: false diff --git a/docs/content/doc/packages/npm.en-us.md b/docs/content/doc/usage/packages/npm.en-us.md similarity index 99% rename from docs/content/doc/packages/npm.en-us.md rename to docs/content/doc/usage/packages/npm.en-us.md index fb13510840ce..a15cdb9a2b61 100644 --- a/docs/content/doc/packages/npm.en-us.md +++ b/docs/content/doc/usage/packages/npm.en-us.md @@ -1,7 +1,7 @@ --- date: "2021-07-20T00:00:00+00:00" title: "npm Packages Repository" -slug: "usage/packages/npm" +slug: "npm" weight: 70 draft: false toc: false diff --git a/docs/content/doc/packages/nuget.en-us.md b/docs/content/doc/usage/packages/nuget.en-us.md similarity index 99% rename from docs/content/doc/packages/nuget.en-us.md rename to docs/content/doc/usage/packages/nuget.en-us.md index 1309b4cab69c..aa88fa625ecc 100644 --- a/docs/content/doc/packages/nuget.en-us.md +++ b/docs/content/doc/usage/packages/nuget.en-us.md @@ -1,7 +1,7 @@ --- date: "2021-07-20T00:00:00+00:00" title: "NuGet Packages Repository" -slug: "usage/packages/nuget" +slug: "nuget" weight: 80 draft: false toc: false diff --git a/docs/content/doc/packages/overview.en-us.md b/docs/content/doc/usage/packages/overview.en-us.md similarity index 67% rename from docs/content/doc/packages/overview.en-us.md rename to docs/content/doc/usage/packages/overview.en-us.md index e6d984af77ce..fdeaf15af0ed 100644 --- a/docs/content/doc/packages/overview.en-us.md +++ b/docs/content/doc/usage/packages/overview.en-us.md @@ -1,7 +1,7 @@ --- date: "2021-07-20T00:00:00+00:00" title: "Package Registry" -slug: "usage/packages/overview" +slug: "overview" weight: 1 draft: false toc: false @@ -27,22 +27,22 @@ The following package managers are currently supported: | Name | Language | Package client | | ---- | -------- | -------------- | -| [Cargo]({{< relref "doc/packages/cargo.en-us.md" >}}) | Rust | `cargo` | -| [Chef]({{< relref "doc/packages/chef.en-us.md" >}}) | - | `knife` | -| [Composer]({{< relref "doc/packages/composer.en-us.md" >}}) | PHP | `composer` | -| [Conan]({{< relref "doc/packages/conan.en-us.md" >}}) | C++ | `conan` | -| [Conda]({{< relref "doc/packages/conda.en-us.md" >}}) | - | `conda` | -| [Container]({{< relref "doc/packages/container.en-us.md" >}}) | - | any OCI compliant client | -| [Generic]({{< relref "doc/packages/generic.en-us.md" >}}) | - | any HTTP client | -| [Helm]({{< relref "doc/packages/helm.en-us.md" >}}) | - | any HTTP client, `cm-push` | -| [Maven]({{< relref "doc/packages/maven.en-us.md" >}}) | Java | `mvn`, `gradle` | -| [npm]({{< relref "doc/packages/npm.en-us.md" >}}) | JavaScript | `npm`, `yarn`, `pnpm` | -| [NuGet]({{< relref "doc/packages/nuget.en-us.md" >}}) | .NET | `nuget` | -| [Pub]({{< relref "doc/packages/pub.en-us.md" >}}) | Dart | `dart`, `flutter` | -| [PyPI]({{< relref "doc/packages/pypi.en-us.md" >}}) | Python | `pip`, `twine` | -| [RubyGems]({{< relref "doc/packages/rubygems.en-us.md" >}}) | Ruby | `gem`, `Bundler` | -| [Swift]({{< relref "doc/packages/rubygems.en-us.md" >}}) | Swift | `swift` | -| [Vagrant]({{< relref "doc/packages/vagrant.en-us.md" >}}) | - | `vagrant` | +| [Cargo]({{< relref "doc/usage/packages/cargo.en-us.md" >}}) | Rust | `cargo` | +| [Chef]({{< relref "doc/usage/packages/chef.en-us.md" >}}) | - | `knife` | +| [Composer]({{< relref "doc/usage/packages/composer.en-us.md" >}}) | PHP | `composer` | +| [Conan]({{< relref "doc/usage/packages/conan.en-us.md" >}}) | C++ | `conan` | +| [Conda]({{< relref "doc/usage/packages/conda.en-us.md" >}}) | - | `conda` | +| [Container]({{< relref "doc/usage/packages/container.en-us.md" >}}) | - | any OCI compliant client | +| [Generic]({{< relref "doc/usage/packages/generic.en-us.md" >}}) | - | any HTTP client | +| [Helm]({{< relref "doc/usage/packages/helm.en-us.md" >}}) | - | any HTTP client, `cm-push` | +| [Maven]({{< relref "doc/usage/packages/maven.en-us.md" >}}) | Java | `mvn`, `gradle` | +| [npm]({{< relref "doc/usage/packages/npm.en-us.md" >}}) | JavaScript | `npm`, `yarn`, `pnpm` | +| [NuGet]({{< relref "doc/usage/packages/nuget.en-us.md" >}}) | .NET | `nuget` | +| [Pub]({{< relref "doc/usage/packages/pub.en-us.md" >}}) | Dart | `dart`, `flutter` | +| [PyPI]({{< relref "doc/usage/packages/pypi.en-us.md" >}}) | Python | `pip`, `twine` | +| [RubyGems]({{< relref "doc/usage/packages/rubygems.en-us.md" >}}) | Ruby | `gem`, `Bundler` | +| [Swift]({{< relref "doc/usage/packages/rubygems.en-us.md" >}}) | Swift | `swift` | +| [Vagrant]({{< relref "doc/usage/packages/vagrant.en-us.md" >}}) | - | `vagrant` | **The following paragraphs only apply if Packages are not globally disabled!** diff --git a/docs/content/doc/packages/pub.en-us.md b/docs/content/doc/usage/packages/pub.en-us.md similarity index 98% rename from docs/content/doc/packages/pub.en-us.md rename to docs/content/doc/usage/packages/pub.en-us.md index ebe42f18224e..f2df2016acab 100644 --- a/docs/content/doc/packages/pub.en-us.md +++ b/docs/content/doc/usage/packages/pub.en-us.md @@ -1,7 +1,7 @@ --- date: "2022-07-31T00:00:00+00:00" title: "Pub Packages Repository" -slug: "usage/packages/pub" +slug: "pub" weight: 90 draft: false toc: false diff --git a/docs/content/doc/packages/pypi.en-us.md b/docs/content/doc/usage/packages/pypi.en-us.md similarity index 98% rename from docs/content/doc/packages/pypi.en-us.md rename to docs/content/doc/usage/packages/pypi.en-us.md index 163eaa964682..84d9453daac1 100644 --- a/docs/content/doc/packages/pypi.en-us.md +++ b/docs/content/doc/usage/packages/pypi.en-us.md @@ -1,7 +1,7 @@ --- date: "2021-07-20T00:00:00+00:00" title: "PyPI Packages Repository" -slug: "usage/packages/pypi" +slug: "pypi" weight: 100 draft: false toc: false diff --git a/docs/content/doc/packages/rubygems.en-us.md b/docs/content/doc/usage/packages/rubygems.en-us.md similarity index 98% rename from docs/content/doc/packages/rubygems.en-us.md rename to docs/content/doc/usage/packages/rubygems.en-us.md index cb53b137d513..be60ed37af28 100644 --- a/docs/content/doc/packages/rubygems.en-us.md +++ b/docs/content/doc/usage/packages/rubygems.en-us.md @@ -1,7 +1,7 @@ --- date: "2021-07-20T00:00:00+00:00" title: "RubyGems Packages Repository" -slug: "usage/packages/rubygems" +slug: "rubygems" weight: 110 draft: false toc: false diff --git a/docs/content/doc/packages/storage.en-us.md b/docs/content/doc/usage/packages/storage.en-us.md similarity index 99% rename from docs/content/doc/packages/storage.en-us.md rename to docs/content/doc/usage/packages/storage.en-us.md index cd5952eb242e..15481ba7a395 100644 --- a/docs/content/doc/packages/storage.en-us.md +++ b/docs/content/doc/usage/packages/storage.en-us.md @@ -1,7 +1,7 @@ --- date: "2022-11-01T00:00:00+00:00" title: "Storage" -slug: "usage/packages/storage" +slug: "storage" weight: 5 draft: false toc: false diff --git a/docs/content/doc/packages/swift.en-us.md b/docs/content/doc/usage/packages/swift.en-us.md similarity index 99% rename from docs/content/doc/packages/swift.en-us.md rename to docs/content/doc/usage/packages/swift.en-us.md index 3f0cb1323945..a1c818021cd3 100644 --- a/docs/content/doc/packages/swift.en-us.md +++ b/docs/content/doc/usage/packages/swift.en-us.md @@ -1,7 +1,7 @@ --- date: "2023-01-10T00:00:00+00:00" title: "Swift Packages Repository" -slug: "usage/packages/swift" +slug: "swift" weight: 95 draft: false toc: false diff --git a/docs/content/doc/packages/vagrant.en-us.md b/docs/content/doc/usage/packages/vagrant.en-us.md similarity index 98% rename from docs/content/doc/packages/vagrant.en-us.md rename to docs/content/doc/usage/packages/vagrant.en-us.md index e224a9955416..5c633b4f7146 100644 --- a/docs/content/doc/packages/vagrant.en-us.md +++ b/docs/content/doc/usage/packages/vagrant.en-us.md @@ -1,7 +1,7 @@ --- date: "2022-08-23T00:00:00+00:00" title: "Vagrant Packages Repository" -slug: "usage/packages/vagrant" +slug: "vagrant" weight: 120 draft: false toc: false diff --git a/docs/content/doc/usage/permissions.en-us.md b/docs/content/doc/usage/permissions.en-us.md index 013dbfabd457..0778f6943f7f 100644 --- a/docs/content/doc/usage/permissions.en-us.md +++ b/docs/content/doc/usage/permissions.en-us.md @@ -5,6 +5,8 @@ slug: "permissions" weight: 14 toc: false draft: false +aliases: + - /en-us/permissions menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/protected-tags.en-us.md b/docs/content/doc/usage/protected-tags.en-us.md index f7404d32cb0d..c5e763659dd2 100644 --- a/docs/content/doc/usage/protected-tags.en-us.md +++ b/docs/content/doc/usage/protected-tags.en-us.md @@ -5,6 +5,8 @@ slug: "protected-tags" weight: 45 toc: false draft: false +aliases: + - /en-us/protected-tags menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/pull-request.en-us.md b/docs/content/doc/usage/pull-request.en-us.md index c7fea88a5a3e..feb8f848c95c 100644 --- a/docs/content/doc/usage/pull-request.en-us.md +++ b/docs/content/doc/usage/pull-request.en-us.md @@ -5,6 +5,8 @@ slug: "pull-request" weight: 13 toc: false draft: false +aliases: + - /en-us/pull-request menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/pull-request.zh-cn.md b/docs/content/doc/usage/pull-request.zh-cn.md index 04125672df92..d64690c05e35 100644 --- a/docs/content/doc/usage/pull-request.zh-cn.md +++ b/docs/content/doc/usage/pull-request.zh-cn.md @@ -5,6 +5,8 @@ slug: "pull-request" weight: 13 toc: false draft: false +aliases: + - /zh-cn/pull-request menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/pull-request.zh-tw.md b/docs/content/doc/usage/pull-request.zh-tw.md index b666fece136f..54cd1783210c 100644 --- a/docs/content/doc/usage/pull-request.zh-tw.md +++ b/docs/content/doc/usage/pull-request.zh-tw.md @@ -5,6 +5,8 @@ slug: "pull-request" weight: 13 toc: false draft: false +aliases: + - /zh-tw/pull-request menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/push.en-us.md b/docs/content/doc/usage/push.en-us.md index cf858e4e511b..097b07c9b4d6 100644 --- a/docs/content/doc/usage/push.en-us.md +++ b/docs/content/doc/usage/push.en-us.md @@ -5,6 +5,9 @@ slug: "push" weight: 15 toc: false draft: false +aliases: + - /en-us/push-to-create + - /en-us/push-options menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/push.zh-tw.md b/docs/content/doc/usage/push.zh-tw.md index f97d4285cc06..5fe5052c113d 100644 --- a/docs/content/doc/usage/push.zh-tw.md +++ b/docs/content/doc/usage/push.zh-tw.md @@ -5,6 +5,8 @@ slug: "push" weight: 15 toc: false draft: false +aliases: + - /zh-tw/push-options menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/repo-mirror.en-us.md b/docs/content/doc/usage/repo-mirror.en-us.md index 9a52282bb3c9..5e2b5c323874 100644 --- a/docs/content/doc/usage/repo-mirror.en-us.md +++ b/docs/content/doc/usage/repo-mirror.en-us.md @@ -5,6 +5,8 @@ slug: "repo-mirror" weight: 45 toc: false draft: false +aliases: + - /en-us/repo-mirror menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/secrets.en-us.md b/docs/content/doc/usage/secrets.en-us.md index b45044cc3315..c193a54a6c09 100644 --- a/docs/content/doc/usage/secrets.en-us.md +++ b/docs/content/doc/usage/secrets.en-us.md @@ -1,10 +1,12 @@ --- date: "2022-12-19T21:26:00+08:00" title: "Secrets" -slug: "usage/secrets" +slug: "secrets" weight: 50 draft: false toc: false +aliases: + - /en-us/secrets menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/template-repositories.en-us.md b/docs/content/doc/usage/template-repositories.en-us.md index 9a2a23ed2b03..0c278648b3ec 100644 --- a/docs/content/doc/usage/template-repositories.en-us.md +++ b/docs/content/doc/usage/template-repositories.en-us.md @@ -5,6 +5,8 @@ slug: "template-repositories" weight: 14 toc: false draft: false +aliases: + - /en-us/template-repositories menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/webhooks.en-us.md b/docs/content/doc/usage/webhooks.en-us.md index 457113c5cf74..24cd48c9193d 100644 --- a/docs/content/doc/usage/webhooks.en-us.md +++ b/docs/content/doc/usage/webhooks.en-us.md @@ -5,6 +5,8 @@ slug: "webhooks" weight: 30 toc: false draft: false +aliases: + - /en-us/webhooks menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/webhooks.zh-cn.md b/docs/content/doc/usage/webhooks.zh-cn.md index 9e9f2bf502f4..44d97cc83fd0 100644 --- a/docs/content/doc/usage/webhooks.zh-cn.md +++ b/docs/content/doc/usage/webhooks.zh-cn.md @@ -5,6 +5,8 @@ slug: "webhooks" weight: 30 toc: false draft: false +aliases: + - /zh-cn/webhooks menu: sidebar: parent: "usage" diff --git a/docs/content/doc/usage/webhooks.zh-tw.md b/docs/content/doc/usage/webhooks.zh-tw.md index 9afad4236998..ca5991354a16 100644 --- a/docs/content/doc/usage/webhooks.zh-tw.md +++ b/docs/content/doc/usage/webhooks.zh-tw.md @@ -5,6 +5,8 @@ slug: "webhooks" weight: 30 toc: false draft: false +aliases: + - /zh-tw/webhooks menu: sidebar: parent: "usage" diff --git a/docs/content/page/index.zh-cn.md b/docs/content/page/index.zh-cn.md index 5af67f5531c0..da25d8ee1366 100644 --- a/docs/content/page/index.zh-cn.md +++ b/docs/content/page/index.zh-cn.md @@ -70,4 +70,4 @@ Gitea的首要目标是创建一个极易安装,运行非常快速,安装和 ## 需要帮助? -如果从本页中没有找到你需要的内容,请访问 [帮助页面]({{< relref "seek-help.zh-cn.md" >}}) +如果从本页中没有找到你需要的内容,请访问 [帮助页面]({{< relref "support.zh-cn.md" >}}) diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 9de5931d7146..1f1f43796cf4 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -487,6 +487,8 @@ var migrations = []Migration{ NewMigration("Fix ExternalTracker and ExternalWiki accessMode in owner and admin team", v1_20.FixExternalTrackerAndExternalWikiAccessModeInOwnerAndAdminTeam), // v254 -> v255 NewMigration("Add ActionTaskOutput table", v1_20.AddActionTaskOutputTable), + // v255 -> v256 + NewMigration("Add ArchivedUnix Column", v1_20.AddArchivedUnixToRepository), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v1_20/v255.go b/models/migrations/v1_20/v255.go new file mode 100644 index 000000000000..14b70f8f962f --- /dev/null +++ b/models/migrations/v1_20/v255.go @@ -0,0 +1,23 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_20 //nolint + +import ( + "code.gitea.io/gitea/modules/timeutil" + + "xorm.io/xorm" +) + +func AddArchivedUnixToRepository(x *xorm.Engine) error { + type Repository struct { + ArchivedUnix timeutil.TimeStamp `xorm:"DEFAULT 0"` + } + + if err := x.Sync(new(Repository)); err != nil { + return err + } + + _, err := x.Exec("UPDATE repository SET archived_unix = updated_unix WHERE is_archived = ? AND archived_unix = 0", true) + return err +} diff --git a/models/repo/archiver.go b/models/repo/archiver.go index 11ecaff34c69..70f53cfe158d 100644 --- a/models/repo/archiver.go +++ b/models/repo/archiver.go @@ -146,6 +146,13 @@ func FindRepoArchives(opts FindRepoArchiversOption) ([]*RepoArchiver, error) { // SetArchiveRepoState sets if a repo is archived func SetArchiveRepoState(repo *Repository, isArchived bool) (err error) { repo.IsArchived = isArchived - _, err = db.GetEngine(db.DefaultContext).Where("id = ?", repo.ID).Cols("is_archived").NoAutoTime().Update(repo) + + if isArchived { + repo.ArchivedUnix = timeutil.TimeStampNow() + } else { + repo.ArchivedUnix = timeutil.TimeStamp(0) + } + + _, err = db.GetEngine(db.DefaultContext).ID(repo.ID).Cols("is_archived", "archived_unix").NoAutoTime().Update(repo) return err } diff --git a/models/repo/repo.go b/models/repo/repo.go index 266cbc288c17..f9de6d493db4 100644 --- a/models/repo/repo.go +++ b/models/repo/repo.go @@ -174,8 +174,9 @@ type Repository struct { // Avatar: ID(10-20)-md5(32) - must fit into 64 symbols Avatar string `xorm:"VARCHAR(64)"` - CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` - UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` + CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` + UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` + ArchivedUnix timeutil.TimeStamp `xorm:"DEFAULT 0"` } func init() { diff --git a/modules/context/api.go b/modules/context/api.go index f7a338469124..ae245ec1cb62 100644 --- a/modules/context/api.go +++ b/modules/context/api.go @@ -337,12 +337,13 @@ func RepoRefForAPI(next http.Handler) http.Handler { if git.IsErrNotExist(err) { ctx.NotFound() } else { - ctx.Error(http.StatusInternalServerError, "GetBlobByPath", err) + ctx.Error(http.StatusInternalServerError, "GetCommit", err) } return } ctx.Repo.Commit = commit ctx.Repo.TreePath = ctx.Params("*") + next.ServeHTTP(w, req) return } diff --git a/modules/context/context.go b/modules/context/context.go index f262c7cce7cb..702da8a965e0 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -446,6 +446,17 @@ func (ctx *Context) JSON(status int, content interface{}) { } } +func removeSessionCookieHeader(w http.ResponseWriter) { + cookies := w.Header()["Set-Cookie"] + w.Header().Del("Set-Cookie") + for _, cookie := range cookies { + if strings.HasPrefix(cookie, setting.SessionConfig.CookieName+"=") { + continue + } + w.Header().Add("Set-Cookie", cookie) + } +} + // Redirect redirects the request func (ctx *Context) Redirect(location string, status ...int) { code := http.StatusSeeOther @@ -453,6 +464,15 @@ func (ctx *Context) Redirect(location string, status ...int) { code = status[0] } + if strings.Contains(location, "://") || strings.HasPrefix(location, "//") { + // Some browsers (Safari) have buggy behavior for Cookie + Cache + External Redirection, eg: /my-path => https://other/path + // 1. the first request to "/my-path" contains cookie + // 2. some time later, the request to "/my-path" doesn't contain cookie (caused by Prevent web tracking) + // 3. Gitea's Sessioner doesn't see the session cookie, so it generates a new session id, and returns it to browser + // 4. then the browser accepts the empty session, then the user is logged out + // So in this case, we should remove the session cookie from the response header + removeSessionCookieHeader(ctx.Resp) + } http.Redirect(ctx.Resp, ctx.Req, location, code) } diff --git a/modules/context/context_test.go b/modules/context/context_test.go new file mode 100644 index 000000000000..e1460c1fd70f --- /dev/null +++ b/modules/context/context_test.go @@ -0,0 +1,40 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package context + +import ( + "net/http" + "testing" + + "code.gitea.io/gitea/modules/setting" + + "github.com/stretchr/testify/assert" +) + +type mockResponseWriter struct { + header http.Header +} + +func (m *mockResponseWriter) Header() http.Header { + return m.header +} + +func (m *mockResponseWriter) Write(bytes []byte) (int, error) { + panic("implement me") +} + +func (m *mockResponseWriter) WriteHeader(statusCode int) { + panic("implement me") +} + +func TestRemoveSessionCookieHeader(t *testing.T) { + w := &mockResponseWriter{} + w.header = http.Header{} + w.header.Add("Set-Cookie", (&http.Cookie{Name: setting.SessionConfig.CookieName, Value: "foo"}).String()) + w.header.Add("Set-Cookie", (&http.Cookie{Name: "other", Value: "bar"}).String()) + assert.Len(t, w.Header().Values("Set-Cookie"), 2) + removeSessionCookieHeader(w) + assert.Len(t, w.Header().Values("Set-Cookie"), 1) + assert.Contains(t, "other=bar", w.Header().Get("Set-Cookie")) +} diff --git a/modules/context/permission.go b/modules/context/permission.go index 8cb5d09eb946..cc53fb99ed74 100644 --- a/modules/context/permission.go +++ b/modules/context/permission.go @@ -4,6 +4,10 @@ package context import ( + "net/http" + + auth_model "code.gitea.io/gitea/models/auth" + repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/log" ) @@ -106,3 +110,32 @@ func RequireRepoReaderOr(unitTypes ...unit.Type) func(ctx *Context) { ctx.NotFound(ctx.Req.URL.RequestURI(), nil) } } + +// RequireRepoScopedToken check whether personal access token has repo scope +func CheckRepoScopedToken(ctx *Context, repo *repo_model.Repository) { + if !ctx.IsBasicAuth || ctx.Data["IsApiToken"] != true { + return + } + + var err error + scope, ok := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope) + if ok { // it's a personal access token but not oauth2 token + var scopeMatched bool + scopeMatched, err = scope.HasScope(auth_model.AccessTokenScopeRepo) + if err != nil { + ctx.ServerError("HasScope", err) + return + } + if !scopeMatched && !repo.IsPrivate { + scopeMatched, err = scope.HasScope(auth_model.AccessTokenScopePublicRepo) + if err != nil { + ctx.ServerError("HasScope", err) + return + } + } + if !scopeMatched { + ctx.Error(http.StatusForbidden) + return + } + } +} diff --git a/modules/setting/markup.go b/modules/setting/markup.go index 969e30e888f8..6c2246342be8 100644 --- a/modules/setting/markup.go +++ b/modules/setting/markup.go @@ -33,7 +33,7 @@ var Markdown = struct { }{ EnableHardLineBreakInComments: true, EnableHardLineBreakInDocuments: false, - FileExtensions: strings.Split(".md,.markdown,.mdown,.mkd", ","), + FileExtensions: strings.Split(".md,.markdown,.mdown,.mkd,.livemd", ","), EnableMath: true, } diff --git a/modules/setting/repository.go b/modules/setting/repository.go index bae3c658a485..20ed6d0dcd55 100644 --- a/modules/setting/repository.go +++ b/modules/setting/repository.go @@ -168,7 +168,7 @@ var ( Editor: struct { LineWrapExtensions []string }{ - LineWrapExtensions: strings.Split(".txt,.md,.markdown,.mdown,.mkd,", ","), + LineWrapExtensions: strings.Split(".txt,.md,.markdown,.mdown,.mkd,.livemd,", ","), }, // Repository upload settings diff --git a/modules/setting/ui.go b/modules/setting/ui.go index 90bad50d3b3b..bf2b2d4bb7e0 100644 --- a/modules/setting/ui.go +++ b/modules/setting/ui.go @@ -77,7 +77,7 @@ var UI = struct { GraphMaxCommitNum: 100, CodeCommentLines: 4, ReactionMaxUserNum: 10, - ThemeColorMetaTag: `#6cc644`, + ThemeColorMetaTag: ``, MaxDisplayFileSize: 8388608, DefaultTheme: `auto`, Themes: []string{`auto`, `gitea`, `arc-green`}, diff --git a/modules/structs/miscellaneous.go b/modules/structs/miscellaneous.go index 8acea84d6cc1..bff10f95b7c5 100644 --- a/modules/structs/miscellaneous.go +++ b/modules/structs/miscellaneous.go @@ -72,6 +72,28 @@ type ServerVersion struct { Version string `json:"version"` } +// GitignoreTemplateInfo name and text of a gitignore template +type GitignoreTemplateInfo struct { + Name string `json:"name"` + Source string `json:"source"` +} + +// LicensesListEntry is used for the API +type LicensesTemplateListEntry struct { + Key string `json:"key"` + Name string `json:"name"` + URL string `json:"url"` +} + +// LicensesInfo contains information about a License +type LicenseTemplateInfo struct { + Key string `json:"key"` + Name string `json:"name"` + URL string `json:"url"` + Implementation string `json:"implementation"` + Body string `json:"body"` +} + // APIError is an api error with a message type APIError struct { Message string `json:"message"` diff --git a/modules/structs/repo.go b/modules/structs/repo.go index 6d3e2c290926..259c23057157 100644 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -80,6 +80,7 @@ type Repository struct { Created time.Time `json:"created_at"` // swagger:strfmt date-time Updated time.Time `json:"updated_at"` + ArchivedAt time.Time `json:"archived_at"` Permissions *Permission `json:"permissions,omitempty"` HasIssues bool `json:"has_issues"` InternalTracker *InternalTracker `json:"internal_tracker,omitempty"` diff --git a/modules/templates/helper.go b/modules/templates/helper.go index b7bef205603f..a290d3897932 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -141,9 +141,6 @@ func NewFuncMap() []template.FuncMap { "TimeSinceUnix": timeutil.TimeSinceUnix, "DateTime": timeutil.DateTime, "Sec2Time": util.SecToTime, - "DateFmtLong": func(t time.Time) string { - return t.Format(time.RFC3339) - }, "LoadTimes": func(startTime time.Time) string { return fmt.Sprint(time.Since(startTime).Nanoseconds()/1e6) + "ms" }, diff --git a/modules/web/handler.go b/modules/web/handler.go index 8a44673f1262..bfb83820c885 100644 --- a/modules/web/handler.go +++ b/modules/web/handler.go @@ -8,7 +8,6 @@ import ( "fmt" "net/http" "reflect" - "strings" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/web/routing" @@ -131,16 +130,22 @@ func hasResponseBeenWritten(argsIn []reflect.Value) bool { // toHandlerProvider converts a handler to a handler provider // A handler provider is a function that takes a "next" http.Handler, it can be used as a middleware func toHandlerProvider(handler any) func(next http.Handler) http.Handler { - if hp, ok := handler.(func(next http.Handler) http.Handler); ok { - return hp - } - funcInfo := routing.GetFuncInfo(handler) fn := reflect.ValueOf(handler) if fn.Type().Kind() != reflect.Func { panic(fmt.Sprintf("handler must be a function, but got %s", fn.Type())) } + if hp, ok := handler.(func(next http.Handler) http.Handler); ok { + return func(next http.Handler) http.Handler { + h := hp(next) // this handle could be dynamically generated, so we can't use it for debug info + return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { + routing.UpdateFuncInfo(req.Context(), funcInfo) + h.ServeHTTP(resp, req) + }) + } + } + provider := func(next http.Handler) http.Handler { return http.HandlerFunc(func(respOrig http.ResponseWriter, req *http.Request) { // wrap the response writer to check whether the response has been written @@ -175,26 +180,3 @@ func toHandlerProvider(handler any) func(next http.Handler) http.Handler { provider(nil).ServeHTTP(nil, nil) // do a pre-check to make sure all arguments and return values are supported return provider } - -// MiddlewareWithPrefix wraps a handler function at a prefix, and make it as a middleware -// TODO: this design is incorrect, the asset handler should not be a middleware -func MiddlewareWithPrefix(pathPrefix string, middleware func(handler http.Handler) http.Handler, handlerFunc http.HandlerFunc) func(next http.Handler) http.Handler { - funcInfo := routing.GetFuncInfo(handlerFunc) - handler := http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { - routing.UpdateFuncInfo(req.Context(), funcInfo) - handlerFunc(resp, req) - }) - return func(next http.Handler) http.Handler { - return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { - if !strings.HasPrefix(req.URL.Path, pathPrefix) { - next.ServeHTTP(resp, req) - return - } - if middleware != nil { - middleware(handler).ServeHTTP(resp, req) - } else { - handler.ServeHTTP(resp, req) - } - }) - } -} diff --git a/modules/web/route.go b/modules/web/route.go index fe3588084941..6fd60f4ca739 100644 --- a/modules/web/route.go +++ b/modules/web/route.go @@ -44,23 +44,13 @@ type Route struct { // NewRoute creates a new route func NewRoute() *Route { r := chi.NewRouter() - return &Route{ - R: r, - curGroupPrefix: "", - curMiddlewares: []interface{}{}, - } + return &Route{R: r} } // Use supports two middlewares func (r *Route) Use(middlewares ...interface{}) { - if r.curGroupPrefix != "" { - // FIXME: this behavior is incorrect, should use "With" instead - r.curMiddlewares = append(r.curMiddlewares, middlewares...) - } else { - // FIXME: another misuse, the "Use" with empty middlewares is called after "Mount" - for _, m := range middlewares { - r.R.Use(toHandlerProvider(m)) - } + for _, m := range middlewares { + r.R.Use(toHandlerProvider(m)) } } @@ -116,9 +106,7 @@ func (r *Route) Methods(method, pattern string, h []any) { // Mount attaches another Route along ./pattern/* func (r *Route) Mount(pattern string, subR *Route) { - middlewares := make([]interface{}, len(r.curMiddlewares)) - copy(middlewares, r.curMiddlewares) - subR.Use(middlewares...) + subR.Use(r.curMiddlewares...) r.R.Mount(r.getPattern(pattern), subR.R) } diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index ef9990d26587..3fff13c5a27e 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -109,6 +109,7 @@ error = Error error404 = The page you are trying to reach either does not exist or you are not authorized to view it. never = Never +unknown = Unknown rss_feed = RSS Feed @@ -992,6 +993,7 @@ template.one_item = Must select at least one template item template.invalid = Must select a template repository archive.title = This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests. +archive.title_date = This repository has been archived on %s. You can view files and clone it, but cannot push or open issues/pull-requests. archive.issue.nocomment = This repo is archived. You cannot comment on issues. archive.pull.nocomment = This repo is archived. You cannot comment on pull requests. @@ -1540,6 +1542,7 @@ issues.dependency.issue_closing_blockedby = Closing this issue is blocked by the issues.dependency.issue_close_blocks = This issue blocks closing of the following issues issues.dependency.pr_close_blocks = This pull request blocks closing of the following issues issues.dependency.issue_close_blocked = You need to close all issues blocking this issue before you can close it. +issues.dependency.issue_batch_close_blocked = "Cannot batch close issues that you choose, because issue #%d still has open dependencies" issues.dependency.pr_close_blocked = You need to close all issues blocking this pull request before you can merge it. issues.dependency.blocks_short = Blocks issues.dependency.blocked_by_short = Depends on @@ -2956,6 +2959,7 @@ config.mailer_sendmail_timeout = Sendmail Timeout config.mailer_use_dummy = Dummy config.test_email_placeholder = Email (e.g. test@example.com) config.send_test_mail = Send Testing Email +config.send_test_mail_submit = Send config.test_mail_failed = Failed to send a testing email to "%s": %v config.test_mail_sent = A testing email has been sent to "%s". @@ -3354,6 +3358,7 @@ deletion = Remove secret deletion.description = Removing a secret is permanent and cannot be undone. Continue? deletion.success = The secret has been removed. deletion.failed = Failed to remove secret. +management = Secrets Management [actions] actions = Actions diff --git a/options/locale/locale_ko-KR.ini b/options/locale/locale_ko-KR.ini index d000c71cad73..82f7effb5285 100644 --- a/options/locale/locale_ko-KR.ini +++ b/options/locale/locale_ko-KR.ini @@ -95,7 +95,7 @@ license=오픈 소스 [install] install=설치 title=초기 설정 -docker_helper=Gitea를 Docker에서 실행하려면 설정 전에 이 문서를 읽어보세요. +docker_helper="Gitea를 Docker에서 실행하려면 설정 전에 이 문서를 읽어보세요." db_title=데이터베이스 설정 db_type=데이터베이스 유형 host=호스트 @@ -444,8 +444,8 @@ manage_gpg_keys=GPG 키 관리 add_key=키 추가 ssh_desc=이러한 SSH 공용 키는 귀하의 계정과 연결되어 있습니다. 해당 개인 키는 당신의 저장소에 대한 전체 액세스를 가능하게 합니다. gpg_desc=이러한 GPG 공개키는 당신의 계정과 연결되어있습니다. 커밋이 검증될 수 있도록 당신의 개인 키를 안전하게 유지하십시오. -ssh_helper=도움이 필요하세요? GitHub의 설명서를 참조하시기 바랍니다: SSH 키 생성하기 또는 SSH를 사용할 때 일반적인 문제 -gpg_helper=도움이 필요하세요? GitHub의 설명서를 참조하시기 바랍니다: GPG키에 대하여. +ssh_helper="도움이 필요하세요? GitHub의 설명서를 참조하시기 바랍니다: SSH 키 생성하기 또는 SSH를 사용할 때 일반적인 문제" +gpg_helper="도움이 필요하세요? GitHub의 설명서를 참조하시기 바랍니다: GPG키에 대하여." add_new_key=SSH 키 추가 add_new_gpg_key=GPG 키 추가 gpg_key_id_used=같은 ID의 GPG 공개키가 이미 존재합니다. @@ -557,7 +557,7 @@ visibility=가시성 visibility_helper=개인 저장소로 만들기 visibility_helper_forced=사이트 관리자가 새 레포지토리에 대해 비공개로만 생성되도록 하였습니다. visibility_fork_helper=(변경사항을 적용하는 경우 모든 포크가 영향을 받게 됩니다.) -clone_helper=클론하는데에 도움이 필요하면 Help에 방문하세요. +clone_helper="클론하는데에 도움이 필요하면 Help에 방문하세요." fork_repo=저장소 포크 fork_from=원본 프로젝트 : fork_visibility_helper=포크된 저장소의 가시성은 변경하실 수 없습니다. @@ -660,7 +660,7 @@ editor.or=혹은 editor.cancel_lower=취소 editor.commit_changes=변경 내용을 커밋 editor.commit_message_desc=선택적 확장 설명을 추가... -editor.commit_directly_to_this_branch=%s 브랜치에서 직접 커밋해주세요. +editor.commit_directly_to_this_branch="%s 브랜치에서 직접 커밋해주세요." editor.create_new_branch=이 커밋에 대한 새로운 브랜치를 만들고 끌어오기 요청을 시작합니다. editor.new_branch_name_desc=새로운 브랜치 명... editor.cancel=취소 @@ -752,7 +752,7 @@ issues.action_milestone=마일스톤 issues.action_milestone_no_select=마일스톤 없음 issues.action_assignee=담당자 issues.action_assignee_no_select=담당자 없음 -issues.opened_by= %[3]s가 %[1]s을 오픈 +issues.opened_by=" %[3]s가 %[1]s을 오픈" issues.previous=이전 issues.next=다음 issues.open_title=오픈 @@ -772,7 +772,7 @@ issues.commit_ref_at=` 커밋 %[2]s에서 이 issues.poster=포스터 issues.collaborator=협업자 issues.owner=소유자 -issues.sign_in_require_desc=로그인하여 이 대화에 참여 +issues.sign_in_require_desc="로그인하여 이 대화에 참여" issues.edit=수정 issues.cancel=취소 issues.save=저장 @@ -810,19 +810,19 @@ issues.add_time_sum_to_small=시간이 입력되지 않았습니다. issues.time_spent_total=총 경과된 시간 issues.time_spent_from_all_authors=`총 경과된 시간: %s` issues.due_date=마감일 -issues.invalid_due_date_format=마감일은 반드시 'yyyy-mm-dd' 형식이어야 합니다. -issues.error_modifying_due_date=마감일 수정을 실패하였습니다. -issues.error_removing_due_date=마감일 삭제를 실패하였습니다. +issues.invalid_due_date_format="마감일은 반드시 'yyyy-mm-dd' 형식이어야 합니다." +issues.error_modifying_due_date="마감일 수정을 실패하였습니다." +issues.error_removing_due_date="마감일 삭제를 실패하였습니다." issues.due_date_form=yyyy-mm-dd issues.due_date_form_add=마감일 추가 issues.due_date_form_edit=편집 issues.due_date_form_remove=삭제 -issues.due_date_not_writer=이슈의 마감일을 갱신하려면 저장소 쓰기 권한이 필요합니다. +issues.due_date_not_writer="이슈의 마감일을 갱신하려면 저장소 쓰기 권한이 필요합니다." issues.due_date_not_set=마감일이 설정되지 않았습니다. issues.due_date_added=마감일 %s 를 추가 %s issues.due_date_remove=%s %s 마감일이 삭제되었습니다. -issues.due_date_overdue=기한 초과 -issues.due_date_invalid=기한이 올바르지 않거나 범위를 벗어났습니다. 'yyyy-mm-dd'형식을 사용해주십시오. +issues.due_date_overdue="기한 초과" +issues.due_date_invalid="기한이 올바르지 않거나 범위를 벗어났습니다. 'yyyy-mm-dd'형식을 사용해주십시오." issues.dependency.title=의존성 issues.dependency.add=의존성 추가... issues.dependency.cancel=취소 @@ -840,7 +840,7 @@ issues.dependency.add_error_dep_exists=의존성이 이미 존재합니다. issues.dependency.add_error_dep_not_same_repo=두 이슈는 같은 레포지토리 안에 있어야 합니다. issues.review.self.approval=자신의 풀 리퀘스트를 승인할 수 없습니다. issues.review.self.rejection=자신의 풀 리퀘스트에 대한 변경을 요청할 수 없습니다. -issues.review.approve=이 변경사항을 승인하였습니다. %s +issues.review.approve="이 변경사항을 승인하였습니다. %s" issues.review.comment=검토됨 %s issues.review.pending=보류 issues.review.review=검토 @@ -856,7 +856,7 @@ pulls.compare_compare=다음으로부터 풀 pulls.filter_branch=Filter Branch pulls.no_results=결과 없음 pulls.create=풀 리퀘스트 생성 -pulls.title_desc=%[2]s 에서 %[3]s 로 %[1]d commits 를 머지하려 합니다 +pulls.title_desc="%[2]s 에서 %[3]s 로 %[1]d commits 를 머지하려 합니다" pulls.merged_title_desc=%[2]s 에서 %[3]s 로 %[1]d commits 를 머지했습니다 %[4]s pulls.tab_conversation=대화 pulls.tab_commits=커밋 @@ -885,7 +885,7 @@ milestones.title=타이틀 milestones.desc=설명 milestones.due_date=기한 (선택 사항) milestones.clear=지우기 -milestones.invalid_due_date_format=마감일은 반드시 'yyyy-mm-dd' 형식이어야 합니다. +milestones.invalid_due_date_format="마감일은 반드시 'yyyy-mm-dd' 형식이어야 합니다." milestones.edit=마일스톤 편집 milestones.cancel=취소 milestones.modify=마일스톤 갱신 @@ -962,7 +962,7 @@ activity.published_release_label=배포됨 search=검색 search.search_repo=저장소 검색 -search.results=%s 에서 "%s" 에 대한 검색 결과 +search.results="%s 에서 \"%s\" 에 대한 검색 결과" search.code_no_results=검색어와 일치하는 소스코드가 없습니다. settings=설정 diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 41f987bb72ce..aab7781dc2eb 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -286,7 +286,7 @@ issues.in_your_repos=在您的仓库中 [explore] repos=仓库 users=用户 -organizations=组织管理 +organizations=组织 search=搜索 code=代码 search.type.tooltip=搜索类型 diff --git a/package-lock.json b/package-lock.json index 9a2f5dc5783f..d899903e4f9e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -65,6 +65,7 @@ "eslint-plugin-import": "2.27.5", "eslint-plugin-jquery": "1.5.1", "eslint-plugin-no-jquery": "2.7.0", + "eslint-plugin-regexp": "1.14.0", "eslint-plugin-sonarjs": "0.19.0", "eslint-plugin-unicorn": "46.0.0", "eslint-plugin-vue": "9.11.0", @@ -2927,6 +2928,15 @@ "node": ">= 12" } }, + "node_modules/comment-parser": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.1.tgz", + "integrity": "sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA==", + "dev": true, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -4560,6 +4570,28 @@ "eslint": ">=2.3.0" } }, + "node_modules/eslint-plugin-regexp": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-1.14.0.tgz", + "integrity": "sha512-5+bBSsRTTtkSf8+/iNSjiOW6qbjAdGyqv88HxPaBNFKxROK+UAdOGDl5Jr+csV5wW2BuOOvaG82zsvTriQBRFA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "comment-parser": "^1.1.2", + "grapheme-splitter": "^1.0.4", + "jsdoctypeparser": "^9.0.0", + "refa": "^0.11.0", + "regexp-ast-analysis": "^0.6.0", + "scslre": "^0.2.0" + }, + "engines": { + "node": "^12 || >=14" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, "node_modules/eslint-plugin-sonarjs": { "version": "0.19.0", "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.19.0.tgz", @@ -6038,6 +6070,18 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsdoctypeparser": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-9.0.0.tgz", + "integrity": "sha512-jrTA2jJIL6/DAEILBEh2/w9QxCuwmvNXIry39Ay/HVfhE3o2yVV0U44blYkqdHA/OKloJEqvJy0xU+GSdE2SIw==", + "dev": true, + "bin": { + "jsdoctypeparser": "bin/jsdoctypeparser" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jsdom": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-21.1.1.tgz", @@ -7934,11 +7978,36 @@ "node": ">=8" } }, + "node_modules/refa": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/refa/-/refa-0.11.0.tgz", + "integrity": "sha512-486O8/pQXwj9jV0mVvUnTsxq0uknpBnNJ0eCUhkZqJRQ8KutrT1PhzmumdCeM1hSBF2eMlFPmwECRER4IbKXlQ==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.0" + }, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, "node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, + "node_modules/regexp-ast-analysis": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regexp-ast-analysis/-/regexp-ast-analysis-0.6.0.tgz", + "integrity": "sha512-OLxjyjPkVH+rQlBLb1I/P/VTmamSjGkvN5PTV5BXP432k3uVz727J7H29GA5IFiY0m7e1xBN7049Wn59FY3DEQ==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.0", + "refa": "^0.11.0" + }, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, "node_modules/regexp-tree": { "version": "0.1.25", "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.25.tgz", @@ -8247,6 +8316,17 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/scslre": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/scslre/-/scslre-0.2.0.tgz", + "integrity": "sha512-4hc49fUMmX3jM0XdFUAPBrs1xwEcdHa0KyjEsjFs+Zfc66mpFpq5YmRgDtl+Ffo6AtJIilfei+yKw8fUn3N88w==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.0", + "refa": "^0.11.0", + "regexp-ast-analysis": "^0.6.0" + } + }, "node_modules/semver": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", diff --git a/package.json b/package.json index ae3b7446fe5a..05b9fed90e00 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "eslint-plugin-import": "2.27.5", "eslint-plugin-jquery": "1.5.1", "eslint-plugin-no-jquery": "2.7.0", + "eslint-plugin-regexp": "1.14.0", "eslint-plugin-sonarjs": "0.19.0", "eslint-plugin-unicorn": "46.0.0", "eslint-plugin-vue": "9.11.0", diff --git a/routers/api/actions/runner/utils.go b/routers/api/actions/runner/utils.go index 705867a9b106..10f92c29f72e 100644 --- a/routers/api/actions/runner/utils.go +++ b/routers/api/actions/runner/utils.go @@ -92,6 +92,21 @@ func generateTaskContext(t *actions_model.ActionTask) *structpb.Struct { event := map[string]interface{}{} _ = json.Unmarshal([]byte(t.Job.Run.EventPayload), &event) + baseRef := "" + headRef := "" + if pullPayload, err := t.Job.Run.GetPullRequestEventPayload(); err == nil && pullPayload.PullRequest != nil && pullPayload.PullRequest.Base != nil && pullPayload.PullRequest.Head != nil { + baseRef = pullPayload.PullRequest.Base.Ref + headRef = pullPayload.PullRequest.Head.Ref + } + refPrefix, refName := git.SplitRefName(t.Job.Run.Ref) + refType := "" + switch refPrefix { + case git.BranchPrefix: + refType = "branch" + case git.TagPrefix: + refType = "tag" + } + taskContext, _ := structpb.NewStruct(map[string]interface{}{ // standard contexts, see https://docs.github.com/en/actions/learn-github-actions/contexts#github-context "action": "", // string, The name of the action currently running, or the id of a step. GitHub removes special characters, and uses the name __run when the current step runs a script without an id. If you use the same action more than once in the same job, the name will include a suffix with the sequence number with underscore before it. For example, the first script you run will have the name __run, and the second script will be named __run_2. Similarly, the second invocation of actions/checkout will be actionscheckout2. @@ -100,19 +115,19 @@ func generateTaskContext(t *actions_model.ActionTask) *structpb.Struct { "action_repository": "", // string, For a step executing an action, this is the owner and repository name of the action. For example, actions/checkout. "action_status": "", // string, For a composite action, the current result of the composite action. "actor": t.Job.Run.TriggerUser.Name, // string, The username of the user that triggered the initial workflow run. If the workflow run is a re-run, this value may differ from github.triggering_actor. Any workflow re-runs will use the privileges of github.actor, even if the actor initiating the re-run (github.triggering_actor) has different privileges. - "api_url": "", // string, The URL of the GitHub REST API. - "base_ref": "", // string, The base_ref or target branch of the pull request in a workflow run. This property is only available when the event that triggers a workflow run is either pull_request or pull_request_target. + "api_url": setting.AppURL + "api/v1", // string, The URL of the GitHub REST API. + "base_ref": baseRef, // string, The base_ref or target branch of the pull request in a workflow run. This property is only available when the event that triggers a workflow run is either pull_request or pull_request_target. "env": "", // string, Path on the runner to the file that sets environment variables from workflow commands. This file is unique to the current step and is a different file for each step in a job. For more information, see "Workflow commands for GitHub Actions." "event": event, // object, The full event webhook payload. You can access individual properties of the event using this context. This object is identical to the webhook payload of the event that triggered the workflow run, and is different for each event. The webhooks for each GitHub Actions event is linked in "Events that trigger workflows." For example, for a workflow run triggered by the push event, this object contains the contents of the push webhook payload. "event_name": t.Job.Run.Event.Event(), // string, The name of the event that triggered the workflow run. "event_path": "", // string, The path to the file on the runner that contains the full event webhook payload. "graphql_url": "", // string, The URL of the GitHub GraphQL API. - "head_ref": "", // string, The head_ref or source branch of the pull request in a workflow run. This property is only available when the event that triggers a workflow run is either pull_request or pull_request_target. + "head_ref": headRef, // string, The head_ref or source branch of the pull request in a workflow run. This property is only available when the event that triggers a workflow run is either pull_request or pull_request_target. "job": fmt.Sprint(t.JobID), // string, The job_id of the current job. "ref": t.Job.Run.Ref, // string, The fully-formed ref of the branch or tag that triggered the workflow run. For workflows triggered by push, this is the branch or tag ref that was pushed. For workflows triggered by pull_request, this is the pull request merge branch. For workflows triggered by release, this is the release tag created. For other triggers, this is the branch or tag ref that triggered the workflow run. This is only set if a branch or tag is available for the event type. The ref given is fully-formed, meaning that for branches the format is refs/heads/, for pull requests it is refs/pull//merge, and for tags it is refs/tags/. For example, refs/heads/feature-branch-1. - "ref_name": git.RefEndName(t.Job.Run.Ref), // string, The short ref name of the branch or tag that triggered the workflow run. This value matches the branch or tag name shown on GitHub. For example, feature-branch-1. + "ref_name": refName, // string, The short ref name of the branch or tag that triggered the workflow run. This value matches the branch or tag name shown on GitHub. For example, feature-branch-1. "ref_protected": false, // boolean, true if branch protections are configured for the ref that triggered the workflow run. - "ref_type": "", // string, The type of ref that triggered the workflow run. Valid values are branch or tag. + "ref_type": refType, // string, The type of ref that triggered the workflow run. Valid values are branch or tag. "path": "", // string, Path on the runner to the file that sets system PATH variables from workflow commands. This file is unique to the current step and is a different file for each step in a job. For more information, see "Workflow commands for GitHub Actions." "repository": t.Job.Run.Repo.OwnerName + "/" + t.Job.Run.Repo.Name, // string, The owner and repository name. For example, Codertocat/Hello-World. "repository_owner": t.Job.Run.Repo.OwnerName, // string, The repository owner's name. For example, Codertocat. diff --git a/routers/api/packages/api.go b/routers/api/packages/api.go index 8bf5dbab3599..d5acd3d26116 100644 --- a/routers/api/packages/api.go +++ b/routers/api/packages/api.go @@ -9,6 +9,7 @@ import ( "regexp" "strings" + auth_model "code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" @@ -36,6 +37,32 @@ import ( func reqPackageAccess(accessMode perm.AccessMode) func(ctx *context.Context) { return func(ctx *context.Context) { + if ctx.Data["IsApiToken"] == true { + scope, ok := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope) + if ok { // it's a personal access token but not oauth2 token + scopeMatched := false + var err error + if accessMode == perm.AccessModeRead { + scopeMatched, err = scope.HasScope(auth_model.AccessTokenScopeReadPackage) + if err != nil { + ctx.Error(http.StatusInternalServerError, "HasScope", err.Error()) + return + } + } else if accessMode == perm.AccessModeWrite { + scopeMatched, err = scope.HasScope(auth_model.AccessTokenScopeWritePackage) + if err != nil { + ctx.Error(http.StatusInternalServerError, "HasScope", err.Error()) + return + } + } + if !scopeMatched { + ctx.Resp.Header().Set("WWW-Authenticate", `Basic realm="Gitea Package API"`) + ctx.Error(http.StatusUnauthorized, "reqPackageAccess", "user should have specific permission or be a site admin") + return + } + } + } + if ctx.Package.AccessMode < accessMode && !ctx.IsUserSiteAdmin() { ctx.Resp.Header().Set("WWW-Authenticate", `Basic realm="Gitea Package API"`) ctx.Error(http.StatusUnauthorized, "reqPackageAccess", "user should have specific permission or be a site admin") diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index ad68a33d6be1..9a733b832f17 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -719,6 +719,10 @@ func Routes(ctx gocontext.Context) *web.Route { m.Post("/markup", bind(api.MarkupOption{}), misc.Markup) m.Post("/markdown", bind(api.MarkdownOption{}), misc.Markdown) m.Post("/markdown/raw", misc.MarkdownRaw) + m.Get("/gitignore/templates", misc.ListGitignoresTemplates) + m.Get("/gitignore/templates/{name}", misc.GetGitignoreTemplateInfo) + m.Get("/licenses", misc.ListLicenseTemplates) + m.Get("/licenses/{name}", misc.GetLicenseTemplateInfo) m.Group("/settings", func() { m.Get("/ui", settings.GetGeneralUISettings) m.Get("/api", settings.GetGeneralAPISettings) diff --git a/routers/api/v1/misc/gitignore.go b/routers/api/v1/misc/gitignore.go new file mode 100644 index 000000000000..7c7fe4b125fa --- /dev/null +++ b/routers/api/v1/misc/gitignore.go @@ -0,0 +1,56 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package misc + +import ( + "net/http" + + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/options" + repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/util" +) + +// Shows a list of all Gitignore templates +func ListGitignoresTemplates(ctx *context.APIContext) { + // swagger:operation GET /gitignore/templates miscellaneous listGitignoresTemplates + // --- + // summary: Returns a list of all gitignore templates + // produces: + // - application/json + // responses: + // "200": + // "$ref": "#/responses/GitignoreTemplateList" + ctx.JSON(http.StatusOK, repo_module.Gitignores) +} + +// SHows information about a gitignore template +func GetGitignoreTemplateInfo(ctx *context.APIContext) { + // swagger:operation GET /gitignore/templates/{name} miscellaneous getGitignoreTemplateInfo + // --- + // summary: Returns information about a gitignore template + // produces: + // - application/json + // parameters: + // - name: name + // in: path + // description: name of the template + // type: string + // required: true + // responses: + // "200": + // "$ref": "#/responses/GitignoreTemplateInfo" + // "404": + // "$ref": "#/responses/notFound" + name := util.PathJoinRelX(ctx.Params("name")) + + text, err := options.Gitignore(name) + if err != nil { + ctx.NotFound() + return + } + + ctx.JSON(http.StatusOK, &structs.GitignoreTemplateInfo{Name: name, Source: string(text)}) +} diff --git a/routers/api/v1/misc/licenses.go b/routers/api/v1/misc/licenses.go new file mode 100644 index 000000000000..65f63468cfd9 --- /dev/null +++ b/routers/api/v1/misc/licenses.go @@ -0,0 +1,76 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package misc + +import ( + "fmt" + "net/http" + "net/url" + + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/options" + repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/setting" + api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/util" +) + +// Returns a list of all License templates +func ListLicenseTemplates(ctx *context.APIContext) { + // swagger:operation GET /licenses miscellaneous listLicenseTemplates + // --- + // summary: Returns a list of all license templates + // produces: + // - application/json + // responses: + // "200": + // "$ref": "#/responses/LicenseTemplateList" + response := make([]api.LicensesTemplateListEntry, len(repo_module.Licenses)) + for i, license := range repo_module.Licenses { + response[i] = api.LicensesTemplateListEntry{ + Key: license, + Name: license, + URL: fmt.Sprintf("%sapi/v1/licenses/%s", setting.AppURL, url.PathEscape(license)), + } + } + ctx.JSON(http.StatusOK, response) +} + +// Returns information about a gitignore template +func GetLicenseTemplateInfo(ctx *context.APIContext) { + // swagger:operation GET /licenses/{name} miscellaneous getLicenseTemplateInfo + // --- + // summary: Returns information about a license template + // produces: + // - application/json + // parameters: + // - name: name + // in: path + // description: name of the license + // type: string + // required: true + // responses: + // "200": + // "$ref": "#/responses/LicenseTemplateInfo" + // "404": + // "$ref": "#/responses/notFound" + name := util.PathJoinRelX(ctx.Params("name")) + + text, err := options.License(name) + if err != nil { + ctx.NotFound() + return + } + + response := api.LicenseTemplateInfo{ + Key: name, + Name: name, + URL: fmt.Sprintf("%sapi/v1/licenses/%s", setting.AppURL, url.PathEscape(name)), + Body: string(text), + // This is for combatibilty with the GitHub API. This Text is for some reason added to each License response. + Implementation: "Create a text file (typically named LICENSE or LICENSE.txt) in the root of your source code and copy the text of the license into the file", + } + + ctx.JSON(http.StatusOK, response) +} diff --git a/routers/api/v1/swagger/misc.go b/routers/api/v1/swagger/misc.go index a4052a6a763e..5778b659b52b 100644 --- a/routers/api/v1/swagger/misc.go +++ b/routers/api/v1/swagger/misc.go @@ -14,6 +14,34 @@ type swaggerResponseServerVersion struct { Body api.ServerVersion `json:"body"` } +// GitignoreTemplateList +// swagger:response GitignoreTemplateList +type swaggerResponseGitignoreTemplateList struct { + // in:body + Body []string `json:"body"` +} + +// GitignoreTemplateInfo +// swagger:response GitignoreTemplateInfo +type swaggerResponseGitignoreTemplateInfo struct { + // in:body + Body api.GitignoreTemplateInfo `json:"body"` +} + +// LicenseTemplateList +// swagger:response LicenseTemplateList +type swaggerResponseLicensesTemplateList struct { + // in:body + Body []api.LicensesTemplateListEntry `json:"body"` +} + +// LicenseTemplateInfo +// swagger:response LicenseTemplateInfo +type swaggerResponseLicenseTemplateInfo struct { + // in:body + Body api.LicenseTemplateInfo `json:"body"` +} + // StringSlice // swagger:response StringSlice type swaggerResponseStringSlice struct { diff --git a/routers/common/middleware.go b/routers/common/middleware.go index 2abdcb583d8f..28ecf934e1cc 100644 --- a/routers/common/middleware.go +++ b/routers/common/middleware.go @@ -15,24 +15,23 @@ import ( "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/web/routing" + "gitea.com/go-chi/session" "github.com/chi-middleware/proxy" chi "github.com/go-chi/chi/v5" ) -// Middlewares returns common middlewares -func Middlewares() []func(http.Handler) http.Handler { - handlers := []func(http.Handler) http.Handler{ - func(next http.Handler) http.Handler { - return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { - // First of all escape the URL RawPath to ensure that all routing is done using a correctly escaped URL - req.URL.RawPath = req.URL.EscapedPath() +// ProtocolMiddlewares returns HTTP protocol related middlewares +func ProtocolMiddlewares() (handlers []any) { + handlers = append(handlers, func(next http.Handler) http.Handler { + return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { + // First of all escape the URL RawPath to ensure that all routing is done using a correctly escaped URL + req.URL.RawPath = req.URL.EscapedPath() - ctx, _, finished := process.GetManager().AddTypedContext(req.Context(), fmt.Sprintf("%s: %s", req.Method, req.RequestURI), process.RequestProcessType, true) - defer finished() - next.ServeHTTP(context.NewResponse(resp), req.WithContext(cache.WithCacheContext(ctx))) - }) - }, - } + ctx, _, finished := process.GetManager().AddTypedContext(req.Context(), fmt.Sprintf("%s: %s", req.Method, req.RequestURI), process.RequestProcessType, true) + defer finished() + next.ServeHTTP(context.NewResponse(resp), req.WithContext(cache.WithCacheContext(ctx))) + }) + }) if setting.ReverseProxyLimit > 0 { opt := proxy.NewForwardedHeadersOptions(). @@ -112,3 +111,17 @@ func stripSlashesMiddleware(next http.Handler) http.Handler { next.ServeHTTP(resp, req) }) } + +func Sessioner() func(next http.Handler) http.Handler { + return session.Sessioner(session.Options{ + Provider: setting.SessionConfig.Provider, + ProviderConfig: setting.SessionConfig.ProviderConfig, + CookieName: setting.SessionConfig.CookieName, + CookiePath: setting.SessionConfig.CookiePath, + Gclifetime: setting.SessionConfig.Gclifetime, + Maxlifetime: setting.SessionConfig.Maxlifetime, + Secure: setting.SessionConfig.Secure, + SameSite: setting.SessionConfig.SameSite, + Domain: setting.SessionConfig.Domain, + }) +} diff --git a/routers/init.go b/routers/init.go index af768abbf49a..2c26bb5b0767 100644 --- a/routers/init.go +++ b/routers/init.go @@ -177,20 +177,15 @@ func GlobalInitInstalled(ctx context.Context) { func NormalRoutes(ctx context.Context) *web.Route { ctx, _ = templates.HTMLRenderer(ctx) r := web.NewRoute() - for _, middle := range common.Middlewares() { - r.Use(middle) - } + r.Use(common.ProtocolMiddlewares()...) r.Mount("/", web_routers.Routes(ctx)) r.Mount("/api/v1", apiv1.Routes(ctx)) r.Mount("/api/internal", private.Routes()) if setting.Packages.Enabled { - // Add endpoints to match common package manager APIs - // This implements package support for most package managers r.Mount("/api/packages", packages_router.CommonRoutes(ctx)) - // This implements the OCI API (Note this is not preceded by /api but is instead /v2) r.Mount("/v2", packages_router.ContainerRoutes(ctx)) } diff --git a/routers/install/routes.go b/routers/install/routes.go index f52539ec1b87..9c7420c59f05 100644 --- a/routers/install/routes.go +++ b/routers/install/routes.go @@ -19,8 +19,6 @@ import ( "code.gitea.io/gitea/routers/common" "code.gitea.io/gitea/routers/web/healthcheck" "code.gitea.io/gitea/services/forms" - - "gitea.com/go-chi/session" ) type dataStore map[string]interface{} @@ -30,7 +28,6 @@ func (d *dataStore) GetData() map[string]interface{} { } func installRecovery(ctx goctx.Context) func(next http.Handler) http.Handler { - _, rnd := templates.HTMLRenderer(ctx) return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { defer func() { @@ -69,6 +66,7 @@ func installRecovery(ctx goctx.Context) func(next http.Handler) http.Handler { if !setting.IsProd { store["ErrorMsg"] = combinedErr } + _, rnd := templates.HTMLRenderer(ctx) err = rnd.HTML(w, http.StatusInternalServerError, "status/500", templates.BaseVars().Merge(store)) if err != nil { log.Error("%v", err) @@ -83,34 +81,22 @@ func installRecovery(ctx goctx.Context) func(next http.Handler) http.Handler { // Routes registers the installation routes func Routes(ctx goctx.Context) *web.Route { - r := web.NewRoute() - for _, middle := range common.Middlewares() { - r.Use(middle) - } - - r.Use(web.MiddlewareWithPrefix("/assets/", nil, public.AssetsHandlerFunc("/assets/"))) - - r.Use(session.Sessioner(session.Options{ - Provider: setting.SessionConfig.Provider, - ProviderConfig: setting.SessionConfig.ProviderConfig, - CookieName: setting.SessionConfig.CookieName, - CookiePath: setting.SessionConfig.CookiePath, - Gclifetime: setting.SessionConfig.Gclifetime, - Maxlifetime: setting.SessionConfig.Maxlifetime, - Secure: setting.SessionConfig.Secure, - SameSite: setting.SessionConfig.SameSite, - Domain: setting.SessionConfig.Domain, - })) + base := web.NewRoute() + base.Use(common.ProtocolMiddlewares()...) + base.RouteMethods("/assets/*", "GET, HEAD", public.AssetsHandlerFunc("/assets/")) + r := web.NewRoute() + r.Use(common.Sessioner()) r.Use(installRecovery(ctx)) r.Use(Init(ctx)) r.Get("/", Install) // it must be on the root, because the "install.js" use the window.location to replace the "localhost" AppURL r.Post("/", web.Bind(forms.InstallForm{}), SubmitInstall) r.Get("/post-install", InstallDone) r.Get("/api/healthz", healthcheck.Check) - r.NotFound(installNotFound) - return r + + base.Mount("", r) + return base } func installNotFound(w http.ResponseWriter, req *http.Request) { diff --git a/routers/install/routes_test.go b/routers/install/routes_test.go index 35b5e5e9160b..e3d2a4246740 100644 --- a/routers/install/routes_test.go +++ b/routers/install/routes_test.go @@ -11,11 +11,14 @@ import ( ) func TestRoutes(t *testing.T) { + // TODO: this test seems not really testing the handlers ctx, cancel := context.WithCancel(context.Background()) defer cancel() - routes := Routes(ctx) - assert.NotNil(t, routes) - assert.EqualValues(t, "/", routes.R.Routes()[0].Pattern) - assert.Nil(t, routes.R.Routes()[0].SubRoutes) - assert.Len(t, routes.R.Routes()[0].Handlers, 2) + base := Routes(ctx) + assert.NotNil(t, base) + r := base.R.Routes()[1] + routes := r.SubRoutes.Routes()[0] + assert.EqualValues(t, "/", routes.Pattern) + assert.Nil(t, routes.SubRoutes) + assert.Len(t, routes.Handlers, 2) } diff --git a/routers/web/admin/admin.go b/routers/web/admin/admin.go index 9847a6d9236f..35c387c28bd8 100644 --- a/routers/web/admin/admin.go +++ b/routers/web/admin/admin.go @@ -113,7 +113,6 @@ func updateSystemStatus() { // Dashboard show admin panel dashboard func Dashboard(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.dashboard") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminDashboard"] = true ctx.Data["Stats"] = activities_model.GetStatistic() ctx.Data["NeedUpdate"] = updatechecker.GetNeedUpdate() @@ -129,7 +128,6 @@ func Dashboard(ctx *context.Context) { func DashboardPost(ctx *context.Context) { form := web.GetForm(ctx).(*forms.AdminDashboardForm) ctx.Data["Title"] = ctx.Tr("admin.dashboard") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminDashboard"] = true ctx.Data["Stats"] = activities_model.GetStatistic() updateSystemStatus() @@ -155,7 +153,6 @@ func DashboardPost(ctx *context.Context) { // Monitor show admin monitor page func Monitor(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.monitor") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminMonitor"] = true ctx.Data["Processes"], ctx.Data["ProcessCount"] = process.GetManager().Processes(false, true) ctx.Data["Entries"] = cron.ListTasks() @@ -167,7 +164,6 @@ func Monitor(ctx *context.Context) { // GoroutineStacktrace show admin monitor goroutines page func GoroutineStacktrace(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.monitor") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminMonitor"] = true processStacks, processCount, goroutineCount, err := process.GetManager().ProcessStacktraces(false, false) @@ -202,7 +198,6 @@ func Queue(ctx *context.Context) { return } ctx.Data["Title"] = ctx.Tr("admin.monitor.queue", mq.Name) - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminMonitor"] = true ctx.Data["Queue"] = mq ctx.HTML(http.StatusOK, tplQueue) diff --git a/routers/web/admin/applications.go b/routers/web/admin/applications.go index 745d17ff2a44..7b2752434037 100644 --- a/routers/web/admin/applications.go +++ b/routers/web/admin/applications.go @@ -31,7 +31,6 @@ func newOAuth2CommonHandlers() *user_setting.OAuth2CommonHandlers { // Applications render org applications page (for org, at the moment, there are only OAuth2 applications) func Applications(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("settings.applications") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminApplications"] = true apps, err := auth.GetOAuth2ApplicationsByUserID(ctx, 0) @@ -47,7 +46,6 @@ func Applications(ctx *context.Context) { // ApplicationsPost response for adding an oauth2 application func ApplicationsPost(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("settings.applications") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminApplications"] = true oa := newOAuth2CommonHandlers() @@ -56,7 +54,6 @@ func ApplicationsPost(ctx *context.Context) { // EditApplication displays the given application func EditApplication(ctx *context.Context) { - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminApplications"] = true oa := newOAuth2CommonHandlers() @@ -66,7 +63,6 @@ func EditApplication(ctx *context.Context) { // EditApplicationPost response for editing oauth2 application func EditApplicationPost(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("settings.applications") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminApplications"] = true oa := newOAuth2CommonHandlers() @@ -76,7 +72,6 @@ func EditApplicationPost(ctx *context.Context) { // ApplicationsRegenerateSecret handles the post request for regenerating the secret func ApplicationsRegenerateSecret(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("settings") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminApplications"] = true oa := newOAuth2CommonHandlers() diff --git a/routers/web/admin/auths.go b/routers/web/admin/auths.go index 6ebd23b7bbd5..b6ea3ff40300 100644 --- a/routers/web/admin/auths.go +++ b/routers/web/admin/auths.go @@ -45,7 +45,6 @@ var ( // Authentications show authentication config page func Authentications(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.authentication") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminAuthentications"] = true var err error @@ -89,7 +88,6 @@ var ( // NewAuthSource render adding a new auth source page func NewAuthSource(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.auths.new") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminAuthentications"] = true ctx.Data["type"] = auth.LDAP.Int() @@ -237,7 +235,6 @@ func parseSSPIConfig(ctx *context.Context, form forms.AuthenticationForm) (*sspi func NewAuthSourcePost(ctx *context.Context) { form := *web.GetForm(ctx).(*forms.AuthenticationForm) ctx.Data["Title"] = ctx.Tr("admin.auths.new") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminAuthentications"] = true ctx.Data["CurrentTypeName"] = auth.Type(form.Type).String() @@ -333,7 +330,6 @@ func NewAuthSourcePost(ctx *context.Context) { // EditAuthSource render editing auth source page func EditAuthSource(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.auths.edit") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminAuthentications"] = true ctx.Data["SecurityProtocols"] = securityProtocols @@ -369,7 +365,6 @@ func EditAuthSource(ctx *context.Context) { func EditAuthSourcePost(ctx *context.Context) { form := *web.GetForm(ctx).(*forms.AuthenticationForm) ctx.Data["Title"] = ctx.Tr("admin.auths.edit") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminAuthentications"] = true ctx.Data["SMTPAuths"] = smtp.Authenticators diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go index 48815dcff8ed..7460ea24a745 100644 --- a/routers/web/admin/config.go +++ b/routers/web/admin/config.go @@ -100,7 +100,6 @@ func shadowPassword(provider, cfgItem string) string { // Config show admin config page func Config(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.config") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminConfig"] = true systemSettings, err := system_model.GetAllSettings(ctx) diff --git a/routers/web/admin/emails.go b/routers/web/admin/emails.go index c16158c6ae47..4618a78c3a7c 100644 --- a/routers/web/admin/emails.go +++ b/routers/web/admin/emails.go @@ -24,7 +24,6 @@ const ( // Emails show all emails func Emails(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.emails") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminEmails"] = true opts := &user_model.SearchEmailOptions{ diff --git a/routers/web/admin/notice.go b/routers/web/admin/notice.go index f60cf90b3c74..9e4588dd7579 100644 --- a/routers/web/admin/notice.go +++ b/routers/web/admin/notice.go @@ -22,7 +22,6 @@ const ( // Notices show notices for admin func Notices(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.notices") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminNotices"] = true total := system_model.CountNotices() diff --git a/routers/web/admin/orgs.go b/routers/web/admin/orgs.go index a4eb0af58d0c..6a3617d67f9b 100644 --- a/routers/web/admin/orgs.go +++ b/routers/web/admin/orgs.go @@ -21,7 +21,6 @@ const ( // Organizations show all the organizations func Organizations(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.organizations") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminOrganizations"] = true explore.RenderUserSearch(ctx, &user_model.SearchUserOptions{ diff --git a/routers/web/admin/packages.go b/routers/web/admin/packages.go index 88fb47ca0179..4d5987e780b6 100644 --- a/routers/web/admin/packages.go +++ b/routers/web/admin/packages.go @@ -64,7 +64,6 @@ func Packages(ctx *context.Context) { } ctx.Data["Title"] = ctx.Tr("packages.title") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminPackages"] = true ctx.Data["Query"] = query ctx.Data["PackageType"] = packageType diff --git a/routers/web/admin/repos.go b/routers/web/admin/repos.go index 53b609af966b..b22546f74994 100644 --- a/routers/web/admin/repos.go +++ b/routers/web/admin/repos.go @@ -29,7 +29,6 @@ const ( // Repos show all the repositories func Repos(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.repositories") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminRepositories"] = true explore.RenderRepoSearch(ctx, &explore.RepoSearchOptions{ @@ -67,7 +66,6 @@ func DeleteRepo(ctx *context.Context) { // UnadoptedRepos lists the unadopted repositories func UnadoptedRepos(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.repositories") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminRepositories"] = true opts := db.ListOptions{ diff --git a/routers/web/admin/runners.go b/routers/web/admin/runners.go index a70b53fdcb1c..eaa268b4f142 100644 --- a/routers/web/admin/runners.go +++ b/routers/web/admin/runners.go @@ -4,75 +4,10 @@ package admin import ( - "net/url" - - actions_model "code.gitea.io/gitea/models/actions" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/setting" - actions_shared "code.gitea.io/gitea/routers/web/shared/actions" -) - -const ( - tplRunners base.TplName = "admin/runners/base" - tplRunnerEdit base.TplName = "admin/runners/edit" ) -// Runners show all the runners -func Runners(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("actions.runners") - ctx.Data["PageIsAdmin"] = true - ctx.Data["PageIsAdminRunners"] = true - - page := ctx.FormInt("page") - if page <= 1 { - page = 1 - } - - opts := actions_model.FindRunnerOptions{ - ListOptions: db.ListOptions{ - Page: page, - PageSize: 100, - }, - Sort: ctx.Req.URL.Query().Get("sort"), - Filter: ctx.Req.URL.Query().Get("q"), - } - - actions_shared.RunnersList(ctx, tplRunners, opts) -} - -// EditRunner show editing runner page -func EditRunner(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("actions.runners.edit_runner") - ctx.Data["PageIsAdmin"] = true - ctx.Data["PageIsAdminRunners"] = true - - page := ctx.FormInt("page") - if page <= 1 { - page = 1 - } - - actions_shared.RunnerDetails(ctx, tplRunnerEdit, page, ctx.ParamsInt64(":runnerid"), 0, 0) -} - -// EditRunnerPost response for editing runner -func EditRunnerPost(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("actions.runners.edit") - ctx.Data["PageIsAdmin"] = true - ctx.Data["PageIsAdminRunners"] = true - actions_shared.RunnerDetailsEditPost(ctx, ctx.ParamsInt64(":runnerid"), 0, 0, - setting.AppSubURL+"/admin/runners/"+url.PathEscape(ctx.Params(":runnerid"))) -} - -// DeleteRunnerPost response for deleting a runner -func DeleteRunnerPost(ctx *context.Context) { - actions_shared.RunnerDeletePost(ctx, ctx.ParamsInt64(":runnerid"), - setting.AppSubURL+"/admin/runners/", - setting.AppSubURL+"/admin/runners/"+url.PathEscape(ctx.Params(":runnerid")), - ) -} - -func ResetRunnerRegistrationToken(ctx *context.Context) { - actions_shared.RunnerResetRegistrationToken(ctx, 0, 0, setting.AppSubURL+"/admin/runners/") +func RedirectToDefaultSetting(ctx *context.Context) { + ctx.Redirect(setting.AppSubURL + "/admin/actions/runners") } diff --git a/routers/web/admin/users.go b/routers/web/admin/users.go index 531f14d08627..2150bc42f7ba 100644 --- a/routers/web/admin/users.go +++ b/routers/web/admin/users.go @@ -37,7 +37,6 @@ const ( // Users show all the users func Users(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.users") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminUsers"] = true extraParamStrings := map[string]string{} @@ -80,7 +79,6 @@ func Users(ctx *context.Context) { // NewUser render adding a new user page func NewUser(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.users.new_account") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminUsers"] = true ctx.Data["DefaultUserVisibilityMode"] = setting.Service.DefaultUserVisibilityMode ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice() @@ -102,7 +100,6 @@ func NewUser(ctx *context.Context) { func NewUserPost(ctx *context.Context) { form := web.GetForm(ctx).(*forms.AdminCreateUserForm) ctx.Data["Title"] = ctx.Tr("admin.users.new_account") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminUsers"] = true ctx.Data["DefaultUserVisibilityMode"] = setting.Service.DefaultUserVisibilityMode ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice() @@ -253,7 +250,6 @@ func prepareUserInfo(ctx *context.Context) *user_model.User { // EditUser show editing user page func EditUser(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.users.edit_account") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminUsers"] = true ctx.Data["DisableRegularOrgCreation"] = setting.Admin.DisableRegularOrgCreation ctx.Data["DisableMigrations"] = setting.Repository.DisableMigrations @@ -271,7 +267,6 @@ func EditUser(ctx *context.Context) { func EditUserPost(ctx *context.Context) { form := web.GetForm(ctx).(*forms.AdminEditUserForm) ctx.Data["Title"] = ctx.Tr("admin.users.edit_account") - ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminUsers"] = true ctx.Data["DisableMigrations"] = setting.Repository.DisableMigrations ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice() diff --git a/routers/web/base.go b/routers/web/base.go index 79991d89db5e..b5d7a737bfc5 100644 --- a/routers/web/base.go +++ b/routers/web/base.go @@ -59,12 +59,7 @@ func storageHandler(storageSetting setting.Storage, prefix string, objStore stor return } - http.Redirect( - w, - req, - u.String(), - http.StatusTemporaryRedirect, - ) + http.Redirect(w, req, u.String(), http.StatusTemporaryRedirect) }) } @@ -122,9 +117,9 @@ func (d *dataStore) GetData() map[string]interface{} { return *d } -// Recovery returns a middleware that recovers from any panics and writes a 500 and a log if so. +// RecoveryWith500Page returns a middleware that recovers from any panics and writes a 500 and a log if so. // This error will be created with the gitea 500 page. -func Recovery(ctx goctx.Context) func(next http.Handler) http.Handler { +func RecoveryWith500Page(ctx goctx.Context) func(next http.Handler) http.Handler { _, rnd := templates.HTMLRenderer(ctx) return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { diff --git a/routers/web/misc/misc.go b/routers/web/misc/misc.go new file mode 100644 index 000000000000..582179990a4c --- /dev/null +++ b/routers/web/misc/misc.go @@ -0,0 +1,49 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package misc + +import ( + "net/http" + "os" + "path" + + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/httpcache" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" +) + +func SSHInfo(rw http.ResponseWriter, req *http.Request) { + if !git.SupportProcReceive { + rw.WriteHeader(http.StatusNotFound) + return + } + rw.Header().Set("content-type", "text/json;charset=UTF-8") + _, err := rw.Write([]byte(`{"type":"gitea","version":1}`)) + if err != nil { + log.Error("fail to write result: err: %v", err) + rw.WriteHeader(http.StatusInternalServerError) + return + } + rw.WriteHeader(http.StatusOK) +} + +func DummyOK(w http.ResponseWriter, req *http.Request) { + w.WriteHeader(http.StatusOK) +} + +func RobotsTxt(w http.ResponseWriter, req *http.Request) { + filePath := path.Join(setting.CustomPath, "robots.txt") + fi, err := os.Stat(filePath) + if err == nil && httpcache.HandleTimeCache(req, w, fi) { + return + } + http.ServeFile(w, req, filePath) +} + +func StaticRedirect(target string) func(w http.ResponseWriter, req *http.Request) { + return func(w http.ResponseWriter, req *http.Request) { + http.Redirect(w, req, path.Join(setting.StaticURLPrefix, target), http.StatusMovedPermanently) + } +} diff --git a/routers/web/org/org_runners.go b/routers/web/org/org_runners.go deleted file mode 100644 index f87a506504af..000000000000 --- a/routers/web/org/org_runners.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2022 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package org - -import ( - "net/url" - - actions_model "code.gitea.io/gitea/models/actions" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/modules/context" - actions_shared "code.gitea.io/gitea/routers/web/shared/actions" -) - -// Runners render runners page -func Runners(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("org.runners") - ctx.Data["PageIsOrgSettings"] = true - ctx.Data["PageIsOrgSettingsRunners"] = true - - page := ctx.FormInt("page") - if page <= 1 { - page = 1 - } - - opts := actions_model.FindRunnerOptions{ - ListOptions: db.ListOptions{ - Page: page, - PageSize: 100, - }, - Sort: ctx.Req.URL.Query().Get("sort"), - Filter: ctx.Req.URL.Query().Get("q"), - OwnerID: ctx.Org.Organization.ID, - WithAvailable: true, - } - - actions_shared.RunnersList(ctx, tplSettingsRunners, opts) -} - -// ResetRunnerRegistrationToken reset runner registration token -func ResetRunnerRegistrationToken(ctx *context.Context) { - actions_shared.RunnerResetRegistrationToken(ctx, - ctx.Org.Organization.ID, 0, - ctx.Org.OrgLink+"/settings/runners") -} - -// RunnersEdit render runner edit page -func RunnersEdit(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("org.runners.edit") - ctx.Data["PageIsOrgSettings"] = true - ctx.Data["PageIsOrgSettingsRunners"] = true - page := ctx.FormInt("page") - if page <= 1 { - page = 1 - } - - actions_shared.RunnerDetails(ctx, tplSettingsRunnersEdit, page, - ctx.ParamsInt64(":runnerid"), ctx.Org.Organization.ID, 0, - ) -} - -// RunnersEditPost response for editing runner -func RunnersEditPost(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("org.runners.edit") - ctx.Data["PageIsOrgSettings"] = true - ctx.Data["PageIsOrgSettingsRunners"] = true - actions_shared.RunnerDetailsEditPost(ctx, ctx.ParamsInt64(":runnerid"), - ctx.Org.Organization.ID, 0, - ctx.Org.OrgLink+"/settings/runners/"+url.PathEscape(ctx.Params(":runnerid"))) -} - -// RunnerDeletePost response for deleting runner -func RunnerDeletePost(ctx *context.Context) { - actions_shared.RunnerDeletePost(ctx, - ctx.ParamsInt64(":runnerid"), - ctx.Org.OrgLink+"/settings/runners", - ctx.Org.OrgLink+"/settings/runners/"+url.PathEscape(ctx.Params(":runnerid"))) -} diff --git a/routers/web/org/setting.go b/routers/web/org/setting.go index db8fc728dffc..4111b1353151 100644 --- a/routers/web/org/setting.go +++ b/routers/web/org/setting.go @@ -37,10 +37,6 @@ const ( tplSettingsHooks base.TplName = "org/settings/hooks" // tplSettingsLabels template path for render labels settings tplSettingsLabels base.TplName = "org/settings/labels" - // tplSettingsRunners template path for render runners settings - tplSettingsRunners base.TplName = "org/settings/runners" - // tplSettingsRunnersEdit template path for render runners edit settings - tplSettingsRunnersEdit base.TplName = "org/settings/runners_edit" ) // Settings render the main settings page diff --git a/routers/web/org/setting/runners.go b/routers/web/org/setting/runners.go new file mode 100644 index 000000000000..c3c771036aad --- /dev/null +++ b/routers/web/org/setting/runners.go @@ -0,0 +1,12 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package setting + +import ( + "code.gitea.io/gitea/modules/context" +) + +func RedirectToDefaultSetting(ctx *context.Context) { + ctx.Redirect(ctx.Org.OrgLink + "/settings/actions/runners") +} diff --git a/routers/web/org/setting_secrets.go b/routers/web/org/setting_secrets.go deleted file mode 100644 index 580a14015bd9..000000000000 --- a/routers/web/org/setting_secrets.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2022 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package org - -import ( - "net/http" - - "code.gitea.io/gitea/modules/base" - "code.gitea.io/gitea/modules/context" - shared "code.gitea.io/gitea/routers/web/shared/secrets" -) - -const ( - tplSettingsSecrets base.TplName = "org/settings/secrets" -) - -// Secrets render organization secrets page -func Secrets(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("secrets.secrets") - ctx.Data["PageIsOrgSettings"] = true - ctx.Data["PageIsOrgSettingsSecrets"] = true - - shared.SetSecretsContext(ctx, ctx.ContextUser.ID, 0) - if ctx.Written() { - return - } - - ctx.HTML(http.StatusOK, tplSettingsSecrets) -} - -// SecretsPost add secrets -func SecretsPost(ctx *context.Context) { - shared.PerformSecretsPost( - ctx, - ctx.ContextUser.ID, - 0, - ctx.Org.OrgLink+"/settings/secrets", - ) -} - -// SecretsDelete delete secrets -func SecretsDelete(ctx *context.Context) { - shared.PerformSecretsDelete( - ctx, - ctx.ContextUser.ID, - 0, - ctx.Org.OrgLink+"/settings/secrets", - ) -} diff --git a/routers/web/org/teams.go b/routers/web/org/teams.go index bae8e5a003c6..2ce4bf532271 100644 --- a/routers/web/org/teams.go +++ b/routers/web/org/teams.go @@ -86,9 +86,17 @@ func TeamsAction(ctx *context.Context) { return } } + + redirect := ctx.Org.OrgLink + "/teams/" + if isOrgMember, err := org_model.IsOrganizationMember(ctx, ctx.Org.Organization.ID, ctx.Doer.ID); err != nil { + ctx.ServerError("IsOrganizationMember", err) + return + } else if !isOrgMember { + redirect = setting.AppSubURL + "/" + } ctx.JSON(http.StatusOK, map[string]interface{}{ - "redirect": ctx.Org.OrgLink + "/teams/", + "redirect": redirect, }) return case "remove": diff --git a/routers/web/repo/attachment.go b/routers/web/repo/attachment.go index 9fb9cb00bf90..c6ea4e3cdb0d 100644 --- a/routers/web/repo/attachment.go +++ b/routers/web/repo/attachment.go @@ -110,6 +110,11 @@ func ServeAttachment(ctx *context.Context, uuid string) { return } } else { // If we have the repository we check access + context.CheckRepoScopedToken(ctx, repository) + if ctx.Written() { + return + } + perm, err := access_model.GetUserRepoPermission(ctx, repository, ctx.Doer) if err != nil { ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err.Error()) diff --git a/routers/web/repo/http.go b/routers/web/repo/http.go index a01bb4f28eef..4e45a9b6e21d 100644 --- a/routers/web/repo/http.go +++ b/routers/web/repo/http.go @@ -19,7 +19,7 @@ import ( "time" actions_model "code.gitea.io/gitea/models/actions" - "code.gitea.io/gitea/models/auth" + auth_model "code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/models/perm" access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" @@ -152,13 +152,18 @@ func httpBase(ctx *context.Context) (h *serviceHandler) { return } + context.CheckRepoScopedToken(ctx, repo) + if ctx.Written() { + return + } + if ctx.IsBasicAuth && ctx.Data["IsApiToken"] != true && ctx.Data["IsActionsToken"] != true { - _, err = auth.GetTwoFactorByUID(ctx.Doer.ID) + _, err = auth_model.GetTwoFactorByUID(ctx.Doer.ID) if err == nil { // TODO: This response should be changed to "invalid credentials" for security reasons once the expectation behind it (creating an app token to authenticate) is properly documented ctx.PlainText(http.StatusUnauthorized, "Users with two-factor authentication enabled cannot perform HTTP/HTTPS operations via plain username and password. Please create and use a personal access token on the user settings page") return - } else if !auth.IsErrTwoFactorNotEnrolled(err) { + } else if !auth_model.IsErrTwoFactorNotEnrolled(err) { ctx.ServerError("IsErrTwoFactorNotEnrolled", err) return } diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index bea35785bbe0..49ea4f2a1f90 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -2689,7 +2689,7 @@ func UpdateIssueStatus(ctx *context.Context) { if err := issue_service.ChangeStatus(issue, ctx.Doer, "", isClosed); err != nil { if issues_model.IsErrDependenciesLeft(err) { ctx.JSON(http.StatusPreconditionFailed, map[string]interface{}{ - "error": "cannot close this issue because it still has open dependencies", + "error": ctx.Tr("repo.issues.dependency.issue_batch_close_blocked", issue.Index), }) return } diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go index 5a97c5190c27..c4b5351eca28 100644 --- a/routers/web/repo/repo.go +++ b/routers/web/repo/repo.go @@ -18,7 +18,9 @@ import ( "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" @@ -59,6 +61,22 @@ func MustBeAbleToUpload(ctx *context.Context) { } } +func CommitInfoCache(ctx *context.Context) { + var err error + ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultBranch) + if err != nil { + ctx.ServerError("GetBranchCommit", err) + return + } + ctx.Repo.CommitsCount, err = ctx.Repo.GetCommitsCount() + if err != nil { + ctx.ServerError("GetCommitsCount", err) + return + } + ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount + ctx.Repo.GitRepo.LastCommitCache = git.NewLastCommitCache(ctx.Repo.CommitsCount, ctx.Repo.Repository.FullName(), ctx.Repo.GitRepo, cache.GetCache()) +} + func checkContextUser(ctx *context.Context, uid int64) *user_model.User { orgs, err := organization.GetOrgsCanCreateRepoByUserID(ctx.Doer.ID) if err != nil { diff --git a/routers/web/repo/runners.go b/routers/web/repo/runners.go deleted file mode 100644 index d3dbff17fddb..000000000000 --- a/routers/web/repo/runners.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2022 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package repo - -import ( - "net/url" - - actions_model "code.gitea.io/gitea/models/actions" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/modules/context" - actions_shared "code.gitea.io/gitea/routers/web/shared/actions" -) - -const ( - tplRunners = "repo/settings/runners" - tplRunnerEdit = "repo/settings/runner_edit" -) - -// Runners render runners page -func Runners(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("actions.runners") - ctx.Data["PageIsSettingsRunners"] = true - - page := ctx.FormInt("page") - if page <= 1 { - page = 1 - } - - opts := actions_model.FindRunnerOptions{ - ListOptions: db.ListOptions{ - Page: page, - PageSize: 100, - }, - Sort: ctx.Req.URL.Query().Get("sort"), - Filter: ctx.Req.URL.Query().Get("q"), - RepoID: ctx.Repo.Repository.ID, - WithAvailable: true, - } - - actions_shared.RunnersList(ctx, tplRunners, opts) -} - -func RunnersEdit(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("actions.runners") - ctx.Data["PageIsSettingsRunners"] = true - page := ctx.FormInt("page") - if page <= 1 { - page = 1 - } - - actions_shared.RunnerDetails(ctx, tplRunnerEdit, page, - ctx.ParamsInt64(":runnerid"), 0, ctx.Repo.Repository.ID, - ) -} - -func RunnersEditPost(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("actions.runners") - ctx.Data["PageIsSettingsRunners"] = true - actions_shared.RunnerDetailsEditPost(ctx, ctx.ParamsInt64(":runnerid"), - 0, ctx.Repo.Repository.ID, - ctx.Repo.RepoLink+"/settings/runners/"+url.PathEscape(ctx.Params(":runnerid"))) -} - -func ResetRunnerRegistrationToken(ctx *context.Context) { - actions_shared.RunnerResetRegistrationToken(ctx, - 0, ctx.Repo.Repository.ID, - ctx.Repo.RepoLink+"/settings/runners") -} - -// RunnerDeletePost response for deleting runner -func RunnerDeletePost(ctx *context.Context) { - actions_shared.RunnerDeletePost(ctx, ctx.ParamsInt64(":runnerid"), - ctx.Repo.RepoLink+"/settings/runners", - ctx.Repo.RepoLink+"/settings/runners/"+url.PathEscape(ctx.Params(":runnerid"))) -} diff --git a/routers/web/repo/setting/runners.go b/routers/web/repo/setting/runners.go new file mode 100644 index 000000000000..e8ad6358261c --- /dev/null +++ b/routers/web/repo/setting/runners.go @@ -0,0 +1,167 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package setting + +import ( + "errors" + "net/http" + "net/url" + + actions_model "code.gitea.io/gitea/models/actions" + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/setting" + actions_shared "code.gitea.io/gitea/routers/web/shared/actions" +) + +const ( + // TODO: Separate secrets from runners when layout is ready + tplRepoRunners base.TplName = "repo/settings/actions" + tplOrgRunners base.TplName = "org/settings/actions" + tplAdminRunners base.TplName = "admin/actions" + tplRepoRunnerEdit base.TplName = "repo/settings/runner_edit" + tplOrgRunnerEdit base.TplName = "org/settings/runners_edit" + tplAdminRunnerEdit base.TplName = "admin/runners/edit" +) + +type runnersCtx struct { + OwnerID int64 + RepoID int64 + IsRepo bool + IsOrg bool + IsAdmin bool + RunnersTemplate base.TplName + RunnerEditTemplate base.TplName + RedirectLink string +} + +func getRunnersCtx(ctx *context.Context) (*runnersCtx, error) { + if ctx.Data["PageIsRepoSettings"] == true { + return &runnersCtx{ + RepoID: ctx.Repo.Repository.ID, + OwnerID: 0, + IsRepo: true, + RunnersTemplate: tplRepoRunners, + RunnerEditTemplate: tplRepoRunnerEdit, + RedirectLink: ctx.Repo.RepoLink + "/settings/actions/runners/", + }, nil + } + + if ctx.Data["PageIsOrgSettings"] == true { + return &runnersCtx{ + RepoID: 0, + OwnerID: ctx.Org.Organization.ID, + IsOrg: true, + RunnersTemplate: tplOrgRunners, + RunnerEditTemplate: tplOrgRunnerEdit, + RedirectLink: ctx.Org.OrgLink + "/settings/actions/runners/", + }, nil + } + + if ctx.Data["PageIsAdmin"] == true { + return &runnersCtx{ + RepoID: 0, + OwnerID: 0, + IsAdmin: true, + RunnersTemplate: tplAdminRunners, + RunnerEditTemplate: tplAdminRunnerEdit, + RedirectLink: setting.AppSubURL + "/admin/actions/runners/", + }, nil + } + + return nil, errors.New("unable to set Runners context") +} + +// Runners render settings/actions/runners page for repo level +func Runners(ctx *context.Context) { + ctx.Data["PageIsSharedSettingsRunners"] = true + ctx.Data["Title"] = ctx.Tr("actions.actions") + ctx.Data["PageType"] = "runners" + + rCtx, err := getRunnersCtx(ctx) + if err != nil { + ctx.ServerError("getRunnersCtx", err) + return + } + + page := ctx.FormInt("page") + if page <= 1 { + page = 1 + } + + opts := actions_model.FindRunnerOptions{ + ListOptions: db.ListOptions{ + Page: page, + PageSize: 100, + }, + Sort: ctx.Req.URL.Query().Get("sort"), + Filter: ctx.Req.URL.Query().Get("q"), + } + if rCtx.IsRepo { + opts.RepoID = rCtx.RepoID + opts.WithAvailable = true + } else if rCtx.IsOrg { + opts.OwnerID = rCtx.OwnerID + opts.WithAvailable = true + } + actions_shared.RunnersList(ctx, opts) + + ctx.HTML(http.StatusOK, rCtx.RunnersTemplate) +} + +// RunnersEdit renders runner edit page for repository level +func RunnersEdit(ctx *context.Context) { + ctx.Data["PageIsSharedSettingsRunners"] = true + ctx.Data["Title"] = ctx.Tr("actions.runners.edit_runner") + rCtx, err := getRunnersCtx(ctx) + if err != nil { + ctx.ServerError("getRunnersCtx", err) + return + } + + page := ctx.FormInt("page") + if page <= 1 { + page = 1 + } + + actions_shared.RunnerDetails(ctx, page, + ctx.ParamsInt64(":runnerid"), rCtx.OwnerID, rCtx.RepoID, + ) + ctx.HTML(http.StatusOK, rCtx.RunnerEditTemplate) +} + +func RunnersEditPost(ctx *context.Context) { + rCtx, err := getRunnersCtx(ctx) + if err != nil { + ctx.ServerError("getRunnersCtx", err) + return + } + actions_shared.RunnerDetailsEditPost(ctx, ctx.ParamsInt64(":runnerid"), + rCtx.OwnerID, rCtx.RepoID, + rCtx.RedirectLink+url.PathEscape(ctx.Params(":runnerid"))) +} + +func ResetRunnerRegistrationToken(ctx *context.Context) { + rCtx, err := getRunnersCtx(ctx) + if err != nil { + ctx.ServerError("getRunnersCtx", err) + return + } + actions_shared.RunnerResetRegistrationToken(ctx, rCtx.OwnerID, rCtx.RepoID, rCtx.RedirectLink) +} + +// RunnerDeletePost response for deleting runner +func RunnerDeletePost(ctx *context.Context) { + rCtx, err := getRunnersCtx(ctx) + if err != nil { + ctx.ServerError("getRunnersCtx", err) + return + } + actions_shared.RunnerDeletePost(ctx, ctx.ParamsInt64(":runnerid"), rCtx.RedirectLink, rCtx.RedirectLink+url.PathEscape(ctx.Params(":runnerid"))) +} + +func RedirectToDefaultSetting(ctx *context.Context) { + ctx.Redirect(ctx.Repo.RepoLink + "/settings/actions/runners") +} diff --git a/routers/web/repo/setting/secrets.go b/routers/web/repo/setting/secrets.go new file mode 100644 index 000000000000..444f16f86c19 --- /dev/null +++ b/routers/web/repo/setting/secrets.go @@ -0,0 +1,115 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package setting + +import ( + "errors" + "net/http" + + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/setting" + shared "code.gitea.io/gitea/routers/web/shared/secrets" +) + +const ( + // TODO: Separate secrets from runners when layout is ready + tplRepoSecrets base.TplName = "repo/settings/actions" + tplOrgSecrets base.TplName = "org/settings/actions" + tplUserSecrets base.TplName = "user/settings/actions" +) + +type secretsCtx struct { + OwnerID int64 + RepoID int64 + IsRepo bool + IsOrg bool + IsUser bool + SecretsTemplate base.TplName + RedirectLink string +} + +func getSecretsCtx(ctx *context.Context) (*secretsCtx, error) { + if ctx.Data["PageIsRepoSettings"] == true { + return &secretsCtx{ + OwnerID: 0, + RepoID: ctx.Repo.Repository.ID, + IsRepo: true, + SecretsTemplate: tplRepoSecrets, + RedirectLink: ctx.Repo.RepoLink + "/settings/actions/secrets", + }, nil + } + + if ctx.Data["PageIsOrgSettings"] == true { + return &secretsCtx{ + OwnerID: ctx.ContextUser.ID, + RepoID: 0, + IsOrg: true, + SecretsTemplate: tplOrgSecrets, + RedirectLink: ctx.Org.OrgLink + "/settings/actions/secrets", + }, nil + } + + if ctx.Data["PageIsUserSettings"] == true { + return &secretsCtx{ + OwnerID: ctx.Doer.ID, + RepoID: 0, + IsUser: true, + SecretsTemplate: tplUserSecrets, + RedirectLink: setting.AppSubURL + "/user/settings/actions/secrets", + }, nil + } + + return nil, errors.New("unable to set Secrets context") +} + +func Secrets(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("actions.actions") + ctx.Data["PageType"] = "secrets" + ctx.Data["PageIsSharedSettingsSecrets"] = true + + sCtx, err := getSecretsCtx(ctx) + if err != nil { + ctx.ServerError("getSecretsCtx", err) + return + } + + if sCtx.IsRepo { + ctx.Data["DisableSSH"] = setting.SSH.Disabled + } + + shared.SetSecretsContext(ctx, sCtx.OwnerID, sCtx.RepoID) + if ctx.Written() { + return + } + ctx.HTML(http.StatusOK, sCtx.SecretsTemplate) +} + +func SecretsPost(ctx *context.Context) { + sCtx, err := getSecretsCtx(ctx) + if err != nil { + ctx.ServerError("getSecretsCtx", err) + return + } + shared.PerformSecretsPost( + ctx, + sCtx.OwnerID, + sCtx.RepoID, + sCtx.RedirectLink, + ) +} + +func SecretsDelete(ctx *context.Context) { + sCtx, err := getSecretsCtx(ctx) + if err != nil { + ctx.ServerError("getSecretsCtx", err) + return + } + shared.PerformSecretsDelete( + ctx, + sCtx.OwnerID, + sCtx.RepoID, + sCtx.RedirectLink, + ) +} diff --git a/routers/web/repo/setting_secrets.go b/routers/web/repo/setting_secrets.go deleted file mode 100644 index 57a4c470dd60..000000000000 --- a/routers/web/repo/setting_secrets.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2022 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package repo - -import ( - "net/http" - - "code.gitea.io/gitea/modules/base" - "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/setting" - shared "code.gitea.io/gitea/routers/web/shared/secrets" -) - -const ( - tplSecrets base.TplName = "repo/settings/secrets" -) - -func Secrets(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("secrets.secrets") - ctx.Data["PageIsSettingsSecrets"] = true - ctx.Data["DisableSSH"] = setting.SSH.Disabled - - shared.SetSecretsContext(ctx, 0, ctx.Repo.Repository.ID) - if ctx.Written() { - return - } - - ctx.HTML(http.StatusOK, tplSecrets) -} - -func SecretsPost(ctx *context.Context) { - shared.PerformSecretsPost( - ctx, - 0, - ctx.Repo.Repository.ID, - ctx.Repo.RepoLink+"/settings/secrets", - ) -} - -func DeleteSecret(ctx *context.Context) { - shared.PerformSecretsDelete( - ctx, - 0, - ctx.Repo.Repository.ID, - ctx.Repo.RepoLink+"/settings/secrets", - ) -} diff --git a/routers/web/repo/webhook.go b/routers/web/repo/webhook.go index f30588967e83..a21b405c9676 100644 --- a/routers/web/repo/webhook.go +++ b/routers/web/repo/webhook.go @@ -67,7 +67,7 @@ type ownerRepoCtx struct { // getOwnerRepoCtx determines whether this is a repo, owner, or admin (both default and system) context. func getOwnerRepoCtx(ctx *context.Context) (*ownerRepoCtx, error) { - if is, ok := ctx.Data["IsRepositoryWebhook"]; ok && is.(bool) { + if ctx.Data["PageIsRepoSettings"] == true { return &ownerRepoCtx{ RepoID: ctx.Repo.Repository.ID, Link: path.Join(ctx.Repo.RepoLink, "settings/hooks"), @@ -76,7 +76,7 @@ func getOwnerRepoCtx(ctx *context.Context) (*ownerRepoCtx, error) { }, nil } - if is, ok := ctx.Data["IsOrganizationWebhook"]; ok && is.(bool) { + if ctx.Data["PageIsOrgSettings"] == true { return &ownerRepoCtx{ OwnerID: ctx.ContextUser.ID, Link: path.Join(ctx.Org.OrgLink, "settings/hooks"), @@ -85,7 +85,7 @@ func getOwnerRepoCtx(ctx *context.Context) (*ownerRepoCtx, error) { }, nil } - if is, ok := ctx.Data["IsUserWebhook"]; ok && is.(bool) { + if ctx.Data["PageIsUserSettings"] == true { return &ownerRepoCtx{ OwnerID: ctx.Doer.ID, Link: path.Join(setting.AppSubURL, "/user/settings/hooks"), @@ -94,7 +94,7 @@ func getOwnerRepoCtx(ctx *context.Context) (*ownerRepoCtx, error) { }, nil } - if ctx.Doer.IsAdmin { + if ctx.Data["PageIsAdmin"] == true { return &ownerRepoCtx{ IsAdmin: true, IsSystemWebhook: ctx.Params(":configType") == "system-hooks", diff --git a/routers/web/shared/actions/runners.go b/routers/web/shared/actions/runners.go index 2c3614cbbcb2..9a50da2b492b 100644 --- a/routers/web/shared/actions/runners.go +++ b/routers/web/shared/actions/runners.go @@ -10,7 +10,6 @@ import ( actions_model "code.gitea.io/gitea/models/actions" "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/util" @@ -18,8 +17,8 @@ import ( "code.gitea.io/gitea/services/forms" ) -// RunnersList render common runners list page -func RunnersList(ctx *context.Context, tplName base.TplName, opts actions_model.FindRunnerOptions) { +// RunnersList prepares data for runners list +func RunnersList(ctx *context.Context, opts actions_model.FindRunnerOptions) { count, err := actions_model.CountRunners(ctx, opts) if err != nil { ctx.ServerError("CountRunners", err) @@ -58,13 +57,12 @@ func RunnersList(ctx *context.Context, tplName base.TplName, opts actions_model. ctx.Data["RunnerRepoID"] = opts.RepoID pager := context.NewPagination(int(count), opts.PageSize, opts.Page, 5) - ctx.Data["Page"] = pager - ctx.HTML(http.StatusOK, tplName) + ctx.Data["Page"] = pager } -// RunnerDetails render runner details page -func RunnerDetails(ctx *context.Context, tplName base.TplName, page int, runnerID, ownerID, repoID int64) { +// RunnerDetails prepares data for runners edit page +func RunnerDetails(ctx *context.Context, page int, runnerID, ownerID, repoID int64) { runner, err := actions_model.GetRunnerByID(ctx, runnerID) if err != nil { ctx.ServerError("GetRunnerByID", err) @@ -111,8 +109,6 @@ func RunnerDetails(ctx *context.Context, tplName base.TplName, page int, runnerI ctx.Data["Tasks"] = tasks pager := context.NewPagination(int(count), opts.PageSize, opts.Page, 5) ctx.Data["Page"] = pager - - ctx.HTML(http.StatusOK, tplName) } // RunnerDetailsEditPost response for edit runner details diff --git a/routers/web/user/home.go b/routers/web/user/home.go index 1f77379044af..1af56e24b046 100644 --- a/routers/web/user/home.go +++ b/routers/web/user/home.go @@ -30,6 +30,8 @@ import ( "code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/routers/web/feed" + context_service "code.gitea.io/gitea/services/context" issue_service "code.gitea.io/gitea/services/issue" pull_service "code.gitea.io/gitea/services/pull" @@ -815,3 +817,51 @@ func ShowGPGKeys(ctx *context.Context) { writer.Close() ctx.PlainTextBytes(http.StatusOK, buf.Bytes()) } + +func UsernameSubRoute(ctx *context.Context) { + // WORKAROUND to support usernames with "." in it + // https://github.com/go-chi/chi/issues/781 + username := ctx.Params("username") + reloadParam := func(suffix string) (success bool) { + ctx.SetParams("username", strings.TrimSuffix(username, suffix)) + context_service.UserAssignmentWeb()(ctx) + return !ctx.Written() + } + switch { + case strings.HasSuffix(username, ".png"): + if reloadParam(".png") { + AvatarByUserName(ctx) + } + case strings.HasSuffix(username, ".keys"): + if reloadParam(".keys") { + ShowSSHKeys(ctx) + } + case strings.HasSuffix(username, ".gpg"): + if reloadParam(".gpg") { + ShowGPGKeys(ctx) + } + case strings.HasSuffix(username, ".rss"): + if !setting.Other.EnableFeed { + ctx.Error(http.StatusNotFound) + return + } + if reloadParam(".rss") { + context_service.UserAssignmentWeb()(ctx) + feed.ShowUserFeedRSS(ctx) + } + case strings.HasSuffix(username, ".atom"): + if !setting.Other.EnableFeed { + ctx.Error(http.StatusNotFound) + return + } + if reloadParam(".atom") { + feed.ShowUserFeedAtom(ctx) + } + default: + context_service.UserAssignmentWeb()(ctx) + if !ctx.Written() { + ctx.Data["EnableFeed"] = setting.Other.EnableFeed + Profile(ctx) + } + } +} diff --git a/routers/web/user/setting/secrets.go b/routers/web/user/setting/secrets.go index 2314f3694f77..eb09477bdb00 100644 --- a/routers/web/user/setting/secrets.go +++ b/routers/web/user/setting/secrets.go @@ -4,44 +4,10 @@ package setting import ( - "net/http" - - "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/setting" - shared "code.gitea.io/gitea/routers/web/shared/secrets" -) - -const ( - tplSettingsSecrets base.TplName = "user/settings/secrets" ) -func Secrets(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("secrets.secrets") - ctx.Data["PageIsSettingsSecrets"] = true - - shared.SetSecretsContext(ctx, ctx.Doer.ID, 0) - if ctx.Written() { - return - } - - ctx.HTML(http.StatusOK, tplSettingsSecrets) -} - -func SecretsPost(ctx *context.Context) { - shared.PerformSecretsPost( - ctx, - ctx.Doer.ID, - 0, - setting.AppSubURL+"/user/settings/secrets", - ) -} - -func SecretsDelete(ctx *context.Context) { - shared.PerformSecretsDelete( - ctx, - ctx.Doer.ID, - 0, - setting.AppSubURL+"/user/settings/secrets", - ) +func RedirectToDefaultSetting(ctx *context.Context) { + ctx.Redirect(setting.AppSubURL + "/user/settings/actions/secrets") } diff --git a/routers/web/web.go b/routers/web/web.go index 779499889fb0..a4ef96ecbe0f 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -6,16 +6,10 @@ package web import ( gocontext "context" "net/http" - "os" - "path" - "strings" "code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/models/unit" - "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/httpcache" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/metrics" "code.gitea.io/gitea/modules/public" @@ -26,6 +20,7 @@ import ( "code.gitea.io/gitea/modules/validation" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web/routing" + "code.gitea.io/gitea/routers/common" "code.gitea.io/gitea/routers/web/admin" "code.gitea.io/gitea/routers/web/auth" "code.gitea.io/gitea/routers/web/devtest" @@ -35,8 +30,10 @@ import ( "code.gitea.io/gitea/routers/web/healthcheck" "code.gitea.io/gitea/routers/web/misc" "code.gitea.io/gitea/routers/web/org" + org_setting "code.gitea.io/gitea/routers/web/org/setting" "code.gitea.io/gitea/routers/web/repo" "code.gitea.io/gitea/routers/web/repo/actions" + repo_setting "code.gitea.io/gitea/routers/web/repo/setting" "code.gitea.io/gitea/routers/web/user" user_setting "code.gitea.io/gitea/routers/web/user/setting" "code.gitea.io/gitea/routers/web/user/setting/security" @@ -48,7 +45,6 @@ import ( _ "code.gitea.io/gitea/modules/session" // to registers all internal adapters "gitea.com/go-chi/captcha" - "gitea.com/go-chi/session" "github.com/NYTimes/gziphandler" "github.com/go-chi/chi/v5/middleware" "github.com/go-chi/cors" @@ -99,49 +95,30 @@ func buildAuthGroup() *auth_service.Group { return group } +func ctxDataSet(args ...any) func(ctx *context.Context) { + return func(ctx *context.Context) { + for i := 0; i < len(args); i += 2 { + ctx.Data[args[i].(string)] = args[i+1] + } + } +} + // Routes returns all web routes func Routes(ctx gocontext.Context) *web.Route { routes := web.NewRoute() - routes.Use(web.MiddlewareWithPrefix("/assets/", CorsHandler(), public.AssetsHandlerFunc("/assets/"))) - - sessioner := session.Sessioner(session.Options{ - Provider: setting.SessionConfig.Provider, - ProviderConfig: setting.SessionConfig.ProviderConfig, - CookieName: setting.SessionConfig.CookieName, - CookiePath: setting.SessionConfig.CookiePath, - Gclifetime: setting.SessionConfig.Gclifetime, - Maxlifetime: setting.SessionConfig.Maxlifetime, - Secure: setting.SessionConfig.Secure, - SameSite: setting.SessionConfig.SameSite, - Domain: setting.SessionConfig.Domain, - }) - routes.Use(sessioner) - - ctx, _ = templates.HTMLRenderer(ctx) - - routes.Use(Recovery(ctx)) - - // We use r.Route here over r.Use because this prevents requests that are not for avatars having to go through this additional handler + routes.Head("/", misc.DummyOK) // for health check - doesn't need to be passed through gzip handler + routes.RouteMethods("/assets/*", "GET, HEAD", CorsHandler(), public.AssetsHandlerFunc("/assets/")) routes.RouteMethods("/avatars/*", "GET, HEAD", storageHandler(setting.Avatar.Storage, "avatars", storage.Avatars)) routes.RouteMethods("/repo-avatars/*", "GET, HEAD", storageHandler(setting.RepoAvatar.Storage, "repo-avatars", storage.RepoAvatars)) + routes.RouteMethods("/apple-touch-icon.png", "GET, HEAD", misc.StaticRedirect("/assets/img/apple-touch-icon.png")) + routes.RouteMethods("/favicon.ico", "GET, HEAD", misc.StaticRedirect("/assets/img/favicon.png")) - // for health check - doesn't need to be passed through gzip handler - routes.Head("/", func(w http.ResponseWriter, req *http.Request) { - w.WriteHeader(http.StatusOK) - }) - - // this png is very likely to always be below the limit for gzip so it doesn't need to pass through gzip - routes.Get("/apple-touch-icon.png", func(w http.ResponseWriter, req *http.Request) { - http.Redirect(w, req, path.Join(setting.StaticURLPrefix, "/assets/img/apple-touch-icon.png"), http.StatusPermanentRedirect) - }) - - // redirect default favicon to the path of the custom favicon with a default as a fallback - routes.Get("/favicon.ico", func(w http.ResponseWriter, req *http.Request) { - http.Redirect(w, req, path.Join(setting.StaticURLPrefix, "/assets/img/favicon.png"), http.StatusMovedPermanently) - }) - - common := []interface{}{} + ctx, _ = templates.HTMLRenderer(ctx) + common := []any{ + common.Sessioner(), + RecoveryWith500Page(ctx), + } if setting.EnableGzip { h, err := gziphandler.GzipHandlerWithOpts(gziphandler.MinSize(GzipMinSize)) @@ -157,42 +134,18 @@ func Routes(ctx gocontext.Context) *web.Route { } if setting.HasRobotsTxt { - routes.Get("/robots.txt", append(common, func(w http.ResponseWriter, req *http.Request) { - filePath := path.Join(setting.CustomPath, "robots.txt") - fi, err := os.Stat(filePath) - if err == nil && httpcache.HandleTimeCache(req, w, fi) { - return - } - http.ServeFile(w, req, filePath) - })...) + routes.Get("/robots.txt", append(common, misc.RobotsTxt)...) } // prometheus metrics endpoint - do not need to go through contexter if setting.Metrics.Enabled { - c := metrics.NewCollector() - prometheus.MustRegister(c) - + prometheus.MustRegister(metrics.NewCollector()) routes.Get("/metrics", append(common, Metrics)...) } - routes.Get("/ssh_info", func(rw http.ResponseWriter, req *http.Request) { - if !git.SupportProcReceive { - rw.WriteHeader(http.StatusNotFound) - return - } - rw.Header().Set("content-type", "text/json;charset=UTF-8") - _, err := rw.Write([]byte(`{"type":"gitea","version":1}`)) - if err != nil { - log.Error("fail to write result: err: %v", err) - rw.WriteHeader(http.StatusInternalServerError) - return - } - rw.WriteHeader(http.StatusOK) - }) - + routes.Get("/ssh_info", misc.SSHInfo) routes.Get("/api/healthz", healthcheck.Check) - // Removed: toolbox.Toolboxer middleware will provide debug information which seems unnecessary common = append(common, context.Contexter(ctx)) group := buildAuthGroup() @@ -207,7 +160,7 @@ func Routes(ctx gocontext.Context) *web.Route { common = append(common, middleware.GetHead) if setting.API.EnableSwagger { - // Note: The route moved from apiroutes because it's in fact want to render a web page + // Note: The route is here but no in API routes because it renders a web page routes.Get("/api/swagger", append(common, misc.Swagger)...) // Render V1 by default } @@ -217,17 +170,14 @@ func Routes(ctx gocontext.Context) *web.Route { common = append(common, goGet) others := web.NewRoute() - for _, middle := range common { - others.Use(middle) - } - - RegisterRoutes(others) + others.Use(common...) + registerRoutes(others) routes.Mount("", others) return routes } -// RegisterRoutes register routes -func RegisterRoutes(m *web.Route) { +// registerRoutes register routes +func registerRoutes(m *web.Route) { reqSignIn := auth_service.VerifyAuthWithOptions(&auth_service.VerifyOptions{SignInRequired: true}) ignSignIn := auth_service.VerifyAuthWithOptions(&auth_service.VerifyOptions{SignInRequired: setting.Service.RequireSignInView}) ignExploreSignIn := auth_service.VerifyAuthWithOptions(&auth_service.VerifyOptions{SignInRequired: setting.Service.RequireSignInView || setting.Service.Explore.RequireSigninView}) @@ -342,6 +292,24 @@ func RegisterRoutes(m *web.Route) { m.Post("/packagist/{id}", web.Bind(forms.NewPackagistHookForm{}), repo.PackagistHooksEditPost) } + addSettingsSecretsRoutes := func() { + m.Group("/secrets", func() { + m.Get("", repo_setting.Secrets) + m.Post("", web.Bind(forms.AddSecretForm{}), repo_setting.SecretsPost) + m.Post("/delete", repo_setting.SecretsDelete) + }) + } + + addSettingsRunnersRoutes := func() { + m.Group("/runners", func() { + m.Get("", repo_setting.Runners) + m.Combo("/{runnerid}").Get(repo_setting.RunnersEdit). + Post(web.Bind(forms.EditRunnerForm{}), repo_setting.RunnersEditPost) + m.Post("/{runnerid}/delete", repo_setting.RunnerDeletePost) + m.Get("/reset_registration_token", repo_setting.ResetRunnerRegistrationToken) + }) + } + // FIXME: not all routes need go through same middleware. // Especially some AJAX requests, we can reduce middleware number to improve performance. // Routers. @@ -354,8 +322,8 @@ func RegisterRoutes(m *web.Route) { m.Get("/nodeinfo", NodeInfoLinks) m.Get("/webfinger", WebfingerQuery) }, federationEnabled) - m.Get("/change-password", func(w http.ResponseWriter, req *http.Request) { - http.Redirect(w, req, "/user/settings/account", http.StatusTemporaryRedirect) + m.Get("/change-password", func(ctx *context.Context) { + ctx.Redirect(setting.AppSubURL + "/user/settings/account") }) }) @@ -501,11 +469,12 @@ func RegisterRoutes(m *web.Route) { }) m.Post("/chef/regenerate_keypair", user_setting.RegenerateChefKeyPair) }, packagesEnabled) - m.Group("/secrets", func() { - m.Get("", user_setting.Secrets) - m.Post("", web.Bind(forms.AddSecretForm{}), user_setting.SecretsPost) - m.Post("/delete", user_setting.SecretsDelete) - }) + + m.Group("/actions", func() { + m.Get("", user_setting.RedirectToDefaultSetting) + addSettingsSecretsRoutes() + }, actions.MustEnableActions) + m.Get("/organization", user_setting.Organization) m.Get("/repos", user_setting.Repos) m.Post("/repos/unadopted", user_setting.AdoptOrDeleteRepository) @@ -519,14 +488,8 @@ func RegisterRoutes(m *web.Route) { m.Post("/replay/{uuid}", repo.ReplayWebhook) }) addWebhookEditRoutes() - }, webhooksEnabled, func(ctx *context.Context) { - ctx.Data["IsUserWebhook"] = true - }) - }, reqSignIn, func(ctx *context.Context) { - ctx.Data["PageIsUserSettings"] = true - ctx.Data["AllThemes"] = setting.UI.Themes - ctx.Data["EnablePackages"] = setting.Packages.Enabled - }) + }, webhooksEnabled) + }, reqSignIn, ctxDataSet("PageIsUserSettings", true, "AllThemes", setting.UI.Themes, "EnablePackages", setting.Packages.Enabled)) m.Group("/user", func() { // r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds) @@ -651,66 +614,15 @@ func RegisterRoutes(m *web.Route) { } }) - m.Group("/runners", func() { - m.Get("", admin.Runners) - m.Get("/reset_registration_token", admin.ResetRunnerRegistrationToken) - m.Combo("/{runnerid}").Get(admin.EditRunner).Post(web.Bind(forms.EditRunnerForm{}), admin.EditRunnerPost) - m.Post("/{runnerid}/delete", admin.DeleteRunnerPost) - }, actions.MustEnableActions) - }, func(ctx *context.Context) { - ctx.Data["EnableOAuth2"] = setting.OAuth2.Enable - ctx.Data["EnablePackages"] = setting.Packages.Enabled - }, adminReq) + m.Group("/actions", func() { + m.Get("", admin.RedirectToDefaultSetting) + addSettingsRunnersRoutes() + }) + }, adminReq, ctxDataSet("EnableOAuth2", setting.OAuth2.Enable, "EnablePackages", setting.Packages.Enabled)) // ***** END: Admin ***** m.Group("", func() { - m.Get("/favicon.ico", func(ctx *context.Context) { - ctx.SetServeHeaders(&context.ServeHeaderOptions{ - Filename: "favicon.png", - }) - http.ServeFile(ctx.Resp, ctx.Req, path.Join(setting.StaticRootPath, "public/img/favicon.png")) - }) - m.Get("/{username}", func(ctx *context.Context) { - // WORKAROUND to support usernames with "." in it - // https://github.com/go-chi/chi/issues/781 - username := ctx.Params("username") - reloadParam := func(suffix string) (success bool) { - ctx.SetParams("username", strings.TrimSuffix(username, suffix)) - context_service.UserAssignmentWeb()(ctx) - return !ctx.Written() - } - switch { - case strings.HasSuffix(username, ".png"): - if reloadParam(".png") { - user.AvatarByUserName(ctx) - } - case strings.HasSuffix(username, ".keys"): - if reloadParam(".keys") { - user.ShowSSHKeys(ctx) - } - case strings.HasSuffix(username, ".gpg"): - if reloadParam(".gpg") { - user.ShowGPGKeys(ctx) - } - case strings.HasSuffix(username, ".rss"): - feedEnabled(ctx) - if !ctx.Written() && reloadParam(".rss") { - context_service.UserAssignmentWeb()(ctx) - feed.ShowUserFeedRSS(ctx) - } - case strings.HasSuffix(username, ".atom"): - feedEnabled(ctx) - if !ctx.Written() && reloadParam(".atom") { - feed.ShowUserFeedAtom(ctx) - } - default: - context_service.UserAssignmentWeb()(ctx) - if !ctx.Written() { - ctx.Data["EnableFeed"] = setting.Other.EnableFeed - user.Profile(ctx) - } - } - }) + m.Get("/{username}", user.UsernameSubRoute) m.Get("/attachments/{uuid}", repo.GetAttachment) }, ignSignIn) @@ -830,9 +742,7 @@ func RegisterRoutes(m *web.Route) { m.Post("/replay/{uuid}", repo.ReplayWebhook) }) addWebhookEditRoutes() - }, webhooksEnabled, func(ctx *context.Context) { - ctx.Data["IsOrganizationWebhook"] = true - }) + }, webhooksEnabled) m.Group("/labels", func() { m.Get("", org.RetrieveLabels, org.Labels) @@ -842,20 +752,12 @@ func RegisterRoutes(m *web.Route) { m.Post("/initialize", web.Bind(forms.InitializeLabelsForm{}), org.InitializeLabels) }) - m.Group("/runners", func() { - m.Get("", org.Runners) - m.Combo("/{runnerid}").Get(org.RunnersEdit). - Post(web.Bind(forms.EditRunnerForm{}), org.RunnersEditPost) - m.Post("/{runnerid}/delete", org.RunnerDeletePost) - m.Get("/reset_registration_token", org.ResetRunnerRegistrationToken) + m.Group("/actions", func() { + m.Get("", org_setting.RedirectToDefaultSetting) + addSettingsRunnersRoutes() + addSettingsSecretsRoutes() }, actions.MustEnableActions) - m.Group("/secrets", func() { - m.Get("", org.Secrets) - m.Post("", web.Bind(forms.AddSecretForm{}), org.SecretsPost) - m.Post("/delete", org.SecretsDelete) - }) - m.RouteMethods("/delete", "GET,POST", org.SettingsDelete) m.Group("/packages", func() { @@ -876,10 +778,7 @@ func RegisterRoutes(m *web.Route) { m.Post("/rebuild", org.RebuildCargoIndex) }) }, packagesEnabled) - }, func(ctx *context.Context) { - ctx.Data["EnableOAuth2"] = setting.OAuth2.Enable - ctx.Data["EnablePackages"] = setting.Packages.Enabled - }) + }, ctxDataSet("EnableOAuth2", setting.OAuth2.Enable, "EnablePackages", setting.Packages.Enabled, "PageIsOrgSettings", true)) }, context.OrgAssignment(true, true)) }, reqSignIn) // ***** END: Organization ***** @@ -1013,9 +912,7 @@ func RegisterRoutes(m *web.Route) { m.Post("/replay/{uuid}", repo.ReplayWebhook) }) addWebhookEditRoutes() - }, webhooksEnabled, func(ctx *context.Context) { - ctx.Data["IsRepositoryWebhook"] = true - }) + }, webhooksEnabled) m.Group("/keys", func() { m.Combo("").Get(repo.DeployKeys). @@ -1023,12 +920,6 @@ func RegisterRoutes(m *web.Route) { m.Post("/delete", repo.DeleteDeployKey) }) - m.Group("/secrets", func() { - m.Get("", repo.Secrets) - m.Post("", web.Bind(forms.AddSecretForm{}), repo.SecretsPost) - m.Post("/delete", repo.DeleteSecret) - }) - m.Group("/lfs", func() { m.Get("/", repo.LFSFiles) m.Get("/show/{oid}", repo.LFSFileGet) @@ -1042,18 +933,12 @@ func RegisterRoutes(m *web.Route) { m.Post("/{lid}/unlock", repo.LFSUnlock) }) }) - - m.Group("/runners", func() { - m.Get("", repo.Runners) - m.Combo("/{runnerid}").Get(repo.RunnersEdit). - Post(web.Bind(forms.EditRunnerForm{}), repo.RunnersEditPost) - m.Post("/{runnerid}/delete", repo.RunnerDeletePost) - m.Get("/reset_registration_token", repo.ResetRunnerRegistrationToken) + m.Group("/actions", func() { + m.Get("", repo_setting.RedirectToDefaultSetting) + addSettingsRunnersRoutes() + addSettingsSecretsRoutes() }, actions.MustEnableActions) - }, func(ctx *context.Context) { - ctx.Data["PageIsSettings"] = true - ctx.Data["LFSStartServer"] = setting.LFS.StartServer - }) + }, ctxDataSet("PageIsRepoSettings", true, "LFSStartServer", setting.LFS.StartServer)) }, reqSignIn, context.RepoAssignment, context.UnitTypes(), reqRepoAdmin, context.RepoRef()) m.Post("/{username}/{reponame}/action/{action}", reqSignIn, context.RepoAssignment, context.UnitTypes(), repo.Action) @@ -1204,9 +1089,8 @@ func RegisterRoutes(m *web.Route) { m.Get("", repo.TagsList) m.Get(".rss", feedEnabled, repo.TagsListFeedRSS) m.Get(".atom", feedEnabled, repo.TagsListFeedAtom) - }, func(ctx *context.Context) { - ctx.Data["EnableFeed"] = setting.Other.EnableFeed - }, repo.MustBeNotEmpty, reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag, true)) + }, ctxDataSet("EnableFeed", setting.Other.EnableFeed), + repo.MustBeNotEmpty, reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag, true)) m.Post("/tags/delete", repo.DeleteTag, reqSignIn, repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoCodeWriter, context.RepoRef()) }, reqSignIn, context.RepoAssignment, context.UnitTypes()) @@ -1219,9 +1103,8 @@ func RegisterRoutes(m *web.Route) { m.Get("/latest", repo.LatestRelease) m.Get(".rss", feedEnabled, repo.ReleasesFeedRSS) m.Get(".atom", feedEnabled, repo.ReleasesFeedAtom) - }, func(ctx *context.Context) { - ctx.Data["EnableFeed"] = setting.Other.EnableFeed - }, repo.MustBeNotEmpty, reqRepoReleaseReader, context.RepoRefByType(context.RepoRefTag, true)) + }, ctxDataSet("EnableFeed", setting.Other.EnableFeed), + repo.MustBeNotEmpty, reqRepoReleaseReader, context.RepoRefByType(context.RepoRefTag, true)) m.Get("/releases/attachments/{uuid}", repo.GetAttachment, repo.MustBeNotEmpty, reqRepoReleaseReader) m.Group("/releases", func() { m.Get("/new", repo.NewRelease) @@ -1233,21 +1116,7 @@ func RegisterRoutes(m *web.Route) { m.Group("/releases", func() { m.Get("/edit/*", repo.EditRelease) m.Post("/edit/*", web.Bind(forms.EditReleaseForm{}), repo.EditReleasePost) - }, reqSignIn, repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoReleaseWriter, func(ctx *context.Context) { - var err error - ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultBranch) - if err != nil { - ctx.ServerError("GetBranchCommit", err) - return - } - ctx.Repo.CommitsCount, err = ctx.Repo.GetCommitsCount() - if err != nil { - ctx.ServerError("GetCommitsCount", err) - return - } - ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount - ctx.Repo.GitRepo.LastCommitCache = git.NewLastCommitCache(ctx.Repo.CommitsCount, ctx.Repo.Repository.FullName(), ctx.Repo.GitRepo, cache.GetCache()) - }) + }, reqSignIn, repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoReleaseWriter, repo.CommitInfoCache) }, ignSignIn, context.RepoAssignment, context.UnitTypes(), reqRepoReleaseReader) // to maintain compatibility with old attachments @@ -1326,18 +1195,10 @@ func RegisterRoutes(m *web.Route) { m.Group("/wiki", func() { m.Combo("/"). Get(repo.Wiki). - Post(context.RepoMustNotBeArchived(), - reqSignIn, - reqRepoWikiWriter, - web.Bind(forms.NewWikiForm{}), - repo.WikiPost) + Post(context.RepoMustNotBeArchived(), reqSignIn, reqRepoWikiWriter, web.Bind(forms.NewWikiForm{}), repo.WikiPost) m.Combo("/*"). Get(repo.Wiki). - Post(context.RepoMustNotBeArchived(), - reqSignIn, - reqRepoWikiWriter, - web.Bind(forms.NewWikiForm{}), - repo.WikiPost) + Post(context.RepoMustNotBeArchived(), reqSignIn, reqRepoWikiWriter, web.Bind(forms.NewWikiForm{}), repo.WikiPost) m.Get("/commit/{sha:[a-f0-9]{7,40}}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.Diff) m.Get("/commit/{sha:[a-f0-9]{7,40}}.{ext:patch|diff}", repo.RawDiff) }, repo.MustEnableWiki, func(ctx *context.Context) { @@ -1468,8 +1329,7 @@ func RegisterRoutes(m *web.Route) { m.Group("", func() { m.Get("/forks", repo.Forks) }, context.RepoRef(), reqRepoCodeReader) - m.Get("/commit/{sha:([a-f0-9]{7,40})}.{ext:patch|diff}", - repo.MustBeNotEmpty, reqRepoCodeReader, repo.RawDiff) + m.Get("/commit/{sha:([a-f0-9]{7,40})}.{ext:patch|diff}", repo.MustBeNotEmpty, reqRepoCodeReader, repo.RawDiff) }, ignSignIn, context.RepoAssignment, context.UnitTypes()) m.Post("/{username}/{reponame}/lastcommit/*", ignSignInAndCsrf, context.RepoAssignment, context.UnitTypes(), context.RepoRefByType(context.RepoRefCommit), reqRepoCodeReader, repo.LastCommit) diff --git a/services/auth/basic.go b/services/auth/basic.go index dc03780905c9..36480568ff0a 100644 --- a/services/auth/basic.go +++ b/services/auth/basic.go @@ -102,6 +102,7 @@ func (b *Basic) Verify(req *http.Request, w http.ResponseWriter, store DataStore } store.GetData()["IsApiToken"] = true + store.GetData()["ApiTokenScope"] = token.Scope return u, nil } else if !auth_model.IsErrAccessTokenNotExist(err) && !auth_model.IsErrAccessTokenEmpty(err) { log.Error("GetAccessTokenBySha: %v", err) diff --git a/services/auth/middleware.go b/services/auth/middleware.go index b96810f17f6d..abeafed9cb46 100644 --- a/services/auth/middleware.go +++ b/services/auth/middleware.go @@ -236,7 +236,6 @@ func VerifyAuthWithOptionsAPI(options *VerifyOptions) func(ctx *context.APIConte }) return } - ctx.Data["PageIsAdmin"] = true } } } diff --git a/services/convert/repository.go b/services/convert/repository.go index a2a8570cc94d..f470fd16564e 100644 --- a/services/convert/repository.go +++ b/services/convert/repository.go @@ -183,6 +183,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, mode perm.Acc DefaultBranch: repo.DefaultBranch, Created: repo.CreatedUnix.AsTime(), Updated: repo.UpdatedUnix.AsTime(), + ArchivedAt: repo.ArchivedUnix.AsTime(), Permissions: permission, HasIssues: hasIssues, ExternalTracker: externalTracker, diff --git a/services/lfs/locks.go b/services/lfs/locks.go index d963d9ab574f..1e5db6bd2014 100644 --- a/services/lfs/locks.go +++ b/services/lfs/locks.go @@ -58,6 +58,11 @@ func GetListLockHandler(ctx *context.Context) { } repository.MustOwner(ctx) + context.CheckRepoScopedToken(ctx, repository) + if ctx.Written() { + return + } + authenticated := authenticate(ctx, repository, rv.Authorization, true, false) if !authenticated { ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs") @@ -145,6 +150,11 @@ func PostLockHandler(ctx *context.Context) { } repository.MustOwner(ctx) + context.CheckRepoScopedToken(ctx, repository) + if ctx.Written() { + return + } + authenticated := authenticate(ctx, repository, authorization, true, true) if !authenticated { ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs") @@ -212,6 +222,11 @@ func VerifyLockHandler(ctx *context.Context) { } repository.MustOwner(ctx) + context.CheckRepoScopedToken(ctx, repository) + if ctx.Written() { + return + } + authenticated := authenticate(ctx, repository, authorization, true, true) if !authenticated { ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs") @@ -278,6 +293,11 @@ func UnLockHandler(ctx *context.Context) { } repository.MustOwner(ctx) + context.CheckRepoScopedToken(ctx, repository) + if ctx.Written() { + return + } + authenticated := authenticate(ctx, repository, authorization, true, true) if !authenticated { ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs") diff --git a/services/lfs/server.go b/services/lfs/server.go index 44de9ba74f2b..64e120339454 100644 --- a/services/lfs/server.go +++ b/services/lfs/server.go @@ -423,6 +423,11 @@ func getAuthenticatedRepository(ctx *context.Context, rc *requestContext, requir return nil } + context.CheckRepoScopedToken(ctx, repository) + if ctx.Written() { + return nil + } + return repository } diff --git a/services/repository/files/update.go b/services/repository/files/update.go index 45a469239665..25014f441833 100644 --- a/services/repository/files/update.go +++ b/services/repository/files/update.go @@ -458,6 +458,11 @@ func CreateOrUpdateRepoFile(ctx context.Context, repo *repo_model.Repository, do if err != nil { return nil, err } + + if repo.IsEmpty { + _ = repo_model.UpdateRepositoryCols(ctx, &repo_model.Repository{ID: repo.ID, IsEmpty: false}, "is_empty") + } + return file, nil } diff --git a/templates/admin/runners/base.tmpl b/templates/admin/actions.tmpl similarity index 77% rename from templates/admin/runners/base.tmpl rename to templates/admin/actions.tmpl index 36495b6a0b94..9640e0fd1f4c 100644 --- a/templates/admin/runners/base.tmpl +++ b/templates/admin/actions.tmpl @@ -1,5 +1,7 @@ -{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin runners")}} +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin actions")}}
+ {{if eq .PageType "runners"}} {{template "shared/actions/runner_list" .}} + {{end}}
{{template "admin/layout_footer" .}} diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index 136ad38f1632..f0d0ad3643a2 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -238,16 +238,18 @@
{{.Mailer.SMTPPort}}
{{end}}
{{.locale.Tr "admin.config.mailer_user"}}
-
{{if .Mailer.User}}{{.Mailer.User}}{{else}}(empty){{end}}

-
- {{.CsrfTokenHtml}} -
-
+
{{if .Mailer.User}}{{.Mailer.User}}{{else}}(empty){{end}}
+
+
{{.locale.Tr "admin.config.send_test_mail"}}
+
+ + {{.CsrfTokenHtml}} +
-
- - + + + {{end}}
diff --git a/templates/admin/cron.tmpl b/templates/admin/cron.tmpl index 267da00759b5..6ab37ca35484 100644 --- a/templates/admin/cron.tmpl +++ b/templates/admin/cron.tmpl @@ -21,7 +21,7 @@ {{$.locale.Tr (printf "admin.dashboard.%s" .Name)}} {{.Spec}} - {{DateTime "full" (DateFmtLong .Next)}} + {{DateTime "full" .Next}} {{if gt .Prev.Year 1}}{{DateTime "full" .Prev}}{{else}}N/A{{end}} {{.ExecTimes}} {{if eq .Status ""}}—{{else if eq .Status "finished"}}{{svg "octicon-check" 16}}{{else}}{{svg "octicon-x" 16}}{{end}} diff --git a/templates/admin/dashboard.tmpl b/templates/admin/dashboard.tmpl index 93fcae4ca4d4..678445137660 100644 --- a/templates/admin/dashboard.tmpl +++ b/templates/admin/dashboard.tmpl @@ -16,63 +16,63 @@

{{.locale.Tr "admin.dashboard.operations"}}

-
- {{.CsrfTokenHtml}} -
- +
+ + {{.CsrfTokenHtml}} +
- + - + - + - + {{if and (not .SSH.Disabled) (not .SSH.StartBuiltinServer)}} - + - + {{end}} - + - + - + - + - +
{{.locale.Tr "admin.dashboard.delete_inactive_accounts"}}
{{.locale.Tr "admin.dashboard.delete_repo_archives"}}
{{.locale.Tr "admin.dashboard.delete_missing_repos"}}
{{.locale.Tr "admin.dashboard.git_gc_repos"}}
{{.locale.Tr "admin.dashboard.resync_all_sshkeys"}}
{{.locale.Tr "admin.dashboard.resync_all_sshkeys.desc"}}
{{.locale.Tr "admin.dashboard.resync_all_sshprincipals"}}
{{.locale.Tr "admin.dashboard.resync_all_sshprincipals.desc"}}
{{.locale.Tr "admin.dashboard.resync_all_hooks"}}
{{.locale.Tr "admin.dashboard.reinit_missing_repos"}}
{{.locale.Tr "admin.dashboard.sync_external_users"}}
{{.locale.Tr "admin.dashboard.repo_health_check"}}
{{.locale.Tr "admin.dashboard.delete_generated_repository_avatars"}}
-
-
+ +

{{.locale.Tr "admin.dashboard.system_status"}} diff --git a/templates/admin/navbar.tmpl b/templates/admin/navbar.tmpl index e8eb54e58da4..51a93bacd7b6 100644 --- a/templates/admin/navbar.tmpl +++ b/templates/admin/navbar.tmpl @@ -35,9 +35,14 @@ {{end}} {{if .EnableActions}} - - {{.locale.Tr "actions.runners"}} - +
+ {{.locale.Tr "actions.actions"}} + +
{{end}} {{.locale.Tr "admin.config"}} diff --git a/templates/admin/notice.tmpl b/templates/admin/notice.tmpl index bd6b74dd2bdf..3dbae0462575 100644 --- a/templates/admin/notice.tmpl +++ b/templates/admin/notice.tmpl @@ -3,67 +3,60 @@

{{.locale.Tr "admin.notices.system_notice_list"}} ({{.locale.Tr "admin.total" .Total}})

-
- - +
+ + + + + + + + + + + + {{range .Notices}} - - - - - - + + + + + + - - - {{range .Notices}} + {{end}} + + {{if .Notices}} + - - - - - - - - {{end}} - - {{if .Notices}} - - - - + - - - {{end}} -
ID{{.locale.Tr "admin.notices.type"}}{{.locale.Tr "admin.notices.desc"}}{{.locale.Tr "admin.users.created"}}{{.locale.Tr "admin.notices.op"}}
ID{{.locale.Tr "admin.notices.type"}}{{.locale.Tr "admin.notices.desc"}}{{.locale.Tr "admin.users.created"}}{{.locale.Tr "admin.notices.op"}}
{{.ID}}{{$.locale.Tr .TrStr}}{{.Description}}{{DateTime "short" .CreatedUnix}}{{svg "octicon-note" 16}}
-
- -
-
{{.ID}}{{$.locale.Tr .TrStr}}{{.Description}}{{DateTime "short" .CreatedUnix}}{{svg "octicon-note" 16 "view-detail"}}
-
- {{.CsrfTokenHtml}} - -
-
+
+ {{.CsrfTokenHtml}} + +
+
-
- + + + + + + {{end}} + {{template "base/paginate" .}} diff --git a/templates/admin/repo/list.tmpl b/templates/admin/repo/list.tmpl index 3d09f2de2397..515ec78a346c 100644 --- a/templates/admin/repo/list.tmpl +++ b/templates/admin/repo/list.tmpl @@ -1,4 +1,4 @@ -{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin user")}} +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin")}}

{{.locale.Tr "admin.repos.repo_manage_panel"}} ({{.locale.Tr "admin.total" .Total}}) diff --git a/templates/admin/repo/unadopted.tmpl b/templates/admin/repo/unadopted.tmpl index 3e47447178c9..27898a185400 100644 --- a/templates/admin/repo/unadopted.tmpl +++ b/templates/admin/repo/unadopted.tmpl @@ -1,4 +1,4 @@ -{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin user")}} +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin")}}

{{.locale.Tr "admin.repos.unadopted"}} @@ -18,47 +18,44 @@ {{if .search}}
{{if .Dirs}} -
+
{{range $dirI, $dir := .Dirs}} -
-
- {{svg "octicon-file-directory-fill"}} - {{$dir}} -
- -