diff --git a/.drone.yml b/.drone.yml index 8a73e84a0..f2b34ef7e 100644 --- a/.drone.yml +++ b/.drone.yml @@ -561,7 +561,7 @@ steps: # TODO: We should probably build all dependencies into a test image - name: test-e2e - image: mcr.microsoft.com/playwright:v1.27.0-focal + image: mcr.microsoft.com/playwright:v1.27.1-focal commands: - curl -sLO https://go.dev/dl/go1.19.linux-amd64.tar.gz && tar -C /usr/local -xzf go1.19.linux-amd64.tar.gz - groupadd --gid 1001 gitea && useradd -m --gid 1001 --uid 1001 gitea diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 4dafc8f49..cd86b680e 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -254,7 +254,7 @@ rules: no-irregular-whitespace: [2] no-iterator: [2] no-label-var: [2] - no-labels: [2] + no-labels: [0] no-lone-blocks: [2] no-lonely-if: [0] no-loop-func: [0] @@ -333,7 +333,7 @@ rules: no-void: [2] no-warning-comments: [0] no-whitespace-before-property: [2] - no-with: [2] + no-with: [0] nonblock-statement-body-position: [2] object-curly-newline: [0] object-curly-spacing: [2, never] @@ -378,11 +378,11 @@ rules: sonarjs/no-duplicated-branches: [0] sonarjs/no-element-overwrite: [2] sonarjs/no-empty-collection: [2] - sonarjs/no-extra-arguments: [0] + sonarjs/no-extra-arguments: [2] sonarjs/no-gratuitous-expressions: [2] sonarjs/no-identical-conditions: [2] - sonarjs/no-identical-expressions: [0] - sonarjs/no-identical-functions: [0] + sonarjs/no-identical-expressions: [2] + sonarjs/no-identical-functions: [2, 5] sonarjs/no-ignored-return: [2] sonarjs/no-inverted-boolean-check: [2] sonarjs/no-nested-switch: [0] @@ -394,7 +394,7 @@ rules: sonarjs/no-small-switch: [0] sonarjs/no-unused-collection: [2] sonarjs/no-use-of-empty-return-value: [2] - sonarjs/no-useless-catch: [0] + sonarjs/no-useless-catch: [2] sonarjs/non-existent-operator: [2] sonarjs/prefer-immediate-return: [0] sonarjs/prefer-object-literal: [0] diff --git a/.stylelintrc.yaml b/.stylelintrc.yaml index 9bad55d37..342bf6a4e 100644 --- a/.stylelintrc.yaml +++ b/.stylelintrc.yaml @@ -16,6 +16,7 @@ rules: declaration-empty-line-before: null function-no-unknown: null hue-degree-notation: null + import-notation: string indentation: 2 max-line-length: null no-descending-specificity: null diff --git a/MAINTAINERS b/MAINTAINERS index 660f35607..d383b8b16 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -44,7 +44,6 @@ Janis Estelmann (@KN4CK3R) Steven Kriegler (@justusbunsi) Jimmy Praet (@jpraet) Leon Hofmeister (@delvh) -Gusted (@silentcodeg) Wim (@42wim) xinyu (@penlinux) diff --git a/Makefile b/Makefile index f1b6790dc..4ca346c63 100644 --- a/Makefile +++ b/Makefile @@ -100,7 +100,8 @@ LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(G LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64 -GO_PACKAGES ?= $(filter-out code.gitea.io/gitea/models/migrations code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./... | grep -v /vendor/)) +GO_PACKAGES ?= $(filter-out code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./... | grep -v /vendor/)) +GO_TEST_PACKAGES ?= $(filter-out $(shell $(GO) list code.gitea.io/gitea/models/migrations/...) code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./... | grep -v /vendor/)) FOMANTIC_WORK_DIR := web_src/fomantic @@ -366,7 +367,7 @@ test: test-frontend test-backend .PHONY: test-backend test-backend: @echo "Running go test with $(GOTESTFLAGS) -tags '$(TEST_TAGS)'..." - @$(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' $(GO_PACKAGES) + @$(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' $(GO_TEST_PACKAGES) .PHONY: test-frontend test-frontend: node_modules @@ -387,7 +388,7 @@ test-check: .PHONY: test\#% test\#%: @echo "Running go test with -tags '$(TEST_TAGS)'..." - @$(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -run $(subst .,/,$*) $(GO_PACKAGES) + @$(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -run $(subst .,/,$*) $(GO_TEST_PACKAGES) .PHONY: coverage coverage: @@ -398,7 +399,7 @@ coverage: .PHONY: unit-test-coverage unit-test-coverage: @echo "Running unit-test-coverage $(GOTESTFLAGS) -tags '$(TEST_TAGS)'..." - @$(GO) test $(GOTESTFLAGS) -timeout=20m -tags='$(TEST_TAGS)' -cover -coverprofile coverage.out $(GO_PACKAGES) && echo "\n==>\033[32m Ok\033[m\n" || exit 1 + @$(GO) test $(GOTESTFLAGS) -timeout=20m -tags='$(TEST_TAGS)' -cover -coverprofile coverage.out $(GO_TEST_PACKAGES) && echo "\n==>\033[32m Ok\033[m\n" || exit 1 .PHONY: tidy tidy: @@ -442,14 +443,7 @@ test-sqlite\#%: integrations.sqlite.test generate-ini-sqlite GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.sqlite.test -test.run $(subst .,/,$*) .PHONY: test-sqlite-migration -test-sqlite-migration: migrations.sqlite.test migrations.individual.sqlite.test generate-ini-sqlite - GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./migrations.sqlite.test - GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./migrations.individual.sqlite.test - -.PHONY: test-sqlite-migration\#% -test-sqlite-migration\#%: migrations.sqlite.test migrations.individual.sqlite.test generate-ini-sqlite - GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./migrations.individual.sqlite.test -test.run $(subst .,/,$*) - +test-sqlite-migration: migrations.sqlite.test migrations.individual.sqlite.test generate-ini-mysql: sed -e 's|{{TEST_MYSQL_HOST}}|${TEST_MYSQL_HOST}|g' \ @@ -470,9 +464,7 @@ test-mysql\#%: integrations.mysql.test generate-ini-mysql GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.mysql.test -test.run $(subst .,/,$*) .PHONY: test-mysql-migration -test-mysql-migration: migrations.mysql.test migrations.individual.mysql.test generate-ini-mysql - GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./migrations.mysql.test - GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./migrations.individual.mysql.test +test-mysql-migration: migrations.mysql.test migrations.individual.mysql.test generate-ini-mysql8: sed -e 's|{{TEST_MYSQL8_HOST}}|${TEST_MYSQL8_HOST}|g' \ @@ -493,9 +485,7 @@ test-mysql8\#%: integrations.mysql8.test generate-ini-mysql8 GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./integrations.mysql8.test -test.run $(subst .,/,$*) .PHONY: test-mysql8-migration -test-mysql8-migration: migrations.mysql8.test migrations.individual.mysql8.test generate-ini-mysql8 - GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./migrations.mysql8.test - GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./migrations.individual.mysql8.test +test-mysql8-migration: migrations.mysql8.test migrations.individual.mysql8.test generate-ini-pgsql: sed -e 's|{{TEST_PGSQL_HOST}}|${TEST_PGSQL_HOST}|g' \ @@ -517,9 +507,7 @@ test-pgsql\#%: integrations.pgsql.test generate-ini-pgsql GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./integrations.pgsql.test -test.run $(subst .,/,$*) .PHONY: test-pgsql-migration -test-pgsql-migration: migrations.pgsql.test migrations.individual.pgsql.test generate-ini-pgsql - GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./migrations.pgsql.test - GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./migrations.individual.pgsql.test +test-pgsql-migration: migrations.pgsql.test migrations.individual.pgsql.test generate-ini-mssql: sed -e 's|{{TEST_MSSQL_HOST}}|${TEST_MSSQL_HOST}|g' \ @@ -540,9 +528,7 @@ test-mssql\#%: integrations.mssql.test generate-ini-mssql GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./integrations.mssql.test -test.run $(subst .,/,$*) .PHONY: test-mssql-migration -test-mssql-migration: migrations.mssql.test migrations.individual.mssql.test generate-ini-mssql - GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./migrations.mssql.test -test.failfast - GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./migrations.individual.mssql.test -test.failfast +test-mssql-migration: migrations.mssql.test migrations.individual.mssql.test .PHONY: playwright playwright: $(PLAYWRIGHT_DIR) @@ -637,50 +623,82 @@ integrations.sqlite.test: git-check $(GO_SOURCES) $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.sqlite.test -tags '$(TEST_TAGS)' integrations.cover.test: git-check $(GO_SOURCES) - $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -coverpkg $(shell echo $(GO_PACKAGES) | tr ' ' ',') -o integrations.cover.test + $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -coverpkg $(shell echo $(GO_TEST_PACKAGES) | tr ' ' ',') -o integrations.cover.test integrations.cover.sqlite.test: git-check $(GO_SOURCES) - $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -coverpkg $(shell echo $(GO_PACKAGES) | tr ' ' ',') -o integrations.cover.sqlite.test -tags '$(TEST_TAGS)' + $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -coverpkg $(shell echo $(GO_TEST_PACKAGES) | tr ' ' ',') -o integrations.cover.sqlite.test -tags '$(TEST_TAGS)' .PHONY: migrations.mysql.test -migrations.mysql.test: $(GO_SOURCES) +migrations.mysql.test: $(GO_SOURCES) generate-ini-mysql $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mysql.test + GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./migrations.mysql.test .PHONY: migrations.mysql8.test -migrations.mysql8.test: $(GO_SOURCES) +migrations.mysql8.test: $(GO_SOURCES) generate-ini-mysql8 $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mysql8.test + GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./migrations.mysql8.test .PHONY: migrations.pgsql.test -migrations.pgsql.test: $(GO_SOURCES) +migrations.pgsql.test: $(GO_SOURCES) generate-ini-pgsql $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.pgsql.test + GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./migrations.pgsql.test .PHONY: migrations.mssql.test -migrations.mssql.test: $(GO_SOURCES) +migrations.mssql.test: $(GO_SOURCES) generate-ini-mssql $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mssql.test + GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./migrations.mssql.test .PHONY: migrations.sqlite.test -migrations.sqlite.test: $(GO_SOURCES) +migrations.sqlite.test: $(GO_SOURCES) generate-ini-sqlite $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.sqlite.test -tags '$(TEST_TAGS)' + GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./migrations.sqlite.test .PHONY: migrations.individual.mysql.test migrations.individual.mysql.test: $(GO_SOURCES) - $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/models/migrations -o migrations.individual.mysql.test + for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \ + GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \ + done .PHONY: migrations.individual.mysql8.test migrations.individual.mysql8.test: $(GO_SOURCES) - $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/models/migrations -o migrations.individual.mysql8.test + for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \ + GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \ + done + +.PHONY: migrations.individual.mysql8.test\#% +migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite + GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$* .PHONY: migrations.individual.pgsql.test migrations.individual.pgsql.test: $(GO_SOURCES) - $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/models/migrations -o migrations.individual.pgsql.test + for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \ + GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \ + done + +.PHONY: migrations.individual.pgsql.test\#% +migrations.individual.pgsql.test\#%: $(GO_SOURCES) generate-ini-pgsql + GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$* + .PHONY: migrations.individual.mssql.test -migrations.individual.mssql.test: $(GO_SOURCES) - $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/models/migrations -o migrations.individual.mssql.test +migrations.individual.mssql.test: $(GO_SOURCES) generate-ini-mssql + for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \ + GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg -test.failfast; \ + done + +.PHONY: migrations.individual.mssql.test\#% +migrations.individual.mssql.test\#%: $(GO_SOURCES) generate-ini-mssql + GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$* .PHONY: migrations.individual.sqlite.test -migrations.individual.sqlite.test: $(GO_SOURCES) - $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/models/migrations -o migrations.individual.sqlite.test -tags '$(TEST_TAGS)' +migrations.individual.sqlite.test: $(GO_SOURCES) generate-ini-sqlite + for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \ + GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \ + done + +.PHONY: migrations.individual.sqlite.test\#% +migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite + GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$* e2e.mysql.test: $(GO_SOURCES) $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.mysql.test diff --git a/assets/go-licenses.json b/assets/go-licenses.json index db0b00865..c4b62475f 100644 --- a/assets/go-licenses.json +++ b/assets/go-licenses.json @@ -244,6 +244,11 @@ "path": "github.com/cpuguy83/go-md2man/v2/md2man/LICENSE.md", "licenseText": "The MIT License (MIT)\n\nCopyright (c) 2014 Brian Goff\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n" }, + { + "name": "github.com/davecgh/go-spew/spew", + "path": "github.com/davecgh/go-spew/spew/LICENSE", + "licenseText": "ISC License\n\nCopyright (c) 2012-2016 Dave Collins \u003cdave@davec.name\u003e\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n" + }, { "name": "github.com/denisenkom/go-mssqldb", "path": "github.com/denisenkom/go-mssqldb/LICENSE.txt", @@ -369,6 +374,11 @@ "path": "github.com/go-sql-driver/mysql/LICENSE", "licenseText": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\"\n means each individual or legal entity that creates, contributes to\n the creation of, or owns Covered Software.\n\n1.2. \"Contributor Version\"\n means the combination of the Contributions of others (if any) used\n by a Contributor and that particular Contributor's Contribution.\n\n1.3. \"Contribution\"\n means Covered Software of a particular Contributor.\n\n1.4. \"Covered Software\"\n means Source Code Form to which the initial Contributor has attached\n the notice in Exhibit A, the Executable Form of such Source Code\n Form, and Modifications of such Source Code Form, in each case\n including portions thereof.\n\n1.5. \"Incompatible With Secondary Licenses\"\n means\n\n (a) that the initial Contributor has attached the notice described\n in Exhibit B to the Covered Software; or\n\n (b) that the Covered Software was made available under the terms of\n version 1.1 or earlier of the License, but not also under the\n terms of a Secondary License.\n\n1.6. \"Executable Form\"\n means any form of the work other than Source Code Form.\n\n1.7. \"Larger Work\"\n means a work that combines Covered Software with other material, in \n a separate file or files, that is not Covered Software.\n\n1.8. \"License\"\n means this document.\n\n1.9. \"Licensable\"\n means having the right to grant, to the maximum extent possible,\n whether at the time of the initial grant or subsequently, any and\n all of the rights conveyed by this License.\n\n1.10. \"Modifications\"\n means any of the following:\n\n (a) any file in Source Code Form that results from an addition to,\n deletion from, or modification of the contents of Covered\n Software; or\n\n (b) any new file in Source Code Form that contains any Covered\n Software.\n\n1.11. \"Patent Claims\" of a Contributor\n means any patent claim(s), including without limitation, method,\n process, and apparatus claims, in any patent Licensable by such\n Contributor that would be infringed, but for the grant of the\n License, by the making, using, selling, offering for sale, having\n made, import, or transfer of either its Contributions or its\n Contributor Version.\n\n1.12. \"Secondary License\"\n means either the GNU General Public License, Version 2.0, the GNU\n Lesser General Public License, Version 2.1, the GNU Affero General\n Public License, Version 3.0, or any later versions of those\n licenses.\n\n1.13. \"Source Code Form\"\n means the form of the work preferred for making modifications.\n\n1.14. \"You\" (or \"Your\")\n means an individual or a legal entity exercising rights under this\n License. For legal entities, \"You\" includes any entity that\n controls, is controlled by, or is under common control with You. For\n purposes of this definition, \"control\" means (a) the power, direct\n or indirect, to cause the direction or management of such entity,\n whether by contract or otherwise, or (b) ownership of more than\n fifty percent (50%) of the outstanding shares or beneficial\n ownership of such entity.\n\n2. License Grants and Conditions\n--------------------------------\n\n2.1. Grants\n\nEach Contributor hereby grants You a world-wide, royalty-free,\nnon-exclusive license:\n\n(a) under intellectual property rights (other than patent or trademark)\n Licensable by such Contributor to use, reproduce, make available,\n modify, display, perform, distribute, and otherwise exploit its\n Contributions, either on an unmodified basis, with Modifications, or\n as part of a Larger Work; and\n\n(b) under Patent Claims of such Contributor to make, use, sell, offer\n for sale, have made, import, and otherwise transfer either its\n Contributions or its Contributor Version.\n\n2.2. Effective Date\n\nThe licenses granted in Section 2.1 with respect to any Contribution\nbecome effective for each Contribution on the date the Contributor first\ndistributes such Contribution.\n\n2.3. Limitations on Grant Scope\n\nThe licenses granted in this Section 2 are the only rights granted under\nthis License. No additional rights or licenses will be implied from the\ndistribution or licensing of Covered Software under this License.\nNotwithstanding Section 2.1(b) above, no patent license is granted by a\nContributor:\n\n(a) for any code that a Contributor has removed from Covered Software;\n or\n\n(b) for infringements caused by: (i) Your and any other third party's\n modifications of Covered Software, or (ii) the combination of its\n Contributions with other software (except as part of its Contributor\n Version); or\n\n(c) under Patent Claims infringed by Covered Software in the absence of\n its Contributions.\n\nThis License does not grant any rights in the trademarks, service marks,\nor logos of any Contributor (except as may be necessary to comply with\nthe notice requirements in Section 3.4).\n\n2.4. Subsequent Licenses\n\nNo Contributor makes additional grants as a result of Your choice to\ndistribute the Covered Software under a subsequent version of this\nLicense (see Section 10.2) or under the terms of a Secondary License (if\npermitted under the terms of Section 3.3).\n\n2.5. Representation\n\nEach Contributor represents that the Contributor believes its\nContributions are its original creation(s) or it has sufficient rights\nto grant the rights to its Contributions conveyed by this License.\n\n2.6. Fair Use\n\nThis License is not intended to limit any rights You have under\napplicable copyright doctrines of fair use, fair dealing, or other\nequivalents.\n\n2.7. Conditions\n\nSections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted\nin Section 2.1.\n\n3. Responsibilities\n-------------------\n\n3.1. Distribution of Source Form\n\nAll distribution of Covered Software in Source Code Form, including any\nModifications that You create or to which You contribute, must be under\nthe terms of this License. You must inform recipients that the Source\nCode Form of the Covered Software is governed by the terms of this\nLicense, and how they can obtain a copy of this License. You may not\nattempt to alter or restrict the recipients' rights in the Source Code\nForm.\n\n3.2. Distribution of Executable Form\n\nIf You distribute Covered Software in Executable Form then:\n\n(a) such Covered Software must also be made available in Source Code\n Form, as described in Section 3.1, and You must inform recipients of\n the Executable Form how they can obtain a copy of such Source Code\n Form by reasonable means in a timely manner, at a charge no more\n than the cost of distribution to the recipient; and\n\n(b) You may distribute such Executable Form under the terms of this\n License, or sublicense it under different terms, provided that the\n license for the Executable Form does not attempt to limit or alter\n the recipients' rights in the Source Code Form under this License.\n\n3.3. Distribution of a Larger Work\n\nYou may create and distribute a Larger Work under terms of Your choice,\nprovided that You also comply with the requirements of this License for\nthe Covered Software. If the Larger Work is a combination of Covered\nSoftware with a work governed by one or more Secondary Licenses, and the\nCovered Software is not Incompatible With Secondary Licenses, this\nLicense permits You to additionally distribute such Covered Software\nunder the terms of such Secondary License(s), so that the recipient of\nthe Larger Work may, at their option, further distribute the Covered\nSoftware under the terms of either this License or such Secondary\nLicense(s).\n\n3.4. Notices\n\nYou may not remove or alter the substance of any license notices\n(including copyright notices, patent notices, disclaimers of warranty,\nor limitations of liability) contained within the Source Code Form of\nthe Covered Software, except that You may alter any license notices to\nthe extent required to remedy known factual inaccuracies.\n\n3.5. Application of Additional Terms\n\nYou may choose to offer, and to charge a fee for, warranty, support,\nindemnity or liability obligations to one or more recipients of Covered\nSoftware. However, You may do so only on Your own behalf, and not on\nbehalf of any Contributor. You must make it absolutely clear that any\nsuch warranty, support, indemnity, or liability obligation is offered by\nYou alone, and You hereby agree to indemnify every Contributor for any\nliability incurred by such Contributor as a result of warranty, support,\nindemnity or liability terms You offer. You may include additional\ndisclaimers of warranty and limitations of liability specific to any\njurisdiction.\n\n4. Inability to Comply Due to Statute or Regulation\n---------------------------------------------------\n\nIf it is impossible for You to comply with any of the terms of this\nLicense with respect to some or all of the Covered Software due to\nstatute, judicial order, or regulation then You must: (a) comply with\nthe terms of this License to the maximum extent possible; and (b)\ndescribe the limitations and the code they affect. Such description must\nbe placed in a text file included with all distributions of the Covered\nSoftware under this License. Except to the extent prohibited by statute\nor regulation, such description must be sufficiently detailed for a\nrecipient of ordinary skill to be able to understand it.\n\n5. Termination\n--------------\n\n5.1. The rights granted under this License will terminate automatically\nif You fail to comply with any of its terms. However, if You become\ncompliant, then the rights granted under this License from a particular\nContributor are reinstated (a) provisionally, unless and until such\nContributor explicitly and finally terminates Your grants, and (b) on an\nongoing basis, if such Contributor fails to notify You of the\nnon-compliance by some reasonable means prior to 60 days after You have\ncome back into compliance. Moreover, Your grants from a particular\nContributor are reinstated on an ongoing basis if such Contributor\nnotifies You of the non-compliance by some reasonable means, this is the\nfirst time You have received notice of non-compliance with this License\nfrom such Contributor, and You become compliant prior to 30 days after\nYour receipt of the notice.\n\n5.2. If You initiate litigation against any entity by asserting a patent\ninfringement claim (excluding declaratory judgment actions,\ncounter-claims, and cross-claims) alleging that a Contributor Version\ndirectly or indirectly infringes any patent, then the rights granted to\nYou by any and all Contributors for the Covered Software under Section\n2.1 of this License shall terminate.\n\n5.3. In the event of termination under Sections 5.1 or 5.2 above, all\nend user license agreements (excluding distributors and resellers) which\nhave been validly granted by You or Your distributors under this License\nprior to termination shall survive termination.\n\n************************************************************************\n* *\n* 6. Disclaimer of Warranty *\n* ------------------------- *\n* *\n* Covered Software is provided under this License on an \"as is\" *\n* basis, without warranty of any kind, either expressed, implied, or *\n* statutory, including, without limitation, warranties that the *\n* Covered Software is free of defects, merchantable, fit for a *\n* particular purpose or non-infringing. The entire risk as to the *\n* quality and performance of the Covered Software is with You. *\n* Should any Covered Software prove defective in any respect, You *\n* (not any Contributor) assume the cost of any necessary servicing, *\n* repair, or correction. This disclaimer of warranty constitutes an *\n* essential part of this License. No use of any Covered Software is *\n* authorized under this License except under this disclaimer. *\n* *\n************************************************************************\n\n************************************************************************\n* *\n* 7. Limitation of Liability *\n* -------------------------- *\n* *\n* Under no circumstances and under no legal theory, whether tort *\n* (including negligence), contract, or otherwise, shall any *\n* Contributor, or anyone who distributes Covered Software as *\n* permitted above, be liable to You for any direct, indirect, *\n* special, incidental, or consequential damages of any character *\n* including, without limitation, damages for lost profits, loss of *\n* goodwill, work stoppage, computer failure or malfunction, or any *\n* and all other commercial damages or losses, even if such party *\n* shall have been informed of the possibility of such damages. This *\n* limitation of liability shall not apply to liability for death or *\n* personal injury resulting from such party's negligence to the *\n* extent applicable law prohibits such limitation. Some *\n* jurisdictions do not allow the exclusion or limitation of *\n* incidental or consequential damages, so this exclusion and *\n* limitation may not apply to You. *\n* *\n************************************************************************\n\n8. Litigation\n-------------\n\nAny litigation relating to this License may be brought only in the\ncourts of a jurisdiction where the defendant maintains its principal\nplace of business and such litigation shall be governed by laws of that\njurisdiction, without reference to its conflict-of-law provisions.\nNothing in this Section shall prevent a party's ability to bring\ncross-claims or counter-claims.\n\n9. Miscellaneous\n----------------\n\nThis License represents the complete agreement concerning the subject\nmatter hereof. If any provision of this License is held to be\nunenforceable, such provision shall be reformed only to the extent\nnecessary to make it enforceable. Any law or regulation which provides\nthat the language of a contract shall be construed against the drafter\nshall not be used to construe this License against a Contributor.\n\n10. Versions of the License\n---------------------------\n\n10.1. New Versions\n\nMozilla Foundation is the license steward. Except as provided in Section\n10.3, no one other than the license steward has the right to modify or\npublish new versions of this License. Each version will be given a\ndistinguishing version number.\n\n10.2. Effect of New Versions\n\nYou may distribute the Covered Software under the terms of the version\nof the License under which You originally received the Covered Software,\nor under the terms of any subsequent version published by the license\nsteward.\n\n10.3. Modified Versions\n\nIf you create software not governed by this License, and you want to\ncreate a new license for such software, you may create and use a\nmodified version of this License if you rename the license and remove\nany references to the name of the license steward (except to note that\nsuch modified license differs from this License).\n\n10.4. Distributing Source Code Form that is Incompatible With Secondary\nLicenses\n\nIf You choose to distribute Source Code Form that is Incompatible With\nSecondary Licenses under the terms of this version of the License, the\nnotice described in Exhibit B of this License must be attached.\n\nExhibit A - Source Code Form License Notice\n-------------------------------------------\n\n This Source Code Form is subject to the terms of the Mozilla Public\n License, v. 2.0. If a copy of the MPL was not distributed with this\n file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nIf it is not possible or desirable to put the notice in a particular\nfile, then You may include the notice in a location (such as a LICENSE\nfile in a relevant directory) where a recipient would be likely to look\nfor such a notice.\n\nYou may add additional accurate notices of copyright ownership.\n\nExhibit B - \"Incompatible With Secondary Licenses\" Notice\n---------------------------------------------------------\n\n This Source Code Form is \"Incompatible With Secondary Licenses\", as\n defined by the Mozilla Public License, v. 2.0.\n" }, + { + "name": "github.com/go-testfixtures/testfixtures/v3", + "path": "github.com/go-testfixtures/testfixtures/v3/LICENSE", + "licenseText": "The MIT License (MIT)\n\nCopyright (c) 2016 Andrey Nering\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n" + }, { "name": "github.com/gobwas/glob", "path": "github.com/gobwas/glob/LICENSE", @@ -689,6 +699,11 @@ "path": "github.com/pkg/errors/LICENSE", "licenseText": "Copyright (c) 2015, Dave Cheney \u003cdave@cheney.net\u003e\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" }, + { + "name": "github.com/pmezard/go-difflib/difflib", + "path": "github.com/pmezard/go-difflib/difflib/LICENSE", + "licenseText": "Copyright (c) 2013, Patrick Mezard\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n Redistributions in binary form must reproduce the above copyright\nnotice, this list of conditions and the following disclaimer in the\ndocumentation and/or other materials provided with the distribution.\n The names of its contributors may not be used to endorse or promote\nproducts derived from this software without specific prior written\npermission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\nIS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\nTO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\nPARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nHOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" + }, { "name": "github.com/pquerna/otp", "path": "github.com/pquerna/otp/LICENSE", @@ -744,6 +759,11 @@ "path": "github.com/ssor/bom/LICENSE", "licenseText": "MIT License\n\nCopyright (c) 2017 Asher\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n" }, + { + "name": "github.com/stretchr/testify/assert", + "path": "github.com/stretchr/testify/assert/LICENSE", + "licenseText": "MIT License\n\nCopyright (c) 2012-2020 Mat Ryer, Tyler Bunnell and contributors.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n" + }, { "name": "github.com/syndtr/goleveldb/leveldb", "path": "github.com/syndtr/goleveldb/leveldb/LICENSE", diff --git a/cmd/doctor.go b/cmd/doctor.go index a11848405..d05a0a98d 100644 --- a/cmd/doctor.go +++ b/cmd/doctor.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/migrations" + migrate_base "code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/modules/doctor" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -114,7 +115,7 @@ func runRecreateTable(ctx *cli.Context) error { if err != nil { return err } - recreateTables := migrations.RecreateTables(beans...) + recreateTables := migrate_base.RecreateTables(beans...) return db.InitEngineWithMigration(stdCtx, func(x *xorm.Engine) error { if err := migrations.EnsureUpToDate(x); err != nil { diff --git a/cmd/migrate_storage.go b/cmd/migrate_storage.go index a283f9140..b6af5b96e 100644 --- a/cmd/migrate_storage.go +++ b/cmd/migrate_storage.go @@ -83,35 +83,35 @@ var CmdMigrateStorage = cli.Command{ } func migrateAttachments(ctx context.Context, dstStorage storage.ObjectStorage) error { - return db.IterateObjects(ctx, func(attach *repo_model.Attachment) error { + return db.Iterate(ctx, nil, func(ctx context.Context, attach *repo_model.Attachment) error { _, err := storage.Copy(dstStorage, attach.RelativePath(), storage.Attachments, attach.RelativePath()) return err }) } func migrateLFS(ctx context.Context, dstStorage storage.ObjectStorage) error { - return db.IterateObjects(ctx, func(mo *git_model.LFSMetaObject) error { + return db.Iterate(ctx, nil, func(ctx context.Context, mo *git_model.LFSMetaObject) error { _, err := storage.Copy(dstStorage, mo.RelativePath(), storage.LFS, mo.RelativePath()) return err }) } func migrateAvatars(ctx context.Context, dstStorage storage.ObjectStorage) error { - return db.IterateObjects(ctx, func(user *user_model.User) error { + return db.Iterate(ctx, nil, func(ctx context.Context, user *user_model.User) error { _, err := storage.Copy(dstStorage, user.CustomAvatarRelativePath(), storage.Avatars, user.CustomAvatarRelativePath()) return err }) } func migrateRepoAvatars(ctx context.Context, dstStorage storage.ObjectStorage) error { - return db.IterateObjects(ctx, func(repo *repo_model.Repository) error { + return db.Iterate(ctx, nil, func(ctx context.Context, repo *repo_model.Repository) error { _, err := storage.Copy(dstStorage, repo.CustomAvatarRelativePath(), storage.RepoAvatars, repo.CustomAvatarRelativePath()) return err }) } func migrateRepoArchivers(ctx context.Context, dstStorage storage.ObjectStorage) error { - return db.IterateObjects(ctx, func(archiver *repo_model.RepoArchiver) error { + return db.Iterate(ctx, nil, func(ctx context.Context, archiver *repo_model.RepoArchiver) error { p := archiver.RelativePath() _, err := storage.Copy(dstStorage, p, storage.RepoArchives, p) return err @@ -119,7 +119,7 @@ func migrateRepoArchivers(ctx context.Context, dstStorage storage.ObjectStorage) } func migratePackages(ctx context.Context, dstStorage storage.ObjectStorage) error { - return db.IterateObjects(ctx, func(pb *packages_model.PackageBlob) error { + return db.Iterate(ctx, nil, func(ctx context.Context, pb *packages_model.PackageBlob) error { p := packages_module.KeyToRelativePath(packages_module.BlobHash256Key(pb.HashSHA256)) _, err := storage.Copy(dstStorage, p, storage.Packages, p) return err diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index c6feae8f5..ef247fa78 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -2196,7 +2196,8 @@ ROUTER = console ;SHOW_FOOTER_VERSION = true ;; Show template execution time in the footer ;SHOW_FOOTER_TEMPLATE_LOAD_TIME = true - +;; Generate sitemap. Defaults to `true`. +; ENABLE_SITEMAP = true ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/docker/root/etc/s6/openssh/setup b/docker/root/etc/s6/openssh/setup index d4b9b9cd3..f43544d65 100755 --- a/docker/root/etc/s6/openssh/setup +++ b/docker/root/etc/s6/openssh/setup @@ -14,11 +14,6 @@ if [ ! -f /data/ssh/ssh_host_rsa_key ]; then ssh-keygen -t rsa -b 2048 -f /data/ssh/ssh_host_rsa_key -N "" > /dev/null fi -if [ ! -f /data/ssh/ssh_host_dsa_key ]; then - echo "Generating /data/ssh/ssh_host_dsa_key..." - ssh-keygen -t dsa -f /data/ssh/ssh_host_dsa_key -N "" > /dev/null -fi - if [ ! -f /data/ssh/ssh_host_ecdsa_key ]; then echo "Generating /data/ssh/ssh_host_ecdsa_key..." ssh-keygen -t ecdsa -b 256 -f /data/ssh/ssh_host_ecdsa_key -N "" > /dev/null @@ -36,17 +31,12 @@ if [ -e /data/ssh/ssh_host_ecdsa_cert ]; then SSH_ECDSA_CERT=${SSH_ECDSA_CERT:-"/data/ssh/ssh_host_ecdsa_cert"} fi -if [ -e /data/ssh/ssh_host_dsa_cert ]; then - SSH_DSA_CERT=${SSH_DSA_CERT:-"/data/ssh/ssh_host_dsa_cert"} -fi - if [ -d /etc/ssh ]; then SSH_PORT=${SSH_PORT:-"22"} \ SSH_LISTEN_PORT=${SSH_LISTEN_PORT:-"${SSH_PORT}"} \ SSH_ED25519_CERT="${SSH_ED25519_CERT:+"HostCertificate "}${SSH_ED25519_CERT}" \ SSH_RSA_CERT="${SSH_RSA_CERT:+"HostCertificate "}${SSH_RSA_CERT}" \ SSH_ECDSA_CERT="${SSH_ECDSA_CERT:+"HostCertificate "}${SSH_ECDSA_CERT}" \ - SSH_DSA_CERT="${SSH_DSA_CERT:+"HostCertificate "}${SSH_DSA_CERT}" \ SSH_MAX_STARTUPS="${SSH_MAX_STARTUPS:+"MaxStartups "}${SSH_MAX_STARTUPS}" \ SSH_MAX_SESSIONS="${SSH_MAX_SESSIONS:+"MaxSessions "}${SSH_MAX_SESSIONS}" \ SSH_INCLUDE_FILE="${SSH_INCLUDE_FILE:+"Include "}${SSH_INCLUDE_FILE}" \ diff --git a/docker/root/etc/templates/sshd_config b/docker/root/etc/templates/sshd_config index 17c2c397b..033c43465 100644 --- a/docker/root/etc/templates/sshd_config +++ b/docker/root/etc/templates/sshd_config @@ -16,8 +16,6 @@ HostKey /data/ssh/ssh_host_rsa_key ${SSH_RSA_CERT} HostKey /data/ssh/ssh_host_ecdsa_key ${SSH_ECDSA_CERT} -HostKey /data/ssh/ssh_host_dsa_key -${SSH_DSA_CERT} AuthorizedKeysFile .ssh/authorized_keys AuthorizedPrincipalsFile .ssh/authorized_principals diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md index 3fd853fb1..df1911934 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md +++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md @@ -810,9 +810,9 @@ Default templates for project boards: - `STACKTRACE_LEVEL`: **log.STACKTRACE_LEVEL**: Sets the log level at which to log stack traces. - `MODE`: **name**: Sets the mode of this sublogger - Defaults to the provided subsection name. This allows you to have two different file loggers at different levels. - `EXPRESSION`: **""**: A regular expression to match either the function name, file or message. Defaults to empty. Only log messages that match the expression will be saved in the logger. -- `FLAGS`: **stdflags**: A comma separated string representing the log flags. Defaults to `stdflags` which represents the prefix: `2009/01/23 01:23:23 ...a/b/c/d.go:23:runtime.Caller() [I]: message`. `none` means don't prefix log lines. See `modules/log/base.go` for more information. +- `FLAGS`: **stdflags**: A comma separated string representing the log flags. Defaults to `stdflags` which represents the prefix: `2009/01/23 01:23:23 ...a/b/c/d.go:23:runtime.Caller() [I]: message`. `none` means don't prefix log lines. See `modules/log/flags.go` for more information. - `PREFIX`: **""**: An additional prefix for every log line in this logger. Defaults to empty. -- `COLORIZE`: **false**: Colorize the log lines by default +- `COLORIZE`: **false**: Whether to colorize the log lines ### Console log mode (`log.console`, `log.console.*`, or `MODE=console`) @@ -1233,3 +1233,4 @@ PROXY_HOSTS = *.github.com - `SHOW_FOOTER_BRANDING`: **false**: Show Gitea branding in the footer. - `SHOW_FOOTER_VERSION`: **true**: Show Gitea and Go version information in the footer. - `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: Show time of template execution in the footer. +- `ENABLE_SITEMAP`: **true**: Generate sitemap. diff --git a/docs/content/doc/advanced/hacking-on-gitea.zh-cn.md b/docs/content/doc/advanced/hacking-on-gitea.zh-cn.md deleted file mode 100644 index 7ad8019c5..000000000 --- a/docs/content/doc/advanced/hacking-on-gitea.zh-cn.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -date: "2016-12-01T16:00:00+02:00" -title: "加入 Gitea 开源" -slug: "hacking-on-gitea" -weight: 10 -toc: false -draft: false -menu: - sidebar: - parent: "advanced" - name: "加入 Gitea 开源" - weight: 10 - identifier: "hacking-on-gitea" ---- - -# Hacking on Gitea - -首先你需要一些运行环境,这和 [从源代码安装]({{< relref "from-source.zh-cn.md" >}}) 相同,如果你还没有设置好,可以先阅读那个章节。 - -如果你想为 Gitea 贡献代码,你需要 Fork 这个项目并且以 `master` 为开发分支。Gitea 使用 Govendor -来管理依赖,因此所有依赖项都被工具自动 copy 在 vendor 子目录下。用下面的命令来下载源码: - -``` -go get -d code.gitea.io/gitea -``` - -然后你可以在 Github 上 fork [Gitea 项目](https://github.com/go-gitea/gitea),之后可以通过下面的命令进入源码目录: - -``` -cd $GOPATH/src/code.gitea.io/gitea -``` - -要创建 pull requests 你还需要在源码中新增一个 remote 指向你 Fork 的地址,直接推送到 origin 的话会告诉你没有写权限: - -``` -git remote rename origin upstream -git remote add origin git@github.com:/gitea.git -git fetch --all --prune -``` - -然后你就可以开始开发了。你可以看一下 `Makefile` 的内容。`make test` 可以运行测试程序, `make build` 将生成一个 `gitea` 可运行文件在根目录。如果你的提交比较复杂,尽量多写一些单元测试代码。 - -好了,到这里你已经设置好了所有的开发 Gitea 所需的环境。欢迎成为 Gitea 的 Contributor。 diff --git a/docs/content/doc/advanced/mail-templates-us.md b/docs/content/doc/advanced/mail-templates.en-us.md similarity index 100% rename from docs/content/doc/advanced/mail-templates-us.md rename to docs/content/doc/advanced/mail-templates.en-us.md diff --git a/docs/content/doc/advanced/make.fr-fr.md b/docs/content/doc/advanced/make.fr-fr.md deleted file mode 100644 index f30b709f0..000000000 --- a/docs/content/doc/advanced/make.fr-fr.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -date: "2017-08-23T09:00:00+02:00" -title: "Make" -slug: "make" -weight: 10 -toc: false -draft: false -menu: - sidebar: - parent: "advanced" - name: "Make" - weight: 30 - identifier: "make" ---- - -# Make - -Gitea fait largement usage de Make pour automatiser les tâches et avoir un développement plus rapide. Ce guide explique comment installer Make. - -### Linux - -Vous pouvez installer Make avec votre gestionnaire de paquetages - -Depuis Ubuntu/Debian: - -```bash -sudo apt-get install build-essential -``` - -Depuis Fedora/RHEL/CentOS: - -```bash -sudo yum install make -``` - -### Windows - -Si vous utilisez Windows, vous pouvez télécharger une des versions suivantes de Make: - -- [Simple binaire](http://www.equation.com/servlet/equation.cmd?fa=make). Copiez-le quelque part et mettez à jour `PATH`. - - [32-bits version](ftp://ftp.equation.com/make/32/make.exe) - - [64-bits version](ftp://ftp.equation.com/make/64/make.exe) -- [MinGW](http://www.mingw.org/) inclut un _build_. Le fichier binaire est nommé `mingw32-make.exe` plutôt que `make.exe`. Ajoutez le dossier `bin` à votre `PATH`. -- [Chocolatey package](https://chocolatey.org/packages/make). Exécutez `choco install make`. diff --git a/docs/content/doc/advanced/make.zh-cn.md b/docs/content/doc/advanced/make.zh-cn.md deleted file mode 100644 index 2491dbe23..000000000 --- a/docs/content/doc/advanced/make.zh-cn.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -date: "2017-01-14T11:00:00-02:00" -title: "Make 安装" -slug: "make" -weight: 10 -toc: false -draft: false -menu: - sidebar: - parent: "advanced" - name: "Make 安装" - weight: 30 - identifier: "make" ---- - -# 安装 Make - -Gitea 大量使用了 Make 工具来自动执行任务并改进开发,本文将介绍如何安装 Make。 - -### 在 Linux 环境下 - -可以使用包管理工具来安装 Make。 - -Ubuntu/Debian 环境,执行以下命令: - -```bash -sudo apt-get install make -``` - -Fedora/RHEL/CentOS,执行以下命令: - -```bash -sudo yum install make -``` - -### 在 Windows 环境下 - -您可以参照以下三种方案在 Windows 环境安装 Make: - -- 直接使用 [exe文件](http://www.equation.com/servlet/equation.cmd?fa=make):将适合您系统的exe文件拷贝到某处并添加至环境变量 `PATH` 中。 - - [32 位版本](ftp://ftp.equation.com/make/32/make.exe) - - [64 位版本](ftp://ftp.equation.com/make/64/make.exe) -- 使用 [MinGW](http://www.mingw.org/) 工具: - - 此处使用二进制文件 `mingw32-make.exe` 替代前面提到的 `make.exe`文件。同样您需要将包含此exe文件的 `bin` 目录添加至环境变量 `PATH`中。 -- 通过 [Chocolatey](https://chocolatey.org/packages/make) 安装: 执行 `choco install make` 命令即可。 diff --git a/docs/content/doc/advanced/third-party-tools.zh-cn.md b/docs/content/doc/advanced/third-party-tools.zh-cn.md deleted file mode 100644 index e961e9ec1..000000000 --- a/docs/content/doc/advanced/third-party-tools.zh-cn.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -date: "2019-03-11T21:45:00+00:00" -title: "高级: 第三方工具" -slug: "third-party-tools" -weight: 50 -toc: false -draft: false -menu: - sidebar: - parent: "advanced" - name: "第三方工具" - weight: 50 - identifier: "third-party-tools" ---- - -# 第三方工具列表 - -**注意:** 这些工具并没有经过Gitea的检验,在这里列出它们只是为了便捷. - -*此列表并不是完整的列表,可以随时咨询如何添加!* - -### 持续集成 - -[BuildKite 连接器](https://github.com/techknowlogick/gitea-buildkite-connector) -[Jenkins 插件](https://github.com/jenkinsci/gitea-plugin) -[Gitea搭配Drone](https://docs.drone.io/installation/gitea) - -### 迁移 - -[Gitea安装脚本](https://git.coolaj86.com/coolaj86/gitea-installer.sh) -[GitHub迁移](https://gitea.com/gitea/migrator) - -### 移动端 - -[安卓客户端GitNex](https://gitlab.com/mmarif4u/gitnex) - -### 编辑器扩展 - -- [Gitea的Visual Studio扩展](https://github.com/maikebing/Gitea.VisualStudio) 从 [Visual Studio 扩展市场](https://marketplace.visualstudio.com/items?itemName=MysticBoy.GiteaExtensionforVisualStudio) 下载 diff --git a/docs/content/doc/developers.zh-cn.md b/docs/content/doc/developers.zh-cn.md index 0a873102b..97fb3a978 100644 --- a/docs/content/doc/developers.zh-cn.md +++ b/docs/content/doc/developers.zh-cn.md @@ -8,6 +8,6 @@ draft: false menu: sidebar: name: "开发者" - weight: 50 + weight: 55 identifier: "developers" --- diff --git a/docs/content/doc/developers/guidelines-backend.md b/docs/content/doc/developers/guidelines-backend.en-us.md similarity index 100% rename from docs/content/doc/developers/guidelines-backend.md rename to docs/content/doc/developers/guidelines-backend.en-us.md diff --git a/docs/content/doc/developers/oauth2-provider.md b/docs/content/doc/developers/oauth2-provider.en-us.md similarity index 100% rename from docs/content/doc/developers/oauth2-provider.md rename to docs/content/doc/developers/oauth2-provider.en-us.md diff --git a/docs/content/doc/features/webhooks.en-us.md b/docs/content/doc/features/webhooks.en-us.md index 2dba7b7f8..ecbe13c3a 100644 --- a/docs/content/doc/features/webhooks.en-us.md +++ b/docs/content/doc/features/webhooks.en-us.md @@ -188,3 +188,7 @@ if (json_last_error() !== JSON_ERROR_NONE) { ``` There is a Test Delivery button in the webhook settings that allows to test the configuration as well as a list of the most Recent Deliveries. + +### Authorization header + +**With 1.19**, Gitea hooks can be configured to send an [authorization header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization) to the webhook target. diff --git a/docs/content/doc/installation/from-source.en-us.md b/docs/content/doc/installation/from-source.en-us.md index 660f996b1..0be5673be 100644 --- a/docs/content/doc/installation/from-source.en-us.md +++ b/docs/content/doc/installation/from-source.en-us.md @@ -87,7 +87,7 @@ To build from source, the following programs must be present on the system: - `go` {{< min-go-version >}} or higher, see [here](https://golang.org/dl/) - `node` {{< min-node-version >}} or higher with `npm`, see [here](https://nodejs.org/en/download/) -- `make`, see here +- `make`, see [here]({{< relref "doc/developers/hacking-on-gitea.en-us.md" >}}#installing-make) Various [make tasks](https://github.com/go-gitea/gitea/blob/main/Makefile) are provided to keep the build process as simple as possible. diff --git a/docs/content/doc/installation/from-source.fr-fr.md b/docs/content/doc/installation/from-source.fr-fr.md index 00f67eab5..2a3ba6dfa 100644 --- a/docs/content/doc/installation/from-source.fr-fr.md +++ b/docs/content/doc/installation/from-source.fr-fr.md @@ -53,7 +53,7 @@ git checkout pr-xyz ## Compilation -Comme nous regroupons déjà toutes les bibliothèques requises pour compiler Gitea, vous pouvez continuer avec le processus de compilation lui-même. Nous fournissons diverses [tâches Make](https://github.com/go-gitea/gitea/blob/master/Makefile) pour rendre le processus de construction aussi simple que possible. Voyez ici comment obtenir Make. Selon vos besoins, vous pourrez éventuellement ajouter diverses options de compilation, vous pouvez choisir entre ces options : +Comme nous regroupons déjà toutes les bibliothèques requises pour compiler Gitea, vous pouvez continuer avec le processus de compilation lui-même. Nous fournissons diverses [tâches Make](https://github.com/go-gitea/gitea/blob/master/Makefile) pour rendre le processus de construction aussi simple que possible. [Voyez ici comment obtenir Make](/fr-fr/hacking-on-gitea/). Selon vos besoins, vous pourrez éventuellement ajouter diverses options de compilation, vous pouvez choisir entre ces options : * `bindata`: Intègre toutes les ressources nécessaires à l'exécution d'une instance de Gitea, ce qui rend un déploiement facile car il n'est pas nécessaire de se préoccuper des fichiers supplémentaires. * `sqlite sqlite_unlock_notify`: Active la prise en charge d'une base de données [SQLite3](https://sqlite.org/), ceci n'est recommandé que pour les petites installations de Gitea. diff --git a/docs/content/doc/installation/from-source.zh-cn.md b/docs/content/doc/installation/from-source.zh-cn.md index 008566e57..73833ec51 100644 --- a/docs/content/doc/installation/from-source.zh-cn.md +++ b/docs/content/doc/installation/from-source.zh-cn.md @@ -54,7 +54,7 @@ git checkout v{{< version >}} - `go` {{< min-go-version >}} 或以上版本, 详见[这里](https://golang.google.cn/doc/install) - `node` {{< min-node-version >}} 或以上版本,并且安装 `npm`, 详见[这里](https://nodejs.org/zh-cn/download/) -- `make`, 详见[这里]({{< relref "make.zh-cn.md" >}}) +- `make`, 详见[这里](/zh-cn/hacking-on-gitea/) 各种可用的 [make 任务](https://github.com/go-gitea/gitea/blob/main/Makefile) 可以用来使编译过程更方便。 diff --git a/docs/content/doc/installation/on-cloud-provider.md b/docs/content/doc/installation/on-cloud-provider.en-us.md similarity index 100% rename from docs/content/doc/installation/on-cloud-provider.md rename to docs/content/doc/installation/on-cloud-provider.en-us.md diff --git a/docs/content/doc/usage/email-setup.en-us.md b/docs/content/doc/usage/email-setup.en-us.md index 533e0fe1a..05cc19c13 100644 --- a/docs/content/doc/usage/email-setup.en-us.md +++ b/docs/content/doc/usage/email-setup.en-us.md @@ -47,7 +47,8 @@ Directly use SMTP server as relay. This option is useful if you don't want to se ENABLED = true FROM = gitea@mydomain.com MAILER_TYPE = smtp -HOST = mail.mydomain.com:587 +SMTP_ADDR = mail.mydomain.com +SMTP_PORT = 587 IS_TLS_ENABLED = true USER = gitea@mydomain.com PASSWD = `password` @@ -75,7 +76,8 @@ The following configuration should work with GMail's SMTP server: ```ini [mailer] ENABLED = true -HOST = smtp.gmail.com:465 +SMTP_ADDR = smtp.gmail.com +SMTP_PORT = 465 FROM = example@gmail.com USER = example@gmail.com PASSWD = *** diff --git a/docs/content/doc/usage/git-lfs-support.md b/docs/content/doc/usage/git-lfs-support.en-us.md similarity index 100% rename from docs/content/doc/usage/git-lfs-support.md rename to docs/content/doc/usage/git-lfs-support.en-us.md diff --git a/docs/content/doc/usage/https-support.md b/docs/content/doc/usage/https-support.en-us.md similarity index 100% rename from docs/content/doc/usage/https-support.md rename to docs/content/doc/usage/https-support.en-us.md diff --git a/docs/content/doc/usage/template-repositories.md b/docs/content/doc/usage/template-repositories.en-us.md similarity index 100% rename from docs/content/doc/usage/template-repositories.md rename to docs/content/doc/usage/template-repositories.en-us.md diff --git a/docs/static/_redirects b/docs/static/_redirects index 676181b61..39bd09f9b 100644 --- a/docs/static/_redirects +++ b/docs/static/_redirects @@ -9,7 +9,10 @@ https://gitea-docs.netlify.com/* https://docs.gitea.io/:splat 302! /en-us/ci-cd/ /en-us/integrations/ 302! /en-us/third-party-tools/ /en-us/integrations/ 302! +/zh-cn/third-party-tools/ /zh-cn/integrations/ 302! /en-us/make/ /en-us/hacking-on-gitea/ 302! +/zh-cn/make/ /zh-cn/hacking-on-gitea/ 302! +/fr-fr/make/ /fr-fr/hacking-on-gitea/ 302! /en-us/upgrade/ /en-us/upgrade-from-gitea/ 302! /fr-fr/upgrade/ /fr-fr/upgrade-from-gitea/ 302! /zh-cn/upgrade/ /zh-cn/upgrade-from-gitea/ 302! diff --git a/models/activities/action.go b/models/activities/action.go index 2d42cca4f..b4fda2241 100644 --- a/models/activities/action.go +++ b/models/activities/action.go @@ -64,6 +64,7 @@ const ( ActionPublishRelease // 24 ActionPullReviewDismissed // 25 ActionPullRequestReadyForReview // 26 + ActionAutoMergePullRequest // 27 ) // Action represents user operation type and other information to @@ -555,7 +556,7 @@ func notifyWatchers(ctx context.Context, actions ...*Action) error { if !permIssue[i] { continue } - case ActionCreatePullRequest, ActionCommentPull, ActionMergePullRequest, ActionClosePullRequest, ActionReopenPullRequest: + case ActionCreatePullRequest, ActionCommentPull, ActionMergePullRequest, ActionClosePullRequest, ActionReopenPullRequest, ActionAutoMergePullRequest: if !permPR[i] { continue } diff --git a/models/db/context.go b/models/db/context.go index 4fd35200c..e90780e4e 100644 --- a/models/db/context.go +++ b/models/db/context.go @@ -8,9 +8,6 @@ import ( "context" "database/sql" - "code.gitea.io/gitea/modules/setting" - - "xorm.io/builder" "xorm.io/xorm/schemas" ) @@ -121,13 +118,6 @@ func WithTx(f func(ctx context.Context) error, stdCtx ...context.Context) error return sess.Commit() } -// Iterate iterates the databases and doing something -func Iterate(ctx context.Context, tableBean interface{}, cond builder.Cond, fun func(idx int, bean interface{}) error) error { - return GetEngine(ctx).Where(cond). - BufferSize(setting.Database.IterateBufferSize). - Iterate(tableBean, fun) -} - // Insert inserts records into database func Insert(ctx context.Context, beans ...interface{}) error { _, err := GetEngine(ctx).Insert(beans...) diff --git a/models/db/iterate.go b/models/db/iterate.go index 3d4fa06ee..cbd2feed2 100644 --- a/models/db/iterate.go +++ b/models/db/iterate.go @@ -8,25 +8,30 @@ import ( "context" "code.gitea.io/gitea/modules/setting" + + "xorm.io/builder" ) -// IterateObjects iterate all the Bean object -func IterateObjects[Object any](ctx context.Context, f func(repo *Object) error) error { +// Iterate iterate all the Bean object +func Iterate[Bean any](ctx context.Context, cond builder.Cond, f func(ctx context.Context, bean *Bean) error) error { var start int batchSize := setting.Database.IterateBufferSize sess := GetEngine(ctx) for { - repos := make([]*Object, 0, batchSize) - if err := sess.Limit(batchSize, start).Find(&repos); err != nil { + beans := make([]*Bean, 0, batchSize) + if cond != nil { + sess = sess.Where(cond) + } + if err := sess.Limit(batchSize, start).Find(&beans); err != nil { return err } - if len(repos) == 0 { + if len(beans) == 0 { return nil } - start += len(repos) + start += len(beans) - for _, repo := range repos { - if err := f(repo); err != nil { + for _, bean := range beans { + if err := f(ctx, bean); err != nil { return err } } diff --git a/models/db/iterate_test.go b/models/db/iterate_test.go new file mode 100644 index 000000000..5d03a6e9c --- /dev/null +++ b/models/db/iterate_test.go @@ -0,0 +1,44 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package db_test + +import ( + "context" + "testing" + + "code.gitea.io/gitea/models/db" + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unittest" + + "github.com/stretchr/testify/assert" +) + +func TestIterate(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + xe := unittest.GetXORMEngine() + assert.NoError(t, xe.Sync(&repo_model.RepoUnit{})) + + var repoCnt int + err := db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repo *repo_model.RepoUnit) error { + repoCnt++ + return nil + }) + assert.NoError(t, err) + assert.EqualValues(t, 79, repoCnt) + + err = db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repoUnit *repo_model.RepoUnit) error { + reopUnit2 := repo_model.RepoUnit{ID: repoUnit.ID} + has, err := db.GetByBean(ctx, &reopUnit2) + if err != nil { + return err + } else if !has { + return db.ErrNotExist{Resource: "repo_unit", ID: repoUnit.ID} + } + assert.EqualValues(t, repoUnit.RepoID, repoUnit.RepoID) + assert.EqualValues(t, repoUnit.CreatedUnix, repoUnit.CreatedUnix) + return nil + }) + assert.NoError(t, err) +} diff --git a/models/migrations/base/db.go b/models/migrations/base/db.go new file mode 100644 index 000000000..5466b7622 --- /dev/null +++ b/models/migrations/base/db.go @@ -0,0 +1,634 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package base + +import ( + "context" + "database/sql" + "errors" + "fmt" + "os" + "path" + "reflect" + "regexp" + "strings" + "time" + + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/unittest" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/util" + + "xorm.io/xorm" + "xorm.io/xorm/schemas" +) + +// RecreateTables will recreate the tables for the provided beans using the newly provided bean definition and move all data to that new table +// WARNING: YOU MUST PROVIDE THE FULL BEAN DEFINITION +func RecreateTables(beans ...interface{}) func(*xorm.Engine) error { + return func(x *xorm.Engine) error { + sess := x.NewSession() + defer sess.Close() + if err := sess.Begin(); err != nil { + return err + } + sess = sess.StoreEngine("InnoDB") + for _, bean := range beans { + log.Info("Recreating Table: %s for Bean: %s", x.TableName(bean), reflect.Indirect(reflect.ValueOf(bean)).Type().Name()) + if err := RecreateTable(sess, bean); err != nil { + return err + } + } + return sess.Commit() + } +} + +// RecreateTable will recreate the table using the newly provided bean definition and move all data to that new table +// WARNING: YOU MUST PROVIDE THE FULL BEAN DEFINITION +// WARNING: YOU MUST COMMIT THE SESSION AT THE END +func RecreateTable(sess *xorm.Session, bean interface{}) error { + // TODO: This will not work if there are foreign keys + + tableName := sess.Engine().TableName(bean) + tempTableName := fmt.Sprintf("tmp_recreate__%s", tableName) + + // We need to move the old table away and create a new one with the correct columns + // We will need to do this in stages to prevent data loss + // + // First create the temporary table + if err := sess.Table(tempTableName).CreateTable(bean); err != nil { + log.Error("Unable to create table %s. Error: %v", tempTableName, err) + return err + } + + if err := sess.Table(tempTableName).CreateUniques(bean); err != nil { + log.Error("Unable to create uniques for table %s. Error: %v", tempTableName, err) + return err + } + + if err := sess.Table(tempTableName).CreateIndexes(bean); err != nil { + log.Error("Unable to create indexes for table %s. Error: %v", tempTableName, err) + return err + } + + // Work out the column names from the bean - these are the columns to select from the old table and install into the new table + table, err := sess.Engine().TableInfo(bean) + if err != nil { + log.Error("Unable to get table info. Error: %v", err) + + return err + } + newTableColumns := table.Columns() + if len(newTableColumns) == 0 { + return fmt.Errorf("no columns in new table") + } + hasID := false + for _, column := range newTableColumns { + hasID = hasID || (column.IsPrimaryKey && column.IsAutoIncrement) + } + + if hasID && setting.Database.UseMSSQL { + if _, err := sess.Exec(fmt.Sprintf("SET IDENTITY_INSERT `%s` ON", tempTableName)); err != nil { + log.Error("Unable to set identity insert for table %s. Error: %v", tempTableName, err) + return err + } + } + + sqlStringBuilder := &strings.Builder{} + _, _ = sqlStringBuilder.WriteString("INSERT INTO `") + _, _ = sqlStringBuilder.WriteString(tempTableName) + _, _ = sqlStringBuilder.WriteString("` (`") + _, _ = sqlStringBuilder.WriteString(newTableColumns[0].Name) + _, _ = sqlStringBuilder.WriteString("`") + for _, column := range newTableColumns[1:] { + _, _ = sqlStringBuilder.WriteString(", `") + _, _ = sqlStringBuilder.WriteString(column.Name) + _, _ = sqlStringBuilder.WriteString("`") + } + _, _ = sqlStringBuilder.WriteString(")") + _, _ = sqlStringBuilder.WriteString(" SELECT ") + if newTableColumns[0].Default != "" { + _, _ = sqlStringBuilder.WriteString("COALESCE(`") + _, _ = sqlStringBuilder.WriteString(newTableColumns[0].Name) + _, _ = sqlStringBuilder.WriteString("`, ") + _, _ = sqlStringBuilder.WriteString(newTableColumns[0].Default) + _, _ = sqlStringBuilder.WriteString(")") + } else { + _, _ = sqlStringBuilder.WriteString("`") + _, _ = sqlStringBuilder.WriteString(newTableColumns[0].Name) + _, _ = sqlStringBuilder.WriteString("`") + } + + for _, column := range newTableColumns[1:] { + if column.Default != "" { + _, _ = sqlStringBuilder.WriteString(", COALESCE(`") + _, _ = sqlStringBuilder.WriteString(column.Name) + _, _ = sqlStringBuilder.WriteString("`, ") + _, _ = sqlStringBuilder.WriteString(column.Default) + _, _ = sqlStringBuilder.WriteString(")") + } else { + _, _ = sqlStringBuilder.WriteString(", `") + _, _ = sqlStringBuilder.WriteString(column.Name) + _, _ = sqlStringBuilder.WriteString("`") + } + } + _, _ = sqlStringBuilder.WriteString(" FROM `") + _, _ = sqlStringBuilder.WriteString(tableName) + _, _ = sqlStringBuilder.WriteString("`") + + if _, err := sess.Exec(sqlStringBuilder.String()); err != nil { + log.Error("Unable to set copy data in to temp table %s. Error: %v", tempTableName, err) + return err + } + + if hasID && setting.Database.UseMSSQL { + if _, err := sess.Exec(fmt.Sprintf("SET IDENTITY_INSERT `%s` OFF", tempTableName)); err != nil { + log.Error("Unable to switch off identity insert for table %s. Error: %v", tempTableName, err) + return err + } + } + + switch { + case setting.Database.UseSQLite3: + // SQLite will drop all the constraints on the old table + if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil { + log.Error("Unable to drop old table %s. Error: %v", tableName, err) + return err + } + + if err := sess.Table(tempTableName).DropIndexes(bean); err != nil { + log.Error("Unable to drop indexes on temporary table %s. Error: %v", tempTableName, err) + return err + } + + if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` RENAME TO `%s`", tempTableName, tableName)); err != nil { + log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) + return err + } + + if err := sess.Table(tableName).CreateIndexes(bean); err != nil { + log.Error("Unable to recreate indexes on table %s. Error: %v", tableName, err) + return err + } + + if err := sess.Table(tableName).CreateUniques(bean); err != nil { + log.Error("Unable to recreate uniques on table %s. Error: %v", tableName, err) + return err + } + + case setting.Database.UseMySQL: + // MySQL will drop all the constraints on the old table + if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil { + log.Error("Unable to drop old table %s. Error: %v", tableName, err) + return err + } + + if err := sess.Table(tempTableName).DropIndexes(bean); err != nil { + log.Error("Unable to drop indexes on temporary table %s. Error: %v", tempTableName, err) + return err + } + + // SQLite and MySQL will move all the constraints from the temporary table to the new table + if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` RENAME TO `%s`", tempTableName, tableName)); err != nil { + log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) + return err + } + + if err := sess.Table(tableName).CreateIndexes(bean); err != nil { + log.Error("Unable to recreate indexes on table %s. Error: %v", tableName, err) + return err + } + + if err := sess.Table(tableName).CreateUniques(bean); err != nil { + log.Error("Unable to recreate uniques on table %s. Error: %v", tableName, err) + return err + } + case setting.Database.UsePostgreSQL: + var originalSequences []string + type sequenceData struct { + LastValue int `xorm:"'last_value'"` + IsCalled bool `xorm:"'is_called'"` + } + sequenceMap := map[string]sequenceData{} + + schema := sess.Engine().Dialect().URI().Schema + sess.Engine().SetSchema("") + if err := sess.Table("information_schema.sequences").Cols("sequence_name").Where("sequence_name LIKE ? || '_%' AND sequence_catalog = ?", tableName, setting.Database.Name).Find(&originalSequences); err != nil { + log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) + return err + } + sess.Engine().SetSchema(schema) + + for _, sequence := range originalSequences { + sequenceData := sequenceData{} + if _, err := sess.Table(sequence).Cols("last_value", "is_called").Get(&sequenceData); err != nil { + log.Error("Unable to get last_value and is_called from %s. Error: %v", sequence, err) + return err + } + sequenceMap[sequence] = sequenceData + + } + + // CASCADE causes postgres to drop all the constraints on the old table + if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s` CASCADE", tableName)); err != nil { + log.Error("Unable to drop old table %s. Error: %v", tableName, err) + return err + } + + // CASCADE causes postgres to move all the constraints from the temporary table to the new table + if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` RENAME TO `%s`", tempTableName, tableName)); err != nil { + log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) + return err + } + + var indices []string + sess.Engine().SetSchema("") + if err := sess.Table("pg_indexes").Cols("indexname").Where("tablename = ? ", tableName).Find(&indices); err != nil { + log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) + return err + } + sess.Engine().SetSchema(schema) + + for _, index := range indices { + newIndexName := strings.Replace(index, "tmp_recreate__", "", 1) + if _, err := sess.Exec(fmt.Sprintf("ALTER INDEX `%s` RENAME TO `%s`", index, newIndexName)); err != nil { + log.Error("Unable to rename %s to %s. Error: %v", index, newIndexName, err) + return err + } + } + + var sequences []string + sess.Engine().SetSchema("") + if err := sess.Table("information_schema.sequences").Cols("sequence_name").Where("sequence_name LIKE 'tmp_recreate__' || ? || '_%' AND sequence_catalog = ?", tableName, setting.Database.Name).Find(&sequences); err != nil { + log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) + return err + } + sess.Engine().SetSchema(schema) + + for _, sequence := range sequences { + newSequenceName := strings.Replace(sequence, "tmp_recreate__", "", 1) + if _, err := sess.Exec(fmt.Sprintf("ALTER SEQUENCE `%s` RENAME TO `%s`", sequence, newSequenceName)); err != nil { + log.Error("Unable to rename %s sequence to %s. Error: %v", sequence, newSequenceName, err) + return err + } + val, ok := sequenceMap[newSequenceName] + if newSequenceName == tableName+"_id_seq" { + if ok && val.LastValue != 0 { + if _, err := sess.Exec(fmt.Sprintf("SELECT setval('%s', %d, %t)", newSequenceName, val.LastValue, val.IsCalled)); err != nil { + log.Error("Unable to reset %s to %d. Error: %v", newSequenceName, val, err) + return err + } + } else { + // We're going to try to guess this + if _, err := sess.Exec(fmt.Sprintf("SELECT setval('%s', COALESCE((SELECT MAX(id)+1 FROM `%s`), 1), false)", newSequenceName, tableName)); err != nil { + log.Error("Unable to reset %s. Error: %v", newSequenceName, err) + return err + } + } + } else if ok { + if _, err := sess.Exec(fmt.Sprintf("SELECT setval('%s', %d, %t)", newSequenceName, val.LastValue, val.IsCalled)); err != nil { + log.Error("Unable to reset %s to %d. Error: %v", newSequenceName, val, err) + return err + } + } + + } + + case setting.Database.UseMSSQL: + // MSSQL will drop all the constraints on the old table + if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil { + log.Error("Unable to drop old table %s. Error: %v", tableName, err) + return err + } + + // MSSQL sp_rename will move all the constraints from the temporary table to the new table + if _, err := sess.Exec(fmt.Sprintf("sp_rename `%s`,`%s`", tempTableName, tableName)); err != nil { + log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) + return err + } + + default: + log.Fatal("Unrecognized DB") + } + return nil +} + +// WARNING: YOU MUST COMMIT THE SESSION AT THE END +func DropTableColumns(sess *xorm.Session, tableName string, columnNames ...string) (err error) { + if tableName == "" || len(columnNames) == 0 { + return nil + } + // TODO: This will not work if there are foreign keys + + switch { + case setting.Database.UseSQLite3: + // First drop the indexes on the columns + res, errIndex := sess.Query(fmt.Sprintf("PRAGMA index_list(`%s`)", tableName)) + if errIndex != nil { + return errIndex + } + for _, row := range res { + indexName := row["name"] + indexRes, err := sess.Query(fmt.Sprintf("PRAGMA index_info(`%s`)", indexName)) + if err != nil { + return err + } + if len(indexRes) != 1 { + continue + } + indexColumn := string(indexRes[0]["name"]) + for _, name := range columnNames { + if name == indexColumn { + _, err := sess.Exec(fmt.Sprintf("DROP INDEX `%s`", indexName)) + if err != nil { + return err + } + } + } + } + + // Here we need to get the columns from the original table + sql := fmt.Sprintf("SELECT sql FROM sqlite_master WHERE tbl_name='%s' and type='table'", tableName) + res, err := sess.Query(sql) + if err != nil { + return err + } + tableSQL := string(res[0]["sql"]) + + // Get the string offset for column definitions: `CREATE TABLE ( column-definitions... )` + columnDefinitionsIndex := strings.Index(tableSQL, "(") + if columnDefinitionsIndex < 0 { + return errors.New("couldn't find column definitions") + } + + // Separate out the column definitions + tableSQL = tableSQL[columnDefinitionsIndex:] + + // Remove the required columnNames + for _, name := range columnNames { + tableSQL = regexp.MustCompile(regexp.QuoteMeta("`"+name+"`")+"[^`,)]*?[,)]").ReplaceAllString(tableSQL, "") + } + + // Ensure the query is ended properly + tableSQL = strings.TrimSpace(tableSQL) + if tableSQL[len(tableSQL)-1] != ')' { + if tableSQL[len(tableSQL)-1] == ',' { + tableSQL = tableSQL[:len(tableSQL)-1] + } + tableSQL += ")" + } + + // Find all the columns in the table + columns := regexp.MustCompile("`([^`]*)`").FindAllString(tableSQL, -1) + + tableSQL = fmt.Sprintf("CREATE TABLE `new_%s_new` ", tableName) + tableSQL + if _, err := sess.Exec(tableSQL); err != nil { + return err + } + + // Now restore the data + columnsSeparated := strings.Join(columns, ",") + insertSQL := fmt.Sprintf("INSERT INTO `new_%s_new` (%s) SELECT %s FROM %s", tableName, columnsSeparated, columnsSeparated, tableName) + if _, err := sess.Exec(insertSQL); err != nil { + return err + } + + // Now drop the old table + if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil { + return err + } + + // Rename the table + if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `new_%s_new` RENAME TO `%s`", tableName, tableName)); err != nil { + return err + } + + case setting.Database.UsePostgreSQL: + cols := "" + for _, col := range columnNames { + if cols != "" { + cols += ", " + } + cols += "DROP COLUMN `" + col + "` CASCADE" + } + if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil { + return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err) + } + case setting.Database.UseMySQL: + // Drop indexes on columns first + sql := fmt.Sprintf("SHOW INDEX FROM %s WHERE column_name IN ('%s')", tableName, strings.Join(columnNames, "','")) + res, err := sess.Query(sql) + if err != nil { + return err + } + for _, index := range res { + indexName := index["column_name"] + if len(indexName) > 0 { + _, err := sess.Exec(fmt.Sprintf("DROP INDEX `%s` ON `%s`", indexName, tableName)) + if err != nil { + return err + } + } + } + + // Now drop the columns + cols := "" + for _, col := range columnNames { + if cols != "" { + cols += ", " + } + cols += "DROP COLUMN `" + col + "`" + } + if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil { + return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err) + } + case setting.Database.UseMSSQL: + cols := "" + for _, col := range columnNames { + if cols != "" { + cols += ", " + } + cols += "`" + strings.ToLower(col) + "`" + } + sql := fmt.Sprintf("SELECT Name FROM sys.default_constraints WHERE parent_object_id = OBJECT_ID('%[1]s') AND parent_column_id IN (SELECT column_id FROM sys.columns WHERE LOWER(name) IN (%[2]s) AND object_id = OBJECT_ID('%[1]s'))", + tableName, strings.ReplaceAll(cols, "`", "'")) + constraints := make([]string, 0) + if err := sess.SQL(sql).Find(&constraints); err != nil { + return fmt.Errorf("Find constraints: %v", err) + } + for _, constraint := range constraints { + if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` DROP CONSTRAINT `%s`", tableName, constraint)); err != nil { + return fmt.Errorf("Drop table `%s` default constraint `%s`: %v", tableName, constraint, err) + } + } + sql = fmt.Sprintf("SELECT DISTINCT Name FROM sys.indexes INNER JOIN sys.index_columns ON indexes.index_id = index_columns.index_id AND indexes.object_id = index_columns.object_id WHERE indexes.object_id = OBJECT_ID('%[1]s') AND index_columns.column_id IN (SELECT column_id FROM sys.columns WHERE LOWER(name) IN (%[2]s) AND object_id = OBJECT_ID('%[1]s'))", + tableName, strings.ReplaceAll(cols, "`", "'")) + constraints = make([]string, 0) + if err := sess.SQL(sql).Find(&constraints); err != nil { + return fmt.Errorf("Find constraints: %v", err) + } + for _, constraint := range constraints { + if _, err := sess.Exec(fmt.Sprintf("DROP INDEX `%[2]s` ON `%[1]s`", tableName, constraint)); err != nil { + return fmt.Errorf("Drop index `%[2]s` on `%[1]s`: %v", tableName, constraint, err) + } + } + + if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` DROP COLUMN %s", tableName, cols)); err != nil { + return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err) + } + default: + log.Fatal("Unrecognized DB") + } + + return nil +} + +// ModifyColumn will modify column's type or other property. SQLITE is not supported +func ModifyColumn(x *xorm.Engine, tableName string, col *schemas.Column) error { + var indexes map[string]*schemas.Index + var err error + // MSSQL have to remove index at first, otherwise alter column will fail + // ref. https://sqlzealots.com/2018/05/09/error-message-the-index-is-dependent-on-column-alter-table-alter-column-failed-because-one-or-more-objects-access-this-column/ + if x.Dialect().URI().DBType == schemas.MSSQL { + indexes, err = x.Dialect().GetIndexes(x.DB(), context.Background(), tableName) + if err != nil { + return err + } + + for _, index := range indexes { + _, err = x.Exec(x.Dialect().DropIndexSQL(tableName, index)) + if err != nil { + return err + } + } + } + + defer func() { + for _, index := range indexes { + _, err = x.Exec(x.Dialect().CreateIndexSQL(tableName, index)) + if err != nil { + log.Error("Create index %s on table %s failed: %v", index.Name, tableName, err) + } + } + }() + + alterSQL := x.Dialect().ModifyColumnSQL(tableName, col) + if _, err := x.Exec(alterSQL); err != nil { + return err + } + return nil +} + +func removeAllWithRetry(dir string) error { + var err error + for i := 0; i < 20; i++ { + err = os.RemoveAll(dir) + if err == nil { + break + } + time.Sleep(100 * time.Millisecond) + } + return err +} + +func newXORMEngine() (*xorm.Engine, error) { + if err := db.InitEngine(context.Background()); err != nil { + return nil, err + } + x := unittest.GetXORMEngine() + return x, nil +} + +func deleteDB() error { + switch { + case setting.Database.UseSQLite3: + if err := util.Remove(setting.Database.Path); err != nil { + return err + } + return os.MkdirAll(path.Dir(setting.Database.Path), os.ModePerm) + + case setting.Database.UseMySQL: + db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/", + setting.Database.User, setting.Database.Passwd, setting.Database.Host)) + if err != nil { + return err + } + defer db.Close() + + if _, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", setting.Database.Name)); err != nil { + return err + } + + if _, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", setting.Database.Name)); err != nil { + return err + } + return nil + case setting.Database.UsePostgreSQL: + db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/?sslmode=%s", + setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.SSLMode)) + if err != nil { + return err + } + defer db.Close() + + if _, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", setting.Database.Name)); err != nil { + return err + } + + if _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", setting.Database.Name)); err != nil { + return err + } + db.Close() + + // Check if we need to setup a specific schema + if len(setting.Database.Schema) != 0 { + db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s", + setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name, setting.Database.SSLMode)) + if err != nil { + return err + } + defer db.Close() + + schrows, err := db.Query(fmt.Sprintf("SELECT 1 FROM information_schema.schemata WHERE schema_name = '%s'", setting.Database.Schema)) + if err != nil { + return err + } + defer schrows.Close() + + if !schrows.Next() { + // Create and setup a DB schema + _, err = db.Exec(fmt.Sprintf("CREATE SCHEMA %s", setting.Database.Schema)) + if err != nil { + return err + } + } + + // Make the user's default search path the created schema; this will affect new connections + _, err = db.Exec(fmt.Sprintf(`ALTER USER "%s" SET search_path = %s`, setting.Database.User, setting.Database.Schema)) + if err != nil { + return err + } + return nil + } + case setting.Database.UseMSSQL: + host, port := setting.ParseMSSQLHostPort(setting.Database.Host) + db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", + host, port, "master", setting.Database.User, setting.Database.Passwd)) + if err != nil { + return err + } + defer db.Close() + + if _, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS [%s]", setting.Database.Name)); err != nil { + return err + } + if _, err = db.Exec(fmt.Sprintf("CREATE DATABASE [%s]", setting.Database.Name)); err != nil { + return err + } + } + + return nil +} diff --git a/models/migrations/base/db_test.go b/models/migrations/base/db_test.go new file mode 100644 index 000000000..ee227b797 --- /dev/null +++ b/models/migrations/base/db_test.go @@ -0,0 +1,97 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package base + +import ( + "testing" + + "code.gitea.io/gitea/modules/timeutil" + + "xorm.io/xorm/names" +) + +func Test_DropTableColumns(t *testing.T) { + x, deferable := PrepareTestEnv(t, 0) + if x == nil || t.Failed() { + defer deferable() + return + } + defer deferable() + + type DropTest struct { + ID int64 `xorm:"pk autoincr"` + FirstColumn string + ToDropColumn string `xorm:"unique"` + AnotherColumn int64 + CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` + UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` + } + + columns := []string{ + "first_column", + "to_drop_column", + "another_column", + "created_unix", + "updated_unix", + } + + for i := range columns { + x.SetMapper(names.GonicMapper{}) + if err := x.Sync2(new(DropTest)); err != nil { + t.Errorf("unable to create DropTest table: %v", err) + return + } + sess := x.NewSession() + if err := sess.Begin(); err != nil { + sess.Close() + t.Errorf("unable to begin transaction: %v", err) + return + } + if err := DropTableColumns(sess, "drop_test", columns[i:]...); err != nil { + sess.Close() + t.Errorf("Unable to drop columns[%d:]: %s from drop_test: %v", i, columns[i:], err) + return + } + if err := sess.Commit(); err != nil { + sess.Close() + t.Errorf("unable to commit transaction: %v", err) + return + } + sess.Close() + if err := x.DropTables(new(DropTest)); err != nil { + t.Errorf("unable to drop table: %v", err) + return + } + for j := range columns[i+1:] { + x.SetMapper(names.GonicMapper{}) + if err := x.Sync2(new(DropTest)); err != nil { + t.Errorf("unable to create DropTest table: %v", err) + return + } + dropcols := append([]string{columns[i]}, columns[j+i+1:]...) + sess := x.NewSession() + if err := sess.Begin(); err != nil { + sess.Close() + t.Errorf("unable to begin transaction: %v", err) + return + } + if err := DropTableColumns(sess, "drop_test", dropcols...); err != nil { + sess.Close() + t.Errorf("Unable to drop columns: %s from drop_test: %v", dropcols, err) + return + } + if err := sess.Commit(); err != nil { + sess.Close() + t.Errorf("unable to commit transaction: %v", err) + return + } + sess.Close() + if err := x.DropTables(new(DropTest)); err != nil { + t.Errorf("unable to drop table: %v", err) + return + } + } + } +} diff --git a/models/migrations/base/hash.go b/models/migrations/base/hash.go new file mode 100644 index 000000000..0f078dd70 --- /dev/null +++ b/models/migrations/base/hash.go @@ -0,0 +1,17 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package base + +import ( + "crypto/sha256" + "fmt" + + "golang.org/x/crypto/pbkdf2" +) + +func HashToken(token, salt string) string { + tempHash := pbkdf2.Key([]byte(token), []byte(salt), 10000, 50, sha256.New) + return fmt.Sprintf("%x", tempHash) +} diff --git a/models/migrations/base/main_test.go b/models/migrations/base/main_test.go new file mode 100644 index 000000000..290d87214 --- /dev/null +++ b/models/migrations/base/main_test.go @@ -0,0 +1,13 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package base + +import ( + "testing" +) + +func TestMain(m *testing.M) { + MainTest(m) +} diff --git a/models/migrations/testlogger_test.go b/models/migrations/base/testlogger.go similarity index 96% rename from models/migrations/testlogger_test.go rename to models/migrations/base/testlogger.go index 0455d9c9a..0f35a078e 100644 --- a/models/migrations/testlogger_test.go +++ b/models/migrations/base/testlogger.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package base import ( "context" @@ -184,9 +184,3 @@ func (log *TestLogger) ReleaseReopen() error { func (log *TestLogger) GetName() string { return "test" } - -func init() { - log.Register("test", NewTestLogger) - _, filename, _, _ := runtime.Caller(0) - prefix = strings.TrimSuffix(filename, "tests/testlogger.go") -} diff --git a/models/migrations/base/tests.go b/models/migrations/base/tests.go new file mode 100644 index 000000000..dafc0df2f --- /dev/null +++ b/models/migrations/base/tests.go @@ -0,0 +1,170 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package base + +import ( + "context" + "fmt" + "os" + "path" + "path/filepath" + "runtime" + "strings" + "testing" + + "code.gitea.io/gitea/models/unittest" + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" + + "github.com/stretchr/testify/assert" + "xorm.io/xorm" +) + +// PrepareTestEnv prepares the test environment and reset the database. The skip parameter should usually be 0. +// Provide models to be sync'd with the database - in particular any models you expect fixtures to be loaded from. +// +// fixtures in `models/migrations/fixtures/` will be loaded automatically +func PrepareTestEnv(t *testing.T, skip int, syncModels ...interface{}) (*xorm.Engine, func()) { + t.Helper() + ourSkip := 2 + ourSkip += skip + deferFn := PrintCurrentTest(t, ourSkip) + assert.NoError(t, os.RemoveAll(setting.RepoRootPath)) + assert.NoError(t, unittest.CopyDir(path.Join(filepath.Dir(setting.AppPath), "tests/gitea-repositories-meta"), setting.RepoRootPath)) + ownerDirs, err := os.ReadDir(setting.RepoRootPath) + if err != nil { + assert.NoError(t, err, "unable to read the new repo root: %v\n", err) + } + for _, ownerDir := range ownerDirs { + if !ownerDir.Type().IsDir() { + continue + } + repoDirs, err := os.ReadDir(filepath.Join(setting.RepoRootPath, ownerDir.Name())) + if err != nil { + assert.NoError(t, err, "unable to read the new repo root: %v\n", err) + } + for _, repoDir := range repoDirs { + _ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "pack"), 0o755) + _ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "info"), 0o755) + _ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "heads"), 0o755) + _ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "tag"), 0o755) + } + } + + if err := deleteDB(); err != nil { + t.Errorf("unable to reset database: %v", err) + return nil, deferFn + } + + x, err := newXORMEngine() + assert.NoError(t, err) + if x != nil { + oldDefer := deferFn + deferFn = func() { + oldDefer() + if err := x.Close(); err != nil { + t.Errorf("error during close: %v", err) + } + if err := deleteDB(); err != nil { + t.Errorf("unable to reset database: %v", err) + } + } + } + if err != nil { + return x, deferFn + } + + if len(syncModels) > 0 { + if err := x.Sync2(syncModels...); err != nil { + t.Errorf("error during sync: %v", err) + return x, deferFn + } + } + + fixturesDir := filepath.Join(filepath.Dir(setting.AppPath), "models", "migrations", "fixtures", t.Name()) + + if _, err := os.Stat(fixturesDir); err == nil { + t.Logf("initializing fixtures from: %s", fixturesDir) + if err := unittest.InitFixtures( + unittest.FixturesOptions{ + Dir: fixturesDir, + }, x); err != nil { + t.Errorf("error whilst initializing fixtures from %s: %v", fixturesDir, err) + return x, deferFn + } + if err := unittest.LoadFixtures(x); err != nil { + t.Errorf("error whilst loading fixtures from %s: %v", fixturesDir, err) + return x, deferFn + } + } else if !os.IsNotExist(err) { + t.Errorf("unexpected error whilst checking for existence of fixtures: %v", err) + } else { + t.Logf("no fixtures found in: %s", fixturesDir) + } + + return x, deferFn +} + +func MainTest(m *testing.M) { + log.Register("test", NewTestLogger) + _, filename, _, _ := runtime.Caller(0) + prefix = strings.TrimSuffix(filename, "tests/testlogger.go") + + giteaRoot := base.SetupGiteaRoot() + if giteaRoot == "" { + fmt.Println("Environment variable $GITEA_ROOT not set") + os.Exit(1) + } + giteaBinary := "gitea" + if runtime.GOOS == "windows" { + giteaBinary += ".exe" + } + setting.AppPath = path.Join(giteaRoot, giteaBinary) + if _, err := os.Stat(setting.AppPath); err != nil { + fmt.Printf("Could not find gitea binary at %s\n", setting.AppPath) + os.Exit(1) + } + + giteaConf := os.Getenv("GITEA_CONF") + if giteaConf == "" { + giteaConf = path.Join(filepath.Dir(setting.AppPath), "tests/sqlite.ini") + fmt.Printf("Environment variable $GITEA_CONF not set - defaulting to %s\n", giteaConf) + } + + if !path.IsAbs(giteaConf) { + setting.CustomConf = path.Join(giteaRoot, giteaConf) + } else { + setting.CustomConf = giteaConf + } + + tmpDataPath, err := os.MkdirTemp("", "data") + if err != nil { + fmt.Printf("Unable to create temporary data path %v\n", err) + os.Exit(1) + } + + setting.AppDataPath = tmpDataPath + + setting.SetCustomPathAndConf("", "", "") + setting.LoadForTest() + if err = git.InitFull(context.Background()); err != nil { + fmt.Printf("Unable to InitFull: %v\n", err) + os.Exit(1) + } + setting.InitDBConfig() + setting.NewLogServices(true) + + exitStatus := m.Run() + + if err := removeAllWithRetry(setting.RepoRootPath); err != nil { + fmt.Fprintf(os.Stderr, "os.RemoveAll: %v\n", err) + } + if err := removeAllWithRetry(tmpDataPath); err != nil { + fmt.Fprintf(os.Stderr, "os.RemoveAll: %v\n", err) + } + os.Exit(exitStatus) +} diff --git a/models/migrations/fixtures/Test_addHeaderAuthorizationEncryptedColWebhook/expected_webhook.yml b/models/migrations/fixtures/Test_addHeaderAuthorizationEncryptedColWebhook/expected_webhook.yml new file mode 100644 index 000000000..f6239998c --- /dev/null +++ b/models/migrations/fixtures/Test_addHeaderAuthorizationEncryptedColWebhook/expected_webhook.yml @@ -0,0 +1,9 @@ +# for matrix, the access_token has been moved to "header_authorization" +- + id: 1 + meta: '{"homeserver_url":"https://matrix.example.com","room_id":"roomID","message_type":1}' + header_authorization: "Bearer s3cr3t" +- + id: 2 + meta: '' + header_authorization: "" diff --git a/models/migrations/fixtures/Test_addHeaderAuthorizationEncryptedColWebhook/hook_task.yml b/models/migrations/fixtures/Test_addHeaderAuthorizationEncryptedColWebhook/hook_task.yml new file mode 100644 index 000000000..8f61d6e70 --- /dev/null +++ b/models/migrations/fixtures/Test_addHeaderAuthorizationEncryptedColWebhook/hook_task.yml @@ -0,0 +1,8 @@ +# unsafe payload +- id: 1 + hook_id: 1 + payload_content: '{"homeserver_url":"https://matrix.example.com","room_id":"roomID","access_token":"s3cr3t","message_type":1}' +# safe payload +- id: 2 + hook_id: 2 + payload_content: '{"homeserver_url":"https://matrix.example.com","room_id":"roomID","message_type":1}' diff --git a/models/migrations/fixtures/Test_addHeaderAuthorizationEncryptedColWebhook/webhook.yml b/models/migrations/fixtures/Test_addHeaderAuthorizationEncryptedColWebhook/webhook.yml new file mode 100644 index 000000000..ec6f9bffa --- /dev/null +++ b/models/migrations/fixtures/Test_addHeaderAuthorizationEncryptedColWebhook/webhook.yml @@ -0,0 +1,10 @@ +# matrix webhook +- id: 1 + type: matrix + meta: '{"homeserver_url":"https://matrix.example.com","room_id":"roomID","access_token":"s3cr3t","message_type":1}' + header_authorization_encrypted: '' +# gitea webhook +- id: 2 + type: gitea + meta: '' + header_authorization_encrypted: '' diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index f1f943a2c..5f5ec8fdd 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -6,20 +6,28 @@ package migrations import ( - "context" - "errors" "fmt" "os" - "reflect" - "regexp" - "strings" + "code.gitea.io/gitea/models/migrations/v1_10" + "code.gitea.io/gitea/models/migrations/v1_11" + "code.gitea.io/gitea/models/migrations/v1_12" + "code.gitea.io/gitea/models/migrations/v1_13" + "code.gitea.io/gitea/models/migrations/v1_14" + "code.gitea.io/gitea/models/migrations/v1_15" + "code.gitea.io/gitea/models/migrations/v1_16" + "code.gitea.io/gitea/models/migrations/v1_17" + "code.gitea.io/gitea/models/migrations/v1_18" + "code.gitea.io/gitea/models/migrations/v1_19" + "code.gitea.io/gitea/models/migrations/v1_6" + "code.gitea.io/gitea/models/migrations/v1_7" + "code.gitea.io/gitea/models/migrations/v1_8" + "code.gitea.io/gitea/models/migrations/v1_9" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "xorm.io/xorm" "xorm.io/xorm/names" - "xorm.io/xorm/schemas" ) const minDBVersion = 70 // Gitea 1.5.3 @@ -66,363 +74,369 @@ var migrations = []Migration{ // Gitea 1.5.0 ends at v69 // v70 -> v71 - NewMigration("add issue_dependencies", addIssueDependencies), + NewMigration("add issue_dependencies", v1_6.AddIssueDependencies), // v71 -> v72 - NewMigration("protect each scratch token", addScratchHash), + NewMigration("protect each scratch token", v1_6.AddScratchHash), // v72 -> v73 - NewMigration("add review", addReview), + NewMigration("add review", v1_6.AddReview), // Gitea 1.6.0 ends at v73 // v73 -> v74 - NewMigration("add must_change_password column for users table", addMustChangePassword), + NewMigration("add must_change_password column for users table", v1_7.AddMustChangePassword), // v74 -> v75 - NewMigration("add approval whitelists to protected branches", addApprovalWhitelistsToProtectedBranches), + NewMigration("add approval whitelists to protected branches", v1_7.AddApprovalWhitelistsToProtectedBranches), // v75 -> v76 - NewMigration("clear nonused data which not deleted when user was deleted", clearNonusedData), + NewMigration("clear nonused data which not deleted when user was deleted", v1_7.ClearNonusedData), // Gitea 1.7.0 ends at v76 // v76 -> v77 - NewMigration("add pull request rebase with merge commit", addPullRequestRebaseWithMerge), + NewMigration("add pull request rebase with merge commit", v1_8.AddPullRequestRebaseWithMerge), // v77 -> v78 - NewMigration("add theme to users", addUserDefaultTheme), + NewMigration("add theme to users", v1_8.AddUserDefaultTheme), // v78 -> v79 - NewMigration("rename repo is_bare to repo is_empty", renameRepoIsBareToIsEmpty), + NewMigration("rename repo is_bare to repo is_empty", v1_8.RenameRepoIsBareToIsEmpty), // v79 -> v80 - NewMigration("add can close issues via commit in any branch", addCanCloseIssuesViaCommitInAnyBranch), + NewMigration("add can close issues via commit in any branch", v1_8.AddCanCloseIssuesViaCommitInAnyBranch), // v80 -> v81 - NewMigration("add is locked to issues", addIsLockedToIssues), + NewMigration("add is locked to issues", v1_8.AddIsLockedToIssues), // v81 -> v82 - NewMigration("update U2F counter type", changeU2FCounterType), + NewMigration("update U2F counter type", v1_8.ChangeU2FCounterType), // Gitea 1.8.0 ends at v82 // v82 -> v83 - NewMigration("hot fix for wrong release sha1 on release table", fixReleaseSha1OnReleaseTable), + NewMigration("hot fix for wrong release sha1 on release table", v1_9.FixReleaseSha1OnReleaseTable), // v83 -> v84 - NewMigration("add uploader id for table attachment", addUploaderIDForAttachment), + NewMigration("add uploader id for table attachment", v1_9.AddUploaderIDForAttachment), // v84 -> v85 - NewMigration("add table to store original imported gpg keys", addGPGKeyImport), + NewMigration("add table to store original imported gpg keys", v1_9.AddGPGKeyImport), // v85 -> v86 - NewMigration("hash application token", hashAppToken), + NewMigration("hash application token", v1_9.HashAppToken), // v86 -> v87 - NewMigration("add http method to webhook", addHTTPMethodToWebhook), + NewMigration("add http method to webhook", v1_9.AddHTTPMethodToWebhook), // v87 -> v88 - NewMigration("add avatar field to repository", addAvatarFieldToRepository), + NewMigration("add avatar field to repository", v1_9.AddAvatarFieldToRepository), // Gitea 1.9.0 ends at v88 // v88 -> v89 - NewMigration("add commit status context field to commit_status", addCommitStatusContext), + NewMigration("add commit status context field to commit_status", v1_10.AddCommitStatusContext), // v89 -> v90 - NewMigration("add original author/url migration info to issues, comments, and repo ", addOriginalMigrationInfo), + NewMigration("add original author/url migration info to issues, comments, and repo ", v1_10.AddOriginalMigrationInfo), // v90 -> v91 - NewMigration("change length of some repository columns", changeSomeColumnsLengthOfRepo), + NewMigration("change length of some repository columns", v1_10.ChangeSomeColumnsLengthOfRepo), // v91 -> v92 - NewMigration("add index on owner_id of repository and type, review_id of comment", addIndexOnRepositoryAndComment), + NewMigration("add index on owner_id of repository and type, review_id of comment", v1_10.AddIndexOnRepositoryAndComment), // v92 -> v93 - NewMigration("remove orphaned repository index statuses", removeLingeringIndexStatus), + NewMigration("remove orphaned repository index statuses", v1_10.RemoveLingeringIndexStatus), // v93 -> v94 - NewMigration("add email notification enabled preference to user", addEmailNotificationEnabledToUser), + NewMigration("add email notification enabled preference to user", v1_10.AddEmailNotificationEnabledToUser), // v94 -> v95 - NewMigration("add enable_status_check, status_check_contexts to protected_branch", addStatusCheckColumnsForProtectedBranches), + NewMigration("add enable_status_check, status_check_contexts to protected_branch", v1_10.AddStatusCheckColumnsForProtectedBranches), // v95 -> v96 - NewMigration("add table columns for cross referencing issues", addCrossReferenceColumns), + NewMigration("add table columns for cross referencing issues", v1_10.AddCrossReferenceColumns), // v96 -> v97 - NewMigration("delete orphaned attachments", deleteOrphanedAttachments), + NewMigration("delete orphaned attachments", v1_10.DeleteOrphanedAttachments), // v97 -> v98 - NewMigration("add repo_admin_change_team_access to user", addRepoAdminChangeTeamAccessColumnForUser), + NewMigration("add repo_admin_change_team_access to user", v1_10.AddRepoAdminChangeTeamAccessColumnForUser), // v98 -> v99 - NewMigration("add original author name and id on migrated release", addOriginalAuthorOnMigratedReleases), + NewMigration("add original author name and id on migrated release", v1_10.AddOriginalAuthorOnMigratedReleases), // v99 -> v100 - NewMigration("add task table and status column for repository table", addTaskTable), + NewMigration("add task table and status column for repository table", v1_10.AddTaskTable), // v100 -> v101 - NewMigration("update migration repositories' service type", updateMigrationServiceTypes), + NewMigration("update migration repositories' service type", v1_10.UpdateMigrationServiceTypes), // v101 -> v102 - NewMigration("change length of some external login users columns", changeSomeColumnsLengthOfExternalLoginUser), + NewMigration("change length of some external login users columns", v1_10.ChangeSomeColumnsLengthOfExternalLoginUser), // Gitea 1.10.0 ends at v102 // v102 -> v103 - NewMigration("update migration repositories' service type", dropColumnHeadUserNameOnPullRequest), + NewMigration("update migration repositories' service type", v1_11.DropColumnHeadUserNameOnPullRequest), // v103 -> v104 - NewMigration("Add WhitelistDeployKeys to protected branch", addWhitelistDeployKeysToBranches), + NewMigration("Add WhitelistDeployKeys to protected branch", v1_11.AddWhitelistDeployKeysToBranches), // v104 -> v105 - NewMigration("remove unnecessary columns from label", removeLabelUneededCols), + NewMigration("remove unnecessary columns from label", v1_11.RemoveLabelUneededCols), // v105 -> v106 - NewMigration("add includes_all_repositories to teams", addTeamIncludesAllRepositories), + NewMigration("add includes_all_repositories to teams", v1_11.AddTeamIncludesAllRepositories), // v106 -> v107 - NewMigration("add column `mode` to table watch", addModeColumnToWatch), + NewMigration("add column `mode` to table watch", v1_11.AddModeColumnToWatch), // v107 -> v108 - NewMigration("Add template options to repository", addTemplateToRepo), + NewMigration("Add template options to repository", v1_11.AddTemplateToRepo), // v108 -> v109 - NewMigration("Add comment_id on table notification", addCommentIDOnNotification), + NewMigration("Add comment_id on table notification", v1_11.AddCommentIDOnNotification), // v109 -> v110 - NewMigration("add can_create_org_repo to team", addCanCreateOrgRepoColumnForTeam), + NewMigration("add can_create_org_repo to team", v1_11.AddCanCreateOrgRepoColumnForTeam), // v110 -> v111 - NewMigration("change review content type to text", changeReviewContentToText), + NewMigration("change review content type to text", v1_11.ChangeReviewContentToText), // v111 -> v112 - NewMigration("update branch protection for can push and whitelist enable", addBranchProtectionCanPushAndEnableWhitelist), + NewMigration("update branch protection for can push and whitelist enable", v1_11.AddBranchProtectionCanPushAndEnableWhitelist), // v112 -> v113 - NewMigration("remove release attachments which repository deleted", removeAttachmentMissedRepo), + NewMigration("remove release attachments which repository deleted", v1_11.RemoveAttachmentMissedRepo), // v113 -> v114 - NewMigration("new feature: change target branch of pull requests", featureChangeTargetBranch), + NewMigration("new feature: change target branch of pull requests", v1_11.FeatureChangeTargetBranch), // v114 -> v115 - NewMigration("Remove authentication credentials from stored URL", sanitizeOriginalURL), + NewMigration("Remove authentication credentials from stored URL", v1_11.SanitizeOriginalURL), // v115 -> v116 - NewMigration("add user_id prefix to existing user avatar name", renameExistingUserAvatarName), + NewMigration("add user_id prefix to existing user avatar name", v1_11.RenameExistingUserAvatarName), // v116 -> v117 - NewMigration("Extend TrackedTimes", extendTrackedTimes), + NewMigration("Extend TrackedTimes", v1_11.ExtendTrackedTimes), // Gitea 1.11.0 ends at v117 // v117 -> v118 - NewMigration("Add block on rejected reviews branch protection", addBlockOnRejectedReviews), + NewMigration("Add block on rejected reviews branch protection", v1_12.AddBlockOnRejectedReviews), // v118 -> v119 - NewMigration("Add commit id and stale to reviews", addReviewCommitAndStale), + NewMigration("Add commit id and stale to reviews", v1_12.AddReviewCommitAndStale), // v119 -> v120 - NewMigration("Fix migrated repositories' git service type", fixMigratedRepositoryServiceType), + NewMigration("Fix migrated repositories' git service type", v1_12.FixMigratedRepositoryServiceType), // v120 -> v121 - NewMigration("Add owner_name on table repository", addOwnerNameOnRepository), + NewMigration("Add owner_name on table repository", v1_12.AddOwnerNameOnRepository), // v121 -> v122 - NewMigration("add is_restricted column for users table", addIsRestricted), + NewMigration("add is_restricted column for users table", v1_12.AddIsRestricted), // v122 -> v123 - NewMigration("Add Require Signed Commits to ProtectedBranch", addRequireSignedCommits), + NewMigration("Add Require Signed Commits to ProtectedBranch", v1_12.AddRequireSignedCommits), // v123 -> v124 - NewMigration("Add original information for reactions", addReactionOriginals), + NewMigration("Add original information for reactions", v1_12.AddReactionOriginals), // v124 -> v125 - NewMigration("Add columns to user and repository", addUserRepoMissingColumns), + NewMigration("Add columns to user and repository", v1_12.AddUserRepoMissingColumns), // v125 -> v126 - NewMigration("Add some columns on review for migration", addReviewMigrateInfo), + NewMigration("Add some columns on review for migration", v1_12.AddReviewMigrateInfo), // v126 -> v127 - NewMigration("Fix topic repository count", fixTopicRepositoryCount), + NewMigration("Fix topic repository count", v1_12.FixTopicRepositoryCount), // v127 -> v128 - NewMigration("add repository code language statistics", addLanguageStats), + NewMigration("add repository code language statistics", v1_12.AddLanguageStats), // v128 -> v129 - NewMigration("fix merge base for pull requests", fixMergeBase), + NewMigration("fix merge base for pull requests", v1_12.FixMergeBase), // v129 -> v130 - NewMigration("remove dependencies from deleted repositories", purgeUnusedDependencies), + NewMigration("remove dependencies from deleted repositories", v1_12.PurgeUnusedDependencies), // v130 -> v131 - NewMigration("Expand webhooks for more granularity", expandWebhooks), + NewMigration("Expand webhooks for more granularity", v1_12.ExpandWebhooks), // v131 -> v132 - NewMigration("Add IsSystemWebhook column to webhooks table", addSystemWebhookColumn), + NewMigration("Add IsSystemWebhook column to webhooks table", v1_12.AddSystemWebhookColumn), // v132 -> v133 - NewMigration("Add Branch Protection Protected Files Column", addBranchProtectionProtectedFilesColumn), + NewMigration("Add Branch Protection Protected Files Column", v1_12.AddBranchProtectionProtectedFilesColumn), // v133 -> v134 - NewMigration("Add EmailHash Table", addEmailHashTable), + NewMigration("Add EmailHash Table", v1_12.AddEmailHashTable), // v134 -> v135 - NewMigration("Refix merge base for merged pull requests", refixMergeBase), + NewMigration("Refix merge base for merged pull requests", v1_12.RefixMergeBase), // v135 -> v136 - NewMigration("Add OrgID column to Labels table", addOrgIDLabelColumn), + NewMigration("Add OrgID column to Labels table", v1_12.AddOrgIDLabelColumn), // v136 -> v137 - NewMigration("Add CommitsAhead and CommitsBehind Column to PullRequest Table", addCommitDivergenceToPulls), + NewMigration("Add CommitsAhead and CommitsBehind Column to PullRequest Table", v1_12.AddCommitDivergenceToPulls), // v137 -> v138 - NewMigration("Add Branch Protection Block Outdated Branch", addBlockOnOutdatedBranch), + NewMigration("Add Branch Protection Block Outdated Branch", v1_12.AddBlockOnOutdatedBranch), // v138 -> v139 - NewMigration("Add ResolveDoerID to Comment table", addResolveDoerIDCommentColumn), + NewMigration("Add ResolveDoerID to Comment table", v1_12.AddResolveDoerIDCommentColumn), // v139 -> v140 - NewMigration("prepend refs/heads/ to issue refs", prependRefsHeadsToIssueRefs), + NewMigration("prepend refs/heads/ to issue refs", v1_12.PrependRefsHeadsToIssueRefs), // Gitea 1.12.0 ends at v140 // v140 -> v141 - NewMigration("Save detected language file size to database instead of percent", fixLanguageStatsToSaveSize), + NewMigration("Save detected language file size to database instead of percent", v1_13.FixLanguageStatsToSaveSize), // v141 -> v142 - NewMigration("Add KeepActivityPrivate to User table", addKeepActivityPrivateUserColumn), + NewMigration("Add KeepActivityPrivate to User table", v1_13.AddKeepActivityPrivateUserColumn), // v142 -> v143 - NewMigration("Ensure Repository.IsArchived is not null", setIsArchivedToFalse), + NewMigration("Ensure Repository.IsArchived is not null", v1_13.SetIsArchivedToFalse), // v143 -> v144 - NewMigration("recalculate Stars number for all user", recalculateStars), + NewMigration("recalculate Stars number for all user", v1_13.RecalculateStars), // v144 -> v145 - NewMigration("update Matrix Webhook http method to 'PUT'", updateMatrixWebhookHTTPMethod), + NewMigration("update Matrix Webhook http method to 'PUT'", v1_13.UpdateMatrixWebhookHTTPMethod), // v145 -> v146 - NewMigration("Increase Language field to 50 in LanguageStats", increaseLanguageField), + NewMigration("Increase Language field to 50 in LanguageStats", v1_13.IncreaseLanguageField), // v146 -> v147 - NewMigration("Add projects info to repository table", addProjectsInfo), + NewMigration("Add projects info to repository table", v1_13.AddProjectsInfo), // v147 -> v148 - NewMigration("create review for 0 review id code comments", createReviewsForCodeComments), + NewMigration("create review for 0 review id code comments", v1_13.CreateReviewsForCodeComments), // v148 -> v149 - NewMigration("remove issue dependency comments who refer to non existing issues", purgeInvalidDependenciesComments), + NewMigration("remove issue dependency comments who refer to non existing issues", v1_13.PurgeInvalidDependenciesComments), // v149 -> v150 - NewMigration("Add Created and Updated to Milestone table", addCreatedAndUpdatedToMilestones), + NewMigration("Add Created and Updated to Milestone table", v1_13.AddCreatedAndUpdatedToMilestones), // v150 -> v151 - NewMigration("add primary key to repo_topic", addPrimaryKeyToRepoTopic), + NewMigration("add primary key to repo_topic", v1_13.AddPrimaryKeyToRepoTopic), // v151 -> v152 - NewMigration("set default password algorithm to Argon2", setDefaultPasswordToArgon2), + NewMigration("set default password algorithm to Argon2", v1_13.SetDefaultPasswordToArgon2), // v152 -> v153 - NewMigration("add TrustModel field to Repository", addTrustModelToRepository), + NewMigration("add TrustModel field to Repository", v1_13.AddTrustModelToRepository), // v153 > v154 - NewMigration("add Team review request support", addTeamReviewRequestSupport), + NewMigration("add Team review request support", v1_13.AddTeamReviewRequestSupport), // v154 > v155 - NewMigration("add timestamps to Star, Label, Follow, Watch and Collaboration", addTimeStamps), + NewMigration("add timestamps to Star, Label, Follow, Watch and Collaboration", v1_13.AddTimeStamps), // Gitea 1.13.0 ends at v155 // v155 -> v156 - NewMigration("add changed_protected_files column for pull_request table", addChangedProtectedFilesPullRequestColumn), + NewMigration("add changed_protected_files column for pull_request table", v1_14.AddChangedProtectedFilesPullRequestColumn), // v156 -> v157 - NewMigration("fix publisher ID for tag releases", fixPublisherIDforTagReleases), + NewMigration("fix publisher ID for tag releases", v1_14.FixPublisherIDforTagReleases), // v157 -> v158 - NewMigration("ensure repo topics are up-to-date", fixRepoTopics), + NewMigration("ensure repo topics are up-to-date", v1_14.FixRepoTopics), // v158 -> v159 - NewMigration("code comment replies should have the commitID of the review they are replying to", updateCodeCommentReplies), + NewMigration("code comment replies should have the commitID of the review they are replying to", v1_14.UpdateCodeCommentReplies), // v159 -> v160 - NewMigration("update reactions constraint", updateReactionConstraint), + NewMigration("update reactions constraint", v1_14.UpdateReactionConstraint), // v160 -> v161 - NewMigration("Add block on official review requests branch protection", addBlockOnOfficialReviewRequests), + NewMigration("Add block on official review requests branch protection", v1_14.AddBlockOnOfficialReviewRequests), // v161 -> v162 - NewMigration("Convert task type from int to string", convertTaskTypeToString), + NewMigration("Convert task type from int to string", v1_14.ConvertTaskTypeToString), // v162 -> v163 - NewMigration("Convert webhook task type from int to string", convertWebhookTaskTypeToString), + NewMigration("Convert webhook task type from int to string", v1_14.ConvertWebhookTaskTypeToString), // v163 -> v164 - NewMigration("Convert topic name from 25 to 50", convertTopicNameFrom25To50), + NewMigration("Convert topic name from 25 to 50", v1_14.ConvertTopicNameFrom25To50), // v164 -> v165 - NewMigration("Add scope and nonce columns to oauth2_grant table", addScopeAndNonceColumnsToOAuth2Grant), + NewMigration("Add scope and nonce columns to oauth2_grant table", v1_14.AddScopeAndNonceColumnsToOAuth2Grant), // v165 -> v166 - NewMigration("Convert hook task type from char(16) to varchar(16) and trim the column", convertHookTaskTypeToVarcharAndTrim), + NewMigration("Convert hook task type from char(16) to varchar(16) and trim the column", v1_14.ConvertHookTaskTypeToVarcharAndTrim), // v166 -> v167 - NewMigration("Where Password is Valid with Empty String delete it", recalculateUserEmptyPWD), + NewMigration("Where Password is Valid with Empty String delete it", v1_14.RecalculateUserEmptyPWD), // v167 -> v168 - NewMigration("Add user redirect", addUserRedirect), + NewMigration("Add user redirect", v1_14.AddUserRedirect), // v168 -> v169 - NewMigration("Recreate user table to fix default values", recreateUserTableToFixDefaultValues), + NewMigration("Recreate user table to fix default values", v1_14.RecreateUserTableToFixDefaultValues), // v169 -> v170 - NewMigration("Update DeleteBranch comments to set the old_ref to the commit_sha", commentTypeDeleteBranchUseOldRef), + NewMigration("Update DeleteBranch comments to set the old_ref to the commit_sha", v1_14.CommentTypeDeleteBranchUseOldRef), // v170 -> v171 - NewMigration("Add Dismissed to Review table", addDismissedReviewColumn), + NewMigration("Add Dismissed to Review table", v1_14.AddDismissedReviewColumn), // v171 -> v172 - NewMigration("Add Sorting to ProjectBoard table", addSortingColToProjectBoard), + NewMigration("Add Sorting to ProjectBoard table", v1_14.AddSortingColToProjectBoard), // v172 -> v173 - NewMigration("Add sessions table for go-chi/session", addSessionTable), + NewMigration("Add sessions table for go-chi/session", v1_14.AddSessionTable), // v173 -> v174 - NewMigration("Add time_id column to Comment", addTimeIDCommentColumn), + NewMigration("Add time_id column to Comment", v1_14.AddTimeIDCommentColumn), // v174 -> v175 - NewMigration("Create repo transfer table", addRepoTransfer), + NewMigration("Create repo transfer table", v1_14.AddRepoTransfer), // v175 -> v176 - NewMigration("Fix Postgres ID Sequences broken by recreate-table", fixPostgresIDSequences), + NewMigration("Fix Postgres ID Sequences broken by recreate-table", v1_14.FixPostgresIDSequences), // v176 -> v177 - NewMigration("Remove invalid labels from comments", removeInvalidLabels), + NewMigration("Remove invalid labels from comments", v1_14.RemoveInvalidLabels), // v177 -> v178 - NewMigration("Delete orphaned IssueLabels", deleteOrphanedIssueLabels), + NewMigration("Delete orphaned IssueLabels", v1_14.DeleteOrphanedIssueLabels), // Gitea 1.14.0 ends at v178 // v178 -> v179 - NewMigration("Add LFS columns to Mirror", addLFSMirrorColumns), + NewMigration("Add LFS columns to Mirror", v1_15.AddLFSMirrorColumns), // v179 -> v180 - NewMigration("Convert avatar url to text", convertAvatarURLToText), + NewMigration("Convert avatar url to text", v1_15.ConvertAvatarURLToText), // v180 -> v181 - NewMigration("Delete credentials from past migrations", deleteMigrationCredentials), + NewMigration("Delete credentials from past migrations", v1_15.DeleteMigrationCredentials), // v181 -> v182 - NewMigration("Always save primary email on email address table", addPrimaryEmail2EmailAddress), + NewMigration("Always save primary email on email address table", v1_15.AddPrimaryEmail2EmailAddress), // v182 -> v183 - NewMigration("Add issue resource index table", addIssueResourceIndexTable), + NewMigration("Add issue resource index table", v1_15.AddIssueResourceIndexTable), // v183 -> v184 - NewMigration("Create PushMirror table", createPushMirrorTable), + NewMigration("Create PushMirror table", v1_15.CreatePushMirrorTable), // v184 -> v185 - NewMigration("Rename Task errors to message", renameTaskErrorsToMessage), + NewMigration("Rename Task errors to message", v1_15.RenameTaskErrorsToMessage), // v185 -> v186 - NewMigration("Add new table repo_archiver", addRepoArchiver), + NewMigration("Add new table repo_archiver", v1_15.AddRepoArchiver), // v186 -> v187 - NewMigration("Create protected tag table", createProtectedTagTable), + NewMigration("Create protected tag table", v1_15.CreateProtectedTagTable), // v187 -> v188 - NewMigration("Drop unneeded webhook related columns", dropWebhookColumns), + NewMigration("Drop unneeded webhook related columns", v1_15.DropWebhookColumns), // v188 -> v189 - NewMigration("Add key is verified to gpg key", addKeyIsVerified), + NewMigration("Add key is verified to gpg key", v1_15.AddKeyIsVerified), // Gitea 1.15.0 ends at v189 // v189 -> v190 - NewMigration("Unwrap ldap.Sources", unwrapLDAPSourceCfg), + NewMigration("Unwrap ldap.Sources", v1_16.UnwrapLDAPSourceCfg), // v190 -> v191 - NewMigration("Add agit flow pull request support", addAgitFlowPullRequest), + NewMigration("Add agit flow pull request support", v1_16.AddAgitFlowPullRequest), // v191 -> v192 - NewMigration("Alter issue/comment table TEXT fields to LONGTEXT", alterIssueAndCommentTextFieldsToLongText), + NewMigration("Alter issue/comment table TEXT fields to LONGTEXT", v1_16.AlterIssueAndCommentTextFieldsToLongText), // v192 -> v193 - NewMigration("RecreateIssueResourceIndexTable to have a primary key instead of an unique index", recreateIssueResourceIndexTable), + NewMigration("RecreateIssueResourceIndexTable to have a primary key instead of an unique index", v1_16.RecreateIssueResourceIndexTable), // v193 -> v194 - NewMigration("Add repo id column for attachment table", addRepoIDForAttachment), + NewMigration("Add repo id column for attachment table", v1_16.AddRepoIDForAttachment), // v194 -> v195 - NewMigration("Add Branch Protection Unprotected Files Column", addBranchProtectionUnprotectedFilesColumn), + NewMigration("Add Branch Protection Unprotected Files Column", v1_16.AddBranchProtectionUnprotectedFilesColumn), // v195 -> v196 - NewMigration("Add table commit_status_index", addTableCommitStatusIndex), + NewMigration("Add table commit_status_index", v1_16.AddTableCommitStatusIndex), // v196 -> v197 - NewMigration("Add Color to ProjectBoard table", addColorColToProjectBoard), + NewMigration("Add Color to ProjectBoard table", v1_16.AddColorColToProjectBoard), // v197 -> v198 - NewMigration("Add renamed_branch table", addRenamedBranchTable), + NewMigration("Add renamed_branch table", v1_16.AddRenamedBranchTable), // v198 -> v199 - NewMigration("Add issue content history table", addTableIssueContentHistory), + NewMigration("Add issue content history table", v1_16.AddTableIssueContentHistory), // v199 -> v200 NewMigration("No-op (remote version is using AppState now)", noopMigration), // v200 -> v201 - NewMigration("Add table app_state", addTableAppState), + NewMigration("Add table app_state", v1_16.AddTableAppState), // v201 -> v202 - NewMigration("Drop table remote_version (if exists)", dropTableRemoteVersion), + NewMigration("Drop table remote_version (if exists)", v1_16.DropTableRemoteVersion), // v202 -> v203 - NewMigration("Create key/value table for user settings", createUserSettingsTable), + NewMigration("Create key/value table for user settings", v1_16.CreateUserSettingsTable), // v203 -> v204 - NewMigration("Add Sorting to ProjectIssue table", addProjectIssueSorting), + NewMigration("Add Sorting to ProjectIssue table", v1_16.AddProjectIssueSorting), // v204 -> v205 - NewMigration("Add key is verified to ssh key", addSSHKeyIsVerified), + NewMigration("Add key is verified to ssh key", v1_16.AddSSHKeyIsVerified), // v205 -> v206 - NewMigration("Migrate to higher varchar on user struct", migrateUserPasswordSalt), + NewMigration("Migrate to higher varchar on user struct", v1_16.MigrateUserPasswordSalt), // v206 -> v207 - NewMigration("Add authorize column to team_unit table", addAuthorizeColForTeamUnit), + NewMigration("Add authorize column to team_unit table", v1_16.AddAuthorizeColForTeamUnit), // v207 -> v208 - NewMigration("Add webauthn table and migrate u2f data to webauthn - NO-OPED", addWebAuthnCred), + NewMigration("Add webauthn table and migrate u2f data to webauthn - NO-OPED", v1_16.AddWebAuthnCred), // v208 -> v209 - NewMigration("Use base32.HexEncoding instead of base64 encoding for cred ID as it is case insensitive - NO-OPED", useBase32HexForCredIDInWebAuthnCredential), + NewMigration("Use base32.HexEncoding instead of base64 encoding for cred ID as it is case insensitive - NO-OPED", v1_16.UseBase32HexForCredIDInWebAuthnCredential), // v209 -> v210 - NewMigration("Increase WebAuthentication CredentialID size to 410 - NO-OPED", increaseCredentialIDTo410), + NewMigration("Increase WebAuthentication CredentialID size to 410 - NO-OPED", v1_16.IncreaseCredentialIDTo410), // v210 -> v211 - NewMigration("v208 was completely broken - remigrate", remigrateU2FCredentials), + NewMigration("v208 was completely broken - remigrate", v1_16.RemigrateU2FCredentials), // Gitea 1.16.2 ends at v211 // v211 -> v212 - NewMigration("Create ForeignReference table", createForeignReferenceTable), + NewMigration("Create ForeignReference table", v1_17.CreateForeignReferenceTable), // v212 -> v213 - NewMigration("Add package tables", addPackageTables), + NewMigration("Add package tables", v1_17.AddPackageTables), // v213 -> v214 - NewMigration("Add allow edits from maintainers to PullRequest table", addAllowMaintainerEdit), + NewMigration("Add allow edits from maintainers to PullRequest table", v1_17.AddAllowMaintainerEdit), // v214 -> v215 - NewMigration("Add auto merge table", addAutoMergeTable), + NewMigration("Add auto merge table", v1_17.AddAutoMergeTable), // v215 -> v216 - NewMigration("allow to view files in PRs", addReviewViewedFiles), + NewMigration("allow to view files in PRs", v1_17.AddReviewViewedFiles), // v216 -> v217 NewMigration("No-op (Improve Action table indices v1)", noopMigration), // v217 -> v218 - NewMigration("Alter hook_task table TEXT fields to LONGTEXT", alterHookTaskTextFieldsToLongText), + NewMigration("Alter hook_task table TEXT fields to LONGTEXT", v1_17.AlterHookTaskTextFieldsToLongText), // v218 -> v219 - NewMigration("Improve Action table indices v2", improveActionTableIndices), + NewMigration("Improve Action table indices v2", v1_17.ImproveActionTableIndices), // v219 -> v220 - NewMigration("Add sync_on_commit column to push_mirror table", addSyncOnCommitColForPushMirror), + NewMigration("Add sync_on_commit column to push_mirror table", v1_17.AddSyncOnCommitColForPushMirror), // v220 -> v221 - NewMigration("Add container repository property", addContainerRepositoryProperty), + NewMigration("Add container repository property", v1_17.AddContainerRepositoryProperty), // v221 -> v222 - NewMigration("Store WebAuthentication CredentialID as bytes and increase size to at least 1024", storeWebauthnCredentialIDAsBytes), + NewMigration("Store WebAuthentication CredentialID as bytes and increase size to at least 1024", v1_17.StoreWebauthnCredentialIDAsBytes), // v222 -> v223 - NewMigration("Drop old CredentialID column", dropOldCredentialIDColumn), + NewMigration("Drop old CredentialID column", v1_17.DropOldCredentialIDColumn), // v223 -> v224 - NewMigration("Rename CredentialIDBytes column to CredentialID", renameCredentialIDBytes), + NewMigration("Rename CredentialIDBytes column to CredentialID", v1_17.RenameCredentialIDBytes), // Gitea 1.17.0 ends at v224 // v224 -> v225 - NewMigration("Add badges to users", createUserBadgesTable), + NewMigration("Add badges to users", v1_18.CreateUserBadgesTable), // v225 -> v226 - NewMigration("Alter gpg_key/public_key content TEXT fields to MEDIUMTEXT", alterPublicGPGKeyContentFieldsToMediumText), + NewMigration("Alter gpg_key/public_key content TEXT fields to MEDIUMTEXT", v1_18.AlterPublicGPGKeyContentFieldsToMediumText), // v226 -> v227 - NewMigration("Conan and generic packages do not need to be semantically versioned", fixPackageSemverField), + NewMigration("Conan and generic packages do not need to be semantically versioned", v1_18.FixPackageSemverField), // v227 -> v228 - NewMigration("Create key/value table for system settings", createSystemSettingsTable), + NewMigration("Create key/value table for system settings", v1_18.CreateSystemSettingsTable), // v228 -> v229 - NewMigration("Add TeamInvite table", addTeamInviteTable), + NewMigration("Add TeamInvite table", v1_18.AddTeamInviteTable), // v229 -> v230 - NewMigration("Update counts of all open milestones", updateOpenMilestoneCounts), + NewMigration("Update counts of all open milestones", v1_18.UpdateOpenMilestoneCounts), // v230 -> v231 - NewMigration("Add ConfidentialClient column (default true) to OAuth2Application table", addConfidentialClientColumnToOAuth2ApplicationTable), + NewMigration("Add ConfidentialClient column (default true) to OAuth2Application table", v1_18.AddConfidentialClientColumnToOAuth2ApplicationTable), + // v231 -> v232 + NewMigration("Add index for hook_task", v1_19.AddIndexForHookTask), + // v232 -> v233 + NewMigration("Alter package_version.metadata_json to LONGTEXT", v1_19.AlterPackageVersionMetadataToLongText), + // v233 -> v234 + NewMigration("Add header_authorization_encrypted column to webhook table", v1_19.AddHeaderAuthorizationEncryptedColWebhook), } // GetCurrentDBVersion returns the current db version @@ -528,499 +542,3 @@ Please try upgrading to a lower version first (suggested v1.6.4), then upgrade t } return nil } - -// RecreateTables will recreate the tables for the provided beans using the newly provided bean definition and move all data to that new table -// WARNING: YOU MUST PROVIDE THE FULL BEAN DEFINITION -func RecreateTables(beans ...interface{}) func(*xorm.Engine) error { - return func(x *xorm.Engine) error { - sess := x.NewSession() - defer sess.Close() - if err := sess.Begin(); err != nil { - return err - } - sess = sess.StoreEngine("InnoDB") - for _, bean := range beans { - log.Info("Recreating Table: %s for Bean: %s", x.TableName(bean), reflect.Indirect(reflect.ValueOf(bean)).Type().Name()) - if err := recreateTable(sess, bean); err != nil { - return err - } - } - return sess.Commit() - } -} - -// recreateTable will recreate the table using the newly provided bean definition and move all data to that new table -// WARNING: YOU MUST PROVIDE THE FULL BEAN DEFINITION -// WARNING: YOU MUST COMMIT THE SESSION AT THE END -func recreateTable(sess *xorm.Session, bean interface{}) error { - // TODO: This will not work if there are foreign keys - - tableName := sess.Engine().TableName(bean) - tempTableName := fmt.Sprintf("tmp_recreate__%s", tableName) - - // We need to move the old table away and create a new one with the correct columns - // We will need to do this in stages to prevent data loss - // - // First create the temporary table - if err := sess.Table(tempTableName).CreateTable(bean); err != nil { - log.Error("Unable to create table %s. Error: %v", tempTableName, err) - return err - } - - if err := sess.Table(tempTableName).CreateUniques(bean); err != nil { - log.Error("Unable to create uniques for table %s. Error: %v", tempTableName, err) - return err - } - - if err := sess.Table(tempTableName).CreateIndexes(bean); err != nil { - log.Error("Unable to create indexes for table %s. Error: %v", tempTableName, err) - return err - } - - // Work out the column names from the bean - these are the columns to select from the old table and install into the new table - table, err := sess.Engine().TableInfo(bean) - if err != nil { - log.Error("Unable to get table info. Error: %v", err) - - return err - } - newTableColumns := table.Columns() - if len(newTableColumns) == 0 { - return fmt.Errorf("no columns in new table") - } - hasID := false - for _, column := range newTableColumns { - hasID = hasID || (column.IsPrimaryKey && column.IsAutoIncrement) - } - - if hasID && setting.Database.UseMSSQL { - if _, err := sess.Exec(fmt.Sprintf("SET IDENTITY_INSERT `%s` ON", tempTableName)); err != nil { - log.Error("Unable to set identity insert for table %s. Error: %v", tempTableName, err) - return err - } - } - - sqlStringBuilder := &strings.Builder{} - _, _ = sqlStringBuilder.WriteString("INSERT INTO `") - _, _ = sqlStringBuilder.WriteString(tempTableName) - _, _ = sqlStringBuilder.WriteString("` (`") - _, _ = sqlStringBuilder.WriteString(newTableColumns[0].Name) - _, _ = sqlStringBuilder.WriteString("`") - for _, column := range newTableColumns[1:] { - _, _ = sqlStringBuilder.WriteString(", `") - _, _ = sqlStringBuilder.WriteString(column.Name) - _, _ = sqlStringBuilder.WriteString("`") - } - _, _ = sqlStringBuilder.WriteString(")") - _, _ = sqlStringBuilder.WriteString(" SELECT ") - if newTableColumns[0].Default != "" { - _, _ = sqlStringBuilder.WriteString("COALESCE(`") - _, _ = sqlStringBuilder.WriteString(newTableColumns[0].Name) - _, _ = sqlStringBuilder.WriteString("`, ") - _, _ = sqlStringBuilder.WriteString(newTableColumns[0].Default) - _, _ = sqlStringBuilder.WriteString(")") - } else { - _, _ = sqlStringBuilder.WriteString("`") - _, _ = sqlStringBuilder.WriteString(newTableColumns[0].Name) - _, _ = sqlStringBuilder.WriteString("`") - } - - for _, column := range newTableColumns[1:] { - if column.Default != "" { - _, _ = sqlStringBuilder.WriteString(", COALESCE(`") - _, _ = sqlStringBuilder.WriteString(column.Name) - _, _ = sqlStringBuilder.WriteString("`, ") - _, _ = sqlStringBuilder.WriteString(column.Default) - _, _ = sqlStringBuilder.WriteString(")") - } else { - _, _ = sqlStringBuilder.WriteString(", `") - _, _ = sqlStringBuilder.WriteString(column.Name) - _, _ = sqlStringBuilder.WriteString("`") - } - } - _, _ = sqlStringBuilder.WriteString(" FROM `") - _, _ = sqlStringBuilder.WriteString(tableName) - _, _ = sqlStringBuilder.WriteString("`") - - if _, err := sess.Exec(sqlStringBuilder.String()); err != nil { - log.Error("Unable to set copy data in to temp table %s. Error: %v", tempTableName, err) - return err - } - - if hasID && setting.Database.UseMSSQL { - if _, err := sess.Exec(fmt.Sprintf("SET IDENTITY_INSERT `%s` OFF", tempTableName)); err != nil { - log.Error("Unable to switch off identity insert for table %s. Error: %v", tempTableName, err) - return err - } - } - - switch { - case setting.Database.UseSQLite3: - // SQLite will drop all the constraints on the old table - if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil { - log.Error("Unable to drop old table %s. Error: %v", tableName, err) - return err - } - - if err := sess.Table(tempTableName).DropIndexes(bean); err != nil { - log.Error("Unable to drop indexes on temporary table %s. Error: %v", tempTableName, err) - return err - } - - if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` RENAME TO `%s`", tempTableName, tableName)); err != nil { - log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) - return err - } - - if err := sess.Table(tableName).CreateIndexes(bean); err != nil { - log.Error("Unable to recreate indexes on table %s. Error: %v", tableName, err) - return err - } - - if err := sess.Table(tableName).CreateUniques(bean); err != nil { - log.Error("Unable to recreate uniques on table %s. Error: %v", tableName, err) - return err - } - - case setting.Database.UseMySQL: - // MySQL will drop all the constraints on the old table - if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil { - log.Error("Unable to drop old table %s. Error: %v", tableName, err) - return err - } - - if err := sess.Table(tempTableName).DropIndexes(bean); err != nil { - log.Error("Unable to drop indexes on temporary table %s. Error: %v", tempTableName, err) - return err - } - - // SQLite and MySQL will move all the constraints from the temporary table to the new table - if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` RENAME TO `%s`", tempTableName, tableName)); err != nil { - log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) - return err - } - - if err := sess.Table(tableName).CreateIndexes(bean); err != nil { - log.Error("Unable to recreate indexes on table %s. Error: %v", tableName, err) - return err - } - - if err := sess.Table(tableName).CreateUniques(bean); err != nil { - log.Error("Unable to recreate uniques on table %s. Error: %v", tableName, err) - return err - } - case setting.Database.UsePostgreSQL: - var originalSequences []string - type sequenceData struct { - LastValue int `xorm:"'last_value'"` - IsCalled bool `xorm:"'is_called'"` - } - sequenceMap := map[string]sequenceData{} - - schema := sess.Engine().Dialect().URI().Schema - sess.Engine().SetSchema("") - if err := sess.Table("information_schema.sequences").Cols("sequence_name").Where("sequence_name LIKE ? || '_%' AND sequence_catalog = ?", tableName, setting.Database.Name).Find(&originalSequences); err != nil { - log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) - return err - } - sess.Engine().SetSchema(schema) - - for _, sequence := range originalSequences { - sequenceData := sequenceData{} - if _, err := sess.Table(sequence).Cols("last_value", "is_called").Get(&sequenceData); err != nil { - log.Error("Unable to get last_value and is_called from %s. Error: %v", sequence, err) - return err - } - sequenceMap[sequence] = sequenceData - - } - - // CASCADE causes postgres to drop all the constraints on the old table - if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s` CASCADE", tableName)); err != nil { - log.Error("Unable to drop old table %s. Error: %v", tableName, err) - return err - } - - // CASCADE causes postgres to move all the constraints from the temporary table to the new table - if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` RENAME TO `%s`", tempTableName, tableName)); err != nil { - log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) - return err - } - - var indices []string - sess.Engine().SetSchema("") - if err := sess.Table("pg_indexes").Cols("indexname").Where("tablename = ? ", tableName).Find(&indices); err != nil { - log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) - return err - } - sess.Engine().SetSchema(schema) - - for _, index := range indices { - newIndexName := strings.Replace(index, "tmp_recreate__", "", 1) - if _, err := sess.Exec(fmt.Sprintf("ALTER INDEX `%s` RENAME TO `%s`", index, newIndexName)); err != nil { - log.Error("Unable to rename %s to %s. Error: %v", index, newIndexName, err) - return err - } - } - - var sequences []string - sess.Engine().SetSchema("") - if err := sess.Table("information_schema.sequences").Cols("sequence_name").Where("sequence_name LIKE 'tmp_recreate__' || ? || '_%' AND sequence_catalog = ?", tableName, setting.Database.Name).Find(&sequences); err != nil { - log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) - return err - } - sess.Engine().SetSchema(schema) - - for _, sequence := range sequences { - newSequenceName := strings.Replace(sequence, "tmp_recreate__", "", 1) - if _, err := sess.Exec(fmt.Sprintf("ALTER SEQUENCE `%s` RENAME TO `%s`", sequence, newSequenceName)); err != nil { - log.Error("Unable to rename %s sequence to %s. Error: %v", sequence, newSequenceName, err) - return err - } - val, ok := sequenceMap[newSequenceName] - if newSequenceName == tableName+"_id_seq" { - if ok && val.LastValue != 0 { - if _, err := sess.Exec(fmt.Sprintf("SELECT setval('%s', %d, %t)", newSequenceName, val.LastValue, val.IsCalled)); err != nil { - log.Error("Unable to reset %s to %d. Error: %v", newSequenceName, val, err) - return err - } - } else { - // We're going to try to guess this - if _, err := sess.Exec(fmt.Sprintf("SELECT setval('%s', COALESCE((SELECT MAX(id)+1 FROM `%s`), 1), false)", newSequenceName, tableName)); err != nil { - log.Error("Unable to reset %s. Error: %v", newSequenceName, err) - return err - } - } - } else if ok { - if _, err := sess.Exec(fmt.Sprintf("SELECT setval('%s', %d, %t)", newSequenceName, val.LastValue, val.IsCalled)); err != nil { - log.Error("Unable to reset %s to %d. Error: %v", newSequenceName, val, err) - return err - } - } - - } - - case setting.Database.UseMSSQL: - // MSSQL will drop all the constraints on the old table - if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil { - log.Error("Unable to drop old table %s. Error: %v", tableName, err) - return err - } - - // MSSQL sp_rename will move all the constraints from the temporary table to the new table - if _, err := sess.Exec(fmt.Sprintf("sp_rename `%s`,`%s`", tempTableName, tableName)); err != nil { - log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) - return err - } - - default: - log.Fatal("Unrecognized DB") - } - return nil -} - -// WARNING: YOU MUST COMMIT THE SESSION AT THE END -func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...string) (err error) { - if tableName == "" || len(columnNames) == 0 { - return nil - } - // TODO: This will not work if there are foreign keys - - switch { - case setting.Database.UseSQLite3: - // First drop the indexes on the columns - res, errIndex := sess.Query(fmt.Sprintf("PRAGMA index_list(`%s`)", tableName)) - if errIndex != nil { - return errIndex - } - for _, row := range res { - indexName := row["name"] - indexRes, err := sess.Query(fmt.Sprintf("PRAGMA index_info(`%s`)", indexName)) - if err != nil { - return err - } - if len(indexRes) != 1 { - continue - } - indexColumn := string(indexRes[0]["name"]) - for _, name := range columnNames { - if name == indexColumn { - _, err := sess.Exec(fmt.Sprintf("DROP INDEX `%s`", indexName)) - if err != nil { - return err - } - } - } - } - - // Here we need to get the columns from the original table - sql := fmt.Sprintf("SELECT sql FROM sqlite_master WHERE tbl_name='%s' and type='table'", tableName) - res, err := sess.Query(sql) - if err != nil { - return err - } - tableSQL := string(res[0]["sql"]) - - // Get the string offset for column definitions: `CREATE TABLE ( column-definitions... )` - columnDefinitionsIndex := strings.Index(tableSQL, "(") - if columnDefinitionsIndex < 0 { - return errors.New("couldn't find column definitions") - } - - // Separate out the column definitions - tableSQL = tableSQL[columnDefinitionsIndex:] - - // Remove the required columnNames - for _, name := range columnNames { - tableSQL = regexp.MustCompile(regexp.QuoteMeta("`"+name+"`")+"[^`,)]*?[,)]").ReplaceAllString(tableSQL, "") - } - - // Ensure the query is ended properly - tableSQL = strings.TrimSpace(tableSQL) - if tableSQL[len(tableSQL)-1] != ')' { - if tableSQL[len(tableSQL)-1] == ',' { - tableSQL = tableSQL[:len(tableSQL)-1] - } - tableSQL += ")" - } - - // Find all the columns in the table - columns := regexp.MustCompile("`([^`]*)`").FindAllString(tableSQL, -1) - - tableSQL = fmt.Sprintf("CREATE TABLE `new_%s_new` ", tableName) + tableSQL - if _, err := sess.Exec(tableSQL); err != nil { - return err - } - - // Now restore the data - columnsSeparated := strings.Join(columns, ",") - insertSQL := fmt.Sprintf("INSERT INTO `new_%s_new` (%s) SELECT %s FROM %s", tableName, columnsSeparated, columnsSeparated, tableName) - if _, err := sess.Exec(insertSQL); err != nil { - return err - } - - // Now drop the old table - if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil { - return err - } - - // Rename the table - if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `new_%s_new` RENAME TO `%s`", tableName, tableName)); err != nil { - return err - } - - case setting.Database.UsePostgreSQL: - cols := "" - for _, col := range columnNames { - if cols != "" { - cols += ", " - } - cols += "DROP COLUMN `" + col + "` CASCADE" - } - if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil { - return fmt.Errorf("Drop table `%s` columns %v: %w", tableName, columnNames, err) - } - case setting.Database.UseMySQL: - // Drop indexes on columns first - sql := fmt.Sprintf("SHOW INDEX FROM %s WHERE column_name IN ('%s')", tableName, strings.Join(columnNames, "','")) - res, err := sess.Query(sql) - if err != nil { - return err - } - for _, index := range res { - indexName := index["column_name"] - if len(indexName) > 0 { - _, err := sess.Exec(fmt.Sprintf("DROP INDEX `%s` ON `%s`", indexName, tableName)) - if err != nil { - return err - } - } - } - - // Now drop the columns - cols := "" - for _, col := range columnNames { - if cols != "" { - cols += ", " - } - cols += "DROP COLUMN `" + col + "`" - } - if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil { - return fmt.Errorf("Drop table `%s` columns %v: %w", tableName, columnNames, err) - } - case setting.Database.UseMSSQL: - cols := "" - for _, col := range columnNames { - if cols != "" { - cols += ", " - } - cols += "`" + strings.ToLower(col) + "`" - } - sql := fmt.Sprintf("SELECT Name FROM sys.default_constraints WHERE parent_object_id = OBJECT_ID('%[1]s') AND parent_column_id IN (SELECT column_id FROM sys.columns WHERE LOWER(name) IN (%[2]s) AND object_id = OBJECT_ID('%[1]s'))", - tableName, strings.ReplaceAll(cols, "`", "'")) - constraints := make([]string, 0) - if err := sess.SQL(sql).Find(&constraints); err != nil { - return fmt.Errorf("Find constraints: %w", err) - } - for _, constraint := range constraints { - if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` DROP CONSTRAINT `%s`", tableName, constraint)); err != nil { - return fmt.Errorf("Drop table `%s` default constraint `%s`: %w", tableName, constraint, err) - } - } - sql = fmt.Sprintf("SELECT DISTINCT Name FROM sys.indexes INNER JOIN sys.index_columns ON indexes.index_id = index_columns.index_id AND indexes.object_id = index_columns.object_id WHERE indexes.object_id = OBJECT_ID('%[1]s') AND index_columns.column_id IN (SELECT column_id FROM sys.columns WHERE LOWER(name) IN (%[2]s) AND object_id = OBJECT_ID('%[1]s'))", - tableName, strings.ReplaceAll(cols, "`", "'")) - constraints = make([]string, 0) - if err := sess.SQL(sql).Find(&constraints); err != nil { - return fmt.Errorf("Find constraints: %w", err) - } - for _, constraint := range constraints { - if _, err := sess.Exec(fmt.Sprintf("DROP INDEX `%[2]s` ON `%[1]s`", tableName, constraint)); err != nil { - return fmt.Errorf("Drop index `%s` on `%s`: %w", constraint, tableName, err) - } - } - - if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` DROP COLUMN %s", tableName, cols)); err != nil { - return fmt.Errorf("Drop table `%s` columns %v: %w", tableName, columnNames, err) - } - default: - log.Fatal("Unrecognized DB") - } - - return nil -} - -// modifyColumn will modify column's type or other property. SQLITE is not supported -func modifyColumn(x *xorm.Engine, tableName string, col *schemas.Column) error { - var indexes map[string]*schemas.Index - var err error - // MSSQL have to remove index at first, otherwise alter column will fail - // ref. https://sqlzealots.com/2018/05/09/error-message-the-index-is-dependent-on-column-alter-table-alter-column-failed-because-one-or-more-objects-access-this-column/ - if x.Dialect().URI().DBType == schemas.MSSQL { - indexes, err = x.Dialect().GetIndexes(x.DB(), context.Background(), tableName) - if err != nil { - return err - } - - for _, index := range indexes { - _, err = x.Exec(x.Dialect().DropIndexSQL(tableName, index)) - if err != nil { - return err - } - } - } - - defer func() { - for _, index := range indexes { - _, err = x.Exec(x.Dialect().CreateIndexSQL(tableName, index)) - if err != nil { - log.Error("Create index %s on table %s failed: %v", index.Name, tableName, err) - } - } - }() - - alterSQL := x.Dialect().ModifyColumnSQL(tableName, col) - if _, err := x.Exec(alterSQL); err != nil { - return err - } - return nil -} diff --git a/models/migrations/migrations_test.go b/models/migrations/migrations_test.go deleted file mode 100644 index 5cd70626b..000000000 --- a/models/migrations/migrations_test.go +++ /dev/null @@ -1,365 +0,0 @@ -// Copyright 2021 The Gitea Authors. All rights reserved. -// Use of this source code is governed by a MIT-style -// license that can be found in the LICENSE file. - -package migrations - -import ( - "context" - "database/sql" - "fmt" - "os" - "path" - "path/filepath" - "runtime" - "testing" - "time" - - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/modules/base" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/timeutil" - "code.gitea.io/gitea/modules/util" - - "github.com/stretchr/testify/assert" - "xorm.io/xorm" - "xorm.io/xorm/names" -) - -func TestMain(m *testing.M) { - giteaRoot := base.SetupGiteaRoot() - if giteaRoot == "" { - fmt.Println("Environment variable $GITEA_ROOT not set") - os.Exit(1) - } - giteaBinary := "gitea" - if runtime.GOOS == "windows" { - giteaBinary += ".exe" - } - setting.AppPath = path.Join(giteaRoot, giteaBinary) - if _, err := os.Stat(setting.AppPath); err != nil { - fmt.Printf("Could not find gitea binary at %s\n", setting.AppPath) - os.Exit(1) - } - - giteaConf := os.Getenv("GITEA_CONF") - if giteaConf == "" { - giteaConf = path.Join(filepath.Dir(setting.AppPath), "tests/sqlite.ini") - fmt.Printf("Environment variable $GITEA_CONF not set - defaulting to %s\n", giteaConf) - } - - if !path.IsAbs(giteaConf) { - setting.CustomConf = path.Join(giteaRoot, giteaConf) - } else { - setting.CustomConf = giteaConf - } - - tmpDataPath, err := os.MkdirTemp("", "data") - if err != nil { - fmt.Printf("Unable to create temporary data path %v\n", err) - os.Exit(1) - } - - setting.AppDataPath = tmpDataPath - - setting.SetCustomPathAndConf("", "", "") - setting.LoadForTest() - if err = git.InitFull(context.Background()); err != nil { - fmt.Printf("Unable to InitFull: %v\n", err) - os.Exit(1) - } - setting.InitDBConfig() - setting.NewLogServices(true) - - exitStatus := m.Run() - - if err := removeAllWithRetry(setting.RepoRootPath); err != nil { - fmt.Fprintf(os.Stderr, "os.RemoveAll: %v\n", err) - } - if err := removeAllWithRetry(tmpDataPath); err != nil { - fmt.Fprintf(os.Stderr, "os.RemoveAll: %v\n", err) - } - os.Exit(exitStatus) -} - -func removeAllWithRetry(dir string) error { - var err error - for i := 0; i < 20; i++ { - err = os.RemoveAll(dir) - if err == nil { - break - } - time.Sleep(100 * time.Millisecond) - } - return err -} - -func newXORMEngine() (*xorm.Engine, error) { - if err := db.InitEngine(context.Background()); err != nil { - return nil, err - } - x := unittest.GetXORMEngine() - return x, nil -} - -func deleteDB() error { - switch { - case setting.Database.UseSQLite3: - if err := util.Remove(setting.Database.Path); err != nil { - return err - } - return os.MkdirAll(path.Dir(setting.Database.Path), os.ModePerm) - - case setting.Database.UseMySQL: - db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/", - setting.Database.User, setting.Database.Passwd, setting.Database.Host)) - if err != nil { - return err - } - defer db.Close() - - if _, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", setting.Database.Name)); err != nil { - return err - } - - if _, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", setting.Database.Name)); err != nil { - return err - } - return nil - case setting.Database.UsePostgreSQL: - db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/?sslmode=%s", - setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.SSLMode)) - if err != nil { - return err - } - defer db.Close() - - if _, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", setting.Database.Name)); err != nil { - return err - } - - if _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", setting.Database.Name)); err != nil { - return err - } - db.Close() - - // Check if we need to setup a specific schema - if len(setting.Database.Schema) != 0 { - db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s", - setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name, setting.Database.SSLMode)) - if err != nil { - return err - } - defer db.Close() - - schrows, err := db.Query(fmt.Sprintf("SELECT 1 FROM information_schema.schemata WHERE schema_name = '%s'", setting.Database.Schema)) - if err != nil { - return err - } - defer schrows.Close() - - if !schrows.Next() { - // Create and setup a DB schema - _, err = db.Exec(fmt.Sprintf("CREATE SCHEMA %s", setting.Database.Schema)) - if err != nil { - return err - } - } - - // Make the user's default search path the created schema; this will affect new connections - _, err = db.Exec(fmt.Sprintf(`ALTER USER "%s" SET search_path = %s`, setting.Database.User, setting.Database.Schema)) - if err != nil { - return err - } - return nil - } - case setting.Database.UseMSSQL: - host, port := setting.ParseMSSQLHostPort(setting.Database.Host) - db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", - host, port, "master", setting.Database.User, setting.Database.Passwd)) - if err != nil { - return err - } - defer db.Close() - - if _, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS [%s]", setting.Database.Name)); err != nil { - return err - } - if _, err = db.Exec(fmt.Sprintf("CREATE DATABASE [%s]", setting.Database.Name)); err != nil { - return err - } - } - - return nil -} - -// prepareTestEnv prepares the test environment and reset the database. The skip parameter should usually be 0. -// Provide models to be sync'd with the database - in particular any models you expect fixtures to be loaded from. -// -// fixtures in `models/migrations/fixtures/` will be loaded automatically -func prepareTestEnv(t *testing.T, skip int, syncModels ...interface{}) (*xorm.Engine, func()) { - t.Helper() - ourSkip := 2 - ourSkip += skip - deferFn := PrintCurrentTest(t, ourSkip) - assert.NoError(t, os.RemoveAll(setting.RepoRootPath)) - assert.NoError(t, unittest.CopyDir(path.Join(filepath.Dir(setting.AppPath), "tests/gitea-repositories-meta"), setting.RepoRootPath)) - ownerDirs, err := os.ReadDir(setting.RepoRootPath) - if err != nil { - assert.NoError(t, err, "unable to read the new repo root: %v\n", err) - } - for _, ownerDir := range ownerDirs { - if !ownerDir.Type().IsDir() { - continue - } - repoDirs, err := os.ReadDir(filepath.Join(setting.RepoRootPath, ownerDir.Name())) - if err != nil { - assert.NoError(t, err, "unable to read the new repo root: %v\n", err) - } - for _, repoDir := range repoDirs { - _ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "pack"), 0o755) - _ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "info"), 0o755) - _ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "heads"), 0o755) - _ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "tag"), 0o755) - } - } - - if err := deleteDB(); err != nil { - t.Errorf("unable to reset database: %v", err) - return nil, deferFn - } - - x, err := newXORMEngine() - assert.NoError(t, err) - if x != nil { - oldDefer := deferFn - deferFn = func() { - oldDefer() - if err := x.Close(); err != nil { - t.Errorf("error during close: %v", err) - } - if err := deleteDB(); err != nil { - t.Errorf("unable to reset database: %v", err) - } - } - } - if err != nil { - return x, deferFn - } - - if len(syncModels) > 0 { - if err := x.Sync2(syncModels...); err != nil { - t.Errorf("error during sync: %v", err) - return x, deferFn - } - } - - fixturesDir := filepath.Join(filepath.Dir(setting.AppPath), "models", "migrations", "fixtures", t.Name()) - - if _, err := os.Stat(fixturesDir); err == nil { - t.Logf("initializing fixtures from: %s", fixturesDir) - if err := unittest.InitFixtures( - unittest.FixturesOptions{ - Dir: fixturesDir, - }, x); err != nil { - t.Errorf("error whilst initializing fixtures from %s: %v", fixturesDir, err) - return x, deferFn - } - if err := unittest.LoadFixtures(x); err != nil { - t.Errorf("error whilst loading fixtures from %s: %v", fixturesDir, err) - return x, deferFn - } - } else if !os.IsNotExist(err) { - t.Errorf("unexpected error whilst checking for existence of fixtures: %v", err) - } else { - t.Logf("no fixtures found in: %s", fixturesDir) - } - - return x, deferFn -} - -func Test_dropTableColumns(t *testing.T) { - x, deferable := prepareTestEnv(t, 0) - if x == nil || t.Failed() { - defer deferable() - return - } - defer deferable() - - type DropTest struct { - ID int64 `xorm:"pk autoincr"` - FirstColumn string - ToDropColumn string `xorm:"unique"` - AnotherColumn int64 - CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` - UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` - } - - columns := []string{ - "first_column", - "to_drop_column", - "another_column", - "created_unix", - "updated_unix", - } - - for i := range columns { - x.SetMapper(names.GonicMapper{}) - if err := x.Sync2(new(DropTest)); err != nil { - t.Errorf("unable to create DropTest table: %v", err) - return - } - sess := x.NewSession() - if err := sess.Begin(); err != nil { - sess.Close() - t.Errorf("unable to begin transaction: %v", err) - return - } - if err := dropTableColumns(sess, "drop_test", columns[i:]...); err != nil { - sess.Close() - t.Errorf("Unable to drop columns[%d:]: %s from drop_test: %v", i, columns[i:], err) - return - } - if err := sess.Commit(); err != nil { - sess.Close() - t.Errorf("unable to commit transaction: %v", err) - return - } - sess.Close() - if err := x.DropTables(new(DropTest)); err != nil { - t.Errorf("unable to drop table: %v", err) - return - } - for j := range columns[i+1:] { - x.SetMapper(names.GonicMapper{}) - if err := x.Sync2(new(DropTest)); err != nil { - t.Errorf("unable to create DropTest table: %v", err) - return - } - dropcols := append([]string{columns[i]}, columns[j+i+1:]...) - sess := x.NewSession() - if err := sess.Begin(); err != nil { - sess.Close() - t.Errorf("unable to begin transaction: %v", err) - return - } - if err := dropTableColumns(sess, "drop_test", dropcols...); err != nil { - sess.Close() - t.Errorf("Unable to drop columns: %s from drop_test: %v", dropcols, err) - return - } - if err := sess.Commit(); err != nil { - sess.Close() - t.Errorf("unable to commit transaction: %v", err) - return - } - sess.Close() - if err := x.DropTables(new(DropTest)); err != nil { - t.Errorf("unable to drop table: %v", err) - return - } - } - } -} diff --git a/models/migrations/v100.go b/models/migrations/v1_10/v100.go similarity index 96% rename from models/migrations/v100.go rename to models/migrations/v1_10/v100.go index 0ff59e004..af58b4b21 100644 --- a/models/migrations/v100.go +++ b/models/migrations/v1_10/v100.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_10 //nolint import ( "net/url" @@ -12,7 +12,7 @@ import ( "xorm.io/xorm" ) -func updateMigrationServiceTypes(x *xorm.Engine) error { +func UpdateMigrationServiceTypes(x *xorm.Engine) error { type Repository struct { ID int64 OriginalServiceType int `xorm:"index default(0)"` diff --git a/models/migrations/v101.go b/models/migrations/v1_10/v101.go similarity index 82% rename from models/migrations/v101.go rename to models/migrations/v1_10/v101.go index 9ef82a293..350e537a9 100644 --- a/models/migrations/v101.go +++ b/models/migrations/v1_10/v101.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_10 //nolint import ( "xorm.io/xorm" ) -func changeSomeColumnsLengthOfExternalLoginUser(x *xorm.Engine) error { +func ChangeSomeColumnsLengthOfExternalLoginUser(x *xorm.Engine) error { type ExternalLoginUser struct { AccessToken string `xorm:"TEXT"` AccessTokenSecret string `xorm:"TEXT"` diff --git a/models/migrations/v88.go b/models/migrations/v1_10/v88.go similarity index 94% rename from models/migrations/v88.go rename to models/migrations/v1_10/v88.go index 11cc26209..32659006e 100644 --- a/models/migrations/v88.go +++ b/models/migrations/v1_10/v88.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_10 //nolint import ( "crypto/sha1" @@ -15,7 +15,7 @@ func hashContext(context string) string { return fmt.Sprintf("%x", sha1.Sum([]byte(context))) } -func addCommitStatusContext(x *xorm.Engine) error { +func AddCommitStatusContext(x *xorm.Engine) error { type CommitStatus struct { ID int64 `xorm:"pk autoincr"` ContextHash string `xorm:"char(40) index"` diff --git a/models/migrations/v89.go b/models/migrations/v1_10/v89.go similarity index 89% rename from models/migrations/v89.go rename to models/migrations/v1_10/v89.go index a972b07b6..4b21ef20f 100644 --- a/models/migrations/v89.go +++ b/models/migrations/v1_10/v89.go @@ -2,11 +2,11 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_10 //nolint import "xorm.io/xorm" -func addOriginalMigrationInfo(x *xorm.Engine) error { +func AddOriginalMigrationInfo(x *xorm.Engine) error { // Issue see models/issue.go type Issue struct { OriginalAuthor string diff --git a/models/migrations/v90.go b/models/migrations/v1_10/v90.go similarity index 83% rename from models/migrations/v90.go rename to models/migrations/v1_10/v90.go index 72f7534dc..aa08ac36b 100644 --- a/models/migrations/v90.go +++ b/models/migrations/v1_10/v90.go @@ -2,11 +2,11 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_10 //nolint import "xorm.io/xorm" -func changeSomeColumnsLengthOfRepo(x *xorm.Engine) error { +func ChangeSomeColumnsLengthOfRepo(x *xorm.Engine) error { type Repository struct { ID int64 `xorm:"pk autoincr"` Description string `xorm:"TEXT"` diff --git a/models/migrations/v91.go b/models/migrations/v1_10/v91.go similarity index 86% rename from models/migrations/v91.go rename to models/migrations/v1_10/v91.go index 3c49d9b96..b8c083f8d 100644 --- a/models/migrations/v91.go +++ b/models/migrations/v1_10/v91.go @@ -2,11 +2,11 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_10 //nolint import "xorm.io/xorm" -func addIndexOnRepositoryAndComment(x *xorm.Engine) error { +func AddIndexOnRepositoryAndComment(x *xorm.Engine) error { type Repository struct { ID int64 `xorm:"pk autoincr"` OwnerID int64 `xorm:"index"` diff --git a/models/migrations/v92.go b/models/migrations/v1_10/v92.go similarity index 82% rename from models/migrations/v92.go rename to models/migrations/v1_10/v92.go index e343dedb6..c0552aaab 100644 --- a/models/migrations/v92.go +++ b/models/migrations/v1_10/v92.go @@ -2,14 +2,14 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_10 //nolint import ( "xorm.io/builder" "xorm.io/xorm" ) -func removeLingeringIndexStatus(x *xorm.Engine) error { +func RemoveLingeringIndexStatus(x *xorm.Engine) error { _, err := x.Exec(builder.Delete(builder.NotIn("`repo_id`", builder.Select("`id`").From("`repository`"))).From("`repo_indexer_status`")) return err } diff --git a/models/migrations/v93.go b/models/migrations/v1_10/v93.go similarity index 80% rename from models/migrations/v93.go rename to models/migrations/v1_10/v93.go index 0cb9d6631..6ce89f0d4 100644 --- a/models/migrations/v93.go +++ b/models/migrations/v1_10/v93.go @@ -2,11 +2,11 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_10 //nolint import "xorm.io/xorm" -func addEmailNotificationEnabledToUser(x *xorm.Engine) error { +func AddEmailNotificationEnabledToUser(x *xorm.Engine) error { // User see models/user.go type User struct { EmailNotificationsPreference string `xorm:"VARCHAR(20) NOT NULL DEFAULT 'enabled'"` diff --git a/models/migrations/v94.go b/models/migrations/v1_10/v94.go similarity index 87% rename from models/migrations/v94.go rename to models/migrations/v1_10/v94.go index 8c1e33b64..542e45c13 100644 --- a/models/migrations/v94.go +++ b/models/migrations/v1_10/v94.go @@ -2,11 +2,11 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_10 //nolint import "xorm.io/xorm" -func addStatusCheckColumnsForProtectedBranches(x *xorm.Engine) error { +func AddStatusCheckColumnsForProtectedBranches(x *xorm.Engine) error { type ProtectedBranch struct { EnableStatusCheck bool `xorm:"NOT NULL DEFAULT false"` StatusCheckContexts []string `xorm:"JSON TEXT"` diff --git a/models/migrations/v95.go b/models/migrations/v1_10/v95.go similarity index 85% rename from models/migrations/v95.go rename to models/migrations/v1_10/v95.go index 94787f750..48a0c4ea7 100644 --- a/models/migrations/v95.go +++ b/models/migrations/v1_10/v95.go @@ -2,11 +2,11 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_10 //nolint import "xorm.io/xorm" -func addCrossReferenceColumns(x *xorm.Engine) error { +func AddCrossReferenceColumns(x *xorm.Engine) error { // Comment see models/comment.go type Comment struct { RefRepoID int64 `xorm:"index"` diff --git a/models/migrations/v96.go b/models/migrations/v1_10/v96.go similarity index 94% rename from models/migrations/v96.go rename to models/migrations/v1_10/v96.go index eaeab72b0..372ca9e65 100644 --- a/models/migrations/v96.go +++ b/models/migrations/v1_10/v96.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_10 //nolint import ( "path/filepath" @@ -13,7 +13,7 @@ import ( "xorm.io/xorm" ) -func deleteOrphanedAttachments(x *xorm.Engine) error { +func DeleteOrphanedAttachments(x *xorm.Engine) error { type Attachment struct { ID int64 `xorm:"pk autoincr"` UUID string `xorm:"uuid UNIQUE"` diff --git a/models/migrations/v97.go b/models/migrations/v1_10/v97.go similarity index 78% rename from models/migrations/v97.go rename to models/migrations/v1_10/v97.go index 8e58886e2..4438a9ed5 100644 --- a/models/migrations/v97.go +++ b/models/migrations/v1_10/v97.go @@ -2,11 +2,11 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_10 //nolint import "xorm.io/xorm" -func addRepoAdminChangeTeamAccessColumnForUser(x *xorm.Engine) error { +func AddRepoAdminChangeTeamAccessColumnForUser(x *xorm.Engine) error { type User struct { RepoAdminChangeTeamAccess bool `xorm:"NOT NULL DEFAULT false"` } diff --git a/models/migrations/v98.go b/models/migrations/v1_10/v98.go similarity index 79% rename from models/migrations/v98.go rename to models/migrations/v1_10/v98.go index 617e1ec3d..8e9ebb7d9 100644 --- a/models/migrations/v98.go +++ b/models/migrations/v1_10/v98.go @@ -2,11 +2,11 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_10 //nolint import "xorm.io/xorm" -func addOriginalAuthorOnMigratedReleases(x *xorm.Engine) error { +func AddOriginalAuthorOnMigratedReleases(x *xorm.Engine) error { type Release struct { ID int64 OriginalAuthor string diff --git a/models/migrations/v99.go b/models/migrations/v1_10/v99.go similarity index 94% rename from models/migrations/v99.go rename to models/migrations/v1_10/v99.go index b6f6babce..21554f6ef 100644 --- a/models/migrations/v99.go +++ b/models/migrations/v1_10/v99.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_10 //nolint import ( "code.gitea.io/gitea/modules/timeutil" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addTaskTable(x *xorm.Engine) error { +func AddTaskTable(x *xorm.Engine) error { // TaskType defines task type type TaskType int diff --git a/models/migrations/v102.go b/models/migrations/v1_11/v102.go similarity index 59% rename from models/migrations/v102.go rename to models/migrations/v1_11/v102.go index 03079d0bb..49d9d3ae7 100644 --- a/models/migrations/v102.go +++ b/models/migrations/v1_11/v102.go @@ -2,19 +2,21 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_11 //nolint import ( + "code.gitea.io/gitea/models/migrations/base" + "xorm.io/xorm" ) -func dropColumnHeadUserNameOnPullRequest(x *xorm.Engine) error { +func DropColumnHeadUserNameOnPullRequest(x *xorm.Engine) error { sess := x.NewSession() defer sess.Close() if err := sess.Begin(); err != nil { return err } - if err := dropTableColumns(sess, "pull_request", "head_user_name"); err != nil { + if err := base.DropTableColumns(sess, "pull_request", "head_user_name"); err != nil { return err } return sess.Commit() diff --git a/models/migrations/v103.go b/models/migrations/v1_11/v103.go similarity index 80% rename from models/migrations/v103.go rename to models/migrations/v1_11/v103.go index fed025c5c..e9114adee 100644 --- a/models/migrations/v103.go +++ b/models/migrations/v1_11/v103.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_11 //nolint import ( "xorm.io/xorm" ) -func addWhitelistDeployKeysToBranches(x *xorm.Engine) error { +func AddWhitelistDeployKeysToBranches(x *xorm.Engine) error { type ProtectedBranch struct { ID int64 WhitelistDeployKeys bool `xorm:"NOT NULL DEFAULT false"` diff --git a/models/migrations/v104.go b/models/migrations/v1_11/v104.go similarity index 65% rename from models/migrations/v104.go rename to models/migrations/v1_11/v104.go index 72e236404..0ab3682f6 100644 --- a/models/migrations/v104.go +++ b/models/migrations/v1_11/v104.go @@ -2,13 +2,15 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_11 //nolint import ( + "code.gitea.io/gitea/models/migrations/base" + "xorm.io/xorm" ) -func removeLabelUneededCols(x *xorm.Engine) error { +func RemoveLabelUneededCols(x *xorm.Engine) error { // Make sure the columns exist before dropping them type Label struct { QueryString string @@ -23,10 +25,10 @@ func removeLabelUneededCols(x *xorm.Engine) error { if err := sess.Begin(); err != nil { return err } - if err := dropTableColumns(sess, "label", "query_string"); err != nil { + if err := base.DropTableColumns(sess, "label", "query_string"); err != nil { return err } - if err := dropTableColumns(sess, "label", "is_selected"); err != nil { + if err := base.DropTableColumns(sess, "label", "is_selected"); err != nil { return err } return sess.Commit() diff --git a/models/migrations/v105.go b/models/migrations/v1_11/v105.go similarity index 86% rename from models/migrations/v105.go rename to models/migrations/v1_11/v105.go index 5d9a98cce..07aeedcd6 100644 --- a/models/migrations/v105.go +++ b/models/migrations/v1_11/v105.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_11 //nolint import ( "xorm.io/xorm" ) -func addTeamIncludesAllRepositories(x *xorm.Engine) error { +func AddTeamIncludesAllRepositories(x *xorm.Engine) error { type Team struct { ID int64 `xorm:"pk autoincr"` IncludesAllRepositories bool `xorm:"NOT NULL DEFAULT false"` diff --git a/models/migrations/v106.go b/models/migrations/v1_11/v106.go similarity index 88% rename from models/migrations/v106.go rename to models/migrations/v1_11/v106.go index 201fc1026..af7750866 100644 --- a/models/migrations/v106.go +++ b/models/migrations/v1_11/v106.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_11 //nolint import ( "xorm.io/xorm" @@ -17,7 +17,7 @@ type Watch struct { Mode RepoWatchMode `xorm:"SMALLINT NOT NULL DEFAULT 1"` } -func addModeColumnToWatch(x *xorm.Engine) (err error) { +func AddModeColumnToWatch(x *xorm.Engine) (err error) { if err = x.Sync2(new(Watch)); err != nil { return } diff --git a/models/migrations/v107.go b/models/migrations/v1_11/v107.go similarity index 83% rename from models/migrations/v107.go rename to models/migrations/v1_11/v107.go index 22990a0fa..5cc0d5282 100644 --- a/models/migrations/v107.go +++ b/models/migrations/v1_11/v107.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_11 //nolint import ( "xorm.io/xorm" ) -func addTemplateToRepo(x *xorm.Engine) error { +func AddTemplateToRepo(x *xorm.Engine) error { type Repository struct { IsTemplate bool `xorm:"INDEX NOT NULL DEFAULT false"` TemplateID int64 `xorm:"INDEX"` diff --git a/models/migrations/v108.go b/models/migrations/v1_11/v108.go similarity index 80% rename from models/migrations/v108.go rename to models/migrations/v1_11/v108.go index 60b8fb47a..06ff1b16e 100644 --- a/models/migrations/v108.go +++ b/models/migrations/v1_11/v108.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_11 //nolint import ( "xorm.io/xorm" ) -func addCommentIDOnNotification(x *xorm.Engine) error { +func AddCommentIDOnNotification(x *xorm.Engine) error { type Notification struct { ID int64 `xorm:"pk autoincr"` CommentID int64 diff --git a/models/migrations/v109.go b/models/migrations/v1_11/v109.go similarity index 77% rename from models/migrations/v109.go rename to models/migrations/v1_11/v109.go index abe731768..2bfd2536b 100644 --- a/models/migrations/v109.go +++ b/models/migrations/v1_11/v109.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_11 //nolint import ( "xorm.io/xorm" ) -func addCanCreateOrgRepoColumnForTeam(x *xorm.Engine) error { +func AddCanCreateOrgRepoColumnForTeam(x *xorm.Engine) error { type Team struct { CanCreateOrgRepo bool `xorm:"NOT NULL DEFAULT false"` } diff --git a/models/migrations/v110.go b/models/migrations/v1_11/v110.go similarity index 91% rename from models/migrations/v110.go rename to models/migrations/v1_11/v110.go index 4a1c3c47a..813a753e0 100644 --- a/models/migrations/v110.go +++ b/models/migrations/v1_11/v110.go @@ -2,14 +2,14 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_11 //nolint import ( "xorm.io/xorm" "xorm.io/xorm/schemas" ) -func changeReviewContentToText(x *xorm.Engine) error { +func ChangeReviewContentToText(x *xorm.Engine) error { switch x.Dialect().URI().DBType { case schemas.MYSQL: _, err := x.Exec("ALTER TABLE review MODIFY COLUMN content TEXT") diff --git a/models/migrations/v111.go b/models/migrations/v1_11/v111.go similarity index 99% rename from models/migrations/v111.go rename to models/migrations/v1_11/v111.go index 65fe7c533..f1f1d7cb0 100644 --- a/models/migrations/v111.go +++ b/models/migrations/v1_11/v111.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_11 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error { +func AddBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error { type ProtectedBranch struct { CanPush bool `xorm:"NOT NULL DEFAULT false"` EnableApprovalsWhitelist bool `xorm:"NOT NULL DEFAULT false"` diff --git a/models/migrations/v112.go b/models/migrations/v1_11/v112.go similarity index 93% rename from models/migrations/v112.go rename to models/migrations/v1_11/v112.go index 9da7d8a78..f8e84cf75 100644 --- a/models/migrations/v112.go +++ b/models/migrations/v1_11/v112.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_11 //nolint import ( "fmt" @@ -15,7 +15,7 @@ import ( "xorm.io/xorm" ) -func removeAttachmentMissedRepo(x *xorm.Engine) error { +func RemoveAttachmentMissedRepo(x *xorm.Engine) error { type Attachment struct { UUID string `xorm:"uuid"` } diff --git a/models/migrations/v113.go b/models/migrations/v1_11/v113.go similarity index 82% rename from models/migrations/v113.go rename to models/migrations/v1_11/v113.go index 4af246863..36ab1bd9c 100644 --- a/models/migrations/v113.go +++ b/models/migrations/v1_11/v113.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_11 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func featureChangeTargetBranch(x *xorm.Engine) error { +func FeatureChangeTargetBranch(x *xorm.Engine) error { type Comment struct { OldRef string NewRef string diff --git a/models/migrations/v114.go b/models/migrations/v1_11/v114.go similarity index 93% rename from models/migrations/v114.go rename to models/migrations/v1_11/v114.go index 4dd07c9e5..688dd06d4 100644 --- a/models/migrations/v114.go +++ b/models/migrations/v1_11/v114.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_11 //nolint import ( "net/url" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func sanitizeOriginalURL(x *xorm.Engine) error { +func SanitizeOriginalURL(x *xorm.Engine) error { type Repository struct { ID int64 OriginalURL string `xorm:"VARCHAR(2048)"` diff --git a/models/migrations/v115.go b/models/migrations/v1_11/v115.go similarity index 98% rename from models/migrations/v115.go rename to models/migrations/v1_11/v115.go index 3e61cb6e0..1fbf0c4f2 100644 --- a/models/migrations/v115.go +++ b/models/migrations/v1_11/v115.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_11 //nolint import ( "crypto/md5" @@ -21,7 +21,7 @@ import ( "xorm.io/xorm" ) -func renameExistingUserAvatarName(x *xorm.Engine) error { +func RenameExistingUserAvatarName(x *xorm.Engine) error { sess := x.NewSession() defer sess.Close() diff --git a/models/migrations/v116.go b/models/migrations/v1_11/v116.go similarity index 89% rename from models/migrations/v116.go rename to models/migrations/v1_11/v116.go index c684c05fd..6b6d91777 100644 --- a/models/migrations/v116.go +++ b/models/migrations/v1_11/v116.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_11 //nolint import ( "xorm.io/xorm" ) -func extendTrackedTimes(x *xorm.Engine) error { +func ExtendTrackedTimes(x *xorm.Engine) error { type TrackedTime struct { Time int64 `xorm:"NOT NULL"` Deleted bool `xorm:"NOT NULL DEFAULT false"` diff --git a/models/migrations/v117.go b/models/migrations/v1_12/v117.go similarity index 80% rename from models/migrations/v117.go rename to models/migrations/v1_12/v117.go index 662d6c7b4..6a102e0df 100644 --- a/models/migrations/v117.go +++ b/models/migrations/v1_12/v117.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "xorm.io/xorm" ) -func addBlockOnRejectedReviews(x *xorm.Engine) error { +func AddBlockOnRejectedReviews(x *xorm.Engine) error { type ProtectedBranch struct { BlockOnRejectedReviews bool `xorm:"NOT NULL DEFAULT false"` } diff --git a/models/migrations/v118.go b/models/migrations/v1_12/v118.go similarity index 88% rename from models/migrations/v118.go rename to models/migrations/v1_12/v118.go index c79cbb8ae..227daffc4 100644 --- a/models/migrations/v118.go +++ b/models/migrations/v1_12/v118.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "xorm.io/xorm" ) -func addReviewCommitAndStale(x *xorm.Engine) error { +func AddReviewCommitAndStale(x *xorm.Engine) error { type Review struct { CommitID string `xorm:"VARCHAR(40)"` Stale bool `xorm:"NOT NULL DEFAULT false"` diff --git a/models/migrations/v119.go b/models/migrations/v1_12/v119.go similarity index 81% rename from models/migrations/v119.go rename to models/migrations/v1_12/v119.go index 9622ff587..998ca004d 100644 --- a/models/migrations/v119.go +++ b/models/migrations/v1_12/v119.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "xorm.io/xorm" ) -func fixMigratedRepositoryServiceType(x *xorm.Engine) error { +func FixMigratedRepositoryServiceType(x *xorm.Engine) error { // structs.GithubService: // GithubService = 2 _, err := x.Exec("UPDATE repository SET original_service_type = ? WHERE original_url LIKE 'https://github.com/%'", 2) diff --git a/models/migrations/v120.go b/models/migrations/v1_12/v120.go similarity index 85% rename from models/migrations/v120.go rename to models/migrations/v1_12/v120.go index 91d5b503f..cc35ce5f3 100644 --- a/models/migrations/v120.go +++ b/models/migrations/v1_12/v120.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "xorm.io/xorm" ) -func addOwnerNameOnRepository(x *xorm.Engine) error { +func AddOwnerNameOnRepository(x *xorm.Engine) error { type Repository struct { OwnerName string } diff --git a/models/migrations/v121.go b/models/migrations/v1_12/v121.go similarity index 84% rename from models/migrations/v121.go rename to models/migrations/v1_12/v121.go index c1ff7df3a..19864658d 100644 --- a/models/migrations/v121.go +++ b/models/migrations/v1_12/v121.go @@ -2,11 +2,11 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import "xorm.io/xorm" -func addIsRestricted(x *xorm.Engine) error { +func AddIsRestricted(x *xorm.Engine) error { // User see models/user.go type User struct { ID int64 `xorm:"pk autoincr"` diff --git a/models/migrations/v122.go b/models/migrations/v1_12/v122.go similarity index 81% rename from models/migrations/v122.go rename to models/migrations/v1_12/v122.go index 7f4a49e69..b0edae93b 100644 --- a/models/migrations/v122.go +++ b/models/migrations/v1_12/v122.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "xorm.io/xorm" ) -func addRequireSignedCommits(x *xorm.Engine) error { +func AddRequireSignedCommits(x *xorm.Engine) error { type ProtectedBranch struct { RequireSignedCommits bool `xorm:"NOT NULL DEFAULT false"` } diff --git a/models/migrations/v123.go b/models/migrations/v1_12/v123.go similarity index 82% rename from models/migrations/v123.go rename to models/migrations/v1_12/v123.go index e1b772381..1ecfdce73 100644 --- a/models/migrations/v123.go +++ b/models/migrations/v1_12/v123.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "xorm.io/xorm" ) -func addReactionOriginals(x *xorm.Engine) error { +func AddReactionOriginals(x *xorm.Engine) error { type Reaction struct { OriginalAuthorID int64 `xorm:"INDEX NOT NULL DEFAULT(0)"` OriginalAuthor string diff --git a/models/migrations/v124.go b/models/migrations/v1_12/v124.go similarity index 86% rename from models/migrations/v124.go rename to models/migrations/v1_12/v124.go index 0b61a04cb..0fc86378d 100644 --- a/models/migrations/v124.go +++ b/models/migrations/v1_12/v124.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "xorm.io/xorm" ) -func addUserRepoMissingColumns(x *xorm.Engine) error { +func AddUserRepoMissingColumns(x *xorm.Engine) error { type VisibleType int type User struct { PasswdHashAlgo string `xorm:"NOT NULL DEFAULT 'pbkdf2'"` diff --git a/models/migrations/v125.go b/models/migrations/v1_12/v125.go similarity index 83% rename from models/migrations/v125.go rename to models/migrations/v1_12/v125.go index 64483e139..d74f888e9 100644 --- a/models/migrations/v125.go +++ b/models/migrations/v1_12/v125.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addReviewMigrateInfo(x *xorm.Engine) error { +func AddReviewMigrateInfo(x *xorm.Engine) error { type Review struct { OriginalAuthor string OriginalAuthorID int64 diff --git a/models/migrations/v126.go b/models/migrations/v1_12/v126.go similarity index 89% rename from models/migrations/v126.go rename to models/migrations/v1_12/v126.go index bce13a61b..51dfb5167 100644 --- a/models/migrations/v126.go +++ b/models/migrations/v1_12/v126.go @@ -2,14 +2,14 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "xorm.io/builder" "xorm.io/xorm" ) -func fixTopicRepositoryCount(x *xorm.Engine) error { +func FixTopicRepositoryCount(x *xorm.Engine) error { _, err := x.Exec(builder.Delete(builder.NotIn("`repo_id`", builder.Select("`id`").From("`repository`"))).From("`repo_topic`")) if err != nil { return err diff --git a/models/migrations/v127.go b/models/migrations/v1_12/v127.go similarity index 94% rename from models/migrations/v127.go rename to models/migrations/v1_12/v127.go index 7be1e326d..5849b8256 100644 --- a/models/migrations/v127.go +++ b/models/migrations/v1_12/v127.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "fmt" @@ -12,7 +12,7 @@ import ( "xorm.io/xorm" ) -func addLanguageStats(x *xorm.Engine) error { +func AddLanguageStats(x *xorm.Engine) error { // LanguageStat see models/repo_language_stats.go type LanguageStat struct { ID int64 `xorm:"pk autoincr"` diff --git a/models/migrations/v128.go b/models/migrations/v1_12/v128.go similarity index 98% rename from models/migrations/v128.go rename to models/migrations/v1_12/v128.go index 7e84ff5b7..71e8e3207 100644 --- a/models/migrations/v128.go +++ b/models/migrations/v1_12/v128.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "fmt" @@ -18,7 +18,7 @@ import ( "xorm.io/xorm" ) -func fixMergeBase(x *xorm.Engine) error { +func FixMergeBase(x *xorm.Engine) error { type Repository struct { ID int64 `xorm:"pk autoincr"` OwnerID int64 `xorm:"UNIQUE(s) index"` diff --git a/models/migrations/v129.go b/models/migrations/v1_12/v129.go similarity index 85% rename from models/migrations/v129.go rename to models/migrations/v1_12/v129.go index e935f2e07..28bc5f604 100644 --- a/models/migrations/v129.go +++ b/models/migrations/v1_12/v129.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "xorm.io/xorm" ) -func purgeUnusedDependencies(x *xorm.Engine) error { +func PurgeUnusedDependencies(x *xorm.Engine) error { if _, err := x.Exec("DELETE FROM issue_dependency WHERE issue_id NOT IN (SELECT id FROM issue)"); err != nil { return err } diff --git a/models/migrations/v130.go b/models/migrations/v1_12/v130.go similarity index 97% rename from models/migrations/v130.go rename to models/migrations/v1_12/v130.go index 7ffed3fd1..ca3765be7 100644 --- a/models/migrations/v130.go +++ b/models/migrations/v1_12/v130.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "code.gitea.io/gitea/modules/json" @@ -11,7 +11,7 @@ import ( "xorm.io/xorm" ) -func expandWebhooks(x *xorm.Engine) error { +func ExpandWebhooks(x *xorm.Engine) error { type HookEvents struct { Create bool `json:"create"` Delete bool `json:"delete"` diff --git a/models/migrations/v131.go b/models/migrations/v1_12/v131.go similarity index 83% rename from models/migrations/v131.go rename to models/migrations/v1_12/v131.go index 48fd3e29c..14d954b4b 100644 --- a/models/migrations/v131.go +++ b/models/migrations/v1_12/v131.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addSystemWebhookColumn(x *xorm.Engine) error { +func AddSystemWebhookColumn(x *xorm.Engine) error { type Webhook struct { IsSystemWebhook bool `xorm:"NOT NULL DEFAULT false"` } diff --git a/models/migrations/v132.go b/models/migrations/v1_12/v132.go similarity index 81% rename from models/migrations/v132.go rename to models/migrations/v1_12/v132.go index e67a67e90..8d93460f7 100644 --- a/models/migrations/v132.go +++ b/models/migrations/v1_12/v132.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addBranchProtectionProtectedFilesColumn(x *xorm.Engine) error { +func AddBranchProtectionProtectedFilesColumn(x *xorm.Engine) error { type ProtectedBranch struct { ProtectedFilePatterns string `xorm:"TEXT"` } diff --git a/models/migrations/v133.go b/models/migrations/v1_12/v133.go similarity index 84% rename from models/migrations/v133.go rename to models/migrations/v1_12/v133.go index ea0411d47..1d69c47b9 100644 --- a/models/migrations/v133.go +++ b/models/migrations/v1_12/v133.go @@ -2,11 +2,11 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import "xorm.io/xorm" -func addEmailHashTable(x *xorm.Engine) error { +func AddEmailHashTable(x *xorm.Engine) error { // EmailHash represents a pre-generated hash map type EmailHash struct { Hash string `xorm:"pk varchar(32)"` diff --git a/models/migrations/v134.go b/models/migrations/v1_12/v134.go similarity index 98% rename from models/migrations/v134.go rename to models/migrations/v1_12/v134.go index 75c676872..297db37a0 100644 --- a/models/migrations/v134.go +++ b/models/migrations/v1_12/v134.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "fmt" @@ -18,7 +18,7 @@ import ( "xorm.io/xorm" ) -func refixMergeBase(x *xorm.Engine) error { +func RefixMergeBase(x *xorm.Engine) error { type Repository struct { ID int64 `xorm:"pk autoincr"` OwnerID int64 `xorm:"UNIQUE(s) index"` diff --git a/models/migrations/v135.go b/models/migrations/v1_12/v135.go similarity index 83% rename from models/migrations/v135.go rename to models/migrations/v1_12/v135.go index eaa852d44..9453ecdd5 100644 --- a/models/migrations/v135.go +++ b/models/migrations/v1_12/v135.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addOrgIDLabelColumn(x *xorm.Engine) error { +func AddOrgIDLabelColumn(x *xorm.Engine) error { type Label struct { OrgID int64 `xorm:"INDEX"` } diff --git a/models/migrations/v136.go b/models/migrations/v1_12/v136.go similarity index 97% rename from models/migrations/v136.go rename to models/migrations/v1_12/v136.go index b2192f385..b114ddf50 100644 --- a/models/migrations/v136.go +++ b/models/migrations/v1_12/v136.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "fmt" @@ -19,7 +19,7 @@ import ( "xorm.io/xorm" ) -func addCommitDivergenceToPulls(x *xorm.Engine) error { +func AddCommitDivergenceToPulls(x *xorm.Engine) error { type Repository struct { ID int64 `xorm:"pk autoincr"` OwnerID int64 `xorm:"UNIQUE(s) index"` diff --git a/models/migrations/v137.go b/models/migrations/v1_12/v137.go similarity index 80% rename from models/migrations/v137.go rename to models/migrations/v1_12/v137.go index f175cf8a8..6eb6b1ebb 100644 --- a/models/migrations/v137.go +++ b/models/migrations/v1_12/v137.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "xorm.io/xorm" ) -func addBlockOnOutdatedBranch(x *xorm.Engine) error { +func AddBlockOnOutdatedBranch(x *xorm.Engine) error { type ProtectedBranch struct { BlockOnOutdatedBranch bool `xorm:"NOT NULL DEFAULT false"` } diff --git a/models/migrations/v138.go b/models/migrations/v1_12/v138.go similarity index 81% rename from models/migrations/v138.go rename to models/migrations/v1_12/v138.go index 03235200a..c101c6e4c 100644 --- a/models/migrations/v138.go +++ b/models/migrations/v1_12/v138.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addResolveDoerIDCommentColumn(x *xorm.Engine) error { +func AddResolveDoerIDCommentColumn(x *xorm.Engine) error { type Comment struct { ResolveDoerID int64 } diff --git a/models/migrations/v139.go b/models/migrations/v1_12/v139.go similarity index 90% rename from models/migrations/v139.go rename to models/migrations/v1_12/v139.go index 46b14b986..69daa94f9 100644 --- a/models/migrations/v139.go +++ b/models/migrations/v1_12/v139.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_12 //nolint import ( "code.gitea.io/gitea/modules/setting" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func prependRefsHeadsToIssueRefs(x *xorm.Engine) error { +func PrependRefsHeadsToIssueRefs(x *xorm.Engine) error { var query string switch { diff --git a/models/migrations/v140.go b/models/migrations/v1_13/v140.go similarity index 86% rename from models/migrations/v140.go rename to models/migrations/v1_13/v140.go index b54740f1a..37aeeaeb6 100644 --- a/models/migrations/v140.go +++ b/models/migrations/v1_13/v140.go @@ -2,17 +2,18 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_13 //nolint import ( "fmt" + "code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/modules/setting" "xorm.io/xorm" ) -func fixLanguageStatsToSaveSize(x *xorm.Engine) error { +func FixLanguageStatsToSaveSize(x *xorm.Engine) error { // LanguageStat see models/repo_language_stats.go type LanguageStat struct { Size int64 `xorm:"NOT NULL DEFAULT 0"` @@ -52,5 +53,5 @@ func fixLanguageStatsToSaveSize(x *xorm.Engine) error { sess := x.NewSession() defer sess.Close() - return dropTableColumns(sess, "language_stat", "percentage") + return base.DropTableColumns(sess, "language_stat", "percentage") } diff --git a/models/migrations/v141.go b/models/migrations/v1_13/v141.go similarity index 81% rename from models/migrations/v141.go rename to models/migrations/v1_13/v141.go index 21247cc78..7dd1cc5d6 100644 --- a/models/migrations/v141.go +++ b/models/migrations/v1_13/v141.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_13 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addKeepActivityPrivateUserColumn(x *xorm.Engine) error { +func AddKeepActivityPrivateUserColumn(x *xorm.Engine) error { type User struct { KeepActivityPrivate bool `xorm:"NOT NULL DEFAULT false"` } diff --git a/models/migrations/v142.go b/models/migrations/v1_13/v142.go similarity index 87% rename from models/migrations/v142.go rename to models/migrations/v1_13/v142.go index d8ccc112d..3a2206b6c 100644 --- a/models/migrations/v142.go +++ b/models/migrations/v1_13/v142.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_13 //nolint import ( "code.gitea.io/gitea/modules/log" @@ -11,7 +11,7 @@ import ( "xorm.io/xorm" ) -func setIsArchivedToFalse(x *xorm.Engine) error { +func SetIsArchivedToFalse(x *xorm.Engine) error { type Repository struct { IsArchived bool `xorm:"INDEX"` } diff --git a/models/migrations/v143.go b/models/migrations/v1_13/v143.go similarity index 93% rename from models/migrations/v143.go rename to models/migrations/v1_13/v143.go index 17f3af449..eee66c0a0 100644 --- a/models/migrations/v143.go +++ b/models/migrations/v1_13/v143.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_13 //nolint import ( "code.gitea.io/gitea/modules/log" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func recalculateStars(x *xorm.Engine) (err error) { +func RecalculateStars(x *xorm.Engine) (err error) { // because of issue https://github.com/go-gitea/gitea/issues/11949, // recalculate Stars number for all users to fully fix it. diff --git a/models/migrations/v144.go b/models/migrations/v1_13/v144.go similarity index 88% rename from models/migrations/v144.go rename to models/migrations/v1_13/v144.go index 81279a54c..0b8b91268 100644 --- a/models/migrations/v144.go +++ b/models/migrations/v1_13/v144.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_13 //nolint import ( "code.gitea.io/gitea/modules/log" @@ -11,7 +11,7 @@ import ( "xorm.io/xorm" ) -func updateMatrixWebhookHTTPMethod(x *xorm.Engine) error { +func UpdateMatrixWebhookHTTPMethod(x *xorm.Engine) error { matrixHookTaskType := 9 // value comes from the models package type Webhook struct { HTTPMethod string diff --git a/models/migrations/v145.go b/models/migrations/v1_13/v145.go similarity index 97% rename from models/migrations/v145.go rename to models/migrations/v1_13/v145.go index afc60497e..b12da3c67 100644 --- a/models/migrations/v145.go +++ b/models/migrations/v1_13/v145.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_13 //nolint import ( "fmt" @@ -12,7 +12,7 @@ import ( "xorm.io/xorm" ) -func increaseLanguageField(x *xorm.Engine) error { +func IncreaseLanguageField(x *xorm.Engine) error { type LanguageStat struct { RepoID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` Language string `xorm:"VARCHAR(50) UNIQUE(s) INDEX NOT NULL"` diff --git a/models/migrations/v146.go b/models/migrations/v1_13/v146.go similarity index 96% rename from models/migrations/v146.go rename to models/migrations/v1_13/v146.go index 092589820..7afd32537 100644 --- a/models/migrations/v146.go +++ b/models/migrations/v1_13/v146.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_13 //nolint import ( "code.gitea.io/gitea/modules/timeutil" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addProjectsInfo(x *xorm.Engine) error { +func AddProjectsInfo(x *xorm.Engine) error { // Create new tables type ( ProjectType uint8 diff --git a/models/migrations/v147.go b/models/migrations/v1_13/v147.go similarity index 98% rename from models/migrations/v147.go rename to models/migrations/v1_13/v147.go index ad4ec4ef7..1518b8dd2 100644 --- a/models/migrations/v147.go +++ b/models/migrations/v1_13/v147.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_13 //nolint import ( "code.gitea.io/gitea/modules/timeutil" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func createReviewsForCodeComments(x *xorm.Engine) error { +func CreateReviewsForCodeComments(x *xorm.Engine) error { // Review type Review struct { ID int64 `xorm:"pk autoincr"` diff --git a/models/migrations/v148.go b/models/migrations/v1_13/v148.go similarity index 79% rename from models/migrations/v148.go rename to models/migrations/v1_13/v148.go index 35d17f5b2..40ede7174 100644 --- a/models/migrations/v148.go +++ b/models/migrations/v1_13/v148.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_13 //nolint import ( "xorm.io/xorm" ) -func purgeInvalidDependenciesComments(x *xorm.Engine) error { +func PurgeInvalidDependenciesComments(x *xorm.Engine) error { _, err := x.Exec("DELETE FROM comment WHERE dependent_issue_id != 0 AND dependent_issue_id NOT IN (SELECT id FROM issue)") return err } diff --git a/models/migrations/v149.go b/models/migrations/v1_13/v149.go similarity index 85% rename from models/migrations/v149.go rename to models/migrations/v1_13/v149.go index 4d2cf5b97..f0054b752 100644 --- a/models/migrations/v149.go +++ b/models/migrations/v1_13/v149.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_13 //nolint import ( "fmt" @@ -12,7 +12,7 @@ import ( "xorm.io/xorm" ) -func addCreatedAndUpdatedToMilestones(x *xorm.Engine) error { +func AddCreatedAndUpdatedToMilestones(x *xorm.Engine) error { type Milestone struct { CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` diff --git a/models/migrations/v150.go b/models/migrations/v1_13/v150.go similarity index 79% rename from models/migrations/v150.go rename to models/migrations/v1_13/v150.go index 41d6a9040..99e6ddf68 100644 --- a/models/migrations/v150.go +++ b/models/migrations/v1_13/v150.go @@ -2,15 +2,16 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_13 //nolint import ( + "code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/modules/timeutil" "xorm.io/xorm" ) -func addPrimaryKeyToRepoTopic(x *xorm.Engine) error { +func AddPrimaryKeyToRepoTopic(x *xorm.Engine) error { // Topic represents a topic of repositories type Topic struct { ID int64 `xorm:"pk autoincr"` @@ -32,8 +33,8 @@ func addPrimaryKeyToRepoTopic(x *xorm.Engine) error { return err } - recreateTable(sess, &Topic{}) - recreateTable(sess, &RepoTopic{}) + base.RecreateTable(sess, &Topic{}) + base.RecreateTable(sess, &RepoTopic{}) return sess.Commit() } diff --git a/models/migrations/v151.go b/models/migrations/v1_13/v151.go similarity index 98% rename from models/migrations/v151.go rename to models/migrations/v1_13/v151.go index 50314d816..9efda9364 100644 --- a/models/migrations/v151.go +++ b/models/migrations/v1_13/v151.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_13 //nolint import ( "context" @@ -16,7 +16,7 @@ import ( "xorm.io/xorm/schemas" ) -func setDefaultPasswordToArgon2(x *xorm.Engine) error { +func SetDefaultPasswordToArgon2(x *xorm.Engine) error { switch { case setting.Database.UseMySQL: _, err := x.Exec("ALTER TABLE `user` ALTER passwd_hash_algo SET DEFAULT 'argon2';") diff --git a/models/migrations/v152.go b/models/migrations/v1_13/v152.go similarity index 77% rename from models/migrations/v152.go rename to models/migrations/v1_13/v152.go index f71f71e22..ec49a2fb9 100644 --- a/models/migrations/v152.go +++ b/models/migrations/v1_13/v152.go @@ -2,11 +2,11 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_13 //nolint import "xorm.io/xorm" -func addTrustModelToRepository(x *xorm.Engine) error { +func AddTrustModelToRepository(x *xorm.Engine) error { type Repository struct { TrustModel int } diff --git a/models/migrations/v153.go b/models/migrations/v1_13/v153.go similarity index 84% rename from models/migrations/v153.go rename to models/migrations/v1_13/v153.go index 1e5ae9f7d..1428edd3c 100644 --- a/models/migrations/v153.go +++ b/models/migrations/v1_13/v153.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_13 //nolint import ( "xorm.io/xorm" ) -func addTeamReviewRequestSupport(x *xorm.Engine) error { +func AddTeamReviewRequestSupport(x *xorm.Engine) error { type Review struct { ReviewerTeamID int64 `xorm:"NOT NULL DEFAULT 0"` } diff --git a/models/migrations/v154.go b/models/migrations/v1_13/v154.go similarity index 95% rename from models/migrations/v154.go rename to models/migrations/v1_13/v154.go index bb17fb472..8976db675 100644 --- a/models/migrations/v154.go +++ b/models/migrations/v1_13/v154.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_13 //nolint import ( "code.gitea.io/gitea/modules/timeutil" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addTimeStamps(x *xorm.Engine) error { +func AddTimeStamps(x *xorm.Engine) error { // this will add timestamps where it is useful to have // Star represents a starred repo by an user. diff --git a/models/migrations/v1_14/main_test.go b/models/migrations/v1_14/main_test.go new file mode 100644 index 000000000..859f7520e --- /dev/null +++ b/models/migrations/v1_14/main_test.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package v1_14 //nolint + +import ( + "testing" + + "code.gitea.io/gitea/models/migrations/base" +) + +func TestMain(m *testing.M) { + base.MainTest(m) +} diff --git a/models/migrations/v155.go b/models/migrations/v1_14/v155.go similarity index 81% rename from models/migrations/v155.go rename to models/migrations/v1_14/v155.go index f95b4dfa3..630eb94f1 100644 --- a/models/migrations/v155.go +++ b/models/migrations/v1_14/v155.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addChangedProtectedFilesPullRequestColumn(x *xorm.Engine) error { +func AddChangedProtectedFilesPullRequestColumn(x *xorm.Engine) error { type PullRequest struct { ChangedProtectedFiles []string `xorm:"TEXT JSON"` } diff --git a/models/migrations/v156.go b/models/migrations/v1_14/v156.go similarity index 98% rename from models/migrations/v156.go rename to models/migrations/v1_14/v156.go index 2c146892d..698c1c942 100644 --- a/models/migrations/v156.go +++ b/models/migrations/v1_14/v156.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "fmt" @@ -25,7 +25,7 @@ func userPath(userName string) string { return filepath.Join(setting.RepoRootPath, strings.ToLower(userName)) } -func fixPublisherIDforTagReleases(x *xorm.Engine) error { +func FixPublisherIDforTagReleases(x *xorm.Engine) error { type Release struct { ID int64 RepoID int64 diff --git a/models/migrations/v157.go b/models/migrations/v1_14/v157.go similarity index 95% rename from models/migrations/v157.go rename to models/migrations/v1_14/v157.go index e6738fd4d..12f0876d6 100644 --- a/models/migrations/v157.go +++ b/models/migrations/v1_14/v157.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "xorm.io/xorm" ) -func fixRepoTopics(x *xorm.Engine) error { +func FixRepoTopics(x *xorm.Engine) error { type Topic struct { ID int64 `xorm:"pk autoincr"` Name string `xorm:"UNIQUE VARCHAR(25)"` diff --git a/models/migrations/v158.go b/models/migrations/v1_14/v158.go similarity index 97% rename from models/migrations/v158.go rename to models/migrations/v1_14/v158.go index 472516d70..e6c9e629f 100644 --- a/models/migrations/v158.go +++ b/models/migrations/v1_14/v158.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "fmt" @@ -14,7 +14,7 @@ import ( "xorm.io/xorm" ) -func updateCodeCommentReplies(x *xorm.Engine) error { +func UpdateCodeCommentReplies(x *xorm.Engine) error { type Comment struct { ID int64 `xorm:"pk autoincr"` CommitSHA string `xorm:"VARCHAR(40)"` diff --git a/models/migrations/v159.go b/models/migrations/v1_14/v159.go similarity index 84% rename from models/migrations/v159.go rename to models/migrations/v1_14/v159.go index 68043b941..60be2b12b 100644 --- a/models/migrations/v159.go +++ b/models/migrations/v1_14/v159.go @@ -2,15 +2,16 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( + "code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/modules/timeutil" "xorm.io/xorm" ) -func updateReactionConstraint(x *xorm.Engine) error { +func UpdateReactionConstraint(x *xorm.Engine) error { // Reaction represents a reactions on issues and comments. type Reaction struct { ID int64 `xorm:"pk autoincr"` @@ -30,7 +31,7 @@ func updateReactionConstraint(x *xorm.Engine) error { return err } - if err := recreateTable(sess, &Reaction{}); err != nil { + if err := base.RecreateTable(sess, &Reaction{}); err != nil { return err } diff --git a/models/migrations/v160.go b/models/migrations/v1_14/v160.go similarity index 79% rename from models/migrations/v160.go rename to models/migrations/v1_14/v160.go index e1a4b4821..5bdf180ef 100644 --- a/models/migrations/v160.go +++ b/models/migrations/v1_14/v160.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "xorm.io/xorm" ) -func addBlockOnOfficialReviewRequests(x *xorm.Engine) error { +func AddBlockOnOfficialReviewRequests(x *xorm.Engine) error { type ProtectedBranch struct { BlockOnOfficialReviewRequests bool `xorm:"NOT NULL DEFAULT false"` } diff --git a/models/migrations/v161.go b/models/migrations/v1_14/v161.go similarity index 86% rename from models/migrations/v161.go rename to models/migrations/v1_14/v161.go index af6bdf16a..cf661caa3 100644 --- a/models/migrations/v161.go +++ b/models/migrations/v1_14/v161.go @@ -2,15 +2,17 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "context" + "code.gitea.io/gitea/models/migrations/base" + "xorm.io/xorm" ) -func convertTaskTypeToString(x *xorm.Engine) error { +func ConvertTaskTypeToString(x *xorm.Engine) error { const ( GOGS int = iota + 1 SLACK @@ -64,7 +66,7 @@ func convertTaskTypeToString(x *xorm.Engine) error { if err := sess.Begin(); err != nil { return err } - if err := dropTableColumns(sess, "hook_task", "type"); err != nil { + if err := base.DropTableColumns(sess, "hook_task", "type"); err != nil { return err } diff --git a/models/migrations/v162.go b/models/migrations/v1_14/v162.go similarity index 82% rename from models/migrations/v162.go rename to models/migrations/v1_14/v162.go index cf2baadbc..bfaa824fa 100644 --- a/models/migrations/v162.go +++ b/models/migrations/v1_14/v162.go @@ -2,13 +2,15 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( + "code.gitea.io/gitea/models/migrations/base" + "xorm.io/xorm" ) -func convertWebhookTaskTypeToString(x *xorm.Engine) error { +func ConvertWebhookTaskTypeToString(x *xorm.Engine) error { const ( GOGS int = iota + 1 SLACK @@ -53,7 +55,7 @@ func convertWebhookTaskTypeToString(x *xorm.Engine) error { if err := sess.Begin(); err != nil { return err } - if err := dropTableColumns(sess, "webhook", "hook_task_type"); err != nil { + if err := base.DropTableColumns(sess, "webhook", "hook_task_type"); err != nil { return err } diff --git a/models/migrations/v163.go b/models/migrations/v1_14/v163.go similarity index 76% rename from models/migrations/v163.go rename to models/migrations/v1_14/v163.go index 150cc34f0..8044dd403 100644 --- a/models/migrations/v163.go +++ b/models/migrations/v1_14/v163.go @@ -2,13 +2,15 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( + "code.gitea.io/gitea/models/migrations/base" + "xorm.io/xorm" ) -func convertTopicNameFrom25To50(x *xorm.Engine) error { +func ConvertTopicNameFrom25To50(x *xorm.Engine) error { type Topic struct { ID int64 `xorm:"pk autoincr"` Name string `xorm:"UNIQUE VARCHAR(50)"` @@ -26,7 +28,7 @@ func convertTopicNameFrom25To50(x *xorm.Engine) error { if err := sess.Begin(); err != nil { return err } - if err := recreateTable(sess, new(Topic)); err != nil { + if err := base.RecreateTable(sess, new(Topic)); err != nil { return err } diff --git a/models/migrations/v164.go b/models/migrations/v1_14/v164.go similarity index 92% rename from models/migrations/v164.go rename to models/migrations/v1_14/v164.go index 02343fac2..0a1424850 100644 --- a/models/migrations/v164.go +++ b/models/migrations/v1_14/v164.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "fmt" @@ -30,7 +30,7 @@ func (grant *OAuth2Grant) TableName() string { return "oauth2_grant" } -func addScopeAndNonceColumnsToOAuth2Grant(x *xorm.Engine) error { +func AddScopeAndNonceColumnsToOAuth2Grant(x *xorm.Engine) error { if err := x.Sync2(new(OAuth2Grant)); err != nil { return fmt.Errorf("Sync2: %w", err) } diff --git a/models/migrations/v165.go b/models/migrations/v1_14/v165.go similarity index 84% rename from models/migrations/v165.go rename to models/migrations/v1_14/v165.go index 87e1a24f2..d42dea96a 100644 --- a/models/migrations/v165.go +++ b/models/migrations/v1_14/v165.go @@ -2,14 +2,16 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( + "code.gitea.io/gitea/models/migrations/base" + "xorm.io/xorm" "xorm.io/xorm/schemas" ) -func convertHookTaskTypeToVarcharAndTrim(x *xorm.Engine) error { +func ConvertHookTaskTypeToVarcharAndTrim(x *xorm.Engine) error { dbType := x.Dialect().URI().DBType if dbType == schemas.SQLITE { // For SQLITE, varchar or char will always be represented as TEXT return nil @@ -19,7 +21,7 @@ func convertHookTaskTypeToVarcharAndTrim(x *xorm.Engine) error { Typ string `xorm:"VARCHAR(16) index"` } - if err := modifyColumn(x, "hook_task", &schemas.Column{ + if err := base.ModifyColumn(x, "hook_task", &schemas.Column{ Name: "typ", SQLType: schemas.SQLType{ Name: "VARCHAR", @@ -45,7 +47,7 @@ func convertHookTaskTypeToVarcharAndTrim(x *xorm.Engine) error { Type string `xorm:"VARCHAR(16) index"` } - if err := modifyColumn(x, "webhook", &schemas.Column{ + if err := base.ModifyColumn(x, "webhook", &schemas.Column{ Name: "type", SQLType: schemas.SQLType{ Name: "VARCHAR", diff --git a/models/migrations/v166.go b/models/migrations/v1_14/v166.go similarity index 97% rename from models/migrations/v166.go rename to models/migrations/v1_14/v166.go index 1b6e68b57..bdb18ffa6 100644 --- a/models/migrations/v166.go +++ b/models/migrations/v1_14/v166.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "crypto/sha256" @@ -16,7 +16,7 @@ import ( "xorm.io/xorm" ) -func recalculateUserEmptyPWD(x *xorm.Engine) (err error) { +func RecalculateUserEmptyPWD(x *xorm.Engine) (err error) { const ( algoBcrypt = "bcrypt" algoScrypt = "scrypt" diff --git a/models/migrations/v167.go b/models/migrations/v1_14/v167.go similarity index 86% rename from models/migrations/v167.go rename to models/migrations/v1_14/v167.go index 26d7cfd4f..8098a7621 100644 --- a/models/migrations/v167.go +++ b/models/migrations/v1_14/v167.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addUserRedirect(x *xorm.Engine) (err error) { +func AddUserRedirect(x *xorm.Engine) (err error) { type UserRedirect struct { ID int64 `xorm:"pk autoincr"` LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"` diff --git a/models/migrations/v168.go b/models/migrations/v1_14/v168.go similarity index 69% rename from models/migrations/v168.go rename to models/migrations/v1_14/v168.go index c34bb1d40..e62ab909a 100644 --- a/models/migrations/v168.go +++ b/models/migrations/v1_14/v168.go @@ -2,10 +2,10 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import "xorm.io/xorm" -func recreateUserTableToFixDefaultValues(_ *xorm.Engine) error { +func RecreateUserTableToFixDefaultValues(_ *xorm.Engine) error { return nil } diff --git a/models/migrations/v169.go b/models/migrations/v1_14/v169.go similarity index 77% rename from models/migrations/v169.go rename to models/migrations/v1_14/v169.go index e976281c5..f5fe332d9 100644 --- a/models/migrations/v169.go +++ b/models/migrations/v1_14/v169.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "xorm.io/xorm" ) -func commentTypeDeleteBranchUseOldRef(x *xorm.Engine) error { +func CommentTypeDeleteBranchUseOldRef(x *xorm.Engine) error { _, err := x.Exec("UPDATE comment SET old_ref = commit_sha, commit_sha = '' WHERE type = 11") return err } diff --git a/models/migrations/v170.go b/models/migrations/v1_14/v170.go similarity index 83% rename from models/migrations/v170.go rename to models/migrations/v1_14/v170.go index 2d654fb2b..cb0f927a2 100644 --- a/models/migrations/v170.go +++ b/models/migrations/v1_14/v170.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addDismissedReviewColumn(x *xorm.Engine) error { +func AddDismissedReviewColumn(x *xorm.Engine) error { type Review struct { Dismissed bool `xorm:"NOT NULL DEFAULT false"` } diff --git a/models/migrations/v171.go b/models/migrations/v1_14/v171.go similarity index 82% rename from models/migrations/v171.go rename to models/migrations/v1_14/v171.go index 8b27493ce..0c94fd4f9 100644 --- a/models/migrations/v171.go +++ b/models/migrations/v1_14/v171.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addSortingColToProjectBoard(x *xorm.Engine) error { +func AddSortingColToProjectBoard(x *xorm.Engine) error { type ProjectBoard struct { Sorting int8 `xorm:"NOT NULL DEFAULT 0"` } diff --git a/models/migrations/v172.go b/models/migrations/v1_14/v172.go similarity index 85% rename from models/migrations/v172.go rename to models/migrations/v1_14/v172.go index 125522a4b..6518c0317 100644 --- a/models/migrations/v172.go +++ b/models/migrations/v1_14/v172.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "code.gitea.io/gitea/modules/timeutil" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addSessionTable(x *xorm.Engine) error { +func AddSessionTable(x *xorm.Engine) error { type Session struct { Key string `xorm:"pk CHAR(16)"` Data []byte `xorm:"BLOB"` diff --git a/models/migrations/v173.go b/models/migrations/v1_14/v173.go similarity index 82% rename from models/migrations/v173.go rename to models/migrations/v1_14/v173.go index c1f167e6f..c8c9c39c6 100644 --- a/models/migrations/v173.go +++ b/models/migrations/v1_14/v173.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addTimeIDCommentColumn(x *xorm.Engine) error { +func AddTimeIDCommentColumn(x *xorm.Engine) error { type Comment struct { TimeID int64 } diff --git a/models/migrations/v174.go b/models/migrations/v1_14/v174.go similarity index 90% rename from models/migrations/v174.go rename to models/migrations/v1_14/v174.go index b6c555525..9a139764c 100644 --- a/models/migrations/v174.go +++ b/models/migrations/v1_14/v174.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addRepoTransfer(x *xorm.Engine) error { +func AddRepoTransfer(x *xorm.Engine) error { type RepoTransfer struct { ID int64 `xorm:"pk autoincr"` DoerID int64 diff --git a/models/migrations/v175.go b/models/migrations/v1_14/v175.go similarity index 95% rename from models/migrations/v175.go rename to models/migrations/v1_14/v175.go index 2dfefe987..e66871f5e 100644 --- a/models/migrations/v175.go +++ b/models/migrations/v1_14/v175.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "fmt" @@ -14,7 +14,7 @@ import ( "xorm.io/xorm" ) -func fixPostgresIDSequences(x *xorm.Engine) error { +func FixPostgresIDSequences(x *xorm.Engine) error { if !setting.Database.UsePostgreSQL { return nil } diff --git a/models/migrations/v176.go b/models/migrations/v1_14/v176.go similarity index 94% rename from models/migrations/v176.go rename to models/migrations/v1_14/v176.go index 6436330a8..4a343159e 100644 --- a/models/migrations/v176.go +++ b/models/migrations/v1_14/v176.go @@ -2,16 +2,16 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "xorm.io/xorm" ) -// removeInvalidLabels looks through the database to look for comments and issue_labels +// RemoveInvalidLabels looks through the database to look for comments and issue_labels // that refer to labels do not belong to the repository or organization that repository // that the issue is in -func removeInvalidLabels(x *xorm.Engine) error { +func RemoveInvalidLabels(x *xorm.Engine) error { type Comment struct { ID int64 `xorm:"pk autoincr"` Type int `xorm:"INDEX"` diff --git a/models/migrations/v176_test.go b/models/migrations/v1_14/v176_test.go similarity index 91% rename from models/migrations/v176_test.go rename to models/migrations/v1_14/v176_test.go index bc066c3b3..c088af906 100644 --- a/models/migrations/v176_test.go +++ b/models/migrations/v1_14/v176_test.go @@ -2,15 +2,17 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "testing" + "code.gitea.io/gitea/models/migrations/base" + "github.com/stretchr/testify/assert" ) -func Test_removeInvalidLabels(t *testing.T) { +func Test_RemoveInvalidLabels(t *testing.T) { // Models used by the migration type Comment struct { ID int64 `xorm:"pk autoincr"` @@ -46,7 +48,7 @@ func Test_removeInvalidLabels(t *testing.T) { } // load and prepare the test database - x, deferable := prepareTestEnv(t, 0, new(Comment), new(Issue), new(Repository), new(IssueLabel), new(Label)) + x, deferable := base.PrepareTestEnv(t, 0, new(Comment), new(Issue), new(Repository), new(IssueLabel), new(Label)) if x == nil || t.Failed() { defer deferable() return @@ -78,7 +80,7 @@ func Test_removeInvalidLabels(t *testing.T) { } // Run the migration - if err := removeInvalidLabels(x); err != nil { + if err := RemoveInvalidLabels(x); err != nil { t.Errorf("unable to RemoveInvalidLabels: %v", err) } diff --git a/models/migrations/v177.go b/models/migrations/v1_14/v177.go similarity index 86% rename from models/migrations/v177.go rename to models/migrations/v1_14/v177.go index f28826f17..c3086cd8e 100644 --- a/models/migrations/v177.go +++ b/models/migrations/v1_14/v177.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "fmt" @@ -10,8 +10,8 @@ import ( "xorm.io/xorm" ) -// deleteOrphanedIssueLabels looks through the database for issue_labels where the label no longer exists and deletes them. -func deleteOrphanedIssueLabels(x *xorm.Engine) error { +// DeleteOrphanedIssueLabels looks through the database for issue_labels where the label no longer exists and deletes them. +func DeleteOrphanedIssueLabels(x *xorm.Engine) error { type IssueLabel struct { ID int64 `xorm:"pk autoincr"` IssueID int64 `xorm:"UNIQUE(s)"` diff --git a/models/migrations/v177_test.go b/models/migrations/v1_14/v177_test.go similarity index 89% rename from models/migrations/v177_test.go rename to models/migrations/v1_14/v177_test.go index 5a58e2c61..4e061316d 100644 --- a/models/migrations/v177_test.go +++ b/models/migrations/v1_14/v177_test.go @@ -2,17 +2,18 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_14 //nolint import ( "testing" + "code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/modules/timeutil" "github.com/stretchr/testify/assert" ) -func Test_deleteOrphanedIssueLabels(t *testing.T) { +func Test_DeleteOrphanedIssueLabels(t *testing.T) { // Create the models used in the migration type IssueLabel struct { ID int64 `xorm:"pk autoincr"` @@ -34,7 +35,7 @@ func Test_deleteOrphanedIssueLabels(t *testing.T) { } // Prepare and load the testing database - x, deferable := prepareTestEnv(t, 0, new(IssueLabel), new(Label)) + x, deferable := base.PrepareTestEnv(t, 0, new(IssueLabel), new(Label)) if x == nil || t.Failed() { defer deferable() return @@ -55,7 +56,7 @@ func Test_deleteOrphanedIssueLabels(t *testing.T) { } // Run the migration - if err := deleteOrphanedIssueLabels(x); err != nil { + if err := DeleteOrphanedIssueLabels(x); err != nil { assert.NoError(t, err) return } diff --git a/models/migrations/v1_15/main_test.go b/models/migrations/v1_15/main_test.go new file mode 100644 index 000000000..d589734e3 --- /dev/null +++ b/models/migrations/v1_15/main_test.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package v1_15 //nolint + +import ( + "testing" + + "code.gitea.io/gitea/models/migrations/base" +) + +func TestMain(m *testing.M) { + base.MainTest(m) +} diff --git a/models/migrations/v178.go b/models/migrations/v1_15/v178.go similarity index 83% rename from models/migrations/v178.go rename to models/migrations/v1_15/v178.go index c2a9af618..27ece9891 100644 --- a/models/migrations/v178.go +++ b/models/migrations/v1_15/v178.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_15 //nolint import ( "xorm.io/xorm" ) -func addLFSMirrorColumns(x *xorm.Engine) error { +func AddLFSMirrorColumns(x *xorm.Engine) error { type Mirror struct { LFS bool `xorm:"lfs_enabled NOT NULL DEFAULT false"` LFSEndpoint string `xorm:"lfs_endpoint TEXT"` diff --git a/models/migrations/v179.go b/models/migrations/v1_15/v179.go similarity index 74% rename from models/migrations/v179.go rename to models/migrations/v1_15/v179.go index e6dddef27..c23bf9176 100644 --- a/models/migrations/v179.go +++ b/models/migrations/v1_15/v179.go @@ -2,21 +2,23 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_15 //nolint import ( + "code.gitea.io/gitea/models/migrations/base" + "xorm.io/xorm" "xorm.io/xorm/schemas" ) -func convertAvatarURLToText(x *xorm.Engine) error { +func ConvertAvatarURLToText(x *xorm.Engine) error { dbType := x.Dialect().URI().DBType if dbType == schemas.SQLITE { // For SQLITE, varchar or char will always be represented as TEXT return nil } // Some oauth2 providers may give very long avatar urls (i.e. Google) - return modifyColumn(x, "external_login_user", &schemas.Column{ + return base.ModifyColumn(x, "external_login_user", &schemas.Column{ Name: "avatar_url", SQLType: schemas.SQLType{ Name: schemas.Text, diff --git a/models/migrations/v180.go b/models/migrations/v1_15/v180.go similarity index 97% rename from models/migrations/v180.go rename to models/migrations/v1_15/v180.go index 4468a7107..fc948bb1f 100644 --- a/models/migrations/v180.go +++ b/models/migrations/v1_15/v180.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_15 //nolint import ( "code.gitea.io/gitea/modules/json" @@ -12,7 +12,7 @@ import ( "xorm.io/xorm" ) -func deleteMigrationCredentials(x *xorm.Engine) (err error) { +func DeleteMigrationCredentials(x *xorm.Engine) (err error) { // Task represents a task type Task struct { ID int64 diff --git a/models/migrations/v181.go b/models/migrations/v1_15/v181.go similarity index 96% rename from models/migrations/v181.go rename to models/migrations/v1_15/v181.go index 65045593a..7ec3dae37 100644 --- a/models/migrations/v181.go +++ b/models/migrations/v1_15/v181.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_15 //nolint import ( "strings" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addPrimaryEmail2EmailAddress(x *xorm.Engine) (err error) { +func AddPrimaryEmail2EmailAddress(x *xorm.Engine) (err error) { type User struct { ID int64 `xorm:"pk autoincr"` Email string `xorm:"NOT NULL"` diff --git a/models/migrations/v181_test.go b/models/migrations/v1_15/v181_test.go similarity index 84% rename from models/migrations/v181_test.go rename to models/migrations/v1_15/v181_test.go index b9a6c6619..f621d0d16 100644 --- a/models/migrations/v181_test.go +++ b/models/migrations/v1_15/v181_test.go @@ -2,16 +2,18 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_15 //nolint import ( "strings" "testing" + "code.gitea.io/gitea/models/migrations/base" + "github.com/stretchr/testify/assert" ) -func Test_addPrimaryEmail2EmailAddress(t *testing.T) { +func Test_AddPrimaryEmail2EmailAddress(t *testing.T) { type User struct { ID int64 Email string @@ -19,14 +21,14 @@ func Test_addPrimaryEmail2EmailAddress(t *testing.T) { } // Prepare and load the testing database - x, deferable := prepareTestEnv(t, 0, new(User)) + x, deferable := base.PrepareTestEnv(t, 0, new(User)) if x == nil || t.Failed() { defer deferable() return } defer deferable() - err := addPrimaryEmail2EmailAddress(x) + err := AddPrimaryEmail2EmailAddress(x) assert.NoError(t, err) type EmailAddress struct { diff --git a/models/migrations/v182.go b/models/migrations/v1_15/v182.go similarity index 92% rename from models/migrations/v182.go rename to models/migrations/v1_15/v182.go index 29c2d2654..32282089a 100644 --- a/models/migrations/v182.go +++ b/models/migrations/v1_15/v182.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_15 //nolint import ( "xorm.io/xorm" ) -func addIssueResourceIndexTable(x *xorm.Engine) error { +func AddIssueResourceIndexTable(x *xorm.Engine) error { type ResourceIndex struct { GroupID int64 `xorm:"pk"` MaxIndex int64 `xorm:"index"` diff --git a/models/migrations/v182_test.go b/models/migrations/v1_15/v182_test.go similarity index 83% rename from models/migrations/v182_test.go rename to models/migrations/v1_15/v182_test.go index 0d3eda9c5..b227e557a 100644 --- a/models/migrations/v182_test.go +++ b/models/migrations/v1_15/v182_test.go @@ -2,15 +2,17 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_15 //nolint import ( "testing" + "code.gitea.io/gitea/models/migrations/base" + "github.com/stretchr/testify/assert" ) -func Test_addIssueResourceIndexTable(t *testing.T) { +func Test_AddIssueResourceIndexTable(t *testing.T) { // Create the models used in the migration type Issue struct { ID int64 `xorm:"pk autoincr"` @@ -19,7 +21,7 @@ func Test_addIssueResourceIndexTable(t *testing.T) { } // Prepare and load the testing database - x, deferable := prepareTestEnv(t, 0, new(Issue)) + x, deferable := base.PrepareTestEnv(t, 0, new(Issue)) if x == nil || t.Failed() { defer deferable() return @@ -27,7 +29,7 @@ func Test_addIssueResourceIndexTable(t *testing.T) { defer deferable() // Run the migration - if err := addIssueResourceIndexTable(x); err != nil { + if err := AddIssueResourceIndexTable(x); err != nil { assert.NoError(t, err) return } diff --git a/models/migrations/v183.go b/models/migrations/v1_15/v183.go similarity index 91% rename from models/migrations/v183.go rename to models/migrations/v1_15/v183.go index 0dc3af28a..48039f8dc 100644 --- a/models/migrations/v183.go +++ b/models/migrations/v1_15/v183.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_15 //nolint import ( "fmt" @@ -13,7 +13,7 @@ import ( "xorm.io/xorm" ) -func createPushMirrorTable(x *xorm.Engine) error { +func CreatePushMirrorTable(x *xorm.Engine) error { type PushMirror struct { ID int64 `xorm:"pk autoincr"` RepoID int64 `xorm:"INDEX"` diff --git a/models/migrations/v184.go b/models/migrations/v1_15/v184.go similarity index 88% rename from models/migrations/v184.go rename to models/migrations/v1_15/v184.go index 593a8100a..195b419bc 100644 --- a/models/migrations/v184.go +++ b/models/migrations/v1_15/v184.go @@ -2,18 +2,19 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_15 //nolint import ( "context" "fmt" + "code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/modules/setting" "xorm.io/xorm" ) -func renameTaskErrorsToMessage(x *xorm.Engine) error { +func RenameTaskErrorsToMessage(x *xorm.Engine) error { type Task struct { Errors string `xorm:"TEXT"` // if task failed, saved the error reason Type int @@ -48,7 +49,7 @@ func renameTaskErrorsToMessage(x *xorm.Engine) error { if messageExist { // if both errors and message exist, drop message at first - if err := dropTableColumns(sess, "task", "message"); err != nil { + if err := base.DropTableColumns(sess, "task", "message"); err != nil { return err } } diff --git a/models/migrations/v185.go b/models/migrations/v1_15/v185.go similarity index 88% rename from models/migrations/v185.go rename to models/migrations/v1_15/v185.go index 096994889..4b8ed2e03 100644 --- a/models/migrations/v185.go +++ b/models/migrations/v1_15/v185.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_15 //nolint import ( "xorm.io/xorm" ) -func addRepoArchiver(x *xorm.Engine) error { +func AddRepoArchiver(x *xorm.Engine) error { // RepoArchiver represents all archivers type RepoArchiver struct { ID int64 `xorm:"pk autoincr"` diff --git a/models/migrations/v186.go b/models/migrations/v1_15/v186.go similarity index 88% rename from models/migrations/v186.go rename to models/migrations/v1_15/v186.go index eb6ec7118..3f53ff6a1 100644 --- a/models/migrations/v186.go +++ b/models/migrations/v1_15/v186.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_15 //nolint import ( "code.gitea.io/gitea/modules/timeutil" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func createProtectedTagTable(x *xorm.Engine) error { +func CreateProtectedTagTable(x *xorm.Engine) error { type ProtectedTag struct { ID int64 `xorm:"pk autoincr"` RepoID int64 diff --git a/models/migrations/v187.go b/models/migrations/v1_15/v187.go similarity index 71% rename from models/migrations/v187.go rename to models/migrations/v1_15/v187.go index 627423717..c3f60d1db 100644 --- a/models/migrations/v187.go +++ b/models/migrations/v1_15/v187.go @@ -2,13 +2,15 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_15 //nolint import ( + "code.gitea.io/gitea/models/migrations/base" + "xorm.io/xorm" ) -func dropWebhookColumns(x *xorm.Engine) error { +func DropWebhookColumns(x *xorm.Engine) error { // Make sure the columns exist before dropping them type Webhook struct { Signature string `xorm:"TEXT"` @@ -35,10 +37,10 @@ func dropWebhookColumns(x *xorm.Engine) error { if err := sess.Begin(); err != nil { return err } - if err := dropTableColumns(sess, "webhook", "signature", "is_ssl"); err != nil { + if err := base.DropTableColumns(sess, "webhook", "signature", "is_ssl"); err != nil { return err } - if err := dropTableColumns(sess, "hook_task", "typ", "url", "signature", "http_method", "content_type", "is_ssl"); err != nil { + if err := base.DropTableColumns(sess, "hook_task", "typ", "url", "signature", "http_method", "content_type", "is_ssl"); err != nil { return err } diff --git a/models/migrations/v188.go b/models/migrations/v1_15/v188.go similarity index 80% rename from models/migrations/v188.go rename to models/migrations/v1_15/v188.go index 52ef4aaa8..265b6f2f3 100644 --- a/models/migrations/v188.go +++ b/models/migrations/v1_15/v188.go @@ -2,11 +2,11 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_15 //nolint import "xorm.io/xorm" -func addKeyIsVerified(x *xorm.Engine) error { +func AddKeyIsVerified(x *xorm.Engine) error { type GPGKey struct { Verified bool `xorm:"NOT NULL DEFAULT false"` } diff --git a/models/migrations/v1_16/main_test.go b/models/migrations/v1_16/main_test.go new file mode 100644 index 000000000..8109a8a26 --- /dev/null +++ b/models/migrations/v1_16/main_test.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package v1_16 //nolint + +import ( + "testing" + + "code.gitea.io/gitea/models/migrations/base" +) + +func TestMain(m *testing.M) { + base.MainTest(m) +} diff --git a/models/migrations/v189.go b/models/migrations/v1_16/v189.go similarity index 92% rename from models/migrations/v189.go rename to models/migrations/v1_16/v189.go index 823e27e2e..b04115845 100644 --- a/models/migrations/v189.go +++ b/models/migrations/v1_16/v189.go @@ -2,18 +2,19 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "encoding/binary" "fmt" + "code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/modules/json" "xorm.io/xorm" ) -func unwrapLDAPSourceCfg(x *xorm.Engine) error { +func UnwrapLDAPSourceCfg(x *xorm.Engine) error { jsonUnmarshalHandleDoubleEncode := func(bs []byte, v interface{}) error { err := json.Unmarshal(bs, v) if err != nil { @@ -103,7 +104,7 @@ func unwrapLDAPSourceCfg(x *xorm.Engine) error { if err := sess.Begin(); err != nil { return err } - if err := dropTableColumns(sess, "login_source", "is_actived"); err != nil { + if err := base.DropTableColumns(sess, "login_source", "is_actived"); err != nil { return err } diff --git a/models/migrations/v189_test.go b/models/migrations/v1_16/v189_test.go similarity index 83% rename from models/migrations/v189_test.go rename to models/migrations/v1_16/v189_test.go index 4ec3fe8c6..9c0f0967c 100644 --- a/models/migrations/v189_test.go +++ b/models/migrations/v1_16/v189_test.go @@ -2,11 +2,12 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "testing" + "code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/modules/json" "github.com/stretchr/testify/assert" @@ -25,9 +26,9 @@ func (ls *LoginSourceOriginalV189) TableName() string { return "login_source" } -func Test_unwrapLDAPSourceCfg(t *testing.T) { +func Test_UnwrapLDAPSourceCfg(t *testing.T) { // Prepare and load the testing database - x, deferable := prepareTestEnv(t, 0, new(LoginSourceOriginalV189)) + x, deferable := base.PrepareTestEnv(t, 0, new(LoginSourceOriginalV189)) if x == nil || t.Failed() { defer deferable() return @@ -44,7 +45,7 @@ func Test_unwrapLDAPSourceCfg(t *testing.T) { } // Run the migration - if err := unwrapLDAPSourceCfg(x); err != nil { + if err := UnwrapLDAPSourceCfg(x); err != nil { assert.NoError(t, err) return } @@ -75,8 +76,8 @@ func Test_unwrapLDAPSourceCfg(t *testing.T) { return } - assert.EqualValues(t, expected, converted, "unwrapLDAPSourceCfg failed for %d", source.ID) - assert.EqualValues(t, source.ID%2 == 0, source.IsActive, "unwrapLDAPSourceCfg failed for %d", source.ID) + assert.EqualValues(t, expected, converted, "UnwrapLDAPSourceCfg failed for %d", source.ID) + assert.EqualValues(t, source.ID%2 == 0, source.IsActive, "UnwrapLDAPSourceCfg failed for %d", source.ID) } } } diff --git a/models/migrations/v190.go b/models/migrations/v1_16/v190.go similarity index 84% rename from models/migrations/v190.go rename to models/migrations/v1_16/v190.go index 00046ff2a..a669fc31f 100644 --- a/models/migrations/v190.go +++ b/models/migrations/v1_16/v190.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addAgitFlowPullRequest(x *xorm.Engine) error { +func AddAgitFlowPullRequest(x *xorm.Engine) error { type PullRequestFlow int type PullRequest struct { diff --git a/models/migrations/v191.go b/models/migrations/v1_16/v191.go similarity index 88% rename from models/migrations/v191.go rename to models/migrations/v1_16/v191.go index 9a688243e..461ac653d 100644 --- a/models/migrations/v191.go +++ b/models/migrations/v1_16/v191.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "code.gitea.io/gitea/modules/setting" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func alterIssueAndCommentTextFieldsToLongText(x *xorm.Engine) error { +func AlterIssueAndCommentTextFieldsToLongText(x *xorm.Engine) error { sess := x.NewSession() defer sess.Close() if err := sess.Begin(); err != nil { diff --git a/models/migrations/v192.go b/models/migrations/v1_16/v192.go similarity index 61% rename from models/migrations/v192.go rename to models/migrations/v1_16/v192.go index f436e93d6..e3ac2654f 100644 --- a/models/migrations/v192.go +++ b/models/migrations/v1_16/v192.go @@ -2,17 +2,19 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( + "code.gitea.io/gitea/models/migrations/base" + "xorm.io/xorm" ) -func recreateIssueResourceIndexTable(x *xorm.Engine) error { +func RecreateIssueResourceIndexTable(x *xorm.Engine) error { type IssueIndex struct { GroupID int64 `xorm:"pk"` MaxIndex int64 `xorm:"index"` } - return RecreateTables(new(IssueIndex))(x) + return base.RecreateTables(new(IssueIndex))(x) } diff --git a/models/migrations/v193.go b/models/migrations/v1_16/v193.go similarity index 93% rename from models/migrations/v193.go rename to models/migrations/v1_16/v193.go index c8244a1b3..8bf960feb 100644 --- a/models/migrations/v193.go +++ b/models/migrations/v1_16/v193.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "xorm.io/xorm" ) -func addRepoIDForAttachment(x *xorm.Engine) error { +func AddRepoIDForAttachment(x *xorm.Engine) error { type Attachment struct { ID int64 `xorm:"pk autoincr"` UUID string `xorm:"uuid UNIQUE"` diff --git a/models/migrations/v193_test.go b/models/migrations/v1_16/v193_test.go similarity index 86% rename from models/migrations/v193_test.go rename to models/migrations/v1_16/v193_test.go index b250d154f..b573a54bb 100644 --- a/models/migrations/v193_test.go +++ b/models/migrations/v1_16/v193_test.go @@ -2,15 +2,17 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "testing" + "code.gitea.io/gitea/models/migrations/base" + "github.com/stretchr/testify/assert" ) -func Test_addRepoIDForAttachment(t *testing.T) { +func Test_AddRepoIDForAttachment(t *testing.T) { type Attachment struct { ID int64 `xorm:"pk autoincr"` UUID string `xorm:"uuid UNIQUE"` @@ -31,14 +33,14 @@ func Test_addRepoIDForAttachment(t *testing.T) { } // Prepare and load the testing database - x, deferrable := prepareTestEnv(t, 0, new(Attachment), new(Issue), new(Release)) + x, deferrable := base.PrepareTestEnv(t, 0, new(Attachment), new(Issue), new(Release)) defer deferrable() if x == nil || t.Failed() { return } // Run the migration - if err := addRepoIDForAttachment(x); err != nil { + if err := AddRepoIDForAttachment(x); err != nil { assert.NoError(t, err) return } diff --git a/models/migrations/v194.go b/models/migrations/v1_16/v194.go similarity index 82% rename from models/migrations/v194.go rename to models/migrations/v1_16/v194.go index 6bd2f19ef..8486b1131 100644 --- a/models/migrations/v194.go +++ b/models/migrations/v1_16/v194.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addBranchProtectionUnprotectedFilesColumn(x *xorm.Engine) error { +func AddBranchProtectionUnprotectedFilesColumn(x *xorm.Engine) error { type ProtectedBranch struct { UnprotectedFilePatterns string `xorm:"TEXT"` } diff --git a/models/migrations/v195.go b/models/migrations/v1_16/v195.go similarity index 94% rename from models/migrations/v195.go rename to models/migrations/v1_16/v195.go index 8594dddf1..a7165cbf7 100644 --- a/models/migrations/v195.go +++ b/models/migrations/v1_16/v195.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addTableCommitStatusIndex(x *xorm.Engine) error { +func AddTableCommitStatusIndex(x *xorm.Engine) error { // CommitStatusIndex represents a table for commit status index type CommitStatusIndex struct { ID int64 diff --git a/models/migrations/v195_test.go b/models/migrations/v1_16/v195_test.go similarity index 85% rename from models/migrations/v195_test.go rename to models/migrations/v1_16/v195_test.go index 05f8469da..06ff13b52 100644 --- a/models/migrations/v195_test.go +++ b/models/migrations/v1_16/v195_test.go @@ -2,15 +2,17 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "testing" + "code.gitea.io/gitea/models/migrations/base" + "github.com/stretchr/testify/assert" ) -func Test_addTableCommitStatusIndex(t *testing.T) { +func Test_AddTableCommitStatusIndex(t *testing.T) { // Create the models used in the migration type CommitStatus struct { ID int64 `xorm:"pk autoincr"` @@ -20,7 +22,7 @@ func Test_addTableCommitStatusIndex(t *testing.T) { } // Prepare and load the testing database - x, deferable := prepareTestEnv(t, 0, new(CommitStatus)) + x, deferable := base.PrepareTestEnv(t, 0, new(CommitStatus)) if x == nil || t.Failed() { defer deferable() return @@ -28,7 +30,7 @@ func Test_addTableCommitStatusIndex(t *testing.T) { defer deferable() // Run the migration - if err := addTableCommitStatusIndex(x); err != nil { + if err := AddTableCommitStatusIndex(x); err != nil { assert.NoError(t, err) return } diff --git a/models/migrations/v196.go b/models/migrations/v1_16/v196.go similarity index 82% rename from models/migrations/v196.go rename to models/migrations/v1_16/v196.go index 0423d0268..b73a56607 100644 --- a/models/migrations/v196.go +++ b/models/migrations/v1_16/v196.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addColorColToProjectBoard(x *xorm.Engine) error { +func AddColorColToProjectBoard(x *xorm.Engine) error { type ProjectBoard struct { Color string `xorm:"VARCHAR(7)"` } diff --git a/models/migrations/v197.go b/models/migrations/v1_16/v197.go similarity index 85% rename from models/migrations/v197.go rename to models/migrations/v1_16/v197.go index 3517896a2..da2e9ae76 100644 --- a/models/migrations/v197.go +++ b/models/migrations/v1_16/v197.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "xorm.io/xorm" ) -func addRenamedBranchTable(x *xorm.Engine) error { +func AddRenamedBranchTable(x *xorm.Engine) error { type RenamedBranch struct { ID int64 `xorm:"pk autoincr"` RepoID int64 `xorm:"INDEX NOT NULL"` diff --git a/models/migrations/v198.go b/models/migrations/v1_16/v198.go similarity index 90% rename from models/migrations/v198.go rename to models/migrations/v1_16/v198.go index 4b1515109..0e09ee530 100644 --- a/models/migrations/v198.go +++ b/models/migrations/v1_16/v198.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "fmt" @@ -12,7 +12,7 @@ import ( "xorm.io/xorm" ) -func addTableIssueContentHistory(x *xorm.Engine) error { +func AddTableIssueContentHistory(x *xorm.Engine) error { type IssueContentHistory struct { ID int64 `xorm:"pk autoincr"` PosterID int64 diff --git a/models/migrations/v199.go b/models/migrations/v1_16/v199.go similarity index 92% rename from models/migrations/v199.go rename to models/migrations/v1_16/v199.go index 29f9d49db..53ed7e4e8 100644 --- a/models/migrations/v199.go +++ b/models/migrations/v1_16/v199.go @@ -2,6 +2,6 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint // We used to use a table `remote_version` to store information for updater, now we use `AppState`, so this migration task is a no-op now. diff --git a/models/migrations/v200.go b/models/migrations/v1_16/v200.go similarity index 86% rename from models/migrations/v200.go rename to models/migrations/v1_16/v200.go index f0f107bf7..70ee36354 100644 --- a/models/migrations/v200.go +++ b/models/migrations/v1_16/v200.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addTableAppState(x *xorm.Engine) error { +func AddTableAppState(x *xorm.Engine) error { type AppState struct { ID string `xorm:"pk varchar(200)"` Revision int64 diff --git a/models/migrations/v201.go b/models/migrations/v1_16/v201.go similarity index 82% rename from models/migrations/v201.go rename to models/migrations/v1_16/v201.go index 637c30617..6a2eda77b 100644 --- a/models/migrations/v201.go +++ b/models/migrations/v1_16/v201.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "xorm.io/xorm" ) -func dropTableRemoteVersion(x *xorm.Engine) error { +func DropTableRemoteVersion(x *xorm.Engine) error { // drop the orphaned table introduced in `v199`, now the update checker also uses AppState, do not need this table _ = x.DropTables("remote_version") return nil diff --git a/models/migrations/v202.go b/models/migrations/v1_16/v202.go similarity index 89% rename from models/migrations/v202.go rename to models/migrations/v1_16/v202.go index 1bfc28d63..de0576b8d 100644 --- a/models/migrations/v202.go +++ b/models/migrations/v1_16/v202.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func createUserSettingsTable(x *xorm.Engine) error { +func CreateUserSettingsTable(x *xorm.Engine) error { type UserSetting struct { ID int64 `xorm:"pk autoincr"` UserID int64 `xorm:"index unique(key_userid)"` // to load all of someone's settings diff --git a/models/migrations/v203.go b/models/migrations/v1_16/v203.go similarity index 82% rename from models/migrations/v203.go rename to models/migrations/v1_16/v203.go index 2e1dd7289..78903cb59 100644 --- a/models/migrations/v203.go +++ b/models/migrations/v1_16/v203.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "xorm.io/xorm" ) -func addProjectIssueSorting(x *xorm.Engine) error { +func AddProjectIssueSorting(x *xorm.Engine) error { // ProjectIssue saves relation from issue to a project type ProjectIssue struct { Sorting int64 `xorm:"NOT NULL DEFAULT 0"` diff --git a/models/migrations/v204.go b/models/migrations/v1_16/v204.go similarity index 80% rename from models/migrations/v204.go rename to models/migrations/v1_16/v204.go index ad21cfbd8..8151866fa 100644 --- a/models/migrations/v204.go +++ b/models/migrations/v1_16/v204.go @@ -2,11 +2,11 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import "xorm.io/xorm" -func addSSHKeyIsVerified(x *xorm.Engine) error { +func AddSSHKeyIsVerified(x *xorm.Engine) error { type PublicKey struct { Verified bool `xorm:"NOT NULL DEFAULT false"` } diff --git a/models/migrations/v205.go b/models/migrations/v1_16/v205.go similarity index 74% rename from models/migrations/v205.go rename to models/migrations/v1_16/v205.go index 7aefa0431..9cca445d3 100644 --- a/models/migrations/v205.go +++ b/models/migrations/v1_16/v205.go @@ -2,21 +2,23 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( + "code.gitea.io/gitea/models/migrations/base" + "xorm.io/xorm" "xorm.io/xorm/schemas" ) -func migrateUserPasswordSalt(x *xorm.Engine) error { +func MigrateUserPasswordSalt(x *xorm.Engine) error { dbType := x.Dialect().URI().DBType // For SQLITE, the max length doesn't matter. if dbType == schemas.SQLITE { return nil } - if err := modifyColumn(x, "user", &schemas.Column{ + if err := base.ModifyColumn(x, "user", &schemas.Column{ Name: "rands", SQLType: schemas.SQLType{ Name: "VARCHAR", @@ -29,7 +31,7 @@ func migrateUserPasswordSalt(x *xorm.Engine) error { return err } - return modifyColumn(x, "user", &schemas.Column{ + return base.ModifyColumn(x, "user", &schemas.Column{ Name: "salt", SQLType: schemas.SQLType{ Name: "VARCHAR", diff --git a/models/migrations/v206.go b/models/migrations/v1_16/v206.go similarity index 89% rename from models/migrations/v206.go rename to models/migrations/v1_16/v206.go index 525a47572..b2530d100 100644 --- a/models/migrations/v206.go +++ b/models/migrations/v1_16/v206.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addAuthorizeColForTeamUnit(x *xorm.Engine) error { +func AddAuthorizeColForTeamUnit(x *xorm.Engine) error { type TeamUnit struct { ID int64 `xorm:"pk autoincr"` OrgID int64 `xorm:"INDEX"` diff --git a/models/migrations/v207.go b/models/migrations/v1_16/v207.go similarity index 79% rename from models/migrations/v207.go rename to models/migrations/v1_16/v207.go index f60dfc3dc..f93ae4c33 100644 --- a/models/migrations/v207.go +++ b/models/migrations/v1_16/v207.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "xorm.io/xorm" ) -func addWebAuthnCred(x *xorm.Engine) error { +func AddWebAuthnCred(x *xorm.Engine) error { // NO-OP Don't migrate here - let v210 do this. return nil diff --git a/models/migrations/v208.go b/models/migrations/v1_16/v208.go similarity index 71% rename from models/migrations/v208.go rename to models/migrations/v1_16/v208.go index 287540612..40f8b05b8 100644 --- a/models/migrations/v208.go +++ b/models/migrations/v1_16/v208.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "xorm.io/xorm" ) -func useBase32HexForCredIDInWebAuthnCredential(x *xorm.Engine) error { +func UseBase32HexForCredIDInWebAuthnCredential(x *xorm.Engine) error { // noop return nil } diff --git a/models/migrations/v209.go b/models/migrations/v1_16/v209.go similarity index 78% rename from models/migrations/v209.go rename to models/migrations/v1_16/v209.go index 710684ef5..e2f06bbfb 100644 --- a/models/migrations/v209.go +++ b/models/migrations/v1_16/v209.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "xorm.io/xorm" ) -func increaseCredentialIDTo410(x *xorm.Engine) error { +func IncreaseCredentialIDTo410(x *xorm.Engine) error { // no-op // v208 was completely wrong // So now we have to no-op again. diff --git a/models/migrations/v210.go b/models/migrations/v1_16/v210.go similarity index 96% rename from models/migrations/v210.go rename to models/migrations/v1_16/v210.go index 891c96fb3..b59b35660 100644 --- a/models/migrations/v210.go +++ b/models/migrations/v1_16/v210.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "crypto/elliptic" @@ -10,6 +10,7 @@ import ( "fmt" "strings" + "code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/modules/timeutil" "github.com/tstranex/u2f" @@ -18,7 +19,7 @@ import ( ) // v208 migration was completely broken -func remigrateU2FCredentials(x *xorm.Engine) error { +func RemigrateU2FCredentials(x *xorm.Engine) error { // Create webauthnCredential table type webauthnCredential struct { ID int64 `xorm:"pk autoincr"` @@ -58,7 +59,7 @@ func remigrateU2FCredentials(x *xorm.Engine) error { return err } - if err := recreateTable(sess, new(webauthnCredential)); err != nil { + if err := base.RecreateTable(sess, new(webauthnCredential)); err != nil { _ = sess.Close() return err } diff --git a/models/migrations/v210_test.go b/models/migrations/v1_16/v210_test.go similarity index 87% rename from models/migrations/v210_test.go rename to models/migrations/v1_16/v210_test.go index 70dbe61b0..20c430594 100644 --- a/models/migrations/v210_test.go +++ b/models/migrations/v1_16/v210_test.go @@ -2,18 +2,19 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_16 //nolint import ( "testing" + "code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/modules/timeutil" "github.com/stretchr/testify/assert" "xorm.io/xorm/schemas" ) -func Test_remigrateU2FCredentials(t *testing.T) { +func Test_RemigrateU2FCredentials(t *testing.T) { // Create webauthnCredential table type WebauthnCredential struct { ID int64 `xorm:"pk autoincr"` @@ -44,7 +45,7 @@ func Test_remigrateU2FCredentials(t *testing.T) { } // Prepare and load the testing database - x, deferable := prepareTestEnv(t, 0, new(WebauthnCredential), new(U2fRegistration), new(ExpectedWebauthnCredential)) + x, deferable := base.PrepareTestEnv(t, 0, new(WebauthnCredential), new(U2fRegistration), new(ExpectedWebauthnCredential)) if x == nil || t.Failed() { defer deferable() return @@ -56,7 +57,7 @@ func Test_remigrateU2FCredentials(t *testing.T) { } // Run the migration - if err := remigrateU2FCredentials(x); err != nil { + if err := RemigrateU2FCredentials(x); err != nil { assert.NoError(t, err) return } diff --git a/models/migrations/v1_17/main_test.go b/models/migrations/v1_17/main_test.go new file mode 100644 index 000000000..0f1708de8 --- /dev/null +++ b/models/migrations/v1_17/main_test.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package v1_17 // nolint + +import ( + "testing" + + "code.gitea.io/gitea/models/migrations/base" +) + +func TestMain(m *testing.M) { + base.MainTest(m) +} diff --git a/models/migrations/v211.go b/models/migrations/v1_17/v211.go similarity index 90% rename from models/migrations/v211.go rename to models/migrations/v1_17/v211.go index ec7cb46d4..de9eb4b4b 100644 --- a/models/migrations/v211.go +++ b/models/migrations/v1_17/v211.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_17 // nolint import ( "fmt" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func createForeignReferenceTable(x *xorm.Engine) error { +func CreateForeignReferenceTable(x *xorm.Engine) error { type ForeignReference struct { // RepoID is the first column in all indices. now we only need 2 indices: (repo, local) and (repo, foreign, type) RepoID int64 `xorm:"UNIQUE(repo_foreign_type) INDEX(repo_local)" ` diff --git a/models/migrations/v212.go b/models/migrations/v1_17/v212.go similarity index 97% rename from models/migrations/v212.go rename to models/migrations/v1_17/v212.go index 9d16f0556..5187f5e72 100644 --- a/models/migrations/v212.go +++ b/models/migrations/v1_17/v212.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_17 // nolint import ( "code.gitea.io/gitea/modules/timeutil" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addPackageTables(x *xorm.Engine) error { +func AddPackageTables(x *xorm.Engine) error { type Package struct { ID int64 `xorm:"pk autoincr"` OwnerID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` diff --git a/models/migrations/v213.go b/models/migrations/v1_17/v213.go similarity index 83% rename from models/migrations/v213.go rename to models/migrations/v1_17/v213.go index b1dbf98d1..7b1b158f9 100644 --- a/models/migrations/v213.go +++ b/models/migrations/v1_17/v213.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_17 // nolint import ( "xorm.io/xorm" ) -func addAllowMaintainerEdit(x *xorm.Engine) error { +func AddAllowMaintainerEdit(x *xorm.Engine) error { // PullRequest represents relation between pull request and repositories. type PullRequest struct { AllowMaintainerEdit bool `xorm:"NOT NULL DEFAULT false"` diff --git a/models/migrations/v214.go b/models/migrations/v1_17/v214.go similarity index 88% rename from models/migrations/v214.go rename to models/migrations/v1_17/v214.go index dfe5d776a..e6fa53d4b 100644 --- a/models/migrations/v214.go +++ b/models/migrations/v1_17/v214.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_17 // nolint import ( "xorm.io/xorm" ) -func addAutoMergeTable(x *xorm.Engine) error { +func AddAutoMergeTable(x *xorm.Engine) error { type MergeStyle string type PullAutoMerge struct { ID int64 `xorm:"pk autoincr"` diff --git a/models/migrations/v215.go b/models/migrations/v1_17/v215.go similarity index 91% rename from models/migrations/v215.go rename to models/migrations/v1_17/v215.go index d65488a18..e14851596 100644 --- a/models/migrations/v215.go +++ b/models/migrations/v1_17/v215.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_17 // nolint import ( "code.gitea.io/gitea/models/pull" @@ -11,7 +11,7 @@ import ( "xorm.io/xorm" ) -func addReviewViewedFiles(x *xorm.Engine) error { +func AddReviewViewedFiles(x *xorm.Engine) error { type ReviewState struct { ID int64 `xorm:"pk autoincr"` UserID int64 `xorm:"NOT NULL UNIQUE(pull_commit_user)"` diff --git a/models/migrations/v216.go b/models/migrations/v1_17/v216.go similarity index 92% rename from models/migrations/v216.go rename to models/migrations/v1_17/v216.go index ab4480840..bde582577 100644 --- a/models/migrations/v216.go +++ b/models/migrations/v1_17/v216.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_17 // nolint // This migration added non-ideal indices to the action table which on larger datasets slowed things down // it has been superceded by v218.go diff --git a/models/migrations/v217.go b/models/migrations/v1_17/v217.go similarity index 87% rename from models/migrations/v217.go rename to models/migrations/v1_17/v217.go index 280dba17a..abba9e8ec 100644 --- a/models/migrations/v217.go +++ b/models/migrations/v1_17/v217.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_17 // nolint import ( "code.gitea.io/gitea/modules/setting" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func alterHookTaskTextFieldsToLongText(x *xorm.Engine) error { +func AlterHookTaskTextFieldsToLongText(x *xorm.Engine) error { sess := x.NewSession() defer sess.Close() if err := sess.Begin(); err != nil { diff --git a/models/migrations/v218.go b/models/migrations/v1_17/v218.go similarity index 95% rename from models/migrations/v218.go rename to models/migrations/v1_17/v218.go index e08c6c5b0..a5cd1c591 100644 --- a/models/migrations/v218.go +++ b/models/migrations/v1_17/v218.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_17 // nolint import ( "code.gitea.io/gitea/modules/setting" @@ -48,6 +48,6 @@ func (*improveActionTableIndicesAction) TableIndices() []*schemas.Index { return indices } -func improveActionTableIndices(x *xorm.Engine) error { +func ImproveActionTableIndices(x *xorm.Engine) error { return x.Sync2(&improveActionTableIndicesAction{}) } diff --git a/models/migrations/v219.go b/models/migrations/v1_17/v219.go similarity index 89% rename from models/migrations/v219.go rename to models/migrations/v1_17/v219.go index 7b4f34b70..d22f4e6b8 100644 --- a/models/migrations/v219.go +++ b/models/migrations/v1_17/v219.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_17 // nolint import ( "time" @@ -13,7 +13,7 @@ import ( "xorm.io/xorm" ) -func addSyncOnCommitColForPushMirror(x *xorm.Engine) error { +func AddSyncOnCommitColForPushMirror(x *xorm.Engine) error { type PushMirror struct { ID int64 `xorm:"pk autoincr"` RepoID int64 `xorm:"INDEX"` diff --git a/models/migrations/v220.go b/models/migrations/v1_17/v220.go similarity index 93% rename from models/migrations/v220.go rename to models/migrations/v1_17/v220.go index 8138bc5bb..bbceb933b 100644 --- a/models/migrations/v220.go +++ b/models/migrations/v1_17/v220.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_17 // nolint import ( packages_model "code.gitea.io/gitea/models/packages" @@ -12,7 +12,7 @@ import ( "xorm.io/xorm/schemas" ) -func addContainerRepositoryProperty(x *xorm.Engine) (err error) { +func AddContainerRepositoryProperty(x *xorm.Engine) (err error) { switch x.Dialect().URI().DBType { case schemas.SQLITE: _, err = x.Exec("INSERT INTO package_property (ref_type, ref_id, name, value) SELECT ?, p.id, ?, u.lower_name || '/' || p.lower_name FROM package p JOIN `user` u ON p.owner_id = u.id WHERE p.type = ?", diff --git a/models/migrations/v221.go b/models/migrations/v1_17/v221.go similarity index 96% rename from models/migrations/v221.go rename to models/migrations/v1_17/v221.go index f3bcfcdf1..17744d53a 100644 --- a/models/migrations/v221.go +++ b/models/migrations/v1_17/v221.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_17 // nolint import ( "encoding/base32" @@ -13,7 +13,7 @@ import ( "xorm.io/xorm" ) -func storeWebauthnCredentialIDAsBytes(x *xorm.Engine) error { +func StoreWebauthnCredentialIDAsBytes(x *xorm.Engine) error { // Create webauthnCredential table type webauthnCredential struct { ID int64 `xorm:"pk autoincr"` diff --git a/models/migrations/v221_test.go b/models/migrations/v1_17/v221_test.go similarity index 85% rename from models/migrations/v221_test.go rename to models/migrations/v1_17/v221_test.go index c50ca5c87..d635820f8 100644 --- a/models/migrations/v221_test.go +++ b/models/migrations/v1_17/v221_test.go @@ -2,16 +2,18 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_17 // nolint import ( "encoding/base32" "testing" + "code.gitea.io/gitea/models/migrations/base" + "github.com/stretchr/testify/assert" ) -func Test_storeWebauthnCredentialIDAsBytes(t *testing.T) { +func Test_StoreWebauthnCredentialIDAsBytes(t *testing.T) { // Create webauthnCredential table type WebauthnCredential struct { ID int64 `xorm:"pk autoincr"` @@ -37,13 +39,13 @@ func Test_storeWebauthnCredentialIDAsBytes(t *testing.T) { } // Prepare and load the testing database - x, deferable := prepareTestEnv(t, 0, new(WebauthnCredential), new(ExpectedWebauthnCredential)) + x, deferable := base.PrepareTestEnv(t, 0, new(WebauthnCredential), new(ExpectedWebauthnCredential)) defer deferable() if x == nil || t.Failed() { return } - if err := storeWebauthnCredentialIDAsBytes(x); err != nil { + if err := StoreWebauthnCredentialIDAsBytes(x); err != nil { assert.NoError(t, err) return } diff --git a/models/migrations/v222.go b/models/migrations/v1_17/v222.go similarity index 89% rename from models/migrations/v222.go rename to models/migrations/v1_17/v222.go index 99acdfd20..3aafb1848 100644 --- a/models/migrations/v222.go +++ b/models/migrations/v1_17/v222.go @@ -2,18 +2,19 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_17 // nolint import ( "context" "fmt" + "code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/modules/timeutil" "xorm.io/xorm" ) -func dropOldCredentialIDColumn(x *xorm.Engine) error { +func DropOldCredentialIDColumn(x *xorm.Engine) error { // This migration maybe rerun so that we should check if it has been run credentialIDExist, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "webauthn_credential", "credential_id") if err != nil { @@ -57,7 +58,7 @@ func dropOldCredentialIDColumn(x *xorm.Engine) error { sess := x.NewSession() defer sess.Close() - if err := dropTableColumns(sess, "webauthn_credential", "credential_id"); err != nil { + if err := base.DropTableColumns(sess, "webauthn_credential", "credential_id"); err != nil { return fmt.Errorf("unable to drop old credentialID column: %w", err) } return sess.Commit() diff --git a/models/migrations/v223.go b/models/migrations/v1_17/v223.go similarity index 93% rename from models/migrations/v223.go rename to models/migrations/v1_17/v223.go index 9f4c6acfe..530ddf0e0 100644 --- a/models/migrations/v223.go +++ b/models/migrations/v1_17/v223.go @@ -2,19 +2,20 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_17 // nolint import ( "context" "fmt" + "code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" "xorm.io/xorm" ) -func renameCredentialIDBytes(x *xorm.Engine) error { +func RenameCredentialIDBytes(x *xorm.Engine) error { // This migration maybe rerun so that we should check if it has been run credentialIDExist, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "webauthn_credential", "credential_id") if err != nil { @@ -59,7 +60,7 @@ func renameCredentialIDBytes(x *xorm.Engine) error { if credentialIDExist { // if both errors and message exist, drop message at first - if err := dropTableColumns(sess, "webauthn_credential", "credential_id"); err != nil { + if err := base.DropTableColumns(sess, "webauthn_credential", "credential_id"); err != nil { return err } } diff --git a/models/migrations/v1_18/main_test.go b/models/migrations/v1_18/main_test.go new file mode 100644 index 000000000..cb0934042 --- /dev/null +++ b/models/migrations/v1_18/main_test.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package v1_18 // nolint + +import ( + "testing" + + "code.gitea.io/gitea/models/migrations/base" +) + +func TestMain(m *testing.M) { + base.MainTest(m) +} diff --git a/models/migrations/v224.go b/models/migrations/v1_18/v224.go similarity index 87% rename from models/migrations/v224.go rename to models/migrations/v1_18/v224.go index 2ed161ef4..34dbcc1aa 100644 --- a/models/migrations/v224.go +++ b/models/migrations/v1_18/v224.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_18 // nolint import ( "xorm.io/xorm" ) -func createUserBadgesTable(x *xorm.Engine) error { +func CreateUserBadgesTable(x *xorm.Engine) error { type Badge struct { ID int64 `xorm:"pk autoincr"` Description string diff --git a/models/migrations/v225.go b/models/migrations/v1_18/v225.go similarity index 87% rename from models/migrations/v225.go rename to models/migrations/v1_18/v225.go index 6dd460eb6..8848a8982 100644 --- a/models/migrations/v225.go +++ b/models/migrations/v1_18/v225.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_18 // nolint import ( "code.gitea.io/gitea/modules/setting" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func alterPublicGPGKeyContentFieldsToMediumText(x *xorm.Engine) error { +func AlterPublicGPGKeyContentFieldsToMediumText(x *xorm.Engine) error { sess := x.NewSession() defer sess.Close() if err := sess.Begin(); err != nil { diff --git a/models/migrations/v226.go b/models/migrations/v1_18/v226.go similarity index 82% rename from models/migrations/v226.go rename to models/migrations/v1_18/v226.go index 2f85bca21..bff88cbef 100644 --- a/models/migrations/v226.go +++ b/models/migrations/v1_18/v226.go @@ -2,14 +2,14 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_18 // nolint import ( "xorm.io/builder" "xorm.io/xorm" ) -func fixPackageSemverField(x *xorm.Engine) error { +func FixPackageSemverField(x *xorm.Engine) error { _, err := x.Exec(builder.Update(builder.Eq{"semver_compatible": false}).From("`package`").Where(builder.In("`type`", "conan", "generic"))) return err } diff --git a/models/migrations/v227.go b/models/migrations/v1_18/v227.go similarity index 95% rename from models/migrations/v227.go rename to models/migrations/v1_18/v227.go index 36c0a5eef..7dc468108 100644 --- a/models/migrations/v227.go +++ b/models/migrations/v1_18/v227.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_18 // nolint import ( "fmt" @@ -43,7 +43,7 @@ func insertSettingsIfNotExist(x *xorm.Engine, sysSettings []*SystemSetting) erro return sess.Commit() } -func createSystemSettingsTable(x *xorm.Engine) error { +func CreateSystemSettingsTable(x *xorm.Engine) error { if err := x.Sync2(new(SystemSetting)); err != nil { return fmt.Errorf("sync2: %w", err) } diff --git a/models/migrations/v228.go b/models/migrations/v1_18/v228.go similarity index 92% rename from models/migrations/v228.go rename to models/migrations/v1_18/v228.go index 62c81ef9d..28ce171b5 100644 --- a/models/migrations/v228.go +++ b/models/migrations/v1_18/v228.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_18 // nolint import ( "code.gitea.io/gitea/modules/timeutil" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addTeamInviteTable(x *xorm.Engine) error { +func AddTeamInviteTable(x *xorm.Engine) error { type TeamInvite struct { ID int64 `xorm:"pk autoincr"` Token string `xorm:"UNIQUE(token) INDEX NOT NULL DEFAULT ''"` diff --git a/models/migrations/v229.go b/models/migrations/v1_18/v229.go similarity index 94% rename from models/migrations/v229.go rename to models/migrations/v1_18/v229.go index 42ec2033f..ea7c3ed32 100644 --- a/models/migrations/v229.go +++ b/models/migrations/v1_18/v229.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_18 //nolint import ( "fmt" @@ -13,7 +13,7 @@ import ( "xorm.io/xorm" ) -func updateOpenMilestoneCounts(x *xorm.Engine) error { +func UpdateOpenMilestoneCounts(x *xorm.Engine) error { var openMilestoneIDs []int64 err := x.Table("milestone").Select("id").Where(builder.Neq{"is_closed": 1}).Find(&openMilestoneIDs) if err != nil { diff --git a/models/migrations/v229_test.go b/models/migrations/v1_18/v229_test.go similarity index 75% rename from models/migrations/v229_test.go rename to models/migrations/v1_18/v229_test.go index f8a147c9b..caa24b26b 100644 --- a/models/migrations/v229_test.go +++ b/models/migrations/v1_18/v229_test.go @@ -2,27 +2,28 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_18 //nolint import ( "testing" "code.gitea.io/gitea/models/issues" + "code.gitea.io/gitea/models/migrations/base" "github.com/stretchr/testify/assert" ) -func Test_updateOpenMilestoneCounts(t *testing.T) { +func Test_UpdateOpenMilestoneCounts(t *testing.T) { type ExpectedMilestone issues.Milestone // Prepare and load the testing database - x, deferable := prepareTestEnv(t, 0, new(issues.Milestone), new(ExpectedMilestone), new(issues.Issue)) + x, deferable := base.PrepareTestEnv(t, 0, new(issues.Milestone), new(ExpectedMilestone), new(issues.Issue)) defer deferable() if x == nil || t.Failed() { return } - if err := updateOpenMilestoneCounts(x); err != nil { + if err := UpdateOpenMilestoneCounts(x); err != nil { assert.NoError(t, err) return } diff --git a/models/migrations/v230.go b/models/migrations/v1_18/v230.go similarity index 72% rename from models/migrations/v230.go rename to models/migrations/v1_18/v230.go index f08e6a376..fe98e07a4 100644 --- a/models/migrations/v230.go +++ b/models/migrations/v1_18/v230.go @@ -2,14 +2,14 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_18 // nolint import ( "xorm.io/xorm" ) -// addConfidentialColumnToOAuth2ApplicationTable: add ConfidentialClient column, setting existing rows to true -func addConfidentialClientColumnToOAuth2ApplicationTable(x *xorm.Engine) error { +// AddConfidentialColumnToOAuth2ApplicationTable: add ConfidentialClient column, setting existing rows to true +func AddConfidentialClientColumnToOAuth2ApplicationTable(x *xorm.Engine) error { type OAuth2Application struct { ConfidentialClient bool `xorm:"NOT NULL DEFAULT TRUE"` } diff --git a/models/migrations/v230_test.go b/models/migrations/v1_18/v230_test.go similarity index 75% rename from models/migrations/v230_test.go rename to models/migrations/v1_18/v230_test.go index 98ba3f5d9..0af13a1b9 100644 --- a/models/migrations/v230_test.go +++ b/models/migrations/v1_18/v230_test.go @@ -2,28 +2,30 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_18 //nolint import ( "testing" + "code.gitea.io/gitea/models/migrations/base" + "github.com/stretchr/testify/assert" ) -func Test_addConfidentialClientColumnToOAuth2ApplicationTable(t *testing.T) { +func Test_AddConfidentialClientColumnToOAuth2ApplicationTable(t *testing.T) { // premigration type OAuth2Application struct { ID int64 } // Prepare and load the testing database - x, deferable := prepareTestEnv(t, 0, new(OAuth2Application)) + x, deferable := base.PrepareTestEnv(t, 0, new(OAuth2Application)) defer deferable() if x == nil || t.Failed() { return } - if err := addConfidentialClientColumnToOAuth2ApplicationTable(x); err != nil { + if err := AddConfidentialClientColumnToOAuth2ApplicationTable(x); err != nil { assert.NoError(t, err) return } diff --git a/models/migrations/v1_19/v231.go b/models/migrations/v1_19/v231.go new file mode 100644 index 000000000..809a1cfa5 --- /dev/null +++ b/models/migrations/v1_19/v231.go @@ -0,0 +1,19 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package v1_19 //nolint + +import ( + "xorm.io/xorm" +) + +func AddIndexForHookTask(x *xorm.Engine) error { + type HookTask struct { + ID int64 `xorm:"pk autoincr"` + HookID int64 `xorm:"index"` + UUID string `xorm:"unique"` + } + + return x.Sync(new(HookTask)) +} diff --git a/models/migrations/v1_19/v232.go b/models/migrations/v1_19/v232.go new file mode 100644 index 000000000..92c9ad84b --- /dev/null +++ b/models/migrations/v1_19/v232.go @@ -0,0 +1,26 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package v1_19 // nolint + +import ( + "code.gitea.io/gitea/modules/setting" + + "xorm.io/xorm" +) + +func AlterPackageVersionMetadataToLongText(x *xorm.Engine) error { + sess := x.NewSession() + defer sess.Close() + if err := sess.Begin(); err != nil { + return err + } + + if setting.Database.UseMySQL { + if _, err := sess.Exec("ALTER TABLE `package_version` MODIFY COLUMN `metadata_json` LONGTEXT"); err != nil { + return err + } + } + return sess.Commit() +} diff --git a/models/migrations/v1_19/v233.go b/models/migrations/v1_19/v233.go new file mode 100644 index 000000000..6443d58fb --- /dev/null +++ b/models/migrations/v1_19/v233.go @@ -0,0 +1,183 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package v1_19 //nolint + +import ( + "fmt" + + "code.gitea.io/gitea/models/webhook" + "code.gitea.io/gitea/modules/json" + "code.gitea.io/gitea/modules/secret" + "code.gitea.io/gitea/modules/setting" + api "code.gitea.io/gitea/modules/structs" + + "xorm.io/builder" + "xorm.io/xorm" +) + +func batchProcess[T any](x *xorm.Engine, buf []T, query func(limit, start int) *xorm.Session, process func(*xorm.Session, T) error) error { + size := cap(buf) + start := 0 + for { + err := query(size, start).Find(&buf) + if err != nil { + return err + } + if len(buf) == 0 { + return nil + } + + err = func() error { + sess := x.NewSession() + defer sess.Close() + if err := sess.Begin(); err != nil { + return fmt.Errorf("unable to allow start session. Error: %w", err) + } + for _, record := range buf { + if err := process(sess, record); err != nil { + return err + } + } + return sess.Commit() + }() + if err != nil { + return err + } + + if len(buf) < size { + return nil + } + start += size + buf = buf[:0] + } +} + +func AddHeaderAuthorizationEncryptedColWebhook(x *xorm.Engine) error { + // Add the column to the table + type Webhook struct { + ID int64 `xorm:"pk autoincr"` + Type webhook.HookType `xorm:"VARCHAR(16) 'type'"` + Meta string `xorm:"TEXT"` // store hook-specific attributes + + // HeaderAuthorizationEncrypted should be accessed using HeaderAuthorization() and SetHeaderAuthorization() + HeaderAuthorizationEncrypted string `xorm:"TEXT"` + } + err := x.Sync(new(Webhook)) + if err != nil { + return err + } + + // Migrate the matrix webhooks + + type MatrixMeta struct { + HomeserverURL string `json:"homeserver_url"` + Room string `json:"room_id"` + MessageType int `json:"message_type"` + } + type MatrixMetaWithAccessToken struct { + MatrixMeta + AccessToken string `json:"access_token"` + } + + err = batchProcess(x, + make([]*Webhook, 0, 50), + func(limit, start int) *xorm.Session { + return x.Where("type=?", "matrix").OrderBy("id").Limit(limit, start) + }, + func(sess *xorm.Session, hook *Webhook) error { + // retrieve token from meta + var withToken MatrixMetaWithAccessToken + err := json.Unmarshal([]byte(hook.Meta), &withToken) + if err != nil { + return fmt.Errorf("unable to unmarshal matrix meta for webhook[id=%d]: %w", hook.ID, err) + } + if withToken.AccessToken == "" { + return nil + } + + // encrypt token + authorization := "Bearer " + withToken.AccessToken + hook.HeaderAuthorizationEncrypted, err = secret.EncryptSecret(setting.SecretKey, authorization) + if err != nil { + return fmt.Errorf("unable to encrypt access token for webhook[id=%d]: %w", hook.ID, err) + } + + // remove token from meta + withoutToken, err := json.Marshal(withToken.MatrixMeta) + if err != nil { + return fmt.Errorf("unable to marshal matrix meta for webhook[id=%d]: %w", hook.ID, err) + } + hook.Meta = string(withoutToken) + + // save in database + count, err := sess.ID(hook.ID).Cols("meta", "header_authorization_encrypted").Update(hook) + if count != 1 || err != nil { + return fmt.Errorf("unable to update header_authorization_encrypted for webhook[id=%d]: %d,%w", hook.ID, count, err) + } + return nil + }) + if err != nil { + return err + } + + // Remove access_token from HookTask + + type HookTask struct { + ID int64 `xorm:"pk autoincr"` + HookID int64 + PayloadContent string `xorm:"LONGTEXT"` + } + + type MatrixPayloadSafe struct { + Body string `json:"body"` + MsgType string `json:"msgtype"` + Format string `json:"format"` + FormattedBody string `json:"formatted_body"` + Commits []*api.PayloadCommit `json:"io.gitea.commits,omitempty"` + } + type MatrixPayloadUnsafe struct { + MatrixPayloadSafe + AccessToken string `json:"access_token"` + } + + err = batchProcess(x, + make([]*HookTask, 0, 50), + func(limit, start int) *xorm.Session { + return x.Where(builder.And( + builder.In("hook_id", builder.Select("id").From("webhook").Where(builder.Eq{"type": "matrix"})), + builder.Like{"payload_content", "access_token"}, + )).OrderBy("id").Limit(limit, 0) // ignore the provided "start", since other payload were already converted and don't contain 'payload_content' anymore + }, + func(sess *xorm.Session, hookTask *HookTask) error { + // retrieve token from payload_content + var withToken MatrixPayloadUnsafe + err := json.Unmarshal([]byte(hookTask.PayloadContent), &withToken) + if err != nil { + return fmt.Errorf("unable to unmarshal payload_content for hook_task[id=%d]: %w", hookTask.ID, err) + } + if withToken.AccessToken == "" { + return nil + } + + // remove token from payload_content + withoutToken, err := json.Marshal(withToken.MatrixPayloadSafe) + if err != nil { + return fmt.Errorf("unable to marshal payload_content for hook_task[id=%d]: %w", hookTask.ID, err) + } + hookTask.PayloadContent = string(withoutToken) + + // save in database + count, err := sess.ID(hookTask.ID).Cols("payload_content").Update(hookTask) + if count != 1 || err != nil { + return fmt.Errorf("unable to update payload_content for hook_task[id=%d]: %d,%w", hookTask.ID, count, err) + } + return nil + }) + if err != nil { + return err + } + + return nil +} diff --git a/models/migrations/v1_19/v233_test.go b/models/migrations/v1_19/v233_test.go new file mode 100644 index 000000000..f0a44df8c --- /dev/null +++ b/models/migrations/v1_19/v233_test.go @@ -0,0 +1,88 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package v1_19 //nolint + +import ( + "testing" + + "code.gitea.io/gitea/models/migrations/base" + "code.gitea.io/gitea/models/webhook" + "code.gitea.io/gitea/modules/json" + "code.gitea.io/gitea/modules/secret" + "code.gitea.io/gitea/modules/setting" + + "github.com/stretchr/testify/assert" +) + +func Test_addHeaderAuthorizationEncryptedColWebhook(t *testing.T) { + // Create Webhook table + type Webhook struct { + ID int64 `xorm:"pk autoincr"` + Type webhook.HookType `xorm:"VARCHAR(16) 'type'"` + Meta string `xorm:"TEXT"` // store hook-specific attributes + + // HeaderAuthorizationEncrypted should be accessed using HeaderAuthorization() and SetHeaderAuthorization() + HeaderAuthorizationEncrypted string `xorm:"TEXT"` + } + + type ExpectedWebhook struct { + ID int64 `xorm:"pk autoincr"` + Meta string + HeaderAuthorization string + } + + type HookTask struct { + ID int64 `xorm:"pk autoincr"` + HookID int64 + PayloadContent string `xorm:"LONGTEXT"` + } + + // Prepare and load the testing database + x, deferable := base.PrepareTestEnv(t, 0, new(Webhook), new(ExpectedWebhook), new(HookTask)) + defer deferable() + if x == nil || t.Failed() { + return + } + + if err := AddHeaderAuthorizationEncryptedColWebhook(x); err != nil { + assert.NoError(t, err) + return + } + + expected := []ExpectedWebhook{} + if err := x.Table("expected_webhook").Asc("id").Find(&expected); !assert.NoError(t, err) { + return + } + + got := []Webhook{} + if err := x.Table("webhook").Select("id, meta, header_authorization_encrypted").Asc("id").Find(&got); !assert.NoError(t, err) { + return + } + + for i, e := range expected { + assert.Equal(t, e.Meta, got[i].Meta) + + if e.HeaderAuthorization == "" { + assert.Equal(t, "", got[i].HeaderAuthorizationEncrypted) + } else { + cipherhex := got[i].HeaderAuthorizationEncrypted + cleartext, err := secret.DecryptSecret(setting.SecretKey, cipherhex) + assert.NoError(t, err) + assert.Equal(t, e.HeaderAuthorization, cleartext) + } + } + + // ensure that no hook_task has some remaining "access_token" + hookTasks := []HookTask{} + if err := x.Table("hook_task").Select("id, payload_content").Asc("id").Find(&hookTasks); !assert.NoError(t, err) { + return + } + for _, h := range hookTasks { + var m map[string]interface{} + err := json.Unmarshal([]byte(h.PayloadContent), &m) + assert.NoError(t, err) + assert.Nil(t, m["access_token"]) + } +} diff --git a/models/migrations/v70.go b/models/migrations/v1_6/v70.go similarity index 97% rename from models/migrations/v70.go rename to models/migrations/v1_6/v70.go index b2563544b..880bcb8af 100644 --- a/models/migrations/v70.go +++ b/models/migrations/v1_6/v70.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_6 // nolint import ( "fmt" @@ -13,7 +13,7 @@ import ( "xorm.io/xorm" ) -func addIssueDependencies(x *xorm.Engine) (err error) { +func AddIssueDependencies(x *xorm.Engine) (err error) { type IssueDependency struct { ID int64 `xorm:"pk autoincr"` UserID int64 `xorm:"NOT NULL"` diff --git a/models/migrations/v71.go b/models/migrations/v1_6/v71.go similarity index 81% rename from models/migrations/v71.go rename to models/migrations/v1_6/v71.go index 70314386d..c021a24ab 100644 --- a/models/migrations/v71.go +++ b/models/migrations/v1_6/v71.go @@ -2,20 +2,19 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_6 // nolint import ( - "crypto/sha256" "fmt" + "code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" - "golang.org/x/crypto/pbkdf2" "xorm.io/xorm" ) -func addScratchHash(x *xorm.Engine) error { +func AddScratchHash(x *xorm.Engine) error { // TwoFactor see models/twofactor.go type TwoFactor struct { ID int64 `xorm:"pk autoincr"` @@ -58,7 +57,7 @@ func addScratchHash(x *xorm.Engine) error { return err } tfa.ScratchSalt = salt - tfa.ScratchHash = hashToken(tfa.ScratchToken, salt) + tfa.ScratchHash = base.HashToken(tfa.ScratchToken, salt) if _, err := sess.ID(tfa.ID).Cols("scratch_salt, scratch_hash").Update(tfa); err != nil { return fmt.Errorf("couldn't add in scratch_hash and scratch_salt: %w", err) @@ -75,13 +74,8 @@ func addScratchHash(x *xorm.Engine) error { return err } - if err := dropTableColumns(sess, "two_factor", "scratch_token"); err != nil { + if err := base.DropTableColumns(sess, "two_factor", "scratch_token"); err != nil { return err } return sess.Commit() } - -func hashToken(token, salt string) string { - tempHash := pbkdf2.Key([]byte(token), []byte(salt), 10000, 50, sha256.New) - return fmt.Sprintf("%x", tempHash) -} diff --git a/models/migrations/v72.go b/models/migrations/v1_6/v72.go similarity index 91% rename from models/migrations/v72.go rename to models/migrations/v1_6/v72.go index 2be423386..275512c4d 100644 --- a/models/migrations/v72.go +++ b/models/migrations/v1_6/v72.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_6 // nolint import ( "fmt" @@ -12,7 +12,7 @@ import ( "xorm.io/xorm" ) -func addReview(x *xorm.Engine) error { +func AddReview(x *xorm.Engine) error { // Review see models/review.go type Review struct { ID int64 `xorm:"pk autoincr"` diff --git a/models/migrations/v73.go b/models/migrations/v1_7/v73.go similarity index 83% rename from models/migrations/v73.go rename to models/migrations/v1_7/v73.go index 0c06e2ba5..aa2cbba88 100644 --- a/models/migrations/v73.go +++ b/models/migrations/v1_7/v73.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_7 // nolint import ( "xorm.io/xorm" ) -func addMustChangePassword(x *xorm.Engine) error { +func AddMustChangePassword(x *xorm.Engine) error { // User see models/user.go type User struct { ID int64 `xorm:"pk autoincr"` diff --git a/models/migrations/v74.go b/models/migrations/v1_7/v74.go similarity index 83% rename from models/migrations/v74.go rename to models/migrations/v1_7/v74.go index f3b38418b..3694d68d3 100644 --- a/models/migrations/v74.go +++ b/models/migrations/v1_7/v74.go @@ -2,11 +2,11 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_7 // nolint import "xorm.io/xorm" -func addApprovalWhitelistsToProtectedBranches(x *xorm.Engine) error { +func AddApprovalWhitelistsToProtectedBranches(x *xorm.Engine) error { type ProtectedBranch struct { ApprovalsWhitelistUserIDs []int64 `xorm:"JSON TEXT"` ApprovalsWhitelistTeamIDs []int64 `xorm:"JSON TEXT"` diff --git a/models/migrations/v75.go b/models/migrations/v1_7/v75.go similarity index 91% rename from models/migrations/v75.go rename to models/migrations/v1_7/v75.go index 208153b9b..df2666735 100644 --- a/models/migrations/v75.go +++ b/models/migrations/v1_7/v75.go @@ -2,14 +2,14 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_7 // nolint import ( "xorm.io/builder" "xorm.io/xorm" ) -func clearNonusedData(x *xorm.Engine) error { +func ClearNonusedData(x *xorm.Engine) error { condDelete := func(colName string) builder.Cond { return builder.NotIn(colName, builder.Select("id").From("`user`")) } diff --git a/models/migrations/v76.go b/models/migrations/v1_8/v76.go similarity index 96% rename from models/migrations/v76.go rename to models/migrations/v1_8/v76.go index 268642272..ef60eb726 100644 --- a/models/migrations/v76.go +++ b/models/migrations/v1_8/v76.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_8 // nolint import ( "fmt" @@ -12,7 +12,7 @@ import ( "xorm.io/xorm" ) -func addPullRequestRebaseWithMerge(x *xorm.Engine) error { +func AddPullRequestRebaseWithMerge(x *xorm.Engine) error { // RepoUnit describes all units of a repository type RepoUnit struct { ID int64 diff --git a/models/migrations/v77.go b/models/migrations/v1_8/v77.go similarity index 80% rename from models/migrations/v77.go rename to models/migrations/v1_8/v77.go index d62fbe7fb..7d5dccc9b 100644 --- a/models/migrations/v77.go +++ b/models/migrations/v1_8/v77.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_8 // nolint import ( "xorm.io/xorm" ) -func addUserDefaultTheme(x *xorm.Engine) error { +func AddUserDefaultTheme(x *xorm.Engine) error { type User struct { Theme string `xorm:"VARCHAR(30) NOT NULL DEFAULT ''"` } diff --git a/models/migrations/v78.go b/models/migrations/v1_8/v78.go similarity index 78% rename from models/migrations/v78.go rename to models/migrations/v1_8/v78.go index e4274ca60..d7943fb0a 100644 --- a/models/migrations/v78.go +++ b/models/migrations/v1_8/v78.go @@ -2,13 +2,15 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_8 // nolint import ( + "code.gitea.io/gitea/models/migrations/base" + "xorm.io/xorm" ) -func renameRepoIsBareToIsEmpty(x *xorm.Engine) error { +func RenameRepoIsBareToIsEmpty(x *xorm.Engine) error { type Repository struct { ID int64 `xorm:"pk autoincr"` IsBare bool @@ -34,7 +36,7 @@ func renameRepoIsBareToIsEmpty(x *xorm.Engine) error { if err := sess.Begin(); err != nil { return err } - if err := dropTableColumns(sess, "repository", "is_bare"); err != nil { + if err := base.DropTableColumns(sess, "repository", "is_bare"); err != nil { return err } diff --git a/models/migrations/v79.go b/models/migrations/v1_8/v79.go similarity index 87% rename from models/migrations/v79.go rename to models/migrations/v1_8/v79.go index 818bfa4a0..6a867f505 100644 --- a/models/migrations/v79.go +++ b/models/migrations/v1_8/v79.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_8 // nolint import ( "code.gitea.io/gitea/modules/setting" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addCanCloseIssuesViaCommitInAnyBranch(x *xorm.Engine) error { +func AddCanCloseIssuesViaCommitInAnyBranch(x *xorm.Engine) error { type Repository struct { ID int64 `xorm:"pk autoincr"` CloseIssuesViaCommitInAnyBranch bool `xorm:"NOT NULL DEFAULT false"` diff --git a/models/migrations/v80.go b/models/migrations/v1_8/v80.go similarity index 83% rename from models/migrations/v80.go rename to models/migrations/v1_8/v80.go index 3c1b3315c..2e1b0631e 100644 --- a/models/migrations/v80.go +++ b/models/migrations/v1_8/v80.go @@ -2,11 +2,11 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_8 // nolint import "xorm.io/xorm" -func addIsLockedToIssues(x *xorm.Engine) error { +func AddIsLockedToIssues(x *xorm.Engine) error { // Issue see models/issue.go type Issue struct { ID int64 `xorm:"pk autoincr"` diff --git a/models/migrations/v81.go b/models/migrations/v1_8/v81.go similarity index 90% rename from models/migrations/v81.go rename to models/migrations/v1_8/v81.go index 5141f9757..b06f879ef 100644 --- a/models/migrations/v81.go +++ b/models/migrations/v1_8/v81.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_8 // nolint import ( "fmt" @@ -11,7 +11,7 @@ import ( "xorm.io/xorm/schemas" ) -func changeU2FCounterType(x *xorm.Engine) error { +func ChangeU2FCounterType(x *xorm.Engine) error { var err error switch x.Dialect().URI().DBType { diff --git a/models/migrations/v82.go b/models/migrations/v1_9/v82.go similarity index 97% rename from models/migrations/v82.go rename to models/migrations/v1_9/v82.go index 8e07e633c..82cb8b3ce 100644 --- a/models/migrations/v82.go +++ b/models/migrations/v1_9/v82.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_9 // nolint import ( "fmt" @@ -15,7 +15,7 @@ import ( "xorm.io/xorm" ) -func fixReleaseSha1OnReleaseTable(x *xorm.Engine) error { +func FixReleaseSha1OnReleaseTable(x *xorm.Engine) error { type Release struct { ID int64 RepoID int64 diff --git a/models/migrations/v83.go b/models/migrations/v1_9/v83.go similarity index 90% rename from models/migrations/v83.go rename to models/migrations/v1_9/v83.go index 6707dbdf8..31cce268e 100644 --- a/models/migrations/v83.go +++ b/models/migrations/v1_9/v83.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_9 //nolint import ( "code.gitea.io/gitea/modules/timeutil" @@ -10,7 +10,7 @@ import ( "xorm.io/xorm" ) -func addUploaderIDForAttachment(x *xorm.Engine) error { +func AddUploaderIDForAttachment(x *xorm.Engine) error { type Attachment struct { ID int64 `xorm:"pk autoincr"` UUID string `xorm:"uuid UNIQUE"` diff --git a/models/migrations/v84.go b/models/migrations/v1_9/v84.go similarity index 83% rename from models/migrations/v84.go rename to models/migrations/v1_9/v84.go index baab29fcd..8aa7fbc07 100644 --- a/models/migrations/v84.go +++ b/models/migrations/v1_9/v84.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_9 //nolint import ( "xorm.io/xorm" ) -func addGPGKeyImport(x *xorm.Engine) error { +func AddGPGKeyImport(x *xorm.Engine) error { type GPGKeyImport struct { KeyID string `xorm:"pk CHAR(16) NOT NULL"` Content string `xorm:"TEXT NOT NULL"` diff --git a/models/migrations/v85.go b/models/migrations/v1_9/v85.go similarity index 92% rename from models/migrations/v85.go rename to models/migrations/v1_9/v85.go index 317660eb6..0cd32c382 100644 --- a/models/migrations/v85.go +++ b/models/migrations/v1_9/v85.go @@ -2,11 +2,12 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_9 //nolint import ( "fmt" + "code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" @@ -14,7 +15,7 @@ import ( "xorm.io/xorm" ) -func hashAppToken(x *xorm.Engine) error { +func HashAppToken(x *xorm.Engine) error { // AccessToken see models/token.go type AccessToken struct { ID int64 `xorm:"pk autoincr"` @@ -70,7 +71,7 @@ func hashAppToken(x *xorm.Engine) error { return err } token.TokenSalt = salt - token.TokenHash = hashToken(token.Sha1, salt) + token.TokenHash = base.HashToken(token.Sha1, salt) if len(token.Sha1) < 8 { log.Warn("Unable to transform token %s with name %s belonging to user ID %d, skipping transformation", token.Sha1, token.Name, token.UID) continue @@ -93,7 +94,7 @@ func hashAppToken(x *xorm.Engine) error { return err } - if err := dropTableColumns(sess, "access_token", "sha1"); err != nil { + if err := base.DropTableColumns(sess, "access_token", "sha1"); err != nil { return err } if err := sess.Commit(); err != nil { diff --git a/models/migrations/v86.go b/models/migrations/v1_9/v86.go similarity index 80% rename from models/migrations/v86.go rename to models/migrations/v1_9/v86.go index 39c196ca6..416e4fad9 100644 --- a/models/migrations/v86.go +++ b/models/migrations/v1_9/v86.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_9 //nolint import ( "xorm.io/xorm" ) -func addHTTPMethodToWebhook(x *xorm.Engine) error { +func AddHTTPMethodToWebhook(x *xorm.Engine) error { type Webhook struct { HTTPMethod string `xorm:"http_method DEFAULT 'POST'"` } diff --git a/models/migrations/v87.go b/models/migrations/v1_9/v87.go similarity index 81% rename from models/migrations/v87.go rename to models/migrations/v1_9/v87.go index 6b5af5be3..97c8f621c 100644 --- a/models/migrations/v87.go +++ b/models/migrations/v1_9/v87.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package migrations +package v1_9 //nolint import ( "xorm.io/xorm" ) -func addAvatarFieldToRepository(x *xorm.Engine) error { +func AddAvatarFieldToRepository(x *xorm.Engine) error { type Repository struct { // ID(10-20)-md5(32) - must fit into 64 symbols Avatar string `xorm:"VARCHAR(64)"` diff --git a/models/packages/package_version.go b/models/packages/package_version.go index f9965bcb7..782261c57 100644 --- a/models/packages/package_version.go +++ b/models/packages/package_version.go @@ -33,7 +33,7 @@ type PackageVersion struct { LowerVersion string `xorm:"UNIQUE(s) INDEX NOT NULL"` CreatedUnix timeutil.TimeStamp `xorm:"created INDEX NOT NULL"` IsInternal bool `xorm:"INDEX NOT NULL DEFAULT false"` - MetadataJSON string `xorm:"metadata_json TEXT"` + MetadataJSON string `xorm:"metadata_json LONGTEXT"` DownloadCount int64 `xorm:"NOT NULL DEFAULT 0"` } diff --git a/models/user/user.go b/models/user/user.go index 9a2da6dbc..84e2c4a9c 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -29,6 +29,7 @@ import ( "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/validation" "golang.org/x/crypto/argon2" "golang.org/x/crypto/bcrypt" @@ -621,7 +622,7 @@ var ( // IsUsableUsername returns an error when a username is reserved func IsUsableUsername(name string) error { // Validate username make sure it satisfies requirement. - if db.AlphaDashDotPattern.MatchString(name) { + if !validation.IsValidUsername(name) { // Note: usually this error is normally caught up earlier in the UI return db.ErrNameCharsNotAllowed{Name: name} } diff --git a/models/webhook/hooktask.go b/models/webhook/hooktask.go index 2b9b63c09..246484aea 100644 --- a/models/webhook/hooktask.go +++ b/models/webhook/hooktask.go @@ -103,9 +103,9 @@ type HookResponse struct { // HookTask represents a hook task. type HookTask struct { - ID int64 `xorm:"pk autoincr"` - HookID int64 - UUID string + ID int64 `xorm:"pk autoincr"` + HookID int64 `xorm:"index"` + UUID string `xorm:"unique"` api.Payloader `xorm:"-"` PayloadContent string `xorm:"LONGTEXT"` EventType HookEventType @@ -270,7 +270,7 @@ func CleanupHookTaskTable(ctx context.Context, cleanupType HookTaskCleanupType, return db.ErrCancelledf("Before deleting hook_task records for hook id %d", hookID) default: } - if err = deleteDeliveredHookTasksByWebhook(hookID, numberToKeep); err != nil { + if err = deleteDeliveredHookTasksByWebhook(ctx, hookID, numberToKeep); err != nil { return err } } @@ -279,10 +279,10 @@ func CleanupHookTaskTable(ctx context.Context, cleanupType HookTaskCleanupType, return nil } -func deleteDeliveredHookTasksByWebhook(hookID int64, numberDeliveriesToKeep int) error { +func deleteDeliveredHookTasksByWebhook(ctx context.Context, hookID int64, numberDeliveriesToKeep int) error { log.Trace("Deleting hook_task rows for webhook %d, keeping the most recent %d deliveries", hookID, numberDeliveriesToKeep) deliveryDates := make([]int64, 0, 10) - err := db.GetEngine(db.DefaultContext).Table("hook_task"). + err := db.GetEngine(ctx).Table("hook_task"). Where("hook_task.hook_id = ? AND hook_task.is_delivered = ? AND hook_task.delivered is not null", hookID, true). Cols("hook_task.delivered"). Join("INNER", "webhook", "hook_task.hook_id = webhook.id"). @@ -294,7 +294,7 @@ func deleteDeliveredHookTasksByWebhook(hookID int64, numberDeliveriesToKeep int) } if len(deliveryDates) > 0 { - deletes, err := db.GetEngine(db.DefaultContext). + deletes, err := db.GetEngine(ctx). Where("hook_id = ? and is_delivered = ? and delivered <= ?", hookID, true, deliveryDates[0]). Delete(new(HookTask)) if err != nil { diff --git a/models/webhook/webhook.go b/models/webhook/webhook.go index aebe0d6e7..6426b9520 100644 --- a/models/webhook/webhook.go +++ b/models/webhook/webhook.go @@ -13,6 +13,8 @@ import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/secret" + "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" @@ -195,6 +197,9 @@ type Webhook struct { Meta string `xorm:"TEXT"` // store hook-specific attributes LastStatus HookStatus // Last delivery status + // HeaderAuthorizationEncrypted should be accessed using HeaderAuthorization() and SetHeaderAuthorization() + HeaderAuthorizationEncrypted string `xorm:"TEXT"` + CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` } @@ -401,6 +406,29 @@ func (w *Webhook) EventsArray() []string { return events } +// HeaderAuthorization returns the decrypted Authorization header. +// Not on the reference (*w), to be accessible on WebhooksNew. +func (w Webhook) HeaderAuthorization() (string, error) { + if w.HeaderAuthorizationEncrypted == "" { + return "", nil + } + return secret.DecryptSecret(setting.SecretKey, w.HeaderAuthorizationEncrypted) +} + +// SetHeaderAuthorization encrypts and sets the Authorization header. +func (w *Webhook) SetHeaderAuthorization(cleartext string) error { + if cleartext == "" { + w.HeaderAuthorizationEncrypted = "" + return nil + } + ciphertext, err := secret.EncryptSecret(setting.SecretKey, cleartext) + if err != nil { + return err + } + w.HeaderAuthorizationEncrypted = ciphertext + return nil +} + // CreateWebhook creates a new web hook. func CreateWebhook(ctx context.Context, w *Webhook) error { w.Type = strings.TrimSpace(w.Type) diff --git a/modules/convert/convert.go b/modules/convert/convert.go index 8c92bbb37..78eb62d42 100644 --- a/modules/convert/convert.go +++ b/modules/convert/convert.go @@ -243,7 +243,7 @@ func ToGPGKeyEmail(email *user_model.EmailAddress) *api.GPGKeyEmail { } // ToHook convert models.Webhook to api.Hook -func ToHook(repoLink string, w *webhook.Webhook) *api.Hook { +func ToHook(repoLink string, w *webhook.Webhook) (*api.Hook, error) { config := map[string]string{ "url": w.URL, "content_type": w.ContentType.Name(), @@ -256,16 +256,22 @@ func ToHook(repoLink string, w *webhook.Webhook) *api.Hook { config["color"] = s.Color } - return &api.Hook{ - ID: w.ID, - Type: w.Type, - URL: fmt.Sprintf("%s/settings/hooks/%d", repoLink, w.ID), - Active: w.IsActive, - Config: config, - Events: w.EventsArray(), - Updated: w.UpdatedUnix.AsTime(), - Created: w.CreatedUnix.AsTime(), + authorizationHeader, err := w.HeaderAuthorization() + if err != nil { + return nil, err } + + return &api.Hook{ + ID: w.ID, + Type: w.Type, + URL: fmt.Sprintf("%s/settings/hooks/%d", repoLink, w.ID), + Active: w.IsActive, + Config: config, + Events: w.EventsArray(), + AuthorizationHeader: authorizationHeader, + Updated: w.UpdatedUnix.AsTime(), + Created: w.CreatedUnix.AsTime(), + }, nil } // ToGitHook convert git.Hook to api.GitHook diff --git a/modules/doctor/breaking.go b/modules/doctor/breaking.go index 51122d9a6..474997acd 100644 --- a/modules/doctor/breaking.go +++ b/modules/doctor/breaking.go @@ -18,10 +18,9 @@ import ( func iterateUserAccounts(ctx context.Context, each func(*user.User) error) error { err := db.Iterate( ctx, - new(user.User), builder.Gt{"id": 0}, - func(idx int, bean interface{}) error { - return each(bean.(*user.User)) + func(ctx context.Context, bean *user.User) error { + return each(bean) }, ) return err diff --git a/modules/doctor/fix16961.go b/modules/doctor/fix16961.go index 307cfcd9f..d9f895739 100644 --- a/modules/doctor/fix16961.go +++ b/modules/doctor/fix16961.go @@ -269,13 +269,10 @@ func fixBrokenRepoUnits16961(ctx context.Context, logger log.Logger, autofix boo err := db.Iterate( ctx, - new(RepoUnit), builder.Gt{ "id": 0, }, - func(idx int, bean interface{}) error { - unit := bean.(*RepoUnit) - + func(ctx context.Context, unit *RepoUnit) error { bs := unit.Config repoUnit := &repo_model.RepoUnit{ ID: unit.ID, diff --git a/modules/doctor/heads.go b/modules/doctor/heads.go index 7f3b2a8a0..33efc27a2 100644 --- a/modules/doctor/heads.go +++ b/modules/doctor/heads.go @@ -49,7 +49,7 @@ func synchronizeRepoHeads(ctx context.Context, logger log.Logger, autofix bool) } // otherwise, let's try fixing HEAD - err := git.NewCommand(ctx, "symbolic-ref").AddDashesAndList("HEAD", repo.DefaultBranch).Run(runOpts) + err := git.NewCommand(ctx, "symbolic-ref").AddDashesAndList("HEAD", git.BranchPrefix+repo.DefaultBranch).Run(runOpts) if err != nil { logger.Warn("Failed to fix HEAD for %s/%s: %v", repo.OwnerName, repo.Name, err) return nil diff --git a/modules/doctor/mergebase.go b/modules/doctor/mergebase.go index b279c453f..9f5e33646 100644 --- a/modules/doctor/mergebase.go +++ b/modules/doctor/mergebase.go @@ -21,10 +21,9 @@ import ( func iteratePRs(ctx context.Context, repo *repo_model.Repository, each func(*repo_model.Repository, *issues_model.PullRequest) error) error { return db.Iterate( ctx, - new(issues_model.PullRequest), builder.Eq{"base_repo_id": repo.ID}, - func(idx int, bean interface{}) error { - return each(repo, bean.(*issues_model.PullRequest)) + func(ctx context.Context, bean *issues_model.PullRequest) error { + return each(repo, bean) }, ) } diff --git a/modules/doctor/misc.go b/modules/doctor/misc.go index 277d66a17..6f0e066f5 100644 --- a/modules/doctor/misc.go +++ b/modules/doctor/misc.go @@ -30,10 +30,9 @@ import ( func iterateRepositories(ctx context.Context, each func(*repo_model.Repository) error) error { err := db.Iterate( ctx, - new(repo_model.Repository), builder.Gt{"id": 0}, - func(idx int, bean interface{}) error { - return each(bean.(*repo_model.Repository)) + func(ctx context.Context, bean *repo_model.Repository) error { + return each(bean) }, ) return err diff --git a/modules/git/repo_language_stats_gogit.go b/modules/git/repo_language_stats_gogit.go index 34b0dc45d..503e774e7 100644 --- a/modules/git/repo_language_stats_gogit.go +++ b/modules/git/repo_language_stats_gogit.go @@ -44,7 +44,15 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err checker, deferable := repo.CheckAttributeReader(commitID) defer deferable() + // sizes contains the current calculated size of all files by language sizes := make(map[string]int64) + // by default we will only count the sizes of programming languages or markup languages + // unless they are explicitly set using linguist-language + includedLanguage := map[string]bool{} + // or if there's only one language in the repository + firstExcludedLanguage := "" + firstExcludedLanguageSize := int64(0) + err = tree.Files().ForEach(func(f *object.File) error { if f.Size == 0 { return nil @@ -75,8 +83,8 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err language = group } + // this language will always be added to the size sizes[language] += f.Size - return nil } else if language, has := attrs["gitlab-language"]; has && language != "unspecified" && language != "" { // strip off a ? if present @@ -90,6 +98,7 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err language = group } + // this language will always be added to the size sizes[language] += f.Size return nil } @@ -124,7 +133,18 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err language = group } - sizes[language] += f.Size + included, checked := includedLanguage[language] + if !checked { + langtype := enry.GetLanguageType(language) + included = langtype == enry.Programming || langtype == enry.Markup + includedLanguage[language] = included + } + if included { + sizes[language] += f.Size + } else if len(sizes) == 0 && (firstExcludedLanguage == "" || firstExcludedLanguage == language) { + firstExcludedLanguage = language + firstExcludedLanguageSize += f.Size + } return nil }) @@ -132,14 +152,9 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err return nil, err } - // filter special languages unless they are the only language - if len(sizes) > 1 { - for language := range sizes { - langtype := enry.GetLanguageType(language) - if langtype != enry.Programming && langtype != enry.Markup { - delete(sizes, language) - } - } + // If there are no included languages add the first excluded language + if len(sizes) == 0 && firstExcludedLanguage != "" { + sizes[firstExcludedLanguage] = firstExcludedLanguageSize } return sizes, nil diff --git a/modules/git/repo_language_stats_nogogit.go b/modules/git/repo_language_stats_nogogit.go index 7388ef403..baeb11490 100644 --- a/modules/git/repo_language_stats_nogogit.go +++ b/modules/git/repo_language_stats_nogogit.go @@ -67,7 +67,16 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err contentBuf := bytes.Buffer{} var content []byte + + // sizes contains the current calculated size of all files by language sizes := make(map[string]int64) + // by default we will only count the sizes of programming languages or markup languages + // unless they are explicitly set using linguist-language + includedLanguage := map[string]bool{} + // or if there's only one language in the repository + firstExcludedLanguage := "" + firstExcludedLanguageSize := int64(0) + for _, f := range entries { select { case <-repo.Ctx.Done(): @@ -107,6 +116,7 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err language = group } + // this language will always be added to the size sizes[language] += f.Size() continue } else if language, has := attrs["gitlab-language"]; has && language != "unspecified" && language != "" { @@ -121,6 +131,7 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err language = group } + // this language will always be added to the size sizes[language] += f.Size() continue } @@ -180,18 +191,24 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err language = group } - sizes[language] += f.Size() + included, checked := includedLanguage[language] + if !checked { + langtype := enry.GetLanguageType(language) + included = langtype == enry.Programming || langtype == enry.Markup + includedLanguage[language] = included + } + if included { + sizes[language] += f.Size() + } else if len(sizes) == 0 && (firstExcludedLanguage == "" || firstExcludedLanguage == language) { + firstExcludedLanguage = language + firstExcludedLanguageSize += f.Size() + } continue } - // filter special languages unless they are the only language - if len(sizes) > 1 { - for language := range sizes { - langtype := enry.GetLanguageType(language) - if langtype != enry.Programming && langtype != enry.Markup { - delete(sizes, language) - } - } + // If there are no included languages add the first excluded language + if len(sizes) == 0 && firstExcludedLanguage != "" { + sizes[firstExcludedLanguage] = firstExcludedLanguageSize } return sizes, nil diff --git a/modules/issue/template/unmarshal.go b/modules/issue/template/unmarshal.go index e695d1e1c..24587b0fe 100644 --- a/modules/issue/template/unmarshal.go +++ b/modules/issue/template/unmarshal.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/util" "gopkg.in/yaml.v2" ) @@ -95,14 +96,27 @@ func unmarshal(filename string, content []byte) (*api.IssueTemplate, error) { }{} if typ := it.Type(); typ == api.IssueTemplateTypeMarkdown { - templateBody, err := markdown.ExtractMetadata(string(content), it) - if err != nil { - return nil, err - } - it.Content = templateBody - if it.About == "" { - if _, err := markdown.ExtractMetadata(string(content), compatibleTemplate); err == nil && compatibleTemplate.About != "" { - it.About = compatibleTemplate.About + if templateBody, err := markdown.ExtractMetadata(string(content), it); err != nil { + // The only thing we know here is that we can't extract metadata from the content, + // it's hard to tell if metadata doesn't exist or metadata isn't valid. + // There's an example template: + // + // --- + // # Title + // --- + // Content + // + // It could be a valid markdown with two horizontal lines, or an invalid markdown with wrong metadata. + + it.Content = string(content) + it.Name = filepath.Base(it.FileName) + it.About, _ = util.SplitStringAtByteN(it.Content, 80) + } else { + it.Content = templateBody + if it.About == "" { + if _, err := markdown.ExtractMetadata(string(content), compatibleTemplate); err == nil && compatibleTemplate.About != "" { + it.About = compatibleTemplate.About + } } } } else if typ == api.IssueTemplateTypeYaml { diff --git a/modules/notification/action/action.go b/modules/notification/action/action.go index d3ff8b156..44d115f3d 100644 --- a/modules/notification/action/action.go +++ b/modules/notification/action/action.go @@ -283,6 +283,20 @@ func (*actionNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doer } } +func (*actionNotifier) NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { + if err := activities_model.NotifyWatchers(&activities_model.Action{ + ActUserID: doer.ID, + ActUser: doer, + OpType: activities_model.ActionAutoMergePullRequest, + Content: fmt.Sprintf("%d|%s", pr.Issue.Index, pr.Issue.Title), + RepoID: pr.Issue.Repo.ID, + Repo: pr.Issue.Repo, + IsPrivate: pr.Issue.Repo.IsPrivate, + }); err != nil { + log.Error("NotifyWatchers [%d]: %v", pr.ID, err) + } +} + func (*actionNotifier) NotifyPullRevieweDismiss(doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { reviewerName := review.Reviewer.Name if len(review.OriginalAuthor) > 0 { diff --git a/modules/notification/base/notifier.go b/modules/notification/base/notifier.go index d6cec92e1..9edab8213 100644 --- a/modules/notification/base/notifier.go +++ b/modules/notification/base/notifier.go @@ -34,7 +34,8 @@ type Notifier interface { NotifyIssueChangeLabels(doer *user_model.User, issue *issues_model.Issue, addedLabels, removedLabels []*issues_model.Label) NotifyNewPullRequest(pr *issues_model.PullRequest, mentions []*user_model.User) - NotifyMergePullRequest(*issues_model.PullRequest, *user_model.User) + NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) + NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) NotifyPullRequestSynchronized(doer *user_model.User, pr *issues_model.PullRequest) NotifyPullRequestReview(pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) NotifyPullRequestCodeComment(pr *issues_model.PullRequest, comment *issues_model.Comment, mentions []*user_model.User) diff --git a/modules/notification/base/null.go b/modules/notification/base/null.go index b113ae79e..f051fbc26 100644 --- a/modules/notification/base/null.go +++ b/modules/notification/base/null.go @@ -54,6 +54,10 @@ func (*NullNotifier) NotifyPullRequestCodeComment(pr *issues_model.PullRequest, func (*NullNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { } +// NotifyAutoMergePullRequest places a place holder function +func (*NullNotifier) NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { +} + // NotifyPullRequestSynchronized places a place holder function func (*NullNotifier) NotifyPullRequestSynchronized(doer *user_model.User, pr *issues_model.PullRequest) { } diff --git a/modules/notification/mail/mail.go b/modules/notification/mail/mail.go index 100b4eb36..54f561839 100644 --- a/modules/notification/mail/mail.go +++ b/modules/notification/mail/mail.go @@ -153,6 +153,16 @@ func (m *mailNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doer } } +func (m *mailNotifier) NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { + if err := pr.LoadIssue(); err != nil { + log.Error("pr.LoadIssue: %v", err) + return + } + if err := mailer.MailParticipants(pr.Issue, doer, activities_model.ActionAutoMergePullRequest, nil); err != nil { + log.Error("MailParticipants: %v", err) + } +} + func (m *mailNotifier) NotifyPullRequestPushCommits(doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) { ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("mailNotifier.NotifyPullRequestPushCommits Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) defer finished() diff --git a/modules/notification/notification.go b/modules/notification/notification.go index 693c7f5c2..7bdc0a04c 100644 --- a/modules/notification/notification.go +++ b/modules/notification/notification.go @@ -98,6 +98,13 @@ func NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) } } +// NotifyAutoMergePullRequest notifies merge pull request to notifiers +func NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { + for _, notifier := range notifiers { + notifier.NotifyAutoMergePullRequest(pr, doer) + } +} + // NotifyNewPullRequest notifies new pull request to notifiers func NotifyNewPullRequest(pr *issues_model.PullRequest, mentions []*user_model.User) { for _, notifier := range notifiers { diff --git a/modules/notification/ui/ui.go b/modules/notification/ui/ui.go index 4d96a6b0e..0e2b3e67c 100644 --- a/modules/notification/ui/ui.go +++ b/modules/notification/ui/ui.go @@ -119,6 +119,10 @@ func (ns *notificationService) NotifyMergePullRequest(pr *issues_model.PullReque }) } +func (ns *notificationService) NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { + ns.NotifyMergePullRequest(pr, doer) +} + func (ns *notificationService) NotifyNewPullRequest(pr *issues_model.PullRequest, mentions []*user_model.User) { if err := pr.LoadIssue(); err != nil { log.Error("Unable to load issue: %d for pr: %d: Error: %v", pr.IssueID, pr.ID, err) diff --git a/modules/notification/webhook/webhook.go b/modules/notification/webhook/webhook.go index 630b56598..c591e1e34 100644 --- a/modules/notification/webhook/webhook.go +++ b/modules/notification/webhook/webhook.go @@ -632,6 +632,11 @@ func (m *webhookNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_ } } +func (m *webhookNotifier) NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { + // just redirect to the NotifyMergePullRequest + m.NotifyMergePullRequest(pr, doer) +} + func (*webhookNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyMergePullRequest Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) defer finished() diff --git a/modules/setting/setting.go b/modules/setting/setting.go index f93be2fbd..2e5bb17b6 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -22,6 +22,7 @@ import ( "time" "code.gitea.io/gitea/modules/container" + "code.gitea.io/gitea/modules/generate" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/user" @@ -451,6 +452,7 @@ var ( RunUser string IsWindows bool HasRobotsTxt bool + EnableSitemap bool InternalToken string // internal access token ) @@ -962,6 +964,11 @@ func loadFromConf(allowEmpty bool, extraConfig string) { SuccessfulTokensCacheSize = sec.Key("SUCCESSFUL_TOKENS_CACHE_SIZE").MustInt(20) InternalToken = loadSecret(sec, "INTERNAL_TOKEN_URI", "INTERNAL_TOKEN") + if InstallLock && InternalToken == "" { + // if Gitea has been installed but the InternalToken hasn't been generated (upgrade from an old release), we should generate + // some users do cluster deployment, they still depend on this auto-generating behavior. + generateSaveInternalToken() + } cfgdata := sec.Key("PASSWORD_COMPLEXITY").Strings(",") if len(cfgdata) == 0 { @@ -1094,6 +1101,7 @@ func loadFromConf(allowEmpty bool, extraConfig string) { ShowFooterBranding = Cfg.Section("other").Key("SHOW_FOOTER_BRANDING").MustBool(false) ShowFooterVersion = Cfg.Section("other").Key("SHOW_FOOTER_VERSION").MustBool(true) ShowFooterTemplateLoadTime = Cfg.Section("other").Key("SHOW_FOOTER_TEMPLATE_LOAD_TIME").MustBool(true) + EnableSitemap = Cfg.Section("other").Key("ENABLE_SITEMAP").MustBool(true) UI.ShowUserEmail = Cfg.Section("ui").Key("SHOW_USER_EMAIL").MustBool(true) UI.DefaultShowFullName = Cfg.Section("ui").Key("DEFAULT_SHOW_FULL_NAME").MustBool(false) @@ -1150,6 +1158,8 @@ func parseAuthorizedPrincipalsAllow(values []string) ([]string, bool) { return authorizedPrincipalsAllow, true } +// loadSecret load the secret from ini by uriKey or verbatimKey, only one of them could be set +// If the secret is loaded from uriKey (file), the file should be non-empty, to guarantee the behavior stable and clear. func loadSecret(sec *ini.Section, uriKey, verbatimKey string) string { // don't allow setting both URI and verbatim string uri := sec.Key(uriKey).String() @@ -1173,7 +1183,15 @@ func loadSecret(sec *ini.Section, uriKey, verbatimKey string) string { if err != nil { log.Fatal("Failed to read %s (%s): %v", uriKey, tempURI.RequestURI(), err) } - return strings.TrimSpace(string(buf)) + val := strings.TrimSpace(string(buf)) + if val == "" { + // The file shouldn't be empty, otherwise we can not know whether the user has ever set the KEY or KEY_URI + // For example: if INTERNAL_TOKEN_URI=file:///empty-file, + // Then if the token is re-generated during installation and saved to INTERNAL_TOKEN + // Then INTERNAL_TOKEN and INTERNAL_TOKEN_URI both exist, that's a fatal error (they shouldn't) + log.Fatal("Failed to read %s (%s): the file is empty", uriKey, tempURI.RequestURI()) + } + return val // only file URIs are allowed default: @@ -1182,6 +1200,19 @@ func loadSecret(sec *ini.Section, uriKey, verbatimKey string) string { } } +// generateSaveInternalToken generates and saves the internal token to app.ini +func generateSaveInternalToken() { + token, err := generate.NewInternalToken() + if err != nil { + log.Fatal("Error generate internal token: %v", err) + } + + InternalToken = token + CreateOrAppendToCustomConf("security.INTERNAL_TOKEN", func(cfg *ini.File) { + cfg.Section("security").Key("INTERNAL_TOKEN").SetValue(token) + }) +} + // MakeAbsoluteAssetURL returns the absolute asset url prefix without a trailing slash func MakeAbsoluteAssetURL(appURL, staticURLPrefix string) string { parsedPrefix, err := url.Parse(strings.TrimSuffix(staticURLPrefix, "/")) diff --git a/modules/structs/admin_user.go b/modules/structs/admin_user.go index eccbf29a4..2f6f502af 100644 --- a/modules/structs/admin_user.go +++ b/modules/structs/admin_user.go @@ -10,7 +10,7 @@ type CreateUserOption struct { SourceID int64 `json:"source_id"` LoginName string `json:"login_name"` // required: true - Username string `json:"username" binding:"Required;AlphaDashDot;MaxSize(40)"` + Username string `json:"username" binding:"Required;Username;MaxSize(40)"` FullName string `json:"full_name" binding:"MaxSize(100)"` // required: true // swagger:strfmt email diff --git a/modules/structs/hook.go b/modules/structs/hook.go index 8321a15a8..f0600a192 100644 --- a/modules/structs/hook.go +++ b/modules/structs/hook.go @@ -18,12 +18,13 @@ var ErrInvalidReceiveHook = errors.New("Invalid JSON payload received over webho // Hook a hook is a web hook when one repository changed type Hook struct { - ID int64 `json:"id"` - Type string `json:"type"` - URL string `json:"-"` - Config map[string]string `json:"config"` - Events []string `json:"events"` - Active bool `json:"active"` + ID int64 `json:"id"` + Type string `json:"type"` + URL string `json:"-"` + Config map[string]string `json:"config"` + Events []string `json:"events"` + AuthorizationHeader string `json:"authorization_header"` + Active bool `json:"active"` // swagger:strfmt date-time Updated time.Time `json:"updated_at"` // swagger:strfmt date-time @@ -43,19 +44,21 @@ type CreateHookOption struct { // enum: dingtalk,discord,gitea,gogs,msteams,slack,telegram,feishu,wechatwork,packagist Type string `json:"type" binding:"Required"` // required: true - Config CreateHookOptionConfig `json:"config" binding:"Required"` - Events []string `json:"events"` - BranchFilter string `json:"branch_filter" binding:"GlobPattern"` + Config CreateHookOptionConfig `json:"config" binding:"Required"` + Events []string `json:"events"` + BranchFilter string `json:"branch_filter" binding:"GlobPattern"` + AuthorizationHeader string `json:"authorization_header"` // default: false Active bool `json:"active"` } // EditHookOption options when modify one hook type EditHookOption struct { - Config map[string]string `json:"config"` - Events []string `json:"events"` - BranchFilter string `json:"branch_filter" binding:"GlobPattern"` - Active *bool `json:"active"` + Config map[string]string `json:"config"` + Events []string `json:"events"` + BranchFilter string `json:"branch_filter" binding:"GlobPattern"` + AuthorizationHeader string `json:"authorization_header"` + Active *bool `json:"active"` } // Payloader payload is some part of one hook diff --git a/modules/structs/issue.go b/modules/structs/issue.go index 27ec81f72..70f5e1ba8 100644 --- a/modules/structs/issue.go +++ b/modules/structs/issue.go @@ -170,7 +170,7 @@ func (it IssueTemplate) Type() IssueTemplateType { if ext := filepath.Ext(it.FileName); ext == ".md" { return IssueTemplateTypeMarkdown } else if ext == ".yaml" || ext == ".yml" { - return "yaml" + return IssueTemplateTypeYaml } - return IssueTemplateTypeYaml + return "" } diff --git a/modules/system/item_runtime.go b/modules/system/item_runtime.go index ef758a567..e022a0daa 100644 --- a/modules/system/item_runtime.go +++ b/modules/system/item_runtime.go @@ -6,7 +6,8 @@ package system // RuntimeState contains app state for runtime, and we can save remote version for update checker here in future type RuntimeState struct { - LastAppPath string `json:"last_app_path"` + LastAppPath string `json:"last_app_path"` + LastCustomConf string `json:"last_custom_conf"` } // Name returns the item name diff --git a/modules/templates/helper.go b/modules/templates/helper.go index a72329144..a127b98dc 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -905,7 +905,7 @@ func ActionIcon(opType activities_model.ActionType) string { return "git-pull-request" case activities_model.ActionCommentIssue, activities_model.ActionCommentPull: return "comment-discussion" - case activities_model.ActionMergePullRequest: + case activities_model.ActionMergePullRequest, activities_model.ActionAutoMergePullRequest: return "git-merge" case activities_model.ActionCloseIssue, activities_model.ActionClosePullRequest: return "issue-closed" diff --git a/modules/validation/binding.go b/modules/validation/binding.go index f08f63242..c054fbe7b 100644 --- a/modules/validation/binding.go +++ b/modules/validation/binding.go @@ -24,6 +24,9 @@ const ( // ErrRegexPattern is returned when a regex pattern is invalid ErrRegexPattern = "RegexPattern" + + // ErrUsername is username error + ErrUsername = "UsernameError" ) // AddBindingRules adds additional binding rules @@ -34,6 +37,7 @@ func AddBindingRules() { addGlobPatternRule() addRegexPatternRule() addGlobOrRegexPatternRule() + addUsernamePatternRule() } func addGitRefNameBindingRule() { @@ -148,6 +152,22 @@ func addGlobOrRegexPatternRule() { }) } +func addUsernamePatternRule() { + binding.AddRule(&binding.Rule{ + IsMatch: func(rule string) bool { + return rule == "Username" + }, + IsValid: func(errs binding.Errors, name string, val interface{}) (bool, binding.Errors) { + str := fmt.Sprintf("%v", val) + if !IsValidUsername(str) { + errs.Add([]string{name}, ErrUsername, "invalid username") + return false, errs + } + return true, errs + }, + }) +} + func portOnly(hostport string) string { colon := strings.IndexByte(hostport, ':') if colon == -1 { diff --git a/modules/validation/helpers.go b/modules/validation/helpers.go index 484b12b2a..8e49c7855 100644 --- a/modules/validation/helpers.go +++ b/modules/validation/helpers.go @@ -91,3 +91,15 @@ func IsValidExternalTrackerURLFormat(uri string) bool { return true } + +var ( + validUsernamePattern = regexp.MustCompile(`^[\da-zA-Z][-.\w]*$`) + invalidUsernamePattern = regexp.MustCompile(`[-._]{2,}|[-._]$`) // No consecutive or trailing non-alphanumeric chars +) + +// IsValidUsername checks if username is valid +func IsValidUsername(name string) bool { + // It is difficult to find a single pattern that is both readable and effective, + // but it's easier to use positive and negative checks. + return validUsernamePattern.MatchString(name) && !invalidUsernamePattern.MatchString(name) +} diff --git a/modules/validation/helpers_test.go b/modules/validation/helpers_test.go index f6f897e82..9bdbdb4a7 100644 --- a/modules/validation/helpers_test.go +++ b/modules/validation/helpers_test.go @@ -155,3 +155,34 @@ func Test_IsValidExternalTrackerURLFormat(t *testing.T) { }) } } + +func TestIsValidUsername(t *testing.T) { + tests := []struct { + arg string + want bool + }{ + {arg: "a", want: true}, + {arg: "abc", want: true}, + {arg: "0.b-c", want: true}, + {arg: "a.b-c_d", want: true}, + {arg: "", want: false}, + {arg: ".abc", want: false}, + {arg: "abc.", want: false}, + {arg: "a..bc", want: false}, + {arg: "a...bc", want: false}, + {arg: "a.-bc", want: false}, + {arg: "a._bc", want: false}, + {arg: "a_-bc", want: false}, + {arg: "a/bc", want: false}, + {arg: "☁️", want: false}, + {arg: "-", want: false}, + {arg: "--diff", want: false}, + {arg: "-im-here", want: false}, + {arg: "a space", want: false}, + } + for _, tt := range tests { + t.Run(tt.arg, func(t *testing.T) { + assert.Equalf(t, tt.want, IsValidUsername(tt.arg), "IsValidUsername(%v)", tt.arg) + }) + } +} diff --git a/modules/web/middleware/binding.go b/modules/web/middleware/binding.go index 636e655b9..cced9717b 100644 --- a/modules/web/middleware/binding.go +++ b/modules/web/middleware/binding.go @@ -135,6 +135,8 @@ func Validate(errs binding.Errors, data map[string]interface{}, f Form, l transl data["ErrorMsg"] = trName + l.Tr("form.glob_pattern_error", errs[0].Message) case validation.ErrRegexPattern: data["ErrorMsg"] = trName + l.Tr("form.regex_pattern_error", errs[0].Message) + case validation.ErrUsername: + data["ErrorMsg"] = trName + l.Tr("form.username_error") default: msg := errs[0].Classification if msg != "" && errs[0].Message != "" { diff --git a/options/license/FSFULLRWD b/options/license/FSFULLRWD new file mode 100644 index 000000000..8dc0b2e5f --- /dev/null +++ b/options/license/FSFULLRWD @@ -0,0 +1,11 @@ +Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + +This Makefile.in is free software; the Free Software Foundation +gives unlimited permission to copy and/or distribute it, +with or without modifications, as long as this notice is preserved. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY, to the extent permitted by law; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. diff --git a/options/license/x11vnc-openssl-exception b/options/license/x11vnc-openssl-exception new file mode 100644 index 000000000..040e31c7a --- /dev/null +++ b/options/license/x11vnc-openssl-exception @@ -0,0 +1,9 @@ +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini index a89e441f7..709a71a13 100644 --- a/options/locale/locale_cs-CZ.ini +++ b/options/locale/locale_cs-CZ.ini @@ -107,6 +107,8 @@ never=Nikdy rss_feed=RSS kanál [filter] +string.asc=A – Z +string.desc=Z – A [error] occurred=Došlo k chybě @@ -236,6 +238,8 @@ no_reply_address=Skrytá e-mailová doména no_reply_address_helper=Název domény pro uživatele se skrytou e-mailovou adresou. Příklad: Pokud je název skryté e-mailové domény nastaven na „noreply.example.org“, uživatelské jméno „joe“ bude zaznamenáno v Gitu jako „joe@noreply.example.org“. password_algorithm=Hash algoritmus hesla password_algorithm_helper=Nastavte algoritmus hashování hesla. Algoritmy mají odlišné požadavky a sílu. `argon2` používá mnoho paměti a může být nevhodný pro malé systémy. +enable_update_checker=Povolit kontrolu aktualizací +enable_update_checker_helper=Kontroluje vydání nových verzí pravidelně připojením ke gitea.io. [home] uname_holder=Uživatelské jméno nebo e-mailová adresa @@ -414,6 +418,10 @@ repo.transfer.body=Chcete-li ji přijmout nebo odmítnout, navštivte %s nebo ji repo.collaborator.added.subject=%s vás přidal do %s repo.collaborator.added.text=Byl jste přidán jako spolupracovník repozitáře: +team_invite.subject=%[1]s vás pozval/a, abyste se připojili k organizaci %[2]s +team_invite.text_1=%[1]s vás pozval/a do týmu %[2]s v organizaci %[3]s. +team_invite.text_2=Pro připojení k týmu klikněte na následující odkaz: +team_invite.text_3=Poznámka: Tato pozvánka byla určena pro %[1]s. Pokud jste neočekávali tuto pozvánku, můžete tento e-mail ignorovat. [modal] yes=Ano @@ -490,6 +498,7 @@ user_not_exist=Tento uživatel neexistuje. team_not_exist=Tento tým neexistuje. last_org_owner=Nemůžete odstranit posledního uživatele z týmu „vlastníci“. Musí existovat alespoň jeden vlastník pro organizaci. cannot_add_org_to_team=Organizace nemůže být přidána jako člen týmu. +duplicate_invite_to_team=Uživatel byl již pozván jako člen týmu. invalid_ssh_key=Nelze ověřit váš SSH klíč: %s invalid_gpg_key=Nelze ověřit váš GPG klíč: %s @@ -742,6 +751,7 @@ create_oauth2_application_button=Vytvořit aplikaci create_oauth2_application_success=Úspěšně jste vytvořili novou OAuth2 aplikaci. update_oauth2_application_success=Úspěšně jste aktualizovali OAuth2 aplikaci. oauth2_application_name=Název aplikace +oauth2_confidential_client=Důvěrný klient. Vyberte aplikace, které zachovávají důvěrnosti v utajení, jako jsou webové aplikace. Nevybírejte pro nativní aplikace včetně stolních a mobilních aplikací. oauth2_redirect_uri=URI přesměrování save_application=Uložit oauth2_client_id=ID klienta @@ -2402,6 +2412,8 @@ teams.members=Členové týmu teams.update_settings=Upravit nastavení teams.delete_team=Smazat tým teams.add_team_member=Přidat člena týmu +teams.invite_team_member=Pozvat do %s +teams.invite_team_member.list=Čekající pozvánky teams.delete_team_title=Smazat tým teams.delete_team_desc=Smazání týmu zruší přístup jeho členům. Pokračovat? teams.delete_team_success=Tým byl odstraněn. @@ -2426,6 +2438,9 @@ teams.all_repositories_helper=Tým má přístup ke všem repositářům. Výbě teams.all_repositories_read_permission_desc=Tomuto týmu je udělen přístup pro Čtení všech repozitářů: členové mohou prohlížet a klonovat repozitáře. teams.all_repositories_write_permission_desc=Tomuto týmu je udělen přístup pro Zápis do všech repozitářů: členové mohou prohlížet a nahrávat do repozitářů. teams.all_repositories_admin_permission_desc=Tomuto týmu je udělen Administrátorský přístup do všech repozitářů: členové mohou prohlížet, nahrávat a přidávat spolupracovníky do repozitářů. +teams.invite.title=Byli jste pozváni do týmu %s v organizaci %s. +teams.invite.by=Pozvání od %s +teams.invite.description=Pro připojení k týmu klikněte na tlačítko níže. [admin] dashboard=Přehled diff --git a/options/locale/locale_el-GR.ini b/options/locale/locale_el-GR.ini index 56d63986e..200dabaf8 100644 --- a/options/locale/locale_el-GR.ini +++ b/options/locale/locale_el-GR.ini @@ -107,6 +107,8 @@ never=Ποτέ rss_feed=Ροή RSS [filter] +string.asc=A - Z +string.desc=Z - A [error] occurred=Παρουσιάστηκε ένα σφάλμα @@ -270,8 +272,11 @@ users=Χρήστες organizations=Οργανισμοί search=Αναζήτηση code=Κώδικας +search.type.tooltip=Τύπος αναζήτησης search.fuzzy=Fuzzy +search.fuzzy.tooltip=Συμπερίληψη και των αποτελεσμάτων που είναι πλησιέστερα με τον όρο αναζήτησης search.match=Ταίριασμα +search.match.tooltip=Συμπερίληψη μόνο των αποτελεσμάτων που ταιριάζουν ακριβώς με τον όρο αναζήτησης code_search_unavailable=Η αναζήτηση κώδικα δεν είναι διαθέσιμη αυτή τη στιγμή. Παρακαλώ επικοινωνήστε με το διαχειριστή. repo_no_results=Δεν βρέθηκαν αποθετήρια που να ταιρίαζουν με τα κριτήρια. user_no_results=Δεν βρέθηκαν χρήστες που να ταιριάζουν με τα κριτήρια. @@ -411,6 +416,10 @@ repo.transfer.body=Για να το αποδεχτείτε ή να το απορ repo.collaborator.added.subject=%s σας πρόσθεσε στο %s repo.collaborator.added.text=Έχετε προστεθεί ως συνεργάτης του αποθετηρίου: +team_invite.subject=%[1]s σας προσκάλεσε να συμμετέχετε στον οργανισμό %[2]s +team_invite.text_1=%[1]s σας προσκάλεσε να συμμετέχετε στην ομάδα %[2]s στον οργανισμός %[3]. +team_invite.text_2=Παρακαλώ κάντε κλικ στον παρακάτω σύνδεσμο για να συμμετάσχετε στην ομάδα: +team_invite.text_3=Σημείωση: Αυτή η πρόσκληση προοριζόταν για %[1]s. Αν δεν περιμένατε αυτή την πρόσκληση, μπορείτε να αγνοήσετε αυτό το email. [modal] yes=Ναι @@ -487,6 +496,7 @@ user_not_exist=Δεν υπάρχει ο χρήστης. team_not_exist=Δεν υπάρχει η ομάδα. last_org_owner=Δεν μπορείτε να καταργήσετε τον τελευταίο χρήστη από την ομάδα 'ιδιοκτήτών'. Πρέπει να υπάρχει τουλάχιστον ένας ιδιοκτήτης για έναν οργανισμό. cannot_add_org_to_team=Ένας οργανισμός δεν μπορεί να προστεθεί ως μέλος ομάδας. +duplicate_invite_to_team=Ο χρήστης είχε ήδη προσκληθεί ως μέλος της ομάδας. invalid_ssh_key=Δεν είναι δυνατή η επαλήθευση του SSH κλειδιού σας: %s invalid_gpg_key=Δεν είναι δυνατή η επαλήθευση του GPG κλειδιού σας: %s @@ -738,6 +748,7 @@ create_oauth2_application_button=Δημιουργία Εφαρμογής create_oauth2_application_success=Δημιουργήσατε επιτυχώς μια νέα εφαρμογή OAuth2. update_oauth2_application_success=Ενημερώσατε επιτυχώς την εφαρμογή OAuth2. oauth2_application_name=Όνομα Εφαρμογής +oauth2_confidential_client=Εμπιστευτικός Πελάτης. Επιλέξτε το για εφαρμογές που διατηρούν το μυστικό κωδικό κρυφό, όπως πχ οι εφαρμογές ιστού. Μην επιλέγετε για εγγενείς εφαρμογές, συμπεριλαμβανομένων εφαρμογών επιφάνειας εργασίας και εφαρμογών για κινητά. oauth2_redirect_uri=URI Ανακατεύθυνσης save_application=Αποθήκευση oauth2_client_id=Ταυτότητα Πελάτη @@ -1763,8 +1774,11 @@ activity.git_stats_deletion_n=%d διαγραφές search=Αναζήτηση search.search_repo=Αναζήτηση αποθετηρίου +search.type.tooltip=Τύπος αναζήτησης search.fuzzy=Fuzzy +search.fuzzy.tooltip=Συμπερίληψη και των αποτελεσμάτων που είναι πλησιέστερα με τον όρο αναζήτησης search.match=Ταίριασμα +search.match.tooltip=Συμπερίληψη μόνο των αποτελεσμάτων που ταιριάζουν ακριβώς με τον όρο αναζήτησης search.results=Αποτελέσματα αναζήτησης για "%s" σε %s search.code_no_results=Δεν βρέθηκε πηγαίος κώδικας που να ταιριάζει με τον όρο αναζήτησης. search.code_search_unavailable=Η αναζήτηση κώδικα δεν είναι διαθέσιμη αυτή τη στιγμή. Παρακαλώ επικοινωνήστε με το διαχειριστή. @@ -1898,6 +1912,7 @@ settings.confirm_delete=Διαγραφή Αποθετηρίου settings.add_collaborator=Προσθήκη Συνεργάτη settings.add_collaborator_success=Έχει προστεθεί ο συνεργάτης. settings.add_collaborator_inactive_user=Δεν είναι δυνατή η προσθήκη ενός ανενεργού χρήστη ως συνεργάτη. +settings.add_collaborator_owner=Δεν είναι δυνατή η προσθήκη ενός ιδιοκτήτη σαν συνεργάτη. settings.add_collaborator_duplicate=Ο συνεργάτης έχει ήδη προστεθεί σε αυτό το αποθετήριο. settings.delete_collaborator=Αφαίρεση settings.collaborator_deletion=Αφαίρεση Συνεργάτη @@ -2393,6 +2408,8 @@ teams.members=Μέλη Ομάδας teams.update_settings=Ενημέρωση Ρυθμίσεων teams.delete_team=Διαγραφή Ομάδας teams.add_team_member=Προσθήκη Μέλους Ομάδας +teams.invite_team_member=Πρόσκληση στο %s +teams.invite_team_member.list=Εκκρεμείς Προσκλήσεις teams.delete_team_title=Διαγραφή Ομάδας teams.delete_team_desc=Η διαγραφή μιας ομάδας ανακαλεί τη πρόσβαση στο αποθετήριο από τα μέλη της. Συνέχεια; teams.delete_team_success=Η ομάδα έχει διαγραφεί. @@ -2417,6 +2434,9 @@ teams.all_repositories_helper=Η ομάδα έχει πρόσβαση σε όλ teams.all_repositories_read_permission_desc=Αυτή η ομάδα χορηγεί πρόσβαση Ανάγνωσης σε όλα τα αποθετήρια: τα μέλη μπορούν να δουν και να κλωνοποιήσουν αποθετήρια. teams.all_repositories_write_permission_desc=Αυτή η ομάδα χορηγεί πρόσβαση Εγγραφής σε όλα τα αποθετήρια: τα μέλη μπορούν να διαβάσουν και να κάνουν push σε αποθετήρια. teams.all_repositories_admin_permission_desc=Αυτή η ομάδα παρέχει πρόσβαση Διαχείρισης σε όλα τα αποθετήρια: τα μέλη μπορούν να διαβάσουν, να κάνουν push και να προσθέσουν συνεργάτες στα αποθετήρια. +teams.invite.title=Έχετε προσκληθεί να συμμετέχετε στην ομάδα %s στον οργανισμό %s. +teams.invite.by=Προσκλήθηκε από %s +teams.invite.description=Παρακαλώ κάντε κλικ στον παρακάτω σύνδεσμο για συμμετοχή στην ομάδα. [admin] dashboard=Πίνακας Ελέγχου @@ -2870,6 +2890,8 @@ config.access_log_template=Πρότυπο config.xorm_log_mode=Λειτουργία Καταγραφών XORM config.xorm_log_sql=Καταγραφή SQL +config.get_setting_failed=Αποτυχία λήψης ρύθμισης %s +config.set_setting_failed=Αποτυχία ορισμού της ρύθμισης %s monitor.cron=Προγραμματισμένες Εργασίες monitor.name=Όνομα @@ -3034,6 +3056,9 @@ pin=Καρφίτσωμα ειδοποίησης mark_as_read=Σήμανση ως αναγνωσμένο mark_as_unread=Σήμανση ως μη αναγνωσμένο mark_all_as_read=Σήμανση όλων ως αναγνωσμένα +subscriptions=Συνδρομές +watching=Παρακολούθηση +no_subscriptions=Καμία συνδρομή [gpg] default_key=Υπογραφή με το προεπιλεγμένο κλειδί @@ -3093,6 +3118,7 @@ container.details.platform=Πλατφόρμα container.details.repository_site=Ιστοσελίδα Αποθετηρίου container.details.documentation_site=Ιστοσελίδα Τεκμηρίωσης container.pull=Κατεβάστε την εικόνα από τη γραμμή εντολών: +container.digest=Σύνοψη: container.documentation=Για περισσότερες πληροφορίες σχετικά με το μητρώο για Container, ανατρέξτε στην τεκμηρίωση. container.multi_arch=ΛΣ / Αρχιτεκτονική container.layers=Στρώματα Εικόνας diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 1566dfc97..e610bc6b2 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -88,6 +88,7 @@ edit = Edit copy = Copy copy_url = Copy URL +copy_content = Copy content copy_branch = Copy branch name copy_success = Copied! copy_error = Copy failed @@ -238,6 +239,8 @@ no_reply_address = Hidden Email Domain no_reply_address_helper = Domain name for users with a hidden email address. For example, the username 'joe' will be logged in Git as 'joe@noreply.example.org' if the hidden email domain is set to 'noreply.example.org'. password_algorithm = Password Hash Algorithm password_algorithm_helper = Set the password hashing algorithm. Algorithms have differing requirements and strength. `argon2` whilst having good characteristics uses a lot of memory and may be inappropriate for small systems. +enable_update_checker = Enable Update Checker +enable_update_checker_helper = Checks for new version releases periodically by connecting to gitea.io. [home] uname_holder = Username or Email Address @@ -461,6 +464,7 @@ url_error = `'%s' is not a valid URL.` include_error = ` must contain substring '%s'.` glob_pattern_error = ` glob pattern is invalid: %s.` regex_pattern_error = ` regex pattern is invalid: %s.` +username_error = ` can only contain alphanumeric chars ('0-9','a-z','A-Z'), dash ('-'), underscore ('_') and dot ('.'). It cannot begin or end with non-alphanumeric chars, and consecutive non-alphanumeric chars are also forbidden.` unknown_error = Unknown error: captcha_incorrect = The CAPTCHA code is incorrect. password_not_match = The passwords do not match. @@ -1087,6 +1091,7 @@ editor.cannot_edit_non_text_files = Binary files cannot be edited in the web int editor.edit_this_file = Edit File editor.this_file_locked = File is locked editor.must_be_on_a_branch = You must be on a branch to make or propose changes to this file. +editor.only_copy_raw = You may only copy raw text files. editor.fork_before_edit = You must fork this repository to make or propose changes to this file. editor.delete_this_file = Delete File editor.must_have_write_access = You must have write access to make or propose changes to this file. @@ -2010,6 +2015,8 @@ settings.event_package = Package settings.event_package_desc = Package created or deleted in a repository. settings.branch_filter = Branch filter settings.branch_filter_desc = Branch whitelist for push, branch creation and branch deletion events, specified as glob pattern. If empty or *, events for all branches are reported. See github.com/gobwas/glob documentation for syntax. Examples: master, {master,release*}. +settings.authorization_header = Authorization Header +settings.authorization_header_desc = Will be included as authorization header for requests when present. Examples: %s. settings.active = Active settings.active_helper = Information about triggered events will be sent to this webhook URL. settings.add_hook_success = The webhook has been added. @@ -2124,7 +2131,6 @@ settings.bot_token = Bot Token settings.chat_id = Chat ID settings.matrix.homeserver_url = Homeserver URL settings.matrix.room_id = Room ID -settings.matrix.access_token = Access Token settings.matrix.message_type = Message Type settings.archive.button = Archive Repo settings.archive.header = Archive This Repo @@ -3001,6 +3007,7 @@ reopen_pull_request = `reopened pull request %[3]s#%[2]s` comment_issue = `commented on issue %[3]s#%[2]s` comment_pull = `commented on pull request %[3]s#%[2]s` merge_pull_request = `merged pull request %[3]s#%[2]s` +auto_merge_pull_request = `automatically merged pull request %[3]s#%[2]s` transfer_repo = transferred repository %s to %s push_tag = pushed tag %[3]s to %[4]s delete_tag = deleted tag %[2]s from %[3]s diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index 11adea655..abb58a4f2 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -107,6 +107,8 @@ never=無し rss_feed=RSSフィード [filter] +string.asc=A - Z +string.desc=Z - A [error] occurred=エラーが発生しました. @@ -414,6 +416,10 @@ repo.transfer.body=承認または拒否するには %s を開きます。 も repo.collaborator.added.subject=%s が %s にあなたを追加しました repo.collaborator.added.text=あなたは次のリポジトリの共同作業者に追加されました: +team_invite.subject=%[1]s さんが %[2]s への参加にあなたを招待しました +team_invite.text_1=%[1]s さんが、組織 %[3]s 内のチーム %[2]s への参加に、あなたを招待しました。 +team_invite.text_2=下のリンクをクリックしてチームに参加してください。 +team_invite.text_3=注: この招待は %[1]s 宛です。 招待に心当たりがなければ、このメールを無視してかまいません。 [modal] yes=はい @@ -490,6 +496,7 @@ user_not_exist=指定されたユーザーは存在しません。 team_not_exist=チームが存在していません。 last_org_owner='Owners'チームから最後のユーザーを削除することはできません。ひとつの組織には少なくとも一人のオーナーが必要です。 cannot_add_org_to_team=組織はチームメンバーとして追加できません。 +duplicate_invite_to_team=指定したユーザーはすでにチームメンバーに招待されています。 invalid_ssh_key=SSHキーが確認できません: %s invalid_gpg_key=GPGキーが確認できません: %s @@ -742,6 +749,7 @@ create_oauth2_application_button=アプリケーション作成 create_oauth2_application_success=新しいOAuth2アプリケーションを作成しました。 update_oauth2_application_success=OAuth2アプリケーションを更新しました。 oauth2_application_name=アプリケーション名 +oauth2_confidential_client=コンフィデンシャルクライアント。 ウェブアプリのように秘密情報を機密にできるアプリの場合に選択します。 デスクトップアプリやモバイルアプリなどのネイティブアプリには選択しないでください。 oauth2_redirect_uri=リダイレクトURI save_application=保存 oauth2_client_id=クライアントID @@ -2402,6 +2410,8 @@ teams.members=チームメンバー teams.update_settings=設定の更新 teams.delete_team=チームを削除 teams.add_team_member=チームメンバーを追加 +teams.invite_team_member=%s への招待 +teams.invite_team_member.list=保留中の招待 teams.delete_team_title=チームの削除 teams.delete_team_desc=チームを削除すると、メンバーはこのリポジトリへのアクセス権を失います。 続行しますか? teams.delete_team_success=チームを削除しました。 @@ -2426,6 +2436,9 @@ teams.all_repositories_helper=チームはすべてのリポジトリにアク teams.all_repositories_read_permission_desc=このチームはすべてのリポジトリ読み取りアクセス権を持ちます: メンバーはリポジトリの閲覧とクローンが可能です。 teams.all_repositories_write_permission_desc=このチームはすべてのリポジトリ書き込みアクセス権を持ちます: メンバーはリポジトリの読み取りとプッシュが可能です。 teams.all_repositories_admin_permission_desc=このチームはすべてのリポジトリ管理者アクセス権を持ちます: メンバーはリポジトリの読み取り、プッシュ、共同作業者の追加が可能です。 +teams.invite.title=あなたは組織 %[2]s 内のチーム %[1]s への参加に招待されました。 +teams.invite.by=%s からの招待 +teams.invite.description=下のボタンをクリックしてチームに参加してください。 [admin] dashboard=ダッシュボード @@ -2879,6 +2892,8 @@ config.access_log_template=テンプレート config.xorm_log_mode=XORMログのモード config.xorm_log_sql=SQLのログ出力 +config.get_setting_failed=%s の取得に失敗しました +config.set_setting_failed=%s の設定に失敗しました monitor.cron=Cronタスク monitor.name=名称 diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index e16f06abf..9c38a1727 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -238,6 +238,8 @@ no_reply_address=Domínio dos emails ocultos no_reply_address_helper=Nome de domínio para utilizadores com um endereço de email oculto. Por exemplo, o nome de utilizador 'silva' será registado no Git como 'silva@semresposta.exemplo.org' se o domínio de email oculto estiver definido como 'semresposta.exemplo.org'. password_algorithm=Algoritmo de Hash da Senha password_algorithm_helper=Definir o algoritmo de hash da senha. Os algoritmos têm requisitos e resistência distintos. `argon2`, embora tenha boas características, usa muita memória e pode ser inapropriado para sistemas pequenos. +enable_update_checker=Habilitar verificador de novidades +enable_update_checker_helper=Verifica, periodicamente, se foi lançada alguma versão nova, fazendo uma ligação ao gitea.io. [home] uname_holder=Nome de utilizador ou endereço de email diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 7b9941aff..ee6f686a8 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -238,6 +238,8 @@ no_reply_address=隐藏电子邮件 no_reply_address_helper=具有隐藏电子邮件地址的用户的域名。例如, 用户名 "joe" 将以 "joe@noreply.example.org" 的身份登录到 Git 中. 如果隐藏的电子邮件域设置为 "noreply.example.org"。 password_algorithm=密码哈希算法 password_algorithm_helper=设置密码哈希算法。 算法具有不同的要求和强度。 具有良好特性的`argon2`却会占用大量内存,可能不适用于小型系统。 +enable_update_checker=启用更新检查 +enable_update_checker_helper=通过连接到 gitea.io 定期检查新版本发布。 [home] uname_holder=用户名或邮箱 @@ -451,7 +453,7 @@ SSPIDefaultLanguage=默认语言 require_error=不能为空。 alpha_dash_error=应该只包含字母数字、破折号 ('-') 和下划线 ('_') 字符。 -alpha_dash_dot_error=' 应该只包含字母数字, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。 +alpha_dash_dot_error=` 应该只包含字母数字, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。` git_ref_name_error=` 必须是格式良好的 git 引用名称。` size_error=长度必须为 %s。 min_size_error=长度最小为 %s 个字符。 @@ -749,6 +751,7 @@ create_oauth2_application_button=创建应用 create_oauth2_application_success=您已成功创建了一个新的 OAuth2 应用。 update_oauth2_application_success=您已成功更新了此 OAuth2 应用。 oauth2_application_name=应用名称 +oauth2_confidential_client=机密客户端。是否是能够维持凭据机密性的应用,比如网页应用程序。如果是本地应用程序请不要勾选,包括桌面和移动端应用。 oauth2_redirect_uri=重定向 URI save_application=保存 oauth2_client_id=客户端ID @@ -2489,9 +2492,9 @@ dashboard.archive_cleanup=删除旧的仓库存档 dashboard.deleted_branches_cleanup=清理已删除的分支 dashboard.update_migration_poster_id=更新迁移的发表者ID dashboard.git_gc_repos=对仓库进行垃圾回收 -dashboard.resync_all_sshkeys=使用 Gitea 的 SSH 密钥更新 '.ssh/authorized_keys' 文件。 +dashboard.resync_all_sshkeys=使用 Gitea 的 SSH 密钥更新「.ssh/authorized_keys」文件。 dashboard.resync_all_sshkeys.desc=(内置的 SSH 服务器不需要。) -dashboard.resync_all_sshprincipals=使用 Gitea 的 SSH 规则更新 '.ssh/authorized_principals' 文件。 +dashboard.resync_all_sshprincipals=使用 Gitea 的 SSH 规则更新「.ssh/authorized_principals」文件。 dashboard.resync_all_sshprincipals.desc=(内置的 SSH 服务器不需要。) dashboard.resync_all_hooks=重新同步所有仓库的 pre-receive、update 和 post-receive 钩子 dashboard.reinit_missing_repos=重新初始化所有丢失的 Git 仓库存在的记录 diff --git a/package-lock.json b/package-lock.json index 69f1ce409..cd11a43e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "@claviska/jquery-minicolors": "2.3.6", "@mcaptcha/vanilla-glue": "0.1.0-alpha-3", "@primer/octicons": "17.7.0", - "@vue/compiler-sfc": "3.2.40", + "@vue/compiler-sfc": "3.2.41", "add-asset-webpack-plugin": "2.0.1", "css-loader": "6.7.1", "dropzone": "6.0.0-beta.2", @@ -21,21 +21,21 @@ "font-awesome": "4.7.0", "jquery": "3.6.1", "jquery.are-you-sure": "1.9.0", - "katex": "0.16.2", + "katex": "0.16.3", "less": "4.1.3", "less-loader": "11.1.0", "license-checker-webpack-plugin": "0.2.1", "mermaid": "9.1.7", "mini-css-extract-plugin": "2.6.1", - "monaco-editor": "0.34.0", + "monaco-editor": "0.34.1", "monaco-editor-webpack-plugin": "7.0.1", "pretty-ms": "8.0.0", "sortablejs": "1.15.0", - "swagger-ui-dist": "4.14.2", + "swagger-ui-dist": "4.15.0", "tippy.js": "6.3.7", "tributejs": "5.1.3", "uint8-to-base64": "0.2.0", - "vue": "3.2.40", + "vue": "3.2.41", "vue-bar-graph": "2.0.0", "vue-loader": "17.0.0", "vue3-calendar-heatmap": "2.0.0", @@ -47,23 +47,23 @@ "wrap-ansi": "8.0.1" }, "devDependencies": { - "@playwright/test": "1.27.0", - "@rollup/pluginutils": "5.0.1", + "@playwright/test": "1.27.1", + "@rollup/pluginutils": "5.0.2", "@stoplight/spectral-cli": "6.5.1", - "eslint": "8.25.0", + "eslint": "8.26.0", "eslint-plugin-import": "2.26.0", "eslint-plugin-jquery": "1.5.1", - "eslint-plugin-sonarjs": "0.15.0", + "eslint-plugin-sonarjs": "0.16.0", "eslint-plugin-unicorn": "44.0.2", "eslint-plugin-vue": "9.6.0", "jsdom": "20.0.1", "markdownlint-cli": "0.32.2", "postcss-less": "6.0.0", - "stylelint": "14.13.0", - "stylelint-config-standard": "28.0.0", - "svgo": "2.8.0", - "updates": "13.1.8", - "vitest": "0.24.1" + "stylelint": "14.14.0", + "stylelint-config-standard": "29.0.0", + "svgo": "3.0.0", + "updates": "13.1.10", + "vitest": "0.24.3" }, "engines": { "node": ">= 14.0.0" @@ -182,9 +182,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.3.tgz", - "integrity": "sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ==", + "version": "7.19.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.6.tgz", + "integrity": "sha512-h1IUp81s2JYJ3mRkdxJgs4UvmSsRvDrx5ICSJbPvtWYv5i1nTBGcBpnog+89rAFMwvvru6E5NUHdBe01UeSzYA==", "bin": { "parser": "bin/babel-parser.js" }, @@ -193,9 +193,9 @@ } }, "node_modules/@braintree/sanitize-url": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.0.tgz", - "integrity": "sha512-mgmE7XBYY/21erpzhexk4Cj1cyTQ9LzvnTxtzM17BJ7ERMNE6W72mQRo0I1Ud8eFJ+RVVIcBNhLFZ3GX4XFz5w==" + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.1.tgz", + "integrity": "sha512-zr9Qs9KFQiEvMWdZesjcmRJlUck5NR+eKGS1uyKk+oYTWwlYrsoPEi6VmG6/TzBD1hKCGEimrhTgGS6hvn/xIQ==" }, "node_modules/@claviska/jquery-minicolors": { "version": "2.3.6", @@ -231,9 +231,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.10.tgz", - "integrity": "sha512-FNONeQPy/ox+5NBkcSbYJxoXj9GWu8gVGJTVmUyoOCKQFDTrHVKgNSzChdNt0I8Aj/iKcsDf2r9BFwv+FSNUXg==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.12.tgz", + "integrity": "sha512-IC7TqIqiyE0MmvAhWkl/8AEzpOtbhRNDo7aph47We1NbE5w2bt/Q+giAhe0YYeVpYnIhGMcuZY92qDK6dQauvA==", "cpu": [ "arm" ], @@ -246,9 +246,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.10.tgz", - "integrity": "sha512-w0Ou3Z83LOYEkwaui2M8VwIp+nLi/NA60lBLMvaJ+vXVMcsARYdEzLNE7RSm4+lSg4zq4d7fAVuzk7PNQ5JFgg==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.12.tgz", + "integrity": "sha512-tZEowDjvU7O7I04GYvWQOS4yyP9E/7YlsB0jjw1Ycukgr2ycEzKyIk5tms5WnLBymaewc6VmRKnn5IJWgK4eFw==", "cpu": [ "loong64" ], @@ -306,9 +306,9 @@ "dev": true }, "node_modules/@humanwhocodes/config-array": { - "version": "0.10.7", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", - "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.6.tgz", + "integrity": "sha512-jJr+hPTJYKyDILJfhNSHsjiwXYf26Flsz8DvNndOsHs5pwSnpGUEy8yzF0JYhCEvTDdV2vuOK5tt8BVhwO5/hg==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", @@ -338,6 +338,19 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", @@ -363,28 +376,15 @@ "@jridgewell/trace-mapping": "^0.3.9" } }, - "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.16", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.16.tgz", - "integrity": "sha512-LCQ+NeThyJ4k1W2d+vIKdxuSt9R3pQSZ4P92m7EakaYuXcVWbHuT5bjNcqLd4Rdgi6xYWYDvBJZJLZSLanjDcA==", + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" @@ -496,13 +496,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.27.0.tgz", - "integrity": "sha512-L4BswoJvGkFsEHhEgzVNHBnkFB1FbnBQn3QmvTl7+AouoJQ4a8tLwZKvytdovCsNi7B5cXuRo58yGvfM5PnExw==", + "version": "1.27.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.27.1.tgz", + "integrity": "sha512-mrL2q0an/7tVqniQQF6RBL2saskjljXzqNcCOVMUjRIgE6Y38nCNaP+Dc2FBW06bcpD3tqIws/HT9qiMHbNU0A==", "dev": true, "dependencies": { "@types/node": "*", - "playwright-core": "1.27.0" + "playwright-core": "1.27.1" }, "bin": { "playwright": "cli.js" @@ -572,10 +572,16 @@ "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", "dev": true }, + "node_modules/@rollup/plugin-commonjs/node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, "node_modules/@rollup/pluginutils": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.1.tgz", - "integrity": "sha512-4HaCVEXXuObvcPUaUlLt4faHYHCeQOOWNj8NKFGaRSrw3ZLD0TWeAFZicV9vXjnE2nkNuaVTfTuwAnjR+6uc9A==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", + "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", "dev": true, "dependencies": { "@types/estree": "^1.0.0", @@ -594,12 +600,6 @@ } } }, - "node_modules/@rollup/pluginutils/node_modules/@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", - "dev": true - }, "node_modules/@stoplight/better-ajv-errors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@stoplight/better-ajv-errors/-/better-ajv-errors-1.0.3.tgz", @@ -757,9 +757,9 @@ } }, "node_modules/@stoplight/spectral-core": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-core/-/spectral-core-1.14.2.tgz", - "integrity": "sha512-W2Z31lasEICpZS50STFskOdkn4g0Va81XA1A88LIj9mvlctDFf4BfpjLgIjKkI4f2DEK5C4j3COcbbzV8y5Xig==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-core/-/spectral-core-1.15.0.tgz", + "integrity": "sha512-+DwK8SmnujMZJaxJeNU11vWY+DFOnt4oQM1TzAuvufdd3Y6Lsno88Jl31OaR1M9Fn7l/u3v1anBB/SSl/fI5rQ==", "dev": true, "dependencies": { "@stoplight/better-ajv-errors": "1.0.3", @@ -948,9 +948,9 @@ } }, "node_modules/@stoplight/spectral-ruleset-bundler": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-ruleset-bundler/-/spectral-ruleset-bundler-1.3.2.tgz", - "integrity": "sha512-sy7mHVBwmo5/8dUlnWiel2UND1Mnu3x+okBAgLmkGcIpXz74rMmVY3h5vT6rjxw65WZ3/c3mtm1dRQuSe+q5fw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-ruleset-bundler/-/spectral-ruleset-bundler-1.3.3.tgz", + "integrity": "sha512-hfHl7XZeF/wWMpSrsLqLnH2GevRHjSIqtBL2aRjO2SjMCTbO9LVz80p4sYaxrCcu4wQ6K71gMZXsG687+3fAeg==", "dev": true, "dependencies": { "@rollup/plugin-commonjs": "~22.0.2", @@ -1031,10 +1031,16 @@ "node": "^12.20 || >=14.13" } }, + "node_modules/@stoplight/spectral-ruleset-bundler/node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, "node_modules/@stoplight/spectral-ruleset-migrator": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-ruleset-migrator/-/spectral-ruleset-migrator-1.7.4.tgz", - "integrity": "sha512-QySMWSvGUC5D8cNDvXhrXEY0a4DB5hewHwjxXbwlH51fVNiVKJ4+KcaCW3s2yAT4T1p6/ij8NkLX9T81D4vSCg==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-ruleset-migrator/-/spectral-ruleset-migrator-1.8.0.tgz", + "integrity": "sha512-zg6RPF+d8uS7zAp5TzUph3hQG4sgGcG5Fsw8Zx24H1REyuSkjiIfyee2Kf13c3BcIlTXvnFc4csz2rNXpZO7Ug==", "dev": true, "dependencies": { "@stoplight/json": "~3.20.1", @@ -1245,9 +1251,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.4.6", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.6.tgz", - "integrity": "sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g==", + "version": "8.4.7", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.7.tgz", + "integrity": "sha512-ehM7cCt2RSFs42mb+lcmhFT9ouIlV92PuaeRGn8N8c98oMjG4Z5pJHA9b1QiCcuqnbPSHcyfiD3mlhqMaHsQIw==", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -1263,9 +1269,9 @@ } }, "node_modules/@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", + "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==" }, "node_modules/@types/json-schema": { "version": "7.0.11", @@ -1290,9 +1296,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.8.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.3.tgz", - "integrity": "sha512-0os9vz6BpGwxGe9LOhgP/ncvYN5Tx1fNcd2TM3rD/aCGBkysb+ZWpXEocG24h6ZzOi13+VB8HndAQFezsSOw1w==" + "version": "18.11.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.4.tgz", + "integrity": "sha512-BxcJpBu8D3kv/GZkx/gSMz6VnTJREBj/4lbzYOQueUOELkt8WrO6zAcSPmp9uRPEW/d+lUO8QK0W2xnS1hEU0A==" }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", @@ -1321,36 +1327,36 @@ "dev": true }, "node_modules/@vue/compiler-core": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.40.tgz", - "integrity": "sha512-2Dc3Stk0J/VyQ4OUr2yEC53kU28614lZS+bnrCbFSAIftBJ40g/2yQzf4mPBiFuqguMB7hyHaujdgZAQ67kZYA==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.41.tgz", + "integrity": "sha512-oA4mH6SA78DT+96/nsi4p9DX97PHcNROxs51lYk7gb9Z4BPKQ3Mh+BLn6CQZBw857Iuhu28BfMSRHAlPvD4vlw==", "dependencies": { "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.40", + "@vue/shared": "3.2.41", "estree-walker": "^2.0.2", "source-map": "^0.6.1" } }, "node_modules/@vue/compiler-dom": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.40.tgz", - "integrity": "sha512-OZCNyYVC2LQJy4H7h0o28rtk+4v+HMQygRTpmibGoG9wZyomQiS5otU7qo3Wlq5UfHDw2RFwxb9BJgKjVpjrQw==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.41.tgz", + "integrity": "sha512-xe5TbbIsonjENxJsYRbDJvthzqxLNk+tb3d/c47zgREDa/PCp6/Y4gC/skM4H6PIuX5DAxm7fFJdbjjUH2QTMw==", "dependencies": { - "@vue/compiler-core": "3.2.40", - "@vue/shared": "3.2.40" + "@vue/compiler-core": "3.2.41", + "@vue/shared": "3.2.41" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.40.tgz", - "integrity": "sha512-tzqwniIN1fu1PDHC3CpqY/dPCfN/RN1thpBC+g69kJcrl7mbGiHKNwbA6kJ3XKKy8R6JLKqcpVugqN4HkeBFFg==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.41.tgz", + "integrity": "sha512-+1P2m5kxOeaxVmJNXnBskAn3BenbTmbxBxWOtBq3mQTCokIreuMULFantBUclP0+KnzNCMOvcnKinqQZmiOF8w==", "dependencies": { "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.40", - "@vue/compiler-dom": "3.2.40", - "@vue/compiler-ssr": "3.2.40", - "@vue/reactivity-transform": "3.2.40", - "@vue/shared": "3.2.40", + "@vue/compiler-core": "3.2.41", + "@vue/compiler-dom": "3.2.41", + "@vue/compiler-ssr": "3.2.41", + "@vue/reactivity-transform": "3.2.41", + "@vue/shared": "3.2.41", "estree-walker": "^2.0.2", "magic-string": "^0.25.7", "postcss": "^8.1.10", @@ -1358,69 +1364,69 @@ } }, "node_modules/@vue/compiler-ssr": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.40.tgz", - "integrity": "sha512-80cQcgasKjrPPuKcxwuCx7feq+wC6oFl5YaKSee9pV3DNq+6fmCVwEEC3vvkf/E2aI76rIJSOYHsWSEIxK74oQ==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.41.tgz", + "integrity": "sha512-Y5wPiNIiaMz/sps8+DmhaKfDm1xgj6GrH99z4gq2LQenfVQcYXmHIOBcs5qPwl7jaW3SUQWjkAPKMfQemEQZwQ==", "dependencies": { - "@vue/compiler-dom": "3.2.40", - "@vue/shared": "3.2.40" + "@vue/compiler-dom": "3.2.41", + "@vue/shared": "3.2.41" } }, "node_modules/@vue/reactivity": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.40.tgz", - "integrity": "sha512-N9qgGLlZmtUBMHF9xDT4EkD9RdXde1Xbveb+niWMXuHVWQP5BzgRmE3SFyUBBcyayG4y1lhoz+lphGRRxxK4RA==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.41.tgz", + "integrity": "sha512-9JvCnlj8uc5xRiQGZ28MKGjuCoPhhTwcoAdv3o31+cfGgonwdPNuvqAXLhlzu4zwqavFEG5tvaoINQEfxz+l6g==", "dependencies": { - "@vue/shared": "3.2.40" + "@vue/shared": "3.2.41" } }, "node_modules/@vue/reactivity-transform": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.40.tgz", - "integrity": "sha512-HQUCVwEaacq6fGEsg2NUuGKIhUveMCjOk8jGHqLXPI2w6zFoPrlQhwWEaINTv5kkZDXKEnCijAp+4gNEHG03yw==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.41.tgz", + "integrity": "sha512-mK5+BNMsL4hHi+IR3Ft/ho6Za+L3FA5j8WvreJ7XzHrqkPq8jtF/SMo7tuc9gHjLDwKZX1nP1JQOKo9IEAn54A==", "dependencies": { "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.40", - "@vue/shared": "3.2.40", + "@vue/compiler-core": "3.2.41", + "@vue/shared": "3.2.41", "estree-walker": "^2.0.2", "magic-string": "^0.25.7" } }, "node_modules/@vue/runtime-core": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.40.tgz", - "integrity": "sha512-U1+rWf0H8xK8aBUZhnrN97yoZfHbjgw/bGUzfgKPJl69/mXDuSg8CbdBYBn6VVQdR947vWneQBFzdhasyzMUKg==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.41.tgz", + "integrity": "sha512-0LBBRwqnI0p4FgIkO9q2aJBBTKDSjzhnxrxHYengkAF6dMOjeAIZFDADAlcf2h3GDALWnblbeprYYpItiulSVQ==", "dependencies": { - "@vue/reactivity": "3.2.40", - "@vue/shared": "3.2.40" + "@vue/reactivity": "3.2.41", + "@vue/shared": "3.2.41" } }, "node_modules/@vue/runtime-dom": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.40.tgz", - "integrity": "sha512-AO2HMQ+0s2+MCec8hXAhxMgWhFhOPJ/CyRXnmTJ6XIOnJFLrH5Iq3TNwvVcODGR295jy77I6dWPj+wvFoSYaww==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.41.tgz", + "integrity": "sha512-U7zYuR1NVIP8BL6jmOqmapRAHovEFp7CSw4pR2FacqewXNGqZaRfHoNLQsqQvVQ8yuZNZtxSZy0FFyC70YXPpA==", "dependencies": { - "@vue/runtime-core": "3.2.40", - "@vue/shared": "3.2.40", + "@vue/runtime-core": "3.2.41", + "@vue/shared": "3.2.41", "csstype": "^2.6.8" } }, "node_modules/@vue/server-renderer": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.40.tgz", - "integrity": "sha512-gtUcpRwrXOJPJ4qyBpU3EyxQa4EkV8I4f8VrDePcGCPe4O/hd0BPS7v9OgjIQob6Ap8VDz9G+mGTKazE45/95w==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.41.tgz", + "integrity": "sha512-7YHLkfJdTlsZTV0ae5sPwl9Gn/EGr2hrlbcS/8naXm2CDpnKUwC68i1wGlrYAfIgYWL7vUZwk2GkYLQH5CvFig==", "dependencies": { - "@vue/compiler-ssr": "3.2.40", - "@vue/shared": "3.2.40" + "@vue/compiler-ssr": "3.2.41", + "@vue/shared": "3.2.41" }, "peerDependencies": { - "vue": "3.2.40" + "vue": "3.2.41" } }, "node_modules/@vue/shared": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.40.tgz", - "integrity": "sha512-0PLQ6RUtZM0vO3teRfzGi4ltLUO5aO+kLgwh4Um3THSR03rpQWLTuRCkuO5A41ITzwdWeKdPHtSARuPkoo5pCQ==" + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.41.tgz", + "integrity": "sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw==" }, "node_modules/@webassemblyjs/ast": { "version": "1.11.1", @@ -1615,9 +1621,9 @@ } }, "node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", "bin": { "acorn": "bin/acorn" }, @@ -2050,9 +2056,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001418", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001418.tgz", - "integrity": "sha512-oIs7+JL3K9JRQ3jPZjlH6qyYDp+nBTCais7hjh0s+fuBwufc7uZ7hPYMXrDOJhV360KGMTcczMRObk0/iMqZRg==", + "version": "1.0.30001423", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001423.tgz", + "integrity": "sha512-09iwWGOlifvE1XuHokFMP7eR38a0JnajoyL3/i87c8ZjRWRrdKo1fqjNfugfBD0UDBIOz0U+jtNhJ0EPm1VleQ==", "funding": [ { "type": "opencollective", @@ -2345,15 +2351,15 @@ } }, "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", "dev": true, "dependencies": { "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", "nth-check": "^2.0.1" }, "funding": { @@ -2361,16 +2367,17 @@ } }, "node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", "dev": true, "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" }, "engines": { - "node": ">=8.0.0" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" } }, "node_modules/css-what": { @@ -2397,15 +2404,16 @@ } }, "node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", "dev": true, "dependencies": { - "css-tree": "^1.1.2" + "css-tree": "~2.2.0" }, "engines": { - "node": ">=8.0.0" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" } }, "node_modules/cssom": { @@ -3198,9 +3206,9 @@ } }, "node_modules/decimal.js": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.1.tgz", - "integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==", + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.2.tgz", + "integrity": "sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==", "dev": true }, "node_modules/deep-eql": { @@ -3415,24 +3423,27 @@ } }, "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dev": true, "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" }, "funding": { "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, "node_modules/dom-serializer/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", "dev": true, + "engines": { + "node": ">=0.12" + }, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -3462,12 +3473,12 @@ } }, "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dev": true, "dependencies": { - "domelementtype": "^2.2.0" + "domelementtype": "^2.3.0" }, "engines": { "node": ">= 4" @@ -3482,14 +3493,14 @@ "integrity": "sha512-Be9tbQMZds4a3C6xTmz68NlMfeONA//4dOavl/1rNw50E+/QO0KVpbcU0PcaW0nsQxurXls9ZocqFxk8R2mWEA==" }, "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", + "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", "dev": true, "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.1" }, "funding": { "url": "https://github.com/fb55/domutils?sponsor=1" @@ -3522,9 +3533,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.276", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.276.tgz", - "integrity": "sha512-EpuHPqu8YhonqLBXHoU6hDJCD98FCe6KDoet3/gY1qsQ6usjJoHqBH2YIVs8FXaAtHwVL8Uqa/fsYao/vq9VWQ==" + "version": "1.4.284", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", + "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==" }, "node_modules/emoji-regex": { "version": "8.0.0", @@ -3692,9 +3703,9 @@ } }, "node_modules/esbuild": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.10.tgz", - "integrity": "sha512-N7wBhfJ/E5fzn/SpNgX+oW2RLRjwaL8Y0ezqNqhjD6w0H2p0rDuEz2FKZqpqLnO8DCaWumKe8dsC/ljvVSSxng==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.12.tgz", + "integrity": "sha512-PcT+/wyDqJQsRVhaE9uX/Oq4XLrFh0ce/bs2TJh4CSaw9xuvI+xFrH2nAYOADbhQjUgAhNWC5LKoUsakm4dxng==", "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -3703,34 +3714,34 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.15.10", - "@esbuild/linux-loong64": "0.15.10", - "esbuild-android-64": "0.15.10", - "esbuild-android-arm64": "0.15.10", - "esbuild-darwin-64": "0.15.10", - "esbuild-darwin-arm64": "0.15.10", - "esbuild-freebsd-64": "0.15.10", - "esbuild-freebsd-arm64": "0.15.10", - "esbuild-linux-32": "0.15.10", - "esbuild-linux-64": "0.15.10", - "esbuild-linux-arm": "0.15.10", - "esbuild-linux-arm64": "0.15.10", - "esbuild-linux-mips64le": "0.15.10", - "esbuild-linux-ppc64le": "0.15.10", - "esbuild-linux-riscv64": "0.15.10", - "esbuild-linux-s390x": "0.15.10", - "esbuild-netbsd-64": "0.15.10", - "esbuild-openbsd-64": "0.15.10", - "esbuild-sunos-64": "0.15.10", - "esbuild-windows-32": "0.15.10", - "esbuild-windows-64": "0.15.10", - "esbuild-windows-arm64": "0.15.10" + "@esbuild/android-arm": "0.15.12", + "@esbuild/linux-loong64": "0.15.12", + "esbuild-android-64": "0.15.12", + "esbuild-android-arm64": "0.15.12", + "esbuild-darwin-64": "0.15.12", + "esbuild-darwin-arm64": "0.15.12", + "esbuild-freebsd-64": "0.15.12", + "esbuild-freebsd-arm64": "0.15.12", + "esbuild-linux-32": "0.15.12", + "esbuild-linux-64": "0.15.12", + "esbuild-linux-arm": "0.15.12", + "esbuild-linux-arm64": "0.15.12", + "esbuild-linux-mips64le": "0.15.12", + "esbuild-linux-ppc64le": "0.15.12", + "esbuild-linux-riscv64": "0.15.12", + "esbuild-linux-s390x": "0.15.12", + "esbuild-netbsd-64": "0.15.12", + "esbuild-openbsd-64": "0.15.12", + "esbuild-sunos-64": "0.15.12", + "esbuild-windows-32": "0.15.12", + "esbuild-windows-64": "0.15.12", + "esbuild-windows-arm64": "0.15.12" } }, "node_modules/esbuild-android-64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.10.tgz", - "integrity": "sha512-UI7krF8OYO1N7JYTgLT9ML5j4+45ra3amLZKx7LO3lmLt1Ibn8t3aZbX5Pu4BjWiqDuJ3m/hsvhPhK/5Y/YpnA==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.12.tgz", + "integrity": "sha512-MJKXwvPY9g0rGps0+U65HlTsM1wUs9lbjt5CU19RESqycGFDRijMDQsh68MtbzkqWSRdEtiKS1mtPzKneaAI0Q==", "cpu": [ "x64" ], @@ -3743,9 +3754,9 @@ } }, "node_modules/esbuild-android-arm64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.10.tgz", - "integrity": "sha512-EOt55D6xBk5O05AK8brXUbZmoFj4chM8u3riGflLa6ziEoVvNjRdD7Cnp82NHQGfSHgYR06XsPI8/sMuA/cUwg==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.12.tgz", + "integrity": "sha512-Hc9SEcZbIMhhLcvhr1DH+lrrec9SFTiRzfJ7EGSBZiiw994gfkVV6vG0sLWqQQ6DD7V4+OggB+Hn0IRUdDUqvA==", "cpu": [ "arm64" ], @@ -3758,9 +3769,9 @@ } }, "node_modules/esbuild-darwin-64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.10.tgz", - "integrity": "sha512-hbDJugTicqIm+WKZgp208d7FcXcaK8j2c0l+fqSJ3d2AzQAfjEYDRM3Z2oMeqSJ9uFxyj/muSACLdix7oTstRA==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.12.tgz", + "integrity": "sha512-qkmqrTVYPFiePt5qFjP8w/S+GIUMbt6k8qmiPraECUWfPptaPJUGkCKrWEfYFRWB7bY23FV95rhvPyh/KARP8Q==", "cpu": [ "x64" ], @@ -3773,9 +3784,9 @@ } }, "node_modules/esbuild-darwin-arm64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.10.tgz", - "integrity": "sha512-M1t5+Kj4IgSbYmunf2BB6EKLkWUq+XlqaFRiGOk8bmBapu9bCDrxjf4kUnWn59Dka3I27EiuHBKd1rSO4osLFQ==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.12.tgz", + "integrity": "sha512-z4zPX02tQ41kcXMyN3c/GfZpIjKoI/BzHrdKUwhC/Ki5BAhWv59A9M8H+iqaRbwpzYrYidTybBwiZAIWCLJAkw==", "cpu": [ "arm64" ], @@ -3788,9 +3799,9 @@ } }, "node_modules/esbuild-freebsd-64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.10.tgz", - "integrity": "sha512-KMBFMa7C8oc97nqDdoZwtDBX7gfpolkk6Bcmj6YFMrtCMVgoU/x2DI1p74DmYl7CSS6Ppa3xgemrLrr5IjIn0w==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.12.tgz", + "integrity": "sha512-XFL7gKMCKXLDiAiBjhLG0XECliXaRLTZh6hsyzqUqPUf/PY4C6EJDTKIeqqPKXaVJ8+fzNek88285krSz1QECw==", "cpu": [ "x64" ], @@ -3803,9 +3814,9 @@ } }, "node_modules/esbuild-freebsd-arm64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.10.tgz", - "integrity": "sha512-m2KNbuCX13yQqLlbSojFMHpewbn8wW5uDS6DxRpmaZKzyq8Dbsku6hHvh2U+BcLwWY4mpgXzFUoENEf7IcioGg==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.12.tgz", + "integrity": "sha512-jwEIu5UCUk6TjiG1X+KQnCGISI+ILnXzIzt9yDVrhjug2fkYzlLbl0K43q96Q3KB66v6N1UFF0r5Ks4Xo7i72g==", "cpu": [ "arm64" ], @@ -3818,9 +3829,9 @@ } }, "node_modules/esbuild-linux-32": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.10.tgz", - "integrity": "sha512-guXrwSYFAvNkuQ39FNeV4sNkNms1bLlA5vF1H0cazZBOLdLFIny6BhT+TUbK/hdByMQhtWQ5jI9VAmPKbVPu1w==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.12.tgz", + "integrity": "sha512-uSQuSEyF1kVzGzuIr4XM+v7TPKxHjBnLcwv2yPyCz8riV8VUCnO/C4BF3w5dHiVpCd5Z1cebBtZJNlC4anWpwA==", "cpu": [ "ia32" ], @@ -3833,9 +3844,9 @@ } }, "node_modules/esbuild-linux-64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.10.tgz", - "integrity": "sha512-jd8XfaSJeucMpD63YNMO1JCrdJhckHWcMv6O233bL4l6ogQKQOxBYSRP/XLWP+6kVTu0obXovuckJDcA0DKtQA==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.12.tgz", + "integrity": "sha512-QcgCKb7zfJxqT9o5z9ZUeGH1k8N6iX1Y7VNsEi5F9+HzN1OIx7ESxtQXDN9jbeUSPiRH1n9cw6gFT3H4qbdvcA==", "cpu": [ "x64" ], @@ -3848,9 +3859,9 @@ } }, "node_modules/esbuild-linux-arm": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.10.tgz", - "integrity": "sha512-6N8vThLL/Lysy9y4Ex8XoLQAlbZKUyExCWyayGi2KgTBelKpPgj6RZnUaKri0dHNPGgReJriKVU6+KDGQwn10A==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.12.tgz", + "integrity": "sha512-Wf7T0aNylGcLu7hBnzMvsTfEXdEdJY/hY3u36Vla21aY66xR0MS5I1Hw8nVquXjTN0A6fk/vnr32tkC/C2lb0A==", "cpu": [ "arm" ], @@ -3863,9 +3874,9 @@ } }, "node_modules/esbuild-linux-arm64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.10.tgz", - "integrity": "sha512-GByBi4fgkvZFTHFDYNftu1DQ1GzR23jws0oWyCfhnI7eMOe+wgwWrc78dbNk709Ivdr/evefm2PJiUBMiusS1A==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.12.tgz", + "integrity": "sha512-HtNq5xm8fUpZKwWKS2/YGwSfTF+339L4aIA8yphNKYJckd5hVdhfdl6GM2P3HwLSCORS++++7++//ApEwXEuAQ==", "cpu": [ "arm64" ], @@ -3878,9 +3889,9 @@ } }, "node_modules/esbuild-linux-mips64le": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.10.tgz", - "integrity": "sha512-BxP+LbaGVGIdQNJUNF7qpYjEGWb0YyHVSKqYKrn+pTwH/SiHUxFyJYSP3pqkku61olQiSBnSmWZ+YUpj78Tw7Q==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.12.tgz", + "integrity": "sha512-Qol3+AvivngUZkTVFgLpb0H6DT+N5/zM3V1YgTkryPYFeUvuT5JFNDR3ZiS6LxhyF8EE+fiNtzwlPqMDqVcc6A==", "cpu": [ "mips64el" ], @@ -3893,9 +3904,9 @@ } }, "node_modules/esbuild-linux-ppc64le": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.10.tgz", - "integrity": "sha512-LoSQCd6498PmninNgqd/BR7z3Bsk/mabImBWuQ4wQgmQEeanzWd5BQU2aNi9mBURCLgyheuZS6Xhrw5luw3OkQ==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.12.tgz", + "integrity": "sha512-4D8qUCo+CFKaR0cGXtGyVsOI7w7k93Qxb3KFXWr75An0DHamYzq8lt7TNZKoOq/Gh8c40/aKaxvcZnTgQ0TJNg==", "cpu": [ "ppc64" ], @@ -3908,9 +3919,9 @@ } }, "node_modules/esbuild-linux-riscv64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.10.tgz", - "integrity": "sha512-Lrl9Cr2YROvPV4wmZ1/g48httE8z/5SCiXIyebiB5N8VT7pX3t6meI7TQVHw/wQpqP/AF4SksDuFImPTM7Z32Q==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.12.tgz", + "integrity": "sha512-G9w6NcuuCI6TUUxe6ka0enjZHDnSVK8bO+1qDhMOCtl7Tr78CcZilJj8SGLN00zO5iIlwNRZKHjdMpfFgNn1VA==", "cpu": [ "riscv64" ], @@ -3923,9 +3934,9 @@ } }, "node_modules/esbuild-linux-s390x": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.10.tgz", - "integrity": "sha512-ReP+6q3eLVVP2lpRrvl5EodKX7EZ1bS1/z5j6hsluAlZP5aHhk6ghT6Cq3IANvvDdscMMCB4QEbI+AjtvoOFpA==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.12.tgz", + "integrity": "sha512-Lt6BDnuXbXeqSlVuuUM5z18GkJAZf3ERskGZbAWjrQoi9xbEIsj/hEzVnSAFLtkfLuy2DE4RwTcX02tZFunXww==", "cpu": [ "s390x" ], @@ -3957,9 +3968,9 @@ } }, "node_modules/esbuild-netbsd-64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.10.tgz", - "integrity": "sha512-iGDYtJCMCqldMskQ4eIV+QSS/CuT7xyy9i2/FjpKvxAuCzrESZXiA1L64YNj6/afuzfBe9i8m/uDkFHy257hTw==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.12.tgz", + "integrity": "sha512-jlUxCiHO1dsqoURZDQts+HK100o0hXfi4t54MNRMCAqKGAV33JCVvMplLAa2FwviSojT/5ZG5HUfG3gstwAG8w==", "cpu": [ "x64" ], @@ -3972,9 +3983,9 @@ } }, "node_modules/esbuild-openbsd-64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.10.tgz", - "integrity": "sha512-ftMMIwHWrnrYnvuJQRJs/Smlcb28F9ICGde/P3FUTCgDDM0N7WA0o9uOR38f5Xe2/OhNCgkjNeb7QeaE3cyWkQ==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.12.tgz", + "integrity": "sha512-1o1uAfRTMIWNOmpf8v7iudND0L6zRBYSH45sofCZywrcf7NcZA+c7aFsS1YryU+yN7aRppTqdUK1PgbZVaB1Dw==", "cpu": [ "x64" ], @@ -3987,9 +3998,9 @@ } }, "node_modules/esbuild-sunos-64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.10.tgz", - "integrity": "sha512-mf7hBL9Uo2gcy2r3rUFMjVpTaGpFJJE5QTDDqUFf1632FxteYANffDZmKbqX0PfeQ2XjUDE604IcE7OJeoHiyg==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.12.tgz", + "integrity": "sha512-nkl251DpoWoBO9Eq9aFdoIt2yYmp4I3kvQjba3jFKlMXuqQ9A4q+JaqdkCouG3DHgAGnzshzaGu6xofGcXyPXg==", "cpu": [ "x64" ], @@ -4002,9 +4013,9 @@ } }, "node_modules/esbuild-windows-32": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.10.tgz", - "integrity": "sha512-ttFVo+Cg8b5+qHmZHbEc8Vl17kCleHhLzgT8X04y8zudEApo0PxPg9Mz8Z2cKH1bCYlve1XL8LkyXGFjtUYeGg==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.12.tgz", + "integrity": "sha512-WlGeBZHgPC00O08luIp5B2SP4cNCp/PcS+3Pcg31kdcJPopHxLkdCXtadLU9J82LCfw4TVls21A6lilQ9mzHrw==", "cpu": [ "ia32" ], @@ -4017,9 +4028,9 @@ } }, "node_modules/esbuild-windows-64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.10.tgz", - "integrity": "sha512-2H0gdsyHi5x+8lbng3hLbxDWR7mKHWh5BXZGKVG830KUmXOOWFE2YKJ4tHRkejRduOGDrBvHBriYsGtmTv3ntA==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.12.tgz", + "integrity": "sha512-VActO3WnWZSN//xjSfbiGOSyC+wkZtI8I4KlgrTo5oHJM6z3MZZBCuFaZHd8hzf/W9KPhF0lY8OqlmWC9HO5AA==", "cpu": [ "x64" ], @@ -4032,9 +4043,9 @@ } }, "node_modules/esbuild-windows-arm64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.10.tgz", - "integrity": "sha512-S+th4F+F8VLsHLR0zrUcG+Et4hx0RKgK1eyHc08kztmLOES8BWwMiaGdoW9hiXuzznXQ0I/Fg904MNbr11Nktw==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.12.tgz", + "integrity": "sha512-Of3MIacva1OK/m4zCNIvBfz8VVROBmQT+gRX6pFTLPngFYcj6TFH/12VveAqq1k9VB2l28EoVMNMUCcmsfwyuA==", "cpu": [ "arm64" ], @@ -4151,14 +4162,15 @@ } }, "node_modules/eslint": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.25.0.tgz", - "integrity": "sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==", + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.26.0.tgz", + "integrity": "sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==", "dev": true, "dependencies": { "@eslint/eslintrc": "^1.3.3", - "@humanwhocodes/config-array": "^0.10.5", + "@humanwhocodes/config-array": "^0.11.6", "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -4174,14 +4186,14 @@ "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", - "glob-parent": "^6.0.1", + "glob-parent": "^6.0.2", "globals": "^13.15.0", - "globby": "^11.1.0", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", @@ -4314,12 +4326,12 @@ } }, "node_modules/eslint-plugin-sonarjs": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.15.0.tgz", - "integrity": "sha512-LuxHdAe6VqSbi1phsUvNjbmXLuvlobmryQJJNyQYbdubCfz6K8tmgoqNiJPnz0pP2AbYDbtuPm0ajOMgMrC+dQ==", + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.16.0.tgz", + "integrity": "sha512-al8ojAzcQW8Eu0tWn841ldhPpPcjrJ59TzzTfAVWR45bWvdAASCmrGl8vK0MWHyKVDdC0i17IGbtQQ1KgxLlVA==", "dev": true, "engines": { - "node": ">=12" + "node": ">=14" }, "peerDependencies": { "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" @@ -5231,9 +5243,9 @@ } }, "node_modules/immer": { - "version": "9.0.15", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz", - "integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==", + "version": "9.0.16", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.16.tgz", + "integrity": "sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ==", "dev": true, "funding": { "type": "opencollective", @@ -5422,9 +5434,9 @@ } }, "node_modules/is-core-module": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "dependencies": { "has": "^1.0.3" }, @@ -5509,6 +5521,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -5636,6 +5657,33 @@ "node": ">=0.10.0" } }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/joycon": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", @@ -5804,9 +5852,9 @@ "integrity": "sha512-b+z6yF1d4EOyDgylzQo5IminlUmzSeqR1hs/bzjBNjuGras4FXq/6TrzjxfN0j+TmI0ltJzTNlqXUMCniciwKQ==" }, "node_modules/katex": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.2.tgz", - "integrity": "sha512-70DJdQAyh9EMsthw3AaQlDyFf54X7nWEUIa5W+rq8XOpEk//w5Th7/8SqFqpvi/KZ2t6MHUj4f9wLmztBmAYQA==", + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.3.tgz", + "integrity": "sha512-3EykQddareoRmbtNiNEDgl3IGjryyrp2eg/25fHDEnlHymIDi33bptkMv6K4EOC2LZCybLW/ZkEo6Le+EM9pmA==", "funding": [ "https://opencollective.com/katex", "https://github.com/sponsors/katex" @@ -5889,28 +5937,6 @@ "webpack": "^5.0.0" } }, - "node_modules/less/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "optional": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/less/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "optional": true, - "bin": { - "semver": "bin/semver" - } - }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -6006,9 +6032,9 @@ } }, "node_modules/loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.3.tgz", + "integrity": "sha512-THWqIsn8QRnvLl0shHYVBN9syumU8pYWEHPTmkiVGd+7K5eFNVSY6AJhRvgGF70gg1Dz+l/k8WicvFCxdEs60A==", "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -6128,6 +6154,28 @@ "sourcemap-codec": "^1.4.8" } }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "optional": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/map-obj": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", @@ -6278,9 +6326,9 @@ } }, "node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", "dev": true }, "node_modules/mdurl": { @@ -6483,10 +6531,13 @@ } }, "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/minimist-options": { "version": "4.1.0", @@ -6508,9 +6559,9 @@ "integrity": "sha512-9ARkWHBs+6YJIvrIp0Ik5tyTTtP9PoV0Ssu2Ocq5y9v8+NOOpWiRshAp8c4rZVWTOe+157on/5G+zj5pwIQFEQ==" }, "node_modules/monaco-editor": { - "version": "0.34.0", - "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.34.0.tgz", - "integrity": "sha512-VF+S5zG8wxfinLKLrWcl4WUizMx+LeJrG4PM/M78OhcwocpV0jiyhX/pG6Q9jIOhrb/ckYi6nHnaR5OojlOZCQ==" + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.34.1.tgz", + "integrity": "sha512-FKc80TyiMaruhJKKPz5SpJPIjL+dflGvz4CpuThaPMc94AyN7SeC9HQ8hrvaxX7EyHdJcUY5i4D0gNyJj1vSZQ==" }, "node_modules/monaco-editor-webpack-plugin": { "version": "7.0.1", @@ -7097,9 +7148,9 @@ } }, "node_modules/playwright-core": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.27.0.tgz", - "integrity": "sha512-VBKaaFUVKDo3akW+o4DwbK1ZyXh46tcSwQKPK3lruh8IJd5feu55XVZx4vOkbb2uqrNdIF51sgsadYT533SdpA==", + "version": "1.27.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.27.1.tgz", + "integrity": "sha512-9EmeXDncC2Pmp/z+teoVYlvmPWUC6ejSSYZUln7YaP89Z6lpAaiaAnqroUt/BoLo8tn7WYShcfaCh+xofZa44Q==", "dev": true, "bin": { "playwright": "cli.js" @@ -7127,9 +7178,9 @@ } }, "node_modules/postcss": { - "version": "8.4.17", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.17.tgz", - "integrity": "sha512-UNxNOLQydcOFi41yHNMcKRZ39NeXlr8AxGuZJsdub8vIb12fHzcq37DTU/QtbI6WLxNg2gF9Z+8qtRwTj1UI1Q==", + "version": "8.4.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz", + "integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==", "funding": [ { "type": "opencollective", @@ -7766,9 +7817,23 @@ "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" }, "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/safe-regex": { "version": "2.1.1", @@ -8042,6 +8107,15 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/sourcemap-codec": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", @@ -8109,13 +8183,6 @@ "spdx-ranges": "^2.0.0" } }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", - "dev": true - }, "node_modules/stacktracey": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/stacktracey/-/stacktracey-2.1.8.tgz", @@ -8193,6 +8260,15 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -8236,9 +8312,9 @@ "dev": true }, "node_modules/stylelint": { - "version": "14.13.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.13.0.tgz", - "integrity": "sha512-NJSAdloiAB/jgVJKxMR90mWlctvmeBFGFVUvyKngi9+j/qPSJ5ZB+u8jOmGbLTnS7OHrII9NFGehPRyar8U5vg==", + "version": "14.14.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.14.0.tgz", + "integrity": "sha512-yUI+4xXfPHVnueYddSQ/e1GuEA/2wVhWQbGj16AmWLtQJtn28lVxfS4b0CsWyVRPgd3Auzi0NXOthIEUhtQmmA==", "dev": true, "dependencies": { "@csstools/selector-specificity": "^2.0.2", @@ -8264,7 +8340,7 @@ "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "picocolors": "^1.0.0", - "postcss": "^8.4.16", + "postcss": "^8.4.17", "postcss-media-query-parser": "^0.2.3", "postcss-resolve-nested-selector": "^0.1.1", "postcss-safe-parser": "^6.0.0", @@ -8301,15 +8377,15 @@ } }, "node_modules/stylelint-config-standard": { - "version": "28.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-28.0.0.tgz", - "integrity": "sha512-q/StuowDdDmFCravzGHAwgS9pjX0bdOQUEBBDIkIWsQuYGgYz/xsO8CM6eepmIQ1fc5bKdDVimlJZ6MoOUcJ5Q==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-29.0.0.tgz", + "integrity": "sha512-uy8tZLbfq6ZrXy4JKu3W+7lYLgRQBxYTUUB88vPgQ+ZzAxdrvcaSUW9hOMNLYBnwH+9Kkj19M2DHdZ4gKwI7tg==", "dev": true, "dependencies": { "stylelint-config-recommended": "^9.0.0" }, "peerDependencies": { - "stylelint": "^14.11.0" + "stylelint": "^14.14.0" } }, "node_modules/stylelint/node_modules/balanced-match": { @@ -8379,24 +8455,27 @@ "dev": true }, "node_modules/svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.0.0.tgz", + "integrity": "sha512-mSqPn6RDeNqJvCeqHERlfWJjd4crP/2PgFelil9WpTwC4D3okAUopPsH3lnEyl7ONXfDVyISOihDjO0uK8YVAA==", "dev": true, "dependencies": { "@trysound/sax": "0.2.0", "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" + "css-select": "^5.1.0", + "css-tree": "^2.2.1", + "csso": "^5.0.5", + "picocolors": "^1.0.0" }, "bin": { "svgo": "bin/svgo" }, "engines": { - "node": ">=10.13.0" + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" } }, "node_modules/svgo/node_modules/commander": { @@ -8409,9 +8488,9 @@ } }, "node_modules/swagger-ui-dist": { - "version": "4.14.2", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.14.2.tgz", - "integrity": "sha512-kOIU7Ts3TrXDLb3/c9jRe4qGp8O3bRT19FFJA8wJfrRFkcK/4atPn3krhtBVJ57ZkNNofworXHxuYwmaisXBdg==" + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.15.0.tgz", + "integrity": "sha512-vAsIdNHraLuBRm1vrxcMaLk/y/PGBTvHLf4lQGQ3LaEXkORtIxw11sBMpYJL3keOLaFJ1OqNXuURd6eShoFLZQ==" }, "node_modules/symbol-tree": { "version": "3.2.4", @@ -8516,19 +8595,6 @@ "ajv": "^6.9.1" } }, - "node_modules/terser-webpack-plugin/node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -8551,34 +8617,11 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/terser-webpack-plugin/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, - "node_modules/terser/node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -8586,9 +8629,9 @@ "dev": true }, "node_modules/tinybench": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.3.0.tgz", - "integrity": "sha512-zs1gMVBwyyG2QbVchYIbnabRhMOCGvrwZz/q+SV+LIMa9q5YDQZi2kkI6ZRqV2Bz7ba1uvrc7ieUoE4KWnGeKg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.3.1.tgz", + "integrity": "sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==", "dev": true }, "node_modules/tinypool": { @@ -8711,15 +8754,6 @@ "json5": "lib/cli.js" } }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/tslib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", @@ -8833,9 +8867,9 @@ } }, "node_modules/updates": { - "version": "13.1.8", - "resolved": "https://registry.npmjs.org/updates/-/updates-13.1.8.tgz", - "integrity": "sha512-hcDCkif1i4MWArx1QkJjLHyPCr8taYyzoypQ7ST/vbmNJyH/cpiawQf+5frvH5uekiSSwtuQNWKdFWB3UH4sew==", + "version": "13.1.10", + "resolved": "https://registry.npmjs.org/updates/-/updates-13.1.10.tgz", + "integrity": "sha512-YSt1ncMoBXAQZndhLwiywvEGHXmA4424SlAf2HMUDuf8qE9Tlqj0s6IANb388HrjkybdZJkaadLSg/hkigwnuQ==", "dev": true, "bin": { "updates": "bin/updates.js" @@ -8964,9 +8998,9 @@ } }, "node_modules/vitest": { - "version": "0.24.1", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.24.1.tgz", - "integrity": "sha512-NKkK1xnDIOOr42pKBfGQQl6b6IWdFVBpG6ZS1T+nUlJuqcOiZ7lxjVwHy9wrtTYpJ0BWww9y6bSGYXubD29Nag==", + "version": "0.24.3", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.24.3.tgz", + "integrity": "sha512-aM0auuPPgMSstWvr851hB74g/LKaKBzSxcG3da7ejfZbx08Y21JpZmbmDYrMTCGhVZKqTGwzcnLMwyfz2WzkhQ==", "dev": true, "dependencies": { "@types/chai": "^4.3.3", @@ -9032,15 +9066,15 @@ } }, "node_modules/vue": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.40.tgz", - "integrity": "sha512-1mGHulzUbl2Nk3pfvI5aXYYyJUs1nm4kyvuz38u4xlQkLUn1i2R7nDbI4TufECmY8v1qNBHYy62bCaM+3cHP2A==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.41.tgz", + "integrity": "sha512-uuuvnrDXEeZ9VUPljgHkqB5IaVO8SxhPpqF2eWOukVrBnRBx2THPSGQBnVRt0GrIG1gvCmFXMGbd7FqcT1ixNQ==", "dependencies": { - "@vue/compiler-dom": "3.2.40", - "@vue/compiler-sfc": "3.2.40", - "@vue/runtime-dom": "3.2.40", - "@vue/server-renderer": "3.2.40", - "@vue/shared": "3.2.40" + "@vue/compiler-dom": "3.2.41", + "@vue/compiler-sfc": "3.2.41", + "@vue/runtime-dom": "3.2.41", + "@vue/server-renderer": "3.2.41", + "@vue/shared": "3.2.41" } }, "node_modules/vue-bar-graph": { @@ -9529,9 +9563,9 @@ } }, "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.1.tgz", - "integrity": "sha512-qDOv24WjnYuL+wbwHdlsYZFy+cgPtrYw0Tn7GLORicQp9BkQLzrgI3Pm4VyR9ERZ41YTn7KlMPuL1n05WdZvmg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "engines": { "node": ">=12" }, @@ -9802,14 +9836,14 @@ } }, "@babel/parser": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.3.tgz", - "integrity": "sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ==" + "version": "7.19.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.6.tgz", + "integrity": "sha512-h1IUp81s2JYJ3mRkdxJgs4UvmSsRvDrx5ICSJbPvtWYv5i1nTBGcBpnog+89rAFMwvvru6E5NUHdBe01UeSzYA==" }, "@braintree/sanitize-url": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.0.tgz", - "integrity": "sha512-mgmE7XBYY/21erpzhexk4Cj1cyTQ9LzvnTxtzM17BJ7ERMNE6W72mQRo0I1Ud8eFJ+RVVIcBNhLFZ3GX4XFz5w==" + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.1.tgz", + "integrity": "sha512-zr9Qs9KFQiEvMWdZesjcmRJlUck5NR+eKGS1uyKk+oYTWwlYrsoPEi6VmG6/TzBD1hKCGEimrhTgGS6hvn/xIQ==" }, "@claviska/jquery-minicolors": { "version": "2.3.6", @@ -9830,15 +9864,15 @@ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==" }, "@esbuild/android-arm": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.10.tgz", - "integrity": "sha512-FNONeQPy/ox+5NBkcSbYJxoXj9GWu8gVGJTVmUyoOCKQFDTrHVKgNSzChdNt0I8Aj/iKcsDf2r9BFwv+FSNUXg==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.12.tgz", + "integrity": "sha512-IC7TqIqiyE0MmvAhWkl/8AEzpOtbhRNDo7aph47We1NbE5w2bt/Q+giAhe0YYeVpYnIhGMcuZY92qDK6dQauvA==", "optional": true }, "@esbuild/linux-loong64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.10.tgz", - "integrity": "sha512-w0Ou3Z83LOYEkwaui2M8VwIp+nLi/NA60lBLMvaJ+vXVMcsARYdEzLNE7RSm4+lSg4zq4d7fAVuzk7PNQ5JFgg==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.12.tgz", + "integrity": "sha512-tZEowDjvU7O7I04GYvWQOS4yyP9E/7YlsB0jjw1Ycukgr2ycEzKyIk5tms5WnLBymaewc6VmRKnn5IJWgK4eFw==", "optional": true }, "@eslint/eslintrc": { @@ -9879,9 +9913,9 @@ } }, "@humanwhocodes/config-array": { - "version": "0.10.7", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", - "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.6.tgz", + "integrity": "sha512-jJr+hPTJYKyDILJfhNSHsjiwXYf26Flsz8DvNndOsHs5pwSnpGUEy8yzF0JYhCEvTDdV2vuOK5tt8BVhwO5/hg==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", @@ -9901,6 +9935,16 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, "@jridgewell/resolve-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", @@ -9918,18 +9962,6 @@ "requires": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } } }, "@jridgewell/sourcemap-codec": { @@ -9938,9 +9970,9 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "@jridgewell/trace-mapping": { - "version": "0.3.16", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.16.tgz", - "integrity": "sha512-LCQ+NeThyJ4k1W2d+vIKdxuSt9R3pQSZ4P92m7EakaYuXcVWbHuT5bjNcqLd4Rdgi6xYWYDvBJZJLZSLanjDcA==", + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", "requires": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" @@ -9997,13 +10029,13 @@ } }, "@playwright/test": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.27.0.tgz", - "integrity": "sha512-L4BswoJvGkFsEHhEgzVNHBnkFB1FbnBQn3QmvTl7+AouoJQ4a8tLwZKvytdovCsNi7B5cXuRo58yGvfM5PnExw==", + "version": "1.27.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.27.1.tgz", + "integrity": "sha512-mrL2q0an/7tVqniQQF6RBL2saskjljXzqNcCOVMUjRIgE6Y38nCNaP+Dc2FBW06bcpD3tqIws/HT9qiMHbNU0A==", "dev": true, "requires": { "@types/node": "*", - "playwright-core": "1.27.0" + "playwright-core": "1.27.1" } }, "@popperjs/core": { @@ -10052,26 +10084,24 @@ "dev": true } } + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true } } }, "@rollup/pluginutils": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.1.tgz", - "integrity": "sha512-4HaCVEXXuObvcPUaUlLt4faHYHCeQOOWNj8NKFGaRSrw3ZLD0TWeAFZicV9vXjnE2nkNuaVTfTuwAnjR+6uc9A==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", + "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", "dev": true, "requires": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^2.3.1" - }, - "dependencies": { - "@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", - "dev": true - } } }, "@stoplight/better-ajv-errors": { @@ -10202,9 +10232,9 @@ } }, "@stoplight/spectral-core": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-core/-/spectral-core-1.14.2.tgz", - "integrity": "sha512-W2Z31lasEICpZS50STFskOdkn4g0Va81XA1A88LIj9mvlctDFf4BfpjLgIjKkI4f2DEK5C4j3COcbbzV8y5Xig==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-core/-/spectral-core-1.15.0.tgz", + "integrity": "sha512-+DwK8SmnujMZJaxJeNU11vWY+DFOnt4oQM1TzAuvufdd3Y6Lsno88Jl31OaR1M9Fn7l/u3v1anBB/SSl/fI5rQ==", "dev": true, "requires": { "@stoplight/better-ajv-errors": "1.0.3", @@ -10366,9 +10396,9 @@ } }, "@stoplight/spectral-ruleset-bundler": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-ruleset-bundler/-/spectral-ruleset-bundler-1.3.2.tgz", - "integrity": "sha512-sy7mHVBwmo5/8dUlnWiel2UND1Mnu3x+okBAgLmkGcIpXz74rMmVY3h5vT6rjxw65WZ3/c3mtm1dRQuSe+q5fw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-ruleset-bundler/-/spectral-ruleset-bundler-1.3.3.tgz", + "integrity": "sha512-hfHl7XZeF/wWMpSrsLqLnH2GevRHjSIqtBL2aRjO2SjMCTbO9LVz80p4sYaxrCcu4wQ6K71gMZXsG687+3fAeg==", "dev": true, "requires": { "@rollup/plugin-commonjs": "~22.0.2", @@ -10432,13 +10462,19 @@ "@types/json-schema": "^7.0.4", "utility-types": "^3.10.0" } + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true } } }, "@stoplight/spectral-ruleset-migrator": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-ruleset-migrator/-/spectral-ruleset-migrator-1.7.4.tgz", - "integrity": "sha512-QySMWSvGUC5D8cNDvXhrXEY0a4DB5hewHwjxXbwlH51fVNiVKJ4+KcaCW3s2yAT4T1p6/ij8NkLX9T81D4vSCg==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-ruleset-migrator/-/spectral-ruleset-migrator-1.8.0.tgz", + "integrity": "sha512-zg6RPF+d8uS7zAp5TzUph3hQG4sgGcG5Fsw8Zx24H1REyuSkjiIfyee2Kf13c3BcIlTXvnFc4csz2rNXpZO7Ug==", "dev": true, "requires": { "@stoplight/json": "~3.20.1", @@ -10622,9 +10658,9 @@ } }, "@types/eslint": { - "version": "8.4.6", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.6.tgz", - "integrity": "sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g==", + "version": "8.4.7", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.7.tgz", + "integrity": "sha512-ehM7cCt2RSFs42mb+lcmhFT9ouIlV92PuaeRGn8N8c98oMjG4Z5pJHA9b1QiCcuqnbPSHcyfiD3mlhqMaHsQIw==", "requires": { "@types/estree": "*", "@types/json-schema": "*" @@ -10640,9 +10676,9 @@ } }, "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", + "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==" }, "@types/json-schema": { "version": "7.0.11", @@ -10667,9 +10703,9 @@ "dev": true }, "@types/node": { - "version": "18.8.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.3.tgz", - "integrity": "sha512-0os9vz6BpGwxGe9LOhgP/ncvYN5Tx1fNcd2TM3rD/aCGBkysb+ZWpXEocG24h6ZzOi13+VB8HndAQFezsSOw1w==" + "version": "18.11.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.4.tgz", + "integrity": "sha512-BxcJpBu8D3kv/GZkx/gSMz6VnTJREBj/4lbzYOQueUOELkt8WrO6zAcSPmp9uRPEW/d+lUO8QK0W2xnS1hEU0A==" }, "@types/normalize-package-data": { "version": "2.4.1", @@ -10698,36 +10734,36 @@ "dev": true }, "@vue/compiler-core": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.40.tgz", - "integrity": "sha512-2Dc3Stk0J/VyQ4OUr2yEC53kU28614lZS+bnrCbFSAIftBJ40g/2yQzf4mPBiFuqguMB7hyHaujdgZAQ67kZYA==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.41.tgz", + "integrity": "sha512-oA4mH6SA78DT+96/nsi4p9DX97PHcNROxs51lYk7gb9Z4BPKQ3Mh+BLn6CQZBw857Iuhu28BfMSRHAlPvD4vlw==", "requires": { "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.40", + "@vue/shared": "3.2.41", "estree-walker": "^2.0.2", "source-map": "^0.6.1" } }, "@vue/compiler-dom": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.40.tgz", - "integrity": "sha512-OZCNyYVC2LQJy4H7h0o28rtk+4v+HMQygRTpmibGoG9wZyomQiS5otU7qo3Wlq5UfHDw2RFwxb9BJgKjVpjrQw==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.41.tgz", + "integrity": "sha512-xe5TbbIsonjENxJsYRbDJvthzqxLNk+tb3d/c47zgREDa/PCp6/Y4gC/skM4H6PIuX5DAxm7fFJdbjjUH2QTMw==", "requires": { - "@vue/compiler-core": "3.2.40", - "@vue/shared": "3.2.40" + "@vue/compiler-core": "3.2.41", + "@vue/shared": "3.2.41" } }, "@vue/compiler-sfc": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.40.tgz", - "integrity": "sha512-tzqwniIN1fu1PDHC3CpqY/dPCfN/RN1thpBC+g69kJcrl7mbGiHKNwbA6kJ3XKKy8R6JLKqcpVugqN4HkeBFFg==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.41.tgz", + "integrity": "sha512-+1P2m5kxOeaxVmJNXnBskAn3BenbTmbxBxWOtBq3mQTCokIreuMULFantBUclP0+KnzNCMOvcnKinqQZmiOF8w==", "requires": { "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.40", - "@vue/compiler-dom": "3.2.40", - "@vue/compiler-ssr": "3.2.40", - "@vue/reactivity-transform": "3.2.40", - "@vue/shared": "3.2.40", + "@vue/compiler-core": "3.2.41", + "@vue/compiler-dom": "3.2.41", + "@vue/compiler-ssr": "3.2.41", + "@vue/reactivity-transform": "3.2.41", + "@vue/shared": "3.2.41", "estree-walker": "^2.0.2", "magic-string": "^0.25.7", "postcss": "^8.1.10", @@ -10735,66 +10771,66 @@ } }, "@vue/compiler-ssr": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.40.tgz", - "integrity": "sha512-80cQcgasKjrPPuKcxwuCx7feq+wC6oFl5YaKSee9pV3DNq+6fmCVwEEC3vvkf/E2aI76rIJSOYHsWSEIxK74oQ==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.41.tgz", + "integrity": "sha512-Y5wPiNIiaMz/sps8+DmhaKfDm1xgj6GrH99z4gq2LQenfVQcYXmHIOBcs5qPwl7jaW3SUQWjkAPKMfQemEQZwQ==", "requires": { - "@vue/compiler-dom": "3.2.40", - "@vue/shared": "3.2.40" + "@vue/compiler-dom": "3.2.41", + "@vue/shared": "3.2.41" } }, "@vue/reactivity": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.40.tgz", - "integrity": "sha512-N9qgGLlZmtUBMHF9xDT4EkD9RdXde1Xbveb+niWMXuHVWQP5BzgRmE3SFyUBBcyayG4y1lhoz+lphGRRxxK4RA==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.41.tgz", + "integrity": "sha512-9JvCnlj8uc5xRiQGZ28MKGjuCoPhhTwcoAdv3o31+cfGgonwdPNuvqAXLhlzu4zwqavFEG5tvaoINQEfxz+l6g==", "requires": { - "@vue/shared": "3.2.40" + "@vue/shared": "3.2.41" } }, "@vue/reactivity-transform": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.40.tgz", - "integrity": "sha512-HQUCVwEaacq6fGEsg2NUuGKIhUveMCjOk8jGHqLXPI2w6zFoPrlQhwWEaINTv5kkZDXKEnCijAp+4gNEHG03yw==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.41.tgz", + "integrity": "sha512-mK5+BNMsL4hHi+IR3Ft/ho6Za+L3FA5j8WvreJ7XzHrqkPq8jtF/SMo7tuc9gHjLDwKZX1nP1JQOKo9IEAn54A==", "requires": { "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.40", - "@vue/shared": "3.2.40", + "@vue/compiler-core": "3.2.41", + "@vue/shared": "3.2.41", "estree-walker": "^2.0.2", "magic-string": "^0.25.7" } }, "@vue/runtime-core": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.40.tgz", - "integrity": "sha512-U1+rWf0H8xK8aBUZhnrN97yoZfHbjgw/bGUzfgKPJl69/mXDuSg8CbdBYBn6VVQdR947vWneQBFzdhasyzMUKg==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.41.tgz", + "integrity": "sha512-0LBBRwqnI0p4FgIkO9q2aJBBTKDSjzhnxrxHYengkAF6dMOjeAIZFDADAlcf2h3GDALWnblbeprYYpItiulSVQ==", "requires": { - "@vue/reactivity": "3.2.40", - "@vue/shared": "3.2.40" + "@vue/reactivity": "3.2.41", + "@vue/shared": "3.2.41" } }, "@vue/runtime-dom": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.40.tgz", - "integrity": "sha512-AO2HMQ+0s2+MCec8hXAhxMgWhFhOPJ/CyRXnmTJ6XIOnJFLrH5Iq3TNwvVcODGR295jy77I6dWPj+wvFoSYaww==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.41.tgz", + "integrity": "sha512-U7zYuR1NVIP8BL6jmOqmapRAHovEFp7CSw4pR2FacqewXNGqZaRfHoNLQsqQvVQ8yuZNZtxSZy0FFyC70YXPpA==", "requires": { - "@vue/runtime-core": "3.2.40", - "@vue/shared": "3.2.40", + "@vue/runtime-core": "3.2.41", + "@vue/shared": "3.2.41", "csstype": "^2.6.8" } }, "@vue/server-renderer": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.40.tgz", - "integrity": "sha512-gtUcpRwrXOJPJ4qyBpU3EyxQa4EkV8I4f8VrDePcGCPe4O/hd0BPS7v9OgjIQob6Ap8VDz9G+mGTKazE45/95w==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.41.tgz", + "integrity": "sha512-7YHLkfJdTlsZTV0ae5sPwl9Gn/EGr2hrlbcS/8naXm2CDpnKUwC68i1wGlrYAfIgYWL7vUZwk2GkYLQH5CvFig==", "requires": { - "@vue/compiler-ssr": "3.2.40", - "@vue/shared": "3.2.40" + "@vue/compiler-ssr": "3.2.41", + "@vue/shared": "3.2.41" } }, "@vue/shared": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.40.tgz", - "integrity": "sha512-0PLQ6RUtZM0vO3teRfzGi4ltLUO5aO+kLgwh4Um3THSR03rpQWLTuRCkuO5A41ITzwdWeKdPHtSARuPkoo5pCQ==" + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.41.tgz", + "integrity": "sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw==" }, "@webassemblyjs/ast": { "version": "1.11.1", @@ -10973,9 +11009,9 @@ } }, "acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==" + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==" }, "acorn-globals": { "version": "7.0.1", @@ -11272,9 +11308,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001418", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001418.tgz", - "integrity": "sha512-oIs7+JL3K9JRQ3jPZjlH6qyYDp+nBTCais7hjh0s+fuBwufc7uZ7hPYMXrDOJhV360KGMTcczMRObk0/iMqZRg==" + "version": "1.0.30001423", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001423.tgz", + "integrity": "sha512-09iwWGOlifvE1XuHokFMP7eR38a0JnajoyL3/i87c8ZjRWRrdKo1fqjNfugfBD0UDBIOz0U+jtNhJ0EPm1VleQ==" }, "chai": { "version": "4.3.6", @@ -11499,26 +11535,26 @@ } }, "css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", "dev": true, "requires": { "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", "dev": true, "requires": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" } }, "css-what": { @@ -11533,12 +11569,12 @@ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" }, "csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", "dev": true, "requires": { - "css-tree": "^1.1.2" + "css-tree": "~2.2.0" } }, "cssom": { @@ -12189,9 +12225,9 @@ } }, "decimal.js": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.1.tgz", - "integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==", + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.2.tgz", + "integrity": "sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==", "dev": true }, "deep-eql": { @@ -12351,20 +12387,20 @@ } }, "dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dev": true, "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" }, "dependencies": { "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", "dev": true } } @@ -12385,12 +12421,12 @@ } }, "domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dev": true, "requires": { - "domelementtype": "^2.2.0" + "domelementtype": "^2.3.0" } }, "dompurify": { @@ -12399,14 +12435,14 @@ "integrity": "sha512-Be9tbQMZds4a3C6xTmz68NlMfeONA//4dOavl/1rNw50E+/QO0KVpbcU0PcaW0nsQxurXls9ZocqFxk8R2mWEA==" }, "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", + "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", "dev": true, "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.1" } }, "dropzone": { @@ -12436,9 +12472,9 @@ } }, "electron-to-chromium": { - "version": "1.4.276", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.276.tgz", - "integrity": "sha512-EpuHPqu8YhonqLBXHoU6hDJCD98FCe6KDoet3/gY1qsQ6usjJoHqBH2YIVs8FXaAtHwVL8Uqa/fsYao/vq9VWQ==" + "version": "1.4.284", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", + "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==" }, "emoji-regex": { "version": "8.0.0", @@ -12567,116 +12603,116 @@ } }, "esbuild": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.10.tgz", - "integrity": "sha512-N7wBhfJ/E5fzn/SpNgX+oW2RLRjwaL8Y0ezqNqhjD6w0H2p0rDuEz2FKZqpqLnO8DCaWumKe8dsC/ljvVSSxng==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.12.tgz", + "integrity": "sha512-PcT+/wyDqJQsRVhaE9uX/Oq4XLrFh0ce/bs2TJh4CSaw9xuvI+xFrH2nAYOADbhQjUgAhNWC5LKoUsakm4dxng==", "requires": { - "@esbuild/android-arm": "0.15.10", - "@esbuild/linux-loong64": "0.15.10", - "esbuild-android-64": "0.15.10", - "esbuild-android-arm64": "0.15.10", - "esbuild-darwin-64": "0.15.10", - "esbuild-darwin-arm64": "0.15.10", - "esbuild-freebsd-64": "0.15.10", - "esbuild-freebsd-arm64": "0.15.10", - "esbuild-linux-32": "0.15.10", - "esbuild-linux-64": "0.15.10", - "esbuild-linux-arm": "0.15.10", - "esbuild-linux-arm64": "0.15.10", - "esbuild-linux-mips64le": "0.15.10", - "esbuild-linux-ppc64le": "0.15.10", - "esbuild-linux-riscv64": "0.15.10", - "esbuild-linux-s390x": "0.15.10", - "esbuild-netbsd-64": "0.15.10", - "esbuild-openbsd-64": "0.15.10", - "esbuild-sunos-64": "0.15.10", - "esbuild-windows-32": "0.15.10", - "esbuild-windows-64": "0.15.10", - "esbuild-windows-arm64": "0.15.10" + "@esbuild/android-arm": "0.15.12", + "@esbuild/linux-loong64": "0.15.12", + "esbuild-android-64": "0.15.12", + "esbuild-android-arm64": "0.15.12", + "esbuild-darwin-64": "0.15.12", + "esbuild-darwin-arm64": "0.15.12", + "esbuild-freebsd-64": "0.15.12", + "esbuild-freebsd-arm64": "0.15.12", + "esbuild-linux-32": "0.15.12", + "esbuild-linux-64": "0.15.12", + "esbuild-linux-arm": "0.15.12", + "esbuild-linux-arm64": "0.15.12", + "esbuild-linux-mips64le": "0.15.12", + "esbuild-linux-ppc64le": "0.15.12", + "esbuild-linux-riscv64": "0.15.12", + "esbuild-linux-s390x": "0.15.12", + "esbuild-netbsd-64": "0.15.12", + "esbuild-openbsd-64": "0.15.12", + "esbuild-sunos-64": "0.15.12", + "esbuild-windows-32": "0.15.12", + "esbuild-windows-64": "0.15.12", + "esbuild-windows-arm64": "0.15.12" } }, "esbuild-android-64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.10.tgz", - "integrity": "sha512-UI7krF8OYO1N7JYTgLT9ML5j4+45ra3amLZKx7LO3lmLt1Ibn8t3aZbX5Pu4BjWiqDuJ3m/hsvhPhK/5Y/YpnA==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.12.tgz", + "integrity": "sha512-MJKXwvPY9g0rGps0+U65HlTsM1wUs9lbjt5CU19RESqycGFDRijMDQsh68MtbzkqWSRdEtiKS1mtPzKneaAI0Q==", "optional": true }, "esbuild-android-arm64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.10.tgz", - "integrity": "sha512-EOt55D6xBk5O05AK8brXUbZmoFj4chM8u3riGflLa6ziEoVvNjRdD7Cnp82NHQGfSHgYR06XsPI8/sMuA/cUwg==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.12.tgz", + "integrity": "sha512-Hc9SEcZbIMhhLcvhr1DH+lrrec9SFTiRzfJ7EGSBZiiw994gfkVV6vG0sLWqQQ6DD7V4+OggB+Hn0IRUdDUqvA==", "optional": true }, "esbuild-darwin-64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.10.tgz", - "integrity": "sha512-hbDJugTicqIm+WKZgp208d7FcXcaK8j2c0l+fqSJ3d2AzQAfjEYDRM3Z2oMeqSJ9uFxyj/muSACLdix7oTstRA==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.12.tgz", + "integrity": "sha512-qkmqrTVYPFiePt5qFjP8w/S+GIUMbt6k8qmiPraECUWfPptaPJUGkCKrWEfYFRWB7bY23FV95rhvPyh/KARP8Q==", "optional": true }, "esbuild-darwin-arm64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.10.tgz", - "integrity": "sha512-M1t5+Kj4IgSbYmunf2BB6EKLkWUq+XlqaFRiGOk8bmBapu9bCDrxjf4kUnWn59Dka3I27EiuHBKd1rSO4osLFQ==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.12.tgz", + "integrity": "sha512-z4zPX02tQ41kcXMyN3c/GfZpIjKoI/BzHrdKUwhC/Ki5BAhWv59A9M8H+iqaRbwpzYrYidTybBwiZAIWCLJAkw==", "optional": true }, "esbuild-freebsd-64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.10.tgz", - "integrity": "sha512-KMBFMa7C8oc97nqDdoZwtDBX7gfpolkk6Bcmj6YFMrtCMVgoU/x2DI1p74DmYl7CSS6Ppa3xgemrLrr5IjIn0w==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.12.tgz", + "integrity": "sha512-XFL7gKMCKXLDiAiBjhLG0XECliXaRLTZh6hsyzqUqPUf/PY4C6EJDTKIeqqPKXaVJ8+fzNek88285krSz1QECw==", "optional": true }, "esbuild-freebsd-arm64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.10.tgz", - "integrity": "sha512-m2KNbuCX13yQqLlbSojFMHpewbn8wW5uDS6DxRpmaZKzyq8Dbsku6hHvh2U+BcLwWY4mpgXzFUoENEf7IcioGg==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.12.tgz", + "integrity": "sha512-jwEIu5UCUk6TjiG1X+KQnCGISI+ILnXzIzt9yDVrhjug2fkYzlLbl0K43q96Q3KB66v6N1UFF0r5Ks4Xo7i72g==", "optional": true }, "esbuild-linux-32": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.10.tgz", - "integrity": "sha512-guXrwSYFAvNkuQ39FNeV4sNkNms1bLlA5vF1H0cazZBOLdLFIny6BhT+TUbK/hdByMQhtWQ5jI9VAmPKbVPu1w==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.12.tgz", + "integrity": "sha512-uSQuSEyF1kVzGzuIr4XM+v7TPKxHjBnLcwv2yPyCz8riV8VUCnO/C4BF3w5dHiVpCd5Z1cebBtZJNlC4anWpwA==", "optional": true }, "esbuild-linux-64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.10.tgz", - "integrity": "sha512-jd8XfaSJeucMpD63YNMO1JCrdJhckHWcMv6O233bL4l6ogQKQOxBYSRP/XLWP+6kVTu0obXovuckJDcA0DKtQA==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.12.tgz", + "integrity": "sha512-QcgCKb7zfJxqT9o5z9ZUeGH1k8N6iX1Y7VNsEi5F9+HzN1OIx7ESxtQXDN9jbeUSPiRH1n9cw6gFT3H4qbdvcA==", "optional": true }, "esbuild-linux-arm": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.10.tgz", - "integrity": "sha512-6N8vThLL/Lysy9y4Ex8XoLQAlbZKUyExCWyayGi2KgTBelKpPgj6RZnUaKri0dHNPGgReJriKVU6+KDGQwn10A==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.12.tgz", + "integrity": "sha512-Wf7T0aNylGcLu7hBnzMvsTfEXdEdJY/hY3u36Vla21aY66xR0MS5I1Hw8nVquXjTN0A6fk/vnr32tkC/C2lb0A==", "optional": true }, "esbuild-linux-arm64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.10.tgz", - "integrity": "sha512-GByBi4fgkvZFTHFDYNftu1DQ1GzR23jws0oWyCfhnI7eMOe+wgwWrc78dbNk709Ivdr/evefm2PJiUBMiusS1A==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.12.tgz", + "integrity": "sha512-HtNq5xm8fUpZKwWKS2/YGwSfTF+339L4aIA8yphNKYJckd5hVdhfdl6GM2P3HwLSCORS++++7++//ApEwXEuAQ==", "optional": true }, "esbuild-linux-mips64le": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.10.tgz", - "integrity": "sha512-BxP+LbaGVGIdQNJUNF7qpYjEGWb0YyHVSKqYKrn+pTwH/SiHUxFyJYSP3pqkku61olQiSBnSmWZ+YUpj78Tw7Q==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.12.tgz", + "integrity": "sha512-Qol3+AvivngUZkTVFgLpb0H6DT+N5/zM3V1YgTkryPYFeUvuT5JFNDR3ZiS6LxhyF8EE+fiNtzwlPqMDqVcc6A==", "optional": true }, "esbuild-linux-ppc64le": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.10.tgz", - "integrity": "sha512-LoSQCd6498PmninNgqd/BR7z3Bsk/mabImBWuQ4wQgmQEeanzWd5BQU2aNi9mBURCLgyheuZS6Xhrw5luw3OkQ==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.12.tgz", + "integrity": "sha512-4D8qUCo+CFKaR0cGXtGyVsOI7w7k93Qxb3KFXWr75An0DHamYzq8lt7TNZKoOq/Gh8c40/aKaxvcZnTgQ0TJNg==", "optional": true }, "esbuild-linux-riscv64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.10.tgz", - "integrity": "sha512-Lrl9Cr2YROvPV4wmZ1/g48httE8z/5SCiXIyebiB5N8VT7pX3t6meI7TQVHw/wQpqP/AF4SksDuFImPTM7Z32Q==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.12.tgz", + "integrity": "sha512-G9w6NcuuCI6TUUxe6ka0enjZHDnSVK8bO+1qDhMOCtl7Tr78CcZilJj8SGLN00zO5iIlwNRZKHjdMpfFgNn1VA==", "optional": true }, "esbuild-linux-s390x": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.10.tgz", - "integrity": "sha512-ReP+6q3eLVVP2lpRrvl5EodKX7EZ1bS1/z5j6hsluAlZP5aHhk6ghT6Cq3IANvvDdscMMCB4QEbI+AjtvoOFpA==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.12.tgz", + "integrity": "sha512-Lt6BDnuXbXeqSlVuuUM5z18GkJAZf3ERskGZbAWjrQoi9xbEIsj/hEzVnSAFLtkfLuy2DE4RwTcX02tZFunXww==", "optional": true }, "esbuild-loader": { @@ -12693,39 +12729,39 @@ } }, "esbuild-netbsd-64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.10.tgz", - "integrity": "sha512-iGDYtJCMCqldMskQ4eIV+QSS/CuT7xyy9i2/FjpKvxAuCzrESZXiA1L64YNj6/afuzfBe9i8m/uDkFHy257hTw==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.12.tgz", + "integrity": "sha512-jlUxCiHO1dsqoURZDQts+HK100o0hXfi4t54MNRMCAqKGAV33JCVvMplLAa2FwviSojT/5ZG5HUfG3gstwAG8w==", "optional": true }, "esbuild-openbsd-64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.10.tgz", - "integrity": "sha512-ftMMIwHWrnrYnvuJQRJs/Smlcb28F9ICGde/P3FUTCgDDM0N7WA0o9uOR38f5Xe2/OhNCgkjNeb7QeaE3cyWkQ==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.12.tgz", + "integrity": "sha512-1o1uAfRTMIWNOmpf8v7iudND0L6zRBYSH45sofCZywrcf7NcZA+c7aFsS1YryU+yN7aRppTqdUK1PgbZVaB1Dw==", "optional": true }, "esbuild-sunos-64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.10.tgz", - "integrity": "sha512-mf7hBL9Uo2gcy2r3rUFMjVpTaGpFJJE5QTDDqUFf1632FxteYANffDZmKbqX0PfeQ2XjUDE604IcE7OJeoHiyg==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.12.tgz", + "integrity": "sha512-nkl251DpoWoBO9Eq9aFdoIt2yYmp4I3kvQjba3jFKlMXuqQ9A4q+JaqdkCouG3DHgAGnzshzaGu6xofGcXyPXg==", "optional": true }, "esbuild-windows-32": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.10.tgz", - "integrity": "sha512-ttFVo+Cg8b5+qHmZHbEc8Vl17kCleHhLzgT8X04y8zudEApo0PxPg9Mz8Z2cKH1bCYlve1XL8LkyXGFjtUYeGg==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.12.tgz", + "integrity": "sha512-WlGeBZHgPC00O08luIp5B2SP4cNCp/PcS+3Pcg31kdcJPopHxLkdCXtadLU9J82LCfw4TVls21A6lilQ9mzHrw==", "optional": true }, "esbuild-windows-64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.10.tgz", - "integrity": "sha512-2H0gdsyHi5x+8lbng3hLbxDWR7mKHWh5BXZGKVG830KUmXOOWFE2YKJ4tHRkejRduOGDrBvHBriYsGtmTv3ntA==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.12.tgz", + "integrity": "sha512-VActO3WnWZSN//xjSfbiGOSyC+wkZtI8I4KlgrTo5oHJM6z3MZZBCuFaZHd8hzf/W9KPhF0lY8OqlmWC9HO5AA==", "optional": true }, "esbuild-windows-arm64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.10.tgz", - "integrity": "sha512-S+th4F+F8VLsHLR0zrUcG+Et4hx0RKgK1eyHc08kztmLOES8BWwMiaGdoW9hiXuzznXQ0I/Fg904MNbr11Nktw==", + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.12.tgz", + "integrity": "sha512-Of3MIacva1OK/m4zCNIvBfz8VVROBmQT+gRX6pFTLPngFYcj6TFH/12VveAqq1k9VB2l28EoVMNMUCcmsfwyuA==", "optional": true }, "escalade": { @@ -12799,14 +12835,15 @@ } }, "eslint": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.25.0.tgz", - "integrity": "sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==", + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.26.0.tgz", + "integrity": "sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==", "dev": true, "requires": { "@eslint/eslintrc": "^1.3.3", - "@humanwhocodes/config-array": "^0.10.5", + "@humanwhocodes/config-array": "^0.11.6", "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -12822,14 +12859,14 @@ "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", - "glob-parent": "^6.0.1", + "glob-parent": "^6.0.2", "globals": "^13.15.0", - "globby": "^11.1.0", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", @@ -12960,9 +12997,9 @@ "requires": {} }, "eslint-plugin-sonarjs": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.15.0.tgz", - "integrity": "sha512-LuxHdAe6VqSbi1phsUvNjbmXLuvlobmryQJJNyQYbdubCfz6K8tmgoqNiJPnz0pP2AbYDbtuPm0ajOMgMrC+dQ==", + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.16.0.tgz", + "integrity": "sha512-al8ojAzcQW8Eu0tWn841ldhPpPcjrJ59TzzTfAVWR45bWvdAASCmrGl8vK0MWHyKVDdC0i17IGbtQQ1KgxLlVA==", "dev": true, "requires": {} }, @@ -13616,9 +13653,9 @@ "optional": true }, "immer": { - "version": "9.0.15", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz", - "integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==", + "version": "9.0.16", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.16.tgz", + "integrity": "sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ==", "dev": true }, "import-fresh": { @@ -13746,9 +13783,9 @@ "dev": true }, "is-core-module": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "requires": { "has": "^1.0.3" } @@ -13800,6 +13837,12 @@ "has-tostringtag": "^1.0.0" } }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -13894,6 +13937,26 @@ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "joycon": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", @@ -14027,9 +14090,9 @@ "integrity": "sha512-b+z6yF1d4EOyDgylzQo5IminlUmzSeqR1hs/bzjBNjuGras4FXq/6TrzjxfN0j+TmI0ltJzTNlqXUMCniciwKQ==" }, "katex": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.2.tgz", - "integrity": "sha512-70DJdQAyh9EMsthw3AaQlDyFf54X7nWEUIa5W+rq8XOpEk//w5Th7/8SqFqpvi/KZ2t6MHUj4f9wLmztBmAYQA==", + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.3.tgz", + "integrity": "sha512-3EykQddareoRmbtNiNEDgl3IGjryyrp2eg/25fHDEnlHymIDi33bptkMv6K4EOC2LZCybLW/ZkEo6Le+EM9pmA==", "requires": { "commander": "^8.0.0" } @@ -14070,24 +14133,6 @@ "parse-node-version": "^1.0.1", "source-map": "~0.6.0", "tslib": "^2.3.0" - }, - "dependencies": { - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "optional": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "optional": true - } } }, "less-loader": { @@ -14177,9 +14222,9 @@ "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==" }, "loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.3.tgz", + "integrity": "sha512-THWqIsn8QRnvLl0shHYVBN9syumU8pYWEHPTmkiVGd+7K5eFNVSY6AJhRvgGF70gg1Dz+l/k8WicvFCxdEs60A==", "requires": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -14284,6 +14329,24 @@ "sourcemap-codec": "^1.4.8" } }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "optional": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "optional": true + } + } + }, "map-obj": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", @@ -14393,9 +14456,9 @@ "dev": true }, "mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", "dev": true }, "mdurl": { @@ -14545,9 +14608,9 @@ } }, "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", "dev": true }, "minimist-options": { @@ -14567,9 +14630,9 @@ "integrity": "sha512-9ARkWHBs+6YJIvrIp0Ik5tyTTtP9PoV0Ssu2Ocq5y9v8+NOOpWiRshAp8c4rZVWTOe+157on/5G+zj5pwIQFEQ==" }, "monaco-editor": { - "version": "0.34.0", - "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.34.0.tgz", - "integrity": "sha512-VF+S5zG8wxfinLKLrWcl4WUizMx+LeJrG4PM/M78OhcwocpV0jiyhX/pG6Q9jIOhrb/ckYi6nHnaR5OojlOZCQ==" + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.34.1.tgz", + "integrity": "sha512-FKc80TyiMaruhJKKPz5SpJPIjL+dflGvz4CpuThaPMc94AyN7SeC9HQ8hrvaxX7EyHdJcUY5i4D0gNyJj1vSZQ==" }, "monaco-editor-webpack-plugin": { "version": "7.0.1", @@ -15003,9 +15066,9 @@ } }, "playwright-core": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.27.0.tgz", - "integrity": "sha512-VBKaaFUVKDo3akW+o4DwbK1ZyXh46tcSwQKPK3lruh8IJd5feu55XVZx4vOkbb2uqrNdIF51sgsadYT533SdpA==", + "version": "1.27.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.27.1.tgz", + "integrity": "sha512-9EmeXDncC2Pmp/z+teoVYlvmPWUC6ejSSYZUln7YaP89Z6lpAaiaAnqroUt/BoLo8tn7WYShcfaCh+xofZa44Q==", "dev": true }, "pluralize": { @@ -15021,9 +15084,9 @@ "dev": true }, "postcss": { - "version": "8.4.17", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.17.tgz", - "integrity": "sha512-UNxNOLQydcOFi41yHNMcKRZ39NeXlr8AxGuZJsdub8vIb12fHzcq37DTU/QtbI6WLxNg2gF9Z+8qtRwTj1UI1Q==", + "version": "8.4.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz", + "integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==", "requires": { "nanoid": "^3.3.4", "picocolors": "^1.0.0", @@ -15465,9 +15528,9 @@ "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" }, "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safe-regex": { "version": "2.1.1", @@ -15682,6 +15745,15 @@ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "sourcemap-codec": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", @@ -15749,12 +15821,6 @@ "spdx-ranges": "^2.0.0" } }, - "stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "dev": true - }, "stacktracey": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/stacktracey/-/stacktracey-2.1.8.tgz", @@ -15817,6 +15883,12 @@ "ansi-regex": "^5.0.1" } }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true + }, "strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -15848,9 +15920,9 @@ "dev": true }, "stylelint": { - "version": "14.13.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.13.0.tgz", - "integrity": "sha512-NJSAdloiAB/jgVJKxMR90mWlctvmeBFGFVUvyKngi9+j/qPSJ5ZB+u8jOmGbLTnS7OHrII9NFGehPRyar8U5vg==", + "version": "14.14.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.14.0.tgz", + "integrity": "sha512-yUI+4xXfPHVnueYddSQ/e1GuEA/2wVhWQbGj16AmWLtQJtn28lVxfS4b0CsWyVRPgd3Auzi0NXOthIEUhtQmmA==", "dev": true, "requires": { "@csstools/selector-specificity": "^2.0.2", @@ -15876,7 +15948,7 @@ "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "picocolors": "^1.0.0", - "postcss": "^8.4.16", + "postcss": "^8.4.17", "postcss-media-query-parser": "^0.2.3", "postcss-resolve-nested-selector": "^0.1.1", "postcss-safe-parser": "^6.0.0", @@ -15915,9 +15987,9 @@ "requires": {} }, "stylelint-config-standard": { - "version": "28.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-28.0.0.tgz", - "integrity": "sha512-q/StuowDdDmFCravzGHAwgS9pjX0bdOQUEBBDIkIWsQuYGgYz/xsO8CM6eepmIQ1fc5bKdDVimlJZ6MoOUcJ5Q==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-29.0.0.tgz", + "integrity": "sha512-uy8tZLbfq6ZrXy4JKu3W+7lYLgRQBxYTUUB88vPgQ+ZzAxdrvcaSUW9hOMNLYBnwH+9Kkj19M2DHdZ4gKwI7tg==", "dev": true, "requires": { "stylelint-config-recommended": "^9.0.0" @@ -15963,18 +16035,17 @@ "dev": true }, "svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.0.0.tgz", + "integrity": "sha512-mSqPn6RDeNqJvCeqHERlfWJjd4crP/2PgFelil9WpTwC4D3okAUopPsH3lnEyl7ONXfDVyISOihDjO0uK8YVAA==", "dev": true, "requires": { "@trysound/sax": "0.2.0", "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" + "css-select": "^5.1.0", + "css-tree": "^2.2.1", + "csso": "^5.0.5", + "picocolors": "^1.0.0" }, "dependencies": { "commander": { @@ -15986,9 +16057,9 @@ } }, "swagger-ui-dist": { - "version": "4.14.2", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.14.2.tgz", - "integrity": "sha512-kOIU7Ts3TrXDLb3/c9jRe4qGp8O3bRT19FFJA8wJfrRFkcK/4atPn3krhtBVJ57ZkNNofworXHxuYwmaisXBdg==" + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.15.0.tgz", + "integrity": "sha512-vAsIdNHraLuBRm1vrxcMaLk/y/PGBTvHLf4lQGQ3LaEXkORtIxw11sBMpYJL3keOLaFJ1OqNXuURd6eShoFLZQ==" }, "symbol-tree": { "version": "3.2.4", @@ -16029,15 +16100,6 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } } } }, @@ -16070,16 +16132,6 @@ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "requires": {} }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -16094,14 +16146,6 @@ "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "requires": { - "has-flag": "^4.0.0" - } } } }, @@ -16112,9 +16156,9 @@ "dev": true }, "tinybench": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.3.0.tgz", - "integrity": "sha512-zs1gMVBwyyG2QbVchYIbnabRhMOCGvrwZz/q+SV+LIMa9q5YDQZi2kkI6ZRqV2Bz7ba1uvrc7ieUoE4KWnGeKg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.3.1.tgz", + "integrity": "sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==", "dev": true }, "tinypool": { @@ -16211,12 +16255,6 @@ "requires": { "minimist": "^1.2.0" } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true } } }, @@ -16296,9 +16334,9 @@ } }, "updates": { - "version": "13.1.8", - "resolved": "https://registry.npmjs.org/updates/-/updates-13.1.8.tgz", - "integrity": "sha512-hcDCkif1i4MWArx1QkJjLHyPCr8taYyzoypQ7ST/vbmNJyH/cpiawQf+5frvH5uekiSSwtuQNWKdFWB3UH4sew==", + "version": "13.1.10", + "resolved": "https://registry.npmjs.org/updates/-/updates-13.1.10.tgz", + "integrity": "sha512-YSt1ncMoBXAQZndhLwiywvEGHXmA4424SlAf2HMUDuf8qE9Tlqj0s6IANb388HrjkybdZJkaadLSg/hkigwnuQ==", "dev": true }, "uri-js": { @@ -16386,9 +16424,9 @@ } }, "vitest": { - "version": "0.24.1", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.24.1.tgz", - "integrity": "sha512-NKkK1xnDIOOr42pKBfGQQl6b6IWdFVBpG6ZS1T+nUlJuqcOiZ7lxjVwHy9wrtTYpJ0BWww9y6bSGYXubD29Nag==", + "version": "0.24.3", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.24.3.tgz", + "integrity": "sha512-aM0auuPPgMSstWvr851hB74g/LKaKBzSxcG3da7ejfZbx08Y21JpZmbmDYrMTCGhVZKqTGwzcnLMwyfz2WzkhQ==", "dev": true, "requires": { "@types/chai": "^4.3.3", @@ -16415,15 +16453,15 @@ } }, "vue": { - "version": "3.2.40", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.40.tgz", - "integrity": "sha512-1mGHulzUbl2Nk3pfvI5aXYYyJUs1nm4kyvuz38u4xlQkLUn1i2R7nDbI4TufECmY8v1qNBHYy62bCaM+3cHP2A==", + "version": "3.2.41", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.41.tgz", + "integrity": "sha512-uuuvnrDXEeZ9VUPljgHkqB5IaVO8SxhPpqF2eWOukVrBnRBx2THPSGQBnVRt0GrIG1gvCmFXMGbd7FqcT1ixNQ==", "requires": { - "@vue/compiler-dom": "3.2.40", - "@vue/compiler-sfc": "3.2.40", - "@vue/runtime-dom": "3.2.40", - "@vue/server-renderer": "3.2.40", - "@vue/shared": "3.2.40" + "@vue/compiler-dom": "3.2.41", + "@vue/compiler-sfc": "3.2.41", + "@vue/runtime-dom": "3.2.41", + "@vue/server-renderer": "3.2.41", + "@vue/shared": "3.2.41" } }, "vue-bar-graph": { @@ -16762,9 +16800,9 @@ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" }, "ansi-styles": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.1.tgz", - "integrity": "sha512-qDOv24WjnYuL+wbwHdlsYZFy+cgPtrYw0Tn7GLORicQp9BkQLzrgI3Pm4VyR9ERZ41YTn7KlMPuL1n05WdZvmg==" + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" }, "emoji-regex": { "version": "9.2.2", diff --git a/package.json b/package.json index cd83d399a..035f3fd0b 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "@claviska/jquery-minicolors": "2.3.6", "@mcaptcha/vanilla-glue": "0.1.0-alpha-3", "@primer/octicons": "17.7.0", - "@vue/compiler-sfc": "3.2.40", + "@vue/compiler-sfc": "3.2.41", "add-asset-webpack-plugin": "2.0.1", "css-loader": "6.7.1", "dropzone": "6.0.0-beta.2", @@ -21,21 +21,21 @@ "font-awesome": "4.7.0", "jquery": "3.6.1", "jquery.are-you-sure": "1.9.0", - "katex": "0.16.2", + "katex": "0.16.3", "less": "4.1.3", "less-loader": "11.1.0", "license-checker-webpack-plugin": "0.2.1", "mermaid": "9.1.7", "mini-css-extract-plugin": "2.6.1", - "monaco-editor": "0.34.0", + "monaco-editor": "0.34.1", "monaco-editor-webpack-plugin": "7.0.1", "pretty-ms": "8.0.0", "sortablejs": "1.15.0", - "swagger-ui-dist": "4.14.2", + "swagger-ui-dist": "4.15.0", "tippy.js": "6.3.7", "tributejs": "5.1.3", "uint8-to-base64": "0.2.0", - "vue": "3.2.40", + "vue": "3.2.41", "vue-bar-graph": "2.0.0", "vue-loader": "17.0.0", "vue3-calendar-heatmap": "2.0.0", @@ -47,23 +47,23 @@ "wrap-ansi": "8.0.1" }, "devDependencies": { - "@playwright/test": "1.27.0", - "@rollup/pluginutils": "5.0.1", + "@playwright/test": "1.27.1", + "@rollup/pluginutils": "5.0.2", "@stoplight/spectral-cli": "6.5.1", - "eslint": "8.25.0", + "eslint": "8.26.0", "eslint-plugin-import": "2.26.0", "eslint-plugin-jquery": "1.5.1", - "eslint-plugin-sonarjs": "0.15.0", + "eslint-plugin-sonarjs": "0.16.0", "eslint-plugin-unicorn": "44.0.2", "eslint-plugin-vue": "9.6.0", "jsdom": "20.0.1", "markdownlint-cli": "0.32.2", "postcss-less": "6.0.0", - "stylelint": "14.13.0", - "stylelint-config-standard": "28.0.0", - "svgo": "2.8.0", - "updates": "13.1.8", - "vitest": "0.24.1" + "stylelint": "14.14.0", + "stylelint-config-standard": "29.0.0", + "svgo": "3.0.0", + "updates": "13.1.10", + "vitest": "0.24.3" }, "browserslist": [ "defaults", diff --git a/public/img/svg/gitea-codebase.svg b/public/img/svg/gitea-codebase.svg index 2438230db..cb95323a0 100644 --- a/public/img/svg/gitea-codebase.svg +++ b/public/img/svg/gitea-codebase.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/img/svg/gitea-composer.svg b/public/img/svg/gitea-composer.svg index 1285b1bf9..6647813b7 100644 --- a/public/img/svg/gitea-composer.svg +++ b/public/img/svg/gitea-composer.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/img/svg/gitea-conan.svg b/public/img/svg/gitea-conan.svg index d7d5ad5f1..55e27f9a4 100644 --- a/public/img/svg/gitea-conan.svg +++ b/public/img/svg/gitea-conan.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/img/svg/gitea-gitea.svg b/public/img/svg/gitea-gitea.svg index 39bf40ecb..b989d10ed 100644 --- a/public/img/svg/gitea-gitea.svg +++ b/public/img/svg/gitea-gitea.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/img/svg/gitea-gogs.svg b/public/img/svg/gitea-gogs.svg index 887147dd1..7c2a02a05 100644 --- a/public/img/svg/gitea-gogs.svg +++ b/public/img/svg/gitea-gogs.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/img/svg/gitea-helm.svg b/public/img/svg/gitea-helm.svg index 5ab50dd29..1e16850e3 100644 --- a/public/img/svg/gitea-helm.svg +++ b/public/img/svg/gitea-helm.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/img/svg/gitea-lock-cog.svg b/public/img/svg/gitea-lock-cog.svg index 0b10e8676..e2b90a267 100644 --- a/public/img/svg/gitea-lock-cog.svg +++ b/public/img/svg/gitea-lock-cog.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/img/svg/gitea-maven.svg b/public/img/svg/gitea-maven.svg index e83e72827..6c1e0bc23 100644 --- a/public/img/svg/gitea-maven.svg +++ b/public/img/svg/gitea-maven.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/img/svg/gitea-npm.svg b/public/img/svg/gitea-npm.svg index 4435e092f..e11a4fcf5 100644 --- a/public/img/svg/gitea-npm.svg +++ b/public/img/svg/gitea-npm.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/img/svg/gitea-nuget.svg b/public/img/svg/gitea-nuget.svg index a5e38de3f..a835cebc9 100644 --- a/public/img/svg/gitea-nuget.svg +++ b/public/img/svg/gitea-nuget.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/img/svg/gitea-pub.svg b/public/img/svg/gitea-pub.svg index 4a750c708..0b326973e 100644 --- a/public/img/svg/gitea-pub.svg +++ b/public/img/svg/gitea-pub.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/img/svg/gitea-python.svg b/public/img/svg/gitea-python.svg index 07548897e..62ec452ae 100644 --- a/public/img/svg/gitea-python.svg +++ b/public/img/svg/gitea-python.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/img/svg/gitea-rubygems.svg b/public/img/svg/gitea-rubygems.svg index 5f54dce48..0747f8585 100644 --- a/public/img/svg/gitea-rubygems.svg +++ b/public/img/svg/gitea-rubygems.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/routers/api/packages/pypi/pypi.go b/routers/api/packages/pypi/pypi.go index 3a046abe1..66380d832 100644 --- a/routers/api/packages/pypi/pypi.go +++ b/routers/api/packages/pypi/pypi.go @@ -25,8 +25,15 @@ import ( var normalizer = strings.NewReplacer(".", "-", "_", "-") var nameMatcher = regexp.MustCompile(`\A[a-zA-Z0-9\.\-_]+\z`) -// https://www.python.org/dev/peps/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions -var versionMatcher = regexp.MustCompile(`^([1-9][0-9]*!)?(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*((a|b|rc)(0|[1-9][0-9]*))?(\.post(0|[1-9][0-9]*))?(\.dev(0|[1-9][0-9]*))?$`) +// https://peps.python.org/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions +var versionMatcher = regexp.MustCompile(`\Av?` + + `(?:[0-9]+!)?` + // epoch + `[0-9]+(?:\.[0-9]+)*` + // release segment + `(?:[-_\.]?(?:a|b|c|rc|alpha|beta|pre|preview)[-_\.]?[0-9]*)?` + // pre-release + `(?:-[0-9]+|[-_\.]?(?:post|rev|r)[-_\.]?[0-9]*)?` + // post release + `(?:[-_\.]?dev[-_\.]?[0-9]*)?` + // dev release + `(?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)?` + // local version + `\z`) func apiError(ctx *context.Context, status int, obj interface{}) { helper.LogAndProcessError(ctx, status, obj, func(message string) { diff --git a/routers/api/v1/org/hook.go b/routers/api/v1/org/hook.go index 2ddb2b2d2..f8ea5a876 100644 --- a/routers/api/v1/org/hook.go +++ b/routers/api/v1/org/hook.go @@ -59,7 +59,11 @@ func ListHooks(ctx *context.APIContext) { hooks := make([]*api.Hook, len(orgHooks)) for i, hook := range orgHooks { - hooks[i] = convert.ToHook(ctx.Org.Organization.AsUser().HomeLink(), hook) + hooks[i], err = convert.ToHook(ctx.Org.Organization.AsUser().HomeLink(), hook) + if err != nil { + ctx.InternalServerError(err) + return + } } ctx.SetTotalCountHeader(count) @@ -95,7 +99,13 @@ func GetHook(ctx *context.APIContext) { if err != nil { return } - ctx.JSON(http.StatusOK, convert.ToHook(org.AsUser().HomeLink(), hook)) + + apiHook, err := convert.ToHook(org.AsUser().HomeLink(), hook) + if err != nil { + ctx.InternalServerError(err) + return + } + ctx.JSON(http.StatusOK, apiHook) } // CreateHook create a hook for an organization diff --git a/routers/api/v1/repo/hook.go b/routers/api/v1/repo/hook.go index 5956fe9da..57fff7d32 100644 --- a/routers/api/v1/repo/hook.go +++ b/routers/api/v1/repo/hook.go @@ -69,7 +69,11 @@ func ListHooks(ctx *context.APIContext) { apiHooks := make([]*api.Hook, len(hooks)) for i := range hooks { - apiHooks[i] = convert.ToHook(ctx.Repo.RepoLink, hooks[i]) + apiHooks[i], err = convert.ToHook(ctx.Repo.RepoLink, hooks[i]) + if err != nil { + ctx.InternalServerError(err) + return + } } ctx.SetTotalCountHeader(count) @@ -112,7 +116,12 @@ func GetHook(ctx *context.APIContext) { if err != nil { return } - ctx.JSON(http.StatusOK, convert.ToHook(repo.RepoLink, hook)) + apiHook, err := convert.ToHook(repo.RepoLink, hook) + if err != nil { + ctx.InternalServerError(err) + return + } + ctx.JSON(http.StatusOK, apiHook) } // TestHook tests a hook diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index ebb9c0f26..f7e82dab3 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -839,7 +839,7 @@ func MergePullRequest(ctx *context.APIContext) { } } - if err := pull_service.Merge(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, repo_model.MergeStyle(form.Do), form.HeadCommitID, message); err != nil { + if err := pull_service.Merge(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, repo_model.MergeStyle(form.Do), form.HeadCommitID, message, false); err != nil { if models.IsErrInvalidMergeStyle(err) { ctx.Error(http.StatusMethodNotAllowed, "Invalid merge style", fmt.Errorf("%s is not allowed an allowed merge style for this repository", repo_model.MergeStyle(form.Do))) } else if models.IsErrMergeConflicts(err) { diff --git a/routers/api/v1/utils/hook.go b/routers/api/v1/utils/hook.go index 7e4dfca9a..aa922f4f5 100644 --- a/routers/api/v1/utils/hook.go +++ b/routers/api/v1/utils/hook.go @@ -72,18 +72,39 @@ func CheckCreateHookOption(ctx *context.APIContext, form *api.CreateHookOption) func AddOrgHook(ctx *context.APIContext, form *api.CreateHookOption) { org := ctx.Org.Organization hook, ok := addHook(ctx, form, org.ID, 0) - if ok { - ctx.JSON(http.StatusCreated, convert.ToHook(org.AsUser().HomeLink(), hook)) + if !ok { + return } + apiHook, ok := toAPIHook(ctx, org.AsUser().HomeLink(), hook) + if !ok { + return + } + ctx.JSON(http.StatusCreated, apiHook) } // AddRepoHook add a hook to a repo. Writes to `ctx` accordingly func AddRepoHook(ctx *context.APIContext, form *api.CreateHookOption) { repo := ctx.Repo hook, ok := addHook(ctx, form, 0, repo.Repository.ID) - if ok { - ctx.JSON(http.StatusCreated, convert.ToHook(repo.RepoLink, hook)) + if !ok { + return } + apiHook, ok := toAPIHook(ctx, repo.RepoLink, hook) + if !ok { + return + } + ctx.JSON(http.StatusCreated, apiHook) +} + +// toAPIHook converts the hook to its API representation. +// If there is an error, write to `ctx` accordingly. Return (hook, ok) +func toAPIHook(ctx *context.APIContext, repoLink string, hook *webhook.Webhook) (*api.Hook, bool) { + apiHook, err := convert.ToHook(repoLink, hook) + if err != nil { + ctx.Error(http.StatusInternalServerError, "ToHook", err) + return nil, false + } + return apiHook, true } func issuesHook(events []string, event string) bool { @@ -135,6 +156,11 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID IsActive: form.Active, Type: form.Type, } + err := w.SetHeaderAuthorization(form.AuthorizationHeader) + if err != nil { + ctx.Error(http.StatusInternalServerError, "SetHeaderAuthorization", err) + return nil, false + } if w.Type == webhook.SLACK { channel, ok := form.Config["channel"] if !ok { @@ -185,7 +211,11 @@ func EditOrgHook(ctx *context.APIContext, form *api.EditHookOption, hookID int64 if err != nil { return } - ctx.JSON(http.StatusOK, convert.ToHook(org.AsUser().HomeLink(), updated)) + apiHook, ok := toAPIHook(ctx, org.AsUser().HomeLink(), updated) + if !ok { + return + } + ctx.JSON(http.StatusOK, apiHook) } // EditRepoHook edit webhook `w` according to `form`. Writes to `ctx` accordingly @@ -202,7 +232,11 @@ func EditRepoHook(ctx *context.APIContext, form *api.EditHookOption, hookID int6 if err != nil { return } - ctx.JSON(http.StatusOK, convert.ToHook(repo.RepoLink, updated)) + apiHook, ok := toAPIHook(ctx, repo.RepoLink, updated) + if !ok { + return + } + ctx.JSON(http.StatusOK, apiHook) } // editHook edit the webhook `w` according to `form`. If an error occurs, write @@ -254,6 +288,12 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *webhook.Webh w.Release = util.IsStringInSlice(string(webhook.HookEventRelease), form.Events, true) w.BranchFilter = form.BranchFilter + err := w.SetHeaderAuthorization(form.AuthorizationHeader) + if err != nil { + ctx.Error(http.StatusInternalServerError, "SetHeaderAuthorization", err) + return false + } + // Issues w.Issues = issuesHook(form.Events, "issues_only") w.IssueAssign = issuesHook(form.Events, string(webhook.HookEventIssueAssign)) diff --git a/routers/init.go b/routers/init.go index 9045437f8..53b33f468 100644 --- a/routers/init.go +++ b/routers/init.go @@ -76,21 +76,31 @@ func InitGitServices() { mustInit(repo_service.Init) } -func syncAppPathForGit(ctx context.Context) error { +func syncAppConfForGit(ctx context.Context) error { runtimeState := new(system.RuntimeState) if err := system.AppState.Get(runtimeState); err != nil { return err } + + updated := false if runtimeState.LastAppPath != setting.AppPath { log.Info("AppPath changed from '%s' to '%s'", runtimeState.LastAppPath, setting.AppPath) + runtimeState.LastAppPath = setting.AppPath + updated = true + } + if runtimeState.LastCustomConf != setting.CustomConf { + log.Info("CustomConf changed from '%s' to '%s'", runtimeState.LastCustomConf, setting.CustomConf) + runtimeState.LastCustomConf = setting.CustomConf + updated = true + } + if updated { log.Info("re-sync repository hooks ...") mustInitCtx(ctx, repo_service.SyncRepositoryHooks) log.Info("re-write ssh public keys ...") mustInit(asymkey_model.RewriteAllPublicKeys) - runtimeState.LastAppPath = setting.AppPath return system.AppState.Set(runtimeState) } return nil @@ -153,7 +163,7 @@ func GlobalInitInstalled(ctx context.Context) { mustInit(repo_migrations.Init) eventsource.GetManager().Init() - mustInitCtx(ctx, syncAppPathForGit) + mustInitCtx(ctx, syncAppConfForGit) mustInit(ssh.Init) diff --git a/routers/install/install.go b/routers/install/install.go index 962dee8c8..184dc5bae 100644 --- a/routers/install/install.go +++ b/routers/install/install.go @@ -457,6 +457,7 @@ func SubmitInstall(ctx *context.Context) { cfg.Section("service").Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").SetValue(fmt.Sprint(form.DefaultAllowCreateOrganization)) cfg.Section("service").Key("DEFAULT_ENABLE_TIMETRACKING").SetValue(fmt.Sprint(form.DefaultEnableTimetracking)) cfg.Section("service").Key("NO_REPLY_ADDRESS").SetValue(fmt.Sprint(form.NoReplyAddress)) + cfg.Section("cron.update_checker").Key("ENABLED").SetValue(fmt.Sprint(form.EnableUpdateChecker)) cfg.Section("").Key("RUN_MODE").SetValue("prod") @@ -473,12 +474,16 @@ func SubmitInstall(ctx *context.Context) { cfg.Section("security").Key("INSTALL_LOCK").SetValue("true") - var internalToken string - if internalToken, err = generate.NewInternalToken(); err != nil { - ctx.RenderWithErr(ctx.Tr("install.internal_token_failed", err), tplInstall, &form) - return + // the internal token could be read from INTERNAL_TOKEN or INTERNAL_TOKEN_URI (the file is guaranteed to be non-empty) + // if there is no InternalToken, generate one and save to security.INTERNAL_TOKEN + if setting.InternalToken == "" { + var internalToken string + if internalToken, err = generate.NewInternalToken(); err != nil { + ctx.RenderWithErr(ctx.Tr("install.internal_token_failed", err), tplInstall, &form) + return + } + cfg.Section("security").Key("INTERNAL_TOKEN").SetValue(internalToken) } - cfg.Section("security").Key("INTERNAL_TOKEN").SetValue(internalToken) // if there is already a SECRET_KEY, we should not overwrite it, otherwise the encrypted data will not be able to be decrypted if setting.SecretKey == "" { diff --git a/routers/private/mail.go b/routers/private/mail.go index e858992ae..255e1d901 100644 --- a/routers/private/mail.go +++ b/routers/private/mail.go @@ -5,6 +5,7 @@ package private import ( + stdCtx "context" "fmt" "net/http" "strconv" @@ -60,7 +61,7 @@ func SendEmail(ctx *context.PrivateContext) { } } } else { - err := db.IterateObjects(ctx, func(user *user_model.User) error { + err := db.Iterate(ctx, nil, func(ctx stdCtx.Context, user *user_model.User) error { if len(user.Email) > 0 && user.IsActive { emails = append(emails, user.Email) } diff --git a/routers/web/dev/template.go b/routers/web/dev/template.go deleted file mode 100644 index afef0d8d1..000000000 --- a/routers/web/dev/template.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2014 The Gogs Authors. All rights reserved. -// Use of this source code is governed by a MIT-style -// license that can be found in the LICENSE file. - -package dev - -import ( - "net/http" - - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/base" - "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/timeutil" -) - -// TemplatePreview render for previewing the indicated template -func TemplatePreview(ctx *context.Context) { - ctx.Data["User"] = user_model.User{Name: "Unknown"} - ctx.Data["AppName"] = setting.AppName - ctx.Data["AppVer"] = setting.AppVer - ctx.Data["AppUrl"] = setting.AppURL - ctx.Data["Code"] = "2014031910370000009fff6782aadb2162b4a997acb69d4400888e0b9274657374" - ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale) - ctx.Data["ResetPwdCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale) - ctx.Data["CurDbValue"] = "" - - ctx.HTML(http.StatusOK, base.TplName(ctx.Params("*"))) -} diff --git a/routers/web/feed/convert.go b/routers/web/feed/convert.go index 645d9370d..c6fc352b6 100644 --- a/routers/web/feed/convert.go +++ b/routers/web/feed/convert.go @@ -115,6 +115,12 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio link.Href = pullLink } title += ctx.TrHTMLEscapeArgs("action.merge_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath()) + case activities_model.ActionAutoMergePullRequest: + pullLink := toPullLink(act) + if link.Href == "#" { + link.Href = pullLink + } + title += ctx.TrHTMLEscapeArgs("action.auto_merge_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath()) case activities_model.ActionCloseIssue: issueLink := toIssueLink(act) if link.Href == "#" { @@ -221,7 +227,7 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio if len(comment) != 0 { desc += "\n\n" + renderMarkdown(ctx, act, comment) } - case activities_model.ActionMergePullRequest: + case activities_model.ActionMergePullRequest, activities_model.ActionAutoMergePullRequest: desc = act.GetIssueInfos()[1] case activities_model.ActionCloseIssue, activities_model.ActionReopenIssue, activities_model.ActionClosePullRequest, activities_model.ActionReopenPullRequest: desc = act.GetIssueTitle() @@ -241,7 +247,7 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio Name: act.ActUser.DisplayName(), Email: act.ActUser.GetEmail(), }, - Id: strconv.FormatInt(act.ID, 10), + Id: fmt.Sprintf("%v: %v", strconv.FormatInt(act.ID, 10), link.Href), Created: act.CreatedUnix.AsTime(), Content: content, }) diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index fc95bbf24..41eac7cc3 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -1002,7 +1002,7 @@ func MergePullRequest(ctx *context.Context) { } } - if err := pull_service.Merge(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, repo_model.MergeStyle(form.Do), form.HeadCommitID, message); err != nil { + if err := pull_service.Merge(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, repo_model.MergeStyle(form.Do), form.HeadCommitID, message, false); err != nil { if models.IsErrInvalidMergeStyle(err) { ctx.Flash.Error(ctx.Tr("repo.pulls.invalid_merge_option")) ctx.Redirect(issue.Link()) diff --git a/routers/web/repo/webhook.go b/routers/web/repo/webhook.go index ee980333b..5496496e8 100644 --- a/routers/web/repo/webhook.go +++ b/routers/web/repo/webhook.go @@ -239,6 +239,11 @@ func createWebhook(ctx *context.Context, params webhookParams) { OrgID: orCtx.OrgID, IsSystemWebhook: orCtx.IsSystemWebhook, } + err = w.SetHeaderAuthorization(params.WebhookForm.AuthorizationHeader) + if err != nil { + ctx.ServerError("SetHeaderAuthorization", err) + return + } if err := w.UpdateEvent(); err != nil { ctx.ServerError("UpdateEvent", err) return @@ -285,6 +290,12 @@ func editWebhook(ctx *context.Context, params webhookParams) { w.HTTPMethod = params.HTTPMethod w.Meta = string(meta) + err = w.SetHeaderAuthorization(params.WebhookForm.AuthorizationHeader) + if err != nil { + ctx.ServerError("SetHeaderAuthorization", err) + return + } + if err := w.UpdateEvent(); err != nil { ctx.ServerError("UpdateEvent", err) return @@ -445,7 +456,6 @@ func matrixHookParams(ctx *context.Context) webhookParams { Meta: &webhook_service.MatrixMeta{ HomeserverURL: form.HomeserverURL, Room: form.RoomID, - AccessToken: form.AccessToken, MessageType: form.MessageType, }, } diff --git a/routers/web/web.go b/routers/web/web.go index 6b33986b6..ae11e916f 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -28,7 +28,6 @@ import ( "code.gitea.io/gitea/modules/web/routing" "code.gitea.io/gitea/routers/web/admin" "code.gitea.io/gitea/routers/web/auth" - "code.gitea.io/gitea/routers/web/dev" "code.gitea.io/gitea/routers/web/events" "code.gitea.io/gitea/routers/web/explore" "code.gitea.io/gitea/routers/web/feed" @@ -296,12 +295,19 @@ func RegisterRoutes(m *web.Route) { } } + sitemapEnabled := func(ctx *context.Context) { + if !setting.EnableSitemap { + ctx.Error(http.StatusNotFound) + return + } + } + // FIXME: not all routes need go through same middleware. // Especially some AJAX requests, we can reduce middleware number to improve performance. // Routers. // for health check m.Get("/", Home) - m.Get("/sitemap.xml", ignExploreSignIn, HomeSitemap) + m.Get("/sitemap.xml", sitemapEnabled, ignExploreSignIn, HomeSitemap) m.Group("/.well-known", func() { m.Get("/openid-configuration", auth.OIDCWellKnown) m.Group("", func() { @@ -318,9 +324,9 @@ func RegisterRoutes(m *web.Route) { ctx.Redirect(setting.AppSubURL + "/explore/repos") }) m.Get("/repos", explore.Repos) - m.Get("/repos/sitemap-{idx}.xml", explore.Repos) + m.Get("/repos/sitemap-{idx}.xml", sitemapEnabled, explore.Repos) m.Get("/users", explore.Users) - m.Get("/users/sitemap-{idx}.xml", explore.Users) + m.Get("/users/sitemap-{idx}.xml", sitemapEnabled, explore.Users) m.Get("/organizations", explore.Organizations) m.Get("/code", explore.Code) m.Get("/topics/search", explore.TopicSearch) @@ -612,10 +618,6 @@ func RegisterRoutes(m *web.Route) { m.Post("/{username}", reqSignIn, context_service.UserAssignmentWeb(), user.Action) - if !setting.IsProd { - m.Get("/template/*", dev.TemplatePreview) - } - reqRepoAdmin := context.RequireRepoAdmin() reqRepoCodeWriter := context.RequireRepoWriter(unit.TypeCode) canEnableEditor := context.CanEnableEditor() diff --git a/services/automerge/automerge.go b/services/automerge/automerge.go index ca008ebfe..3ee8af234 100644 --- a/services/automerge/automerge.go +++ b/services/automerge/automerge.go @@ -257,7 +257,7 @@ func handlePull(pullID int64, sha string) { defer baseGitRepo.Close() } - if err := pull_service.Merge(ctx, pr, doer, baseGitRepo, scheduledPRM.MergeStyle, "", scheduledPRM.Message); err != nil { + if err := pull_service.Merge(ctx, pr, doer, baseGitRepo, scheduledPRM.MergeStyle, "", scheduledPRM.Message, true); err != nil { log.Error("pull_service.Merge: %v", err) return } diff --git a/services/forms/admin.go b/services/forms/admin.go index 5abef0550..537b9f982 100644 --- a/services/forms/admin.go +++ b/services/forms/admin.go @@ -18,7 +18,7 @@ import ( type AdminCreateUserForm struct { LoginType string `binding:"Required"` LoginName string - UserName string `binding:"Required;AlphaDashDot;MaxSize(40)"` + UserName string `binding:"Required;Username;MaxSize(40)"` Email string `binding:"Required;Email;MaxSize(254)"` Password string `binding:"MaxSize(255)"` SendNotify bool @@ -35,7 +35,7 @@ func (f *AdminCreateUserForm) Validate(req *http.Request, errs binding.Errors) b // AdminEditUserForm form for admin to create user type AdminEditUserForm struct { LoginType string `binding:"Required"` - UserName string `binding:"AlphaDashDot;MaxSize(40)"` + UserName string `binding:"Username;MaxSize(40)"` LoginName string FullName string `binding:"MaxSize(100)"` Email string `binding:"Required;Email;MaxSize(254)"` diff --git a/services/forms/org.go b/services/forms/org.go index dec2dbfa6..c7ee91134 100644 --- a/services/forms/org.go +++ b/services/forms/org.go @@ -24,7 +24,7 @@ import ( // CreateOrgForm form for creating organization type CreateOrgForm struct { - OrgName string `binding:"Required;AlphaDashDot;MaxSize(40)" locale:"org.org_name_holder"` + OrgName string `binding:"Required;Username;MaxSize(40)" locale:"org.org_name_holder"` Visibility structs.VisibleType RepoAdminChangeTeamAccess bool } @@ -37,7 +37,7 @@ func (f *CreateOrgForm) Validate(req *http.Request, errs binding.Errors) binding // UpdateOrgSettingForm form for updating organization settings type UpdateOrgSettingForm struct { - Name string `binding:"Required;AlphaDashDot;MaxSize(40)" locale:"org.org_name_holder"` + Name string `binding:"Required;Username;MaxSize(40)" locale:"org.org_name_holder"` FullName string `binding:"MaxSize(100)"` Description string `binding:"MaxSize(255)"` Website string `binding:"ValidUrl;MaxSize(255)"` diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index c1e9cb319..64f47aadd 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -247,6 +247,7 @@ type WebhookForm struct { Package bool Active bool BranchFilter string `binding:"GlobPattern"` + AuthorizationHeader string } // PushOnly if the hook will be triggered when push @@ -359,7 +360,6 @@ func (f *NewTelegramHookForm) Validate(req *http.Request, errs binding.Errors) b type NewMatrixHookForm struct { HomeserverURL string `binding:"Required;ValidUrl"` RoomID string `binding:"Required"` - AccessToken string `binding:"Required"` MessageType int WebhookForm } diff --git a/services/forms/user_form.go b/services/forms/user_form.go index 036c2ca3e..ed8ccf12e 100644 --- a/services/forms/user_form.go +++ b/services/forms/user_form.go @@ -60,11 +60,12 @@ type InstallForm struct { DefaultKeepEmailPrivate bool DefaultAllowCreateOrganization bool DefaultEnableTimetracking bool + EnableUpdateChecker bool NoReplyAddress string PasswordAlgorithm string - AdminName string `binding:"OmitEmpty;AlphaDashDot;MaxSize(30)" locale:"install.admin_name"` + AdminName string `binding:"OmitEmpty;Username;MaxSize(30)" locale:"install.admin_name"` AdminPasswd string `binding:"OmitEmpty;MaxSize(255)" locale:"install.admin_password"` AdminConfirmPasswd string AdminEmail string `binding:"OmitEmpty;MinSize(3);MaxSize(254);Include(@)" locale:"install.admin_email"` @@ -90,7 +91,7 @@ func (f *InstallForm) Validate(req *http.Request, errs binding.Errors) binding.E // RegisterForm form for registering type RegisterForm struct { - UserName string `binding:"Required;AlphaDashDot;MaxSize(40)"` + UserName string `binding:"Required;Username;MaxSize(40)"` Email string `binding:"Required;MaxSize(254)"` Password string `binding:"MaxSize(255)"` Retype string @@ -242,7 +243,7 @@ func (f *IntrospectTokenForm) Validate(req *http.Request, errs binding.Errors) b // UpdateProfileForm form for updating profile type UpdateProfileForm struct { - Name string `binding:"AlphaDashDot;MaxSize(40)"` + Name string `binding:"Username;MaxSize(40)"` FullName string `binding:"MaxSize(100)"` KeepEmailPrivate bool Website string `binding:"ValidSiteUrl;MaxSize(255)"` diff --git a/services/forms/user_form_auth_openid.go b/services/forms/user_form_auth_openid.go index 992517f34..d1ed0a23c 100644 --- a/services/forms/user_form_auth_openid.go +++ b/services/forms/user_form_auth_openid.go @@ -27,7 +27,7 @@ func (f *SignInOpenIDForm) Validate(req *http.Request, errs binding.Errors) bind // SignUpOpenIDForm form for signin up with OpenID type SignUpOpenIDForm struct { - UserName string `binding:"Required;AlphaDashDot;MaxSize(40)"` + UserName string `binding:"Required;Username;MaxSize(40)"` Email string `binding:"Required;Email;MaxSize(254)"` GRecaptchaResponse string `form:"g-recaptcha-response"` HcaptchaResponse string `form:"h-captcha-response"` diff --git a/services/mailer/mail.go b/services/mailer/mail.go index a5bfa496f..85a7d107e 100644 --- a/services/mailer/mail.go +++ b/services/mailer/mail.go @@ -340,7 +340,7 @@ func createReference(issue *issues_model.Issue, comment *issues_model.Comment, a extra = fmt.Sprintf("/close/%d", time.Now().UnixNano()/1e6) case activities_model.ActionReopenIssue, activities_model.ActionReopenPullRequest: extra = fmt.Sprintf("/reopen/%d", time.Now().UnixNano()/1e6) - case activities_model.ActionMergePullRequest: + case activities_model.ActionMergePullRequest, activities_model.ActionAutoMergePullRequest: extra = fmt.Sprintf("/merge/%d", time.Now().UnixNano()/1e6) case activities_model.ActionPullRequestReadyForReview: extra = fmt.Sprintf("/ready/%d", time.Now().UnixNano()/1e6) @@ -451,7 +451,7 @@ func actionToTemplate(issue *issues_model.Issue, actionType activities_model.Act name = "close" case activities_model.ActionReopenIssue, activities_model.ActionReopenPullRequest: name = "reopen" - case activities_model.ActionMergePullRequest: + case activities_model.ActionMergePullRequest, activities_model.ActionAutoMergePullRequest: name = "merge" case activities_model.ActionPullReviewDismissed: name = "review_dismissed" diff --git a/services/mailer/mail_issue.go b/services/mailer/mail_issue.go index 33a20694e..61e276805 100644 --- a/services/mailer/mail_issue.go +++ b/services/mailer/mail_issue.go @@ -25,11 +25,12 @@ func fallbackMailSubject(issue *issues_model.Issue) string { type mailCommentContext struct { context.Context - Issue *issues_model.Issue - Doer *user_model.User - ActionType activities_model.ActionType - Content string - Comment *issues_model.Comment + Issue *issues_model.Issue + Doer *user_model.User + ActionType activities_model.ActionType + Content string + Comment *issues_model.Comment + ForceDoerNotification bool } const ( @@ -93,7 +94,7 @@ func mailIssueCommentToParticipants(ctx *mailCommentContext, mentions []*user_mo visited := make(container.Set[int64], len(unfiltered)+len(mentions)+1) // Avoid mailing the doer - if ctx.Doer.EmailNotificationsPreference != user_model.EmailNotificationsAndYourOwn { + if ctx.Doer.EmailNotificationsPreference != user_model.EmailNotificationsAndYourOwn && !ctx.ForceDoerNotification { visited.Add(ctx.Doer.ID) } @@ -181,17 +182,19 @@ func MailParticipants(issue *issues_model.Issue, doer *user_model.User, opType a content := issue.Content if opType == activities_model.ActionCloseIssue || opType == activities_model.ActionClosePullRequest || opType == activities_model.ActionReopenIssue || opType == activities_model.ActionReopenPullRequest || - opType == activities_model.ActionMergePullRequest { + opType == activities_model.ActionMergePullRequest || opType == activities_model.ActionAutoMergePullRequest { content = "" } + forceDoerNotification := opType == activities_model.ActionAutoMergePullRequest if err := mailIssueCommentToParticipants( &mailCommentContext{ - Context: context.TODO(), // TODO: use a correct context - Issue: issue, - Doer: doer, - ActionType: opType, - Content: content, - Comment: nil, + Context: context.TODO(), // TODO: use a correct context + Issue: issue, + Doer: doer, + ActionType: opType, + Content: content, + Comment: nil, + ForceDoerNotification: forceDoerNotification, }, mentions); err != nil { log.Error("mailIssueCommentToParticipants: %v", err) } diff --git a/services/migrations/github.go b/services/migrations/github.go index 016d05886..e5683fb53 100644 --- a/services/migrations/github.go +++ b/services/migrations/github.go @@ -15,6 +15,7 @@ import ( "strings" "time" + "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" base "code.gitea.io/gitea/modules/migration" "code.gitea.io/gitea/modules/proxy" @@ -307,10 +308,14 @@ func (g *GithubDownloaderV3) GetLabels() ([]*base.Label, error) { } func (g *GithubDownloaderV3) convertGithubRelease(rel *github.RepositoryRelease) *base.Release { + // GitHub allows commitish to be a reference. + // In this case, we need to remove the prefix, i.e. convert "refs/heads/main" to "main". + targetCommitish := strings.TrimPrefix(rel.GetTargetCommitish(), git.BranchPrefix) + r := &base.Release{ Name: rel.GetName(), TagName: rel.GetTagName(), - TargetCommitish: rel.GetTargetCommitish(), + TargetCommitish: targetCommitish, Draft: rel.GetDraft(), Prerelease: rel.GetPrerelease(), Created: rel.GetCreatedAt().Time, diff --git a/services/pull/merge.go b/services/pull/merge.go index 0ca373018..56ee9c9a7 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -133,7 +133,7 @@ func GetDefaultMergeMessage(baseGitRepo *git.Repository, pr *issues_model.PullRe // Merge merges pull request to base repository. // Caller should check PR is ready to be merged (review and status checks) -func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, baseGitRepo *git.Repository, mergeStyle repo_model.MergeStyle, expectedHeadCommitID, message string) error { +func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, baseGitRepo *git.Repository, mergeStyle repo_model.MergeStyle, expectedHeadCommitID, message string, wasAutoMerged bool) error { if err := pr.LoadHeadRepo(); err != nil { log.Error("LoadHeadRepo: %v", err) return fmt.Errorf("LoadHeadRepo: %w", err) @@ -193,7 +193,11 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U log.Error("GetOwner for issue repo [%d]: %v", pr.ID, err) } - notification.NotifyMergePullRequest(pr, doer) + if wasAutoMerged { + notification.NotifyAutoMergePullRequest(pr, doer) + } else { + notification.NotifyMergePullRequest(pr, doer) + } // Reset cached commit count cache.Remove(pr.Issue.Repo.GetCommitsCountCacheKey(pr.BaseBranch, true)) diff --git a/services/repository/adopt.go b/services/repository/adopt.go index 3b986c66c..a9a063954 100644 --- a/services/repository/adopt.go +++ b/services/repository/adopt.go @@ -8,6 +8,7 @@ import ( "context" "fmt" "os" + "path" "path/filepath" "strings" @@ -218,21 +219,21 @@ func DeleteUnadoptedRepository(doer, u *user_model.User, repoName string) error return util.RemoveAll(repoPath) } -type unadoptedRrepositories struct { +type unadoptedRepositories struct { repositories []string index int start int end int } -func (unadopted *unadoptedRrepositories) add(repository string) { +func (unadopted *unadoptedRepositories) add(repository string) { if unadopted.index >= unadopted.start && unadopted.index < unadopted.end { unadopted.repositories = append(unadopted.repositories, repository) } unadopted.index++ } -func checkUnadoptedRepositories(userName string, repoNamesToCheck []string, unadopted *unadoptedRrepositories) error { +func checkUnadoptedRepositories(userName string, repoNamesToCheck []string, unadopted *unadoptedRepositories) error { if len(repoNamesToCheck) == 0 { return nil } @@ -264,7 +265,7 @@ func checkUnadoptedRepositories(userName string, repoNamesToCheck []string, unad } for _, repoName := range repoNamesToCheck { if !repoNames.Contains(repoName) { - unadopted.add(filepath.Join(userName, repoName)) + unadopted.add(path.Join(userName, repoName)) // These are not used as filepaths - but as reponames - therefore use path.Join not filepath.Join } } return nil @@ -292,7 +293,7 @@ func ListUnadoptedRepositories(query string, opts *db.ListOptions) ([]string, in var repoNamesToCheck []string start := (opts.Page - 1) * opts.PageSize - unadopted := &unadoptedRrepositories{ + unadopted := &unadoptedRepositories{ repositories: make([]string, 0, opts.PageSize), start: start, end: start + opts.PageSize, diff --git a/services/repository/adopt_test.go b/services/repository/adopt_test.go index 685bfe9bc..b450005f3 100644 --- a/services/repository/adopt_test.go +++ b/services/repository/adopt_test.go @@ -19,7 +19,7 @@ import ( func TestCheckUnadoptedRepositories_Add(t *testing.T) { start := 10 end := 20 - unadopted := &unadoptedRrepositories{ + unadopted := &unadoptedRepositories{ start: start, end: end, index: 0, @@ -39,7 +39,7 @@ func TestCheckUnadoptedRepositories(t *testing.T) { // // Non existent user // - unadopted := &unadoptedRrepositories{start: 0, end: 100} + unadopted := &unadoptedRepositories{start: 0, end: 100} err := checkUnadoptedRepositories("notauser", []string{"repo"}, unadopted) assert.NoError(t, err) assert.Equal(t, 0, len(unadopted.repositories)) @@ -50,14 +50,14 @@ func TestCheckUnadoptedRepositories(t *testing.T) { userName := "user2" repoName := "repo2" unadoptedRepoName := "unadopted" - unadopted = &unadoptedRrepositories{start: 0, end: 100} + unadopted = &unadoptedRepositories{start: 0, end: 100} err = checkUnadoptedRepositories(userName, []string{repoName, unadoptedRepoName}, unadopted) assert.NoError(t, err) assert.Equal(t, []string{path.Join(userName, unadoptedRepoName)}, unadopted.repositories) // // Existing (adopted) repository is not returned // - unadopted = &unadoptedRrepositories{start: 0, end: 100} + unadopted = &unadoptedRepositories{start: 0, end: 100} err = checkUnadoptedRepositories(userName, []string{repoName}, unadopted) assert.NoError(t, err) assert.Equal(t, 0, len(unadopted.repositories)) diff --git a/services/repository/avatar.go b/services/repository/avatar.go index b80a8fb77..1cf9e869c 100644 --- a/services/repository/avatar.go +++ b/services/repository/avatar.go @@ -96,7 +96,7 @@ func DeleteAvatar(repo *repo_model.Repository) error { // RemoveRandomAvatars removes the randomly generated avatars that were created for repositories func RemoveRandomAvatars(ctx context.Context) error { - return db.IterateObjects(ctx, func(repository *repo_model.Repository) error { + return db.Iterate(ctx, nil, func(ctx context.Context, repository *repo_model.Repository) error { select { case <-ctx.Done(): return db.ErrCancelledf("before random avatars removed for %s", repository.FullName()) diff --git a/services/repository/check.go b/services/repository/check.go index 5529a61b3..5725f540b 100644 --- a/services/repository/check.go +++ b/services/repository/check.go @@ -29,10 +29,8 @@ func GitFsck(ctx context.Context, timeout time.Duration, args []git.CmdArg) erro if err := db.Iterate( ctx, - new(repo_model.Repository), builder.Expr("id>0 AND is_fsck_enabled=?", true), - func(idx int, bean interface{}) error { - repo := bean.(*repo_model.Repository) + func(ctx context.Context, repo *repo_model.Repository) error { select { case <-ctx.Done(): return db.ErrCancelledf("before fsck of %s", repo.FullName()) @@ -64,10 +62,8 @@ func GitGcRepos(ctx context.Context, timeout time.Duration, args ...git.CmdArg) if err := db.Iterate( ctx, - new(repo_model.Repository), builder.Gt{"id": 0}, - func(idx int, bean interface{}) error { - repo := bean.(*repo_model.Repository) + func(ctx context.Context, repo *repo_model.Repository) error { select { case <-ctx.Done(): return db.ErrCancelledf("before GC of %s", repo.FullName()) @@ -113,10 +109,8 @@ func gatherMissingRepoRecords(ctx context.Context) ([]*repo_model.Repository, er repos := make([]*repo_model.Repository, 0, 10) if err := db.Iterate( ctx, - new(repo_model.Repository), builder.Gt{"id": 0}, - func(idx int, bean interface{}) error { - repo := bean.(*repo_model.Repository) + func(ctx context.Context, repo *repo_model.Repository) error { select { case <-ctx.Done(): return db.ErrCancelledf("during gathering missing repo records before checking %s", repo.FullName()) diff --git a/services/repository/hooks.go b/services/repository/hooks.go index d326cd26b..d29384e01 100644 --- a/services/repository/hooks.go +++ b/services/repository/hooks.go @@ -25,10 +25,8 @@ func SyncRepositoryHooks(ctx context.Context) error { if err := db.Iterate( ctx, - new(repo_model.Repository), builder.Gt{"id": 0}, - func(idx int, bean interface{}) error { - repo := bean.(*repo_model.Repository) + func(ctx context.Context, repo *repo_model.Repository) error { select { case <-ctx.Done(): return db.ErrCancelledf("before sync repository hooks for %s", repo.FullName()) diff --git a/services/webhook/deliver.go b/services/webhook/deliver.go index 74a69c297..85717e097 100644 --- a/services/webhook/deliver.go +++ b/services/webhook/deliver.go @@ -90,7 +90,12 @@ func Deliver(ctx context.Context, t *webhook_model.HookTask) error { case http.MethodPut: switch w.Type { case webhook_model.MATRIX: - req, err = getMatrixHookRequest(w, t) + txnID, err := getMatrixTxnID([]byte(t.PayloadContent)) + if err != nil { + return err + } + url := fmt.Sprintf("%s/%s", w.URL, url.PathEscape(txnID)) + req, err = http.NewRequest("PUT", url, strings.NewReader(t.PayloadContent)) if err != nil { return err } @@ -130,6 +135,16 @@ func Deliver(ctx context.Context, t *webhook_model.HookTask) error { req.Header["X-GitHub-Event"] = []string{event} req.Header["X-GitHub-Event-Type"] = []string{eventType} + // Add Authorization Header + authorization, err := w.HeaderAuthorization() + if err != nil { + log.Error("Webhook could not get Authorization header [%d]: %v", w.ID, err) + return err + } + if authorization != "" { + req.Header["Authorization"] = []string{authorization} + } + // Record delivery information. t.RequestInfo = &webhook_model.HookRequest{ URL: req.URL.String(), diff --git a/services/webhook/deliver_test.go b/services/webhook/deliver_test.go index 8d1d587c3..83ca7d617 100644 --- a/services/webhook/deliver_test.go +++ b/services/webhook/deliver_test.go @@ -5,10 +5,16 @@ package webhook import ( + "context" "net/http" + "net/http/httptest" "net/url" "testing" + "time" + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/unittest" + webhook_model "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/setting" "github.com/stretchr/testify/assert" @@ -38,3 +44,38 @@ func TestWebhookProxy(t *testing.T) { } } } + +func TestWebhookDeliverAuthorizationHeader(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + done := make(chan struct{}, 1) + s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "/webhook", r.URL.Path) + assert.Equal(t, "Bearer s3cr3t-t0ken", r.Header.Get("Authorization")) + w.WriteHeader(200) + done <- struct{}{} + })) + t.Cleanup(s.Close) + + hook := &webhook_model.Webhook{ + RepoID: 3, + URL: s.URL + "/webhook", + ContentType: webhook_model.ContentTypeJSON, + IsActive: true, + Type: webhook_model.GITEA, + } + err := hook.SetHeaderAuthorization("Bearer s3cr3t-t0ken") + assert.NoError(t, err) + assert.NoError(t, webhook_model.CreateWebhook(db.DefaultContext, hook)) + + hookTask := &webhook_model.HookTask{HookID: hook.ID, EventType: webhook_model.HookEventPush} + + assert.NoError(t, Deliver(context.Background(), hookTask)) + select { + case <-done: + case <-time.After(5 * time.Second): + t.Fatal("waited to long for request to happen") + } + + assert.True(t, hookTask.IsSucceed) +} diff --git a/services/webhook/main_test.go b/services/webhook/main_test.go index 1dc2e1bd8..5ddb6cf1f 100644 --- a/services/webhook/main_test.go +++ b/services/webhook/main_test.go @@ -9,6 +9,7 @@ import ( "testing" "code.gitea.io/gitea/models/unittest" + "code.gitea.io/gitea/modules/hostmatcher" "code.gitea.io/gitea/modules/setting" _ "code.gitea.io/gitea/models" @@ -17,6 +18,9 @@ import ( func TestMain(m *testing.M) { setting.LoadForTest() setting.NewQueueService() + + // for tests, allow only loopback IPs + setting.Webhook.AllowedHostList = hostmatcher.MatchBuiltinLoopback unittest.MainTest(m, &unittest.TestOptions{ GiteaRootPath: filepath.Join("..", ".."), SetUp: Init, diff --git a/services/webhook/matrix.go b/services/webhook/matrix.go index 6bbae7042..7ff8b1e63 100644 --- a/services/webhook/matrix.go +++ b/services/webhook/matrix.go @@ -6,10 +6,10 @@ package webhook import ( "crypto/sha1" + "encoding/hex" "errors" "fmt" "html" - "net/http" "net/url" "regexp" "strings" @@ -29,7 +29,6 @@ const matrixPayloadSizeLimit = 1024 * 64 type MatrixMeta struct { HomeserverURL string `json:"homeserver_url"` Room string `json:"room_id"` - AccessToken string `json:"access_token"` MessageType int `json:"message_type"` } @@ -47,27 +46,10 @@ func GetMatrixHook(w *webhook_model.Webhook) *MatrixMeta { return s } -// MatrixPayloadUnsafe contains the (unsafe) payload for a Matrix room -type MatrixPayloadUnsafe struct { - MatrixPayloadSafe - AccessToken string `json:"access_token"` -} +var _ PayloadConvertor = &MatrixPayload{} -var _ PayloadConvertor = &MatrixPayloadUnsafe{} - -// safePayload "converts" a unsafe payload to a safe payload -func (m *MatrixPayloadUnsafe) safePayload() *MatrixPayloadSafe { - return &MatrixPayloadSafe{ - Body: m.Body, - MsgType: m.MsgType, - Format: m.Format, - FormattedBody: m.FormattedBody, - Commits: m.Commits, - } -} - -// MatrixPayloadSafe contains (safe) payload for a Matrix room -type MatrixPayloadSafe struct { +// MatrixPayload contains payload for a Matrix room +type MatrixPayload struct { Body string `json:"body"` MsgType string `json:"msgtype"` Format string `json:"format"` @@ -75,8 +57,8 @@ type MatrixPayloadSafe struct { Commits []*api.PayloadCommit `json:"io.gitea.commits,omitempty"` } -// JSONPayload Marshals the MatrixPayloadUnsafe to json -func (m *MatrixPayloadUnsafe) JSONPayload() ([]byte, error) { +// JSONPayload Marshals the MatrixPayload to json +func (m *MatrixPayload) JSONPayload() ([]byte, error) { data, err := json.MarshalIndent(m, "", " ") if err != nil { return []byte{}, err @@ -103,62 +85,62 @@ func MatrixLinkToRef(repoURL, ref string) string { } // Create implements PayloadConvertor Create method -func (m *MatrixPayloadUnsafe) Create(p *api.CreatePayload) (api.Payloader, error) { +func (m *MatrixPayload) Create(p *api.CreatePayload) (api.Payloader, error) { repoLink := MatrixLinkFormatter(p.Repo.HTMLURL, p.Repo.FullName) refLink := MatrixLinkToRef(p.Repo.HTMLURL, p.Ref) text := fmt.Sprintf("[%s:%s] %s created by %s", repoLink, refLink, p.RefType, p.Sender.UserName) - return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil + return getMatrixPayload(text, nil, m.MsgType), nil } // Delete composes Matrix payload for delete a branch or tag. -func (m *MatrixPayloadUnsafe) Delete(p *api.DeletePayload) (api.Payloader, error) { +func (m *MatrixPayload) Delete(p *api.DeletePayload) (api.Payloader, error) { refName := git.RefEndName(p.Ref) repoLink := MatrixLinkFormatter(p.Repo.HTMLURL, p.Repo.FullName) text := fmt.Sprintf("[%s:%s] %s deleted by %s", repoLink, refName, p.RefType, p.Sender.UserName) - return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil + return getMatrixPayload(text, nil, m.MsgType), nil } // Fork composes Matrix payload for forked by a repository. -func (m *MatrixPayloadUnsafe) Fork(p *api.ForkPayload) (api.Payloader, error) { +func (m *MatrixPayload) Fork(p *api.ForkPayload) (api.Payloader, error) { baseLink := MatrixLinkFormatter(p.Forkee.HTMLURL, p.Forkee.FullName) forkLink := MatrixLinkFormatter(p.Repo.HTMLURL, p.Repo.FullName) text := fmt.Sprintf("%s is forked to %s", baseLink, forkLink) - return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil + return getMatrixPayload(text, nil, m.MsgType), nil } // Issue implements PayloadConvertor Issue method -func (m *MatrixPayloadUnsafe) Issue(p *api.IssuePayload) (api.Payloader, error) { +func (m *MatrixPayload) Issue(p *api.IssuePayload) (api.Payloader, error) { text, _, _, _ := getIssuesPayloadInfo(p, MatrixLinkFormatter, true) - return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil + return getMatrixPayload(text, nil, m.MsgType), nil } // IssueComment implements PayloadConvertor IssueComment method -func (m *MatrixPayloadUnsafe) IssueComment(p *api.IssueCommentPayload) (api.Payloader, error) { +func (m *MatrixPayload) IssueComment(p *api.IssueCommentPayload) (api.Payloader, error) { text, _, _ := getIssueCommentPayloadInfo(p, MatrixLinkFormatter, true) - return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil + return getMatrixPayload(text, nil, m.MsgType), nil } // Wiki implements PayloadConvertor Wiki method -func (m *MatrixPayloadUnsafe) Wiki(p *api.WikiPayload) (api.Payloader, error) { +func (m *MatrixPayload) Wiki(p *api.WikiPayload) (api.Payloader, error) { text, _, _ := getWikiPayloadInfo(p, MatrixLinkFormatter, true) - return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil + return getMatrixPayload(text, nil, m.MsgType), nil } // Release implements PayloadConvertor Release method -func (m *MatrixPayloadUnsafe) Release(p *api.ReleasePayload) (api.Payloader, error) { +func (m *MatrixPayload) Release(p *api.ReleasePayload) (api.Payloader, error) { text, _ := getReleasePayloadInfo(p, MatrixLinkFormatter, true) - return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil + return getMatrixPayload(text, nil, m.MsgType), nil } // Push implements PayloadConvertor Push method -func (m *MatrixPayloadUnsafe) Push(p *api.PushPayload) (api.Payloader, error) { +func (m *MatrixPayload) Push(p *api.PushPayload) (api.Payloader, error) { var commitDesc string if p.TotalCommits == 1 { @@ -181,18 +163,18 @@ func (m *MatrixPayloadUnsafe) Push(p *api.PushPayload) (api.Payloader, error) { } - return getMatrixPayloadUnsafe(text, p.Commits, m.AccessToken, m.MsgType), nil + return getMatrixPayload(text, p.Commits, m.MsgType), nil } // PullRequest implements PayloadConvertor PullRequest method -func (m *MatrixPayloadUnsafe) PullRequest(p *api.PullRequestPayload) (api.Payloader, error) { +func (m *MatrixPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, error) { text, _, _, _ := getPullRequestPayloadInfo(p, MatrixLinkFormatter, true) - return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil + return getMatrixPayload(text, nil, m.MsgType), nil } // Review implements PayloadConvertor Review method -func (m *MatrixPayloadUnsafe) Review(p *api.PullRequestPayload, event webhook_model.HookEventType) (api.Payloader, error) { +func (m *MatrixPayload) Review(p *api.PullRequestPayload, event webhook_model.HookEventType) (api.Payloader, error) { senderLink := MatrixLinkFormatter(setting.AppURL+url.PathEscape(p.Sender.UserName), p.Sender.UserName) title := fmt.Sprintf("#%d %s", p.Index, p.PullRequest.Title) titleLink := MatrixLinkFormatter(p.PullRequest.URL, title) @@ -209,11 +191,11 @@ func (m *MatrixPayloadUnsafe) Review(p *api.PullRequestPayload, event webhook_mo text = fmt.Sprintf("[%s] Pull request review %s: %s by %s", repoLink, action, titleLink, senderLink) } - return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil + return getMatrixPayload(text, nil, m.MsgType), nil } // Repository implements PayloadConvertor Repository method -func (m *MatrixPayloadUnsafe) Repository(p *api.RepositoryPayload) (api.Payloader, error) { +func (m *MatrixPayload) Repository(p *api.RepositoryPayload) (api.Payloader, error) { senderLink := MatrixLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName) repoLink := MatrixLinkFormatter(p.Repository.HTMLURL, p.Repository.FullName) var text string @@ -225,27 +207,25 @@ func (m *MatrixPayloadUnsafe) Repository(p *api.RepositoryPayload) (api.Payloade text = fmt.Sprintf("[%s] Repository deleted by %s", repoLink, senderLink) } - return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil + return getMatrixPayload(text, nil, m.MsgType), nil } -// GetMatrixPayload converts a Matrix webhook into a MatrixPayloadUnsafe +// GetMatrixPayload converts a Matrix webhook into a MatrixPayload func GetMatrixPayload(p api.Payloader, event webhook_model.HookEventType, meta string) (api.Payloader, error) { - s := new(MatrixPayloadUnsafe) + s := new(MatrixPayload) matrix := &MatrixMeta{} if err := json.Unmarshal([]byte(meta), &matrix); err != nil { return s, errors.New("GetMatrixPayload meta json:" + err.Error()) } - s.AccessToken = matrix.AccessToken s.MsgType = messageTypeText[matrix.MessageType] return convertPayloader(s, p, event) } -func getMatrixPayloadUnsafe(text string, commits []*api.PayloadCommit, accessToken, msgType string) *MatrixPayloadUnsafe { - p := MatrixPayloadUnsafe{} - p.AccessToken = accessToken +func getMatrixPayload(text string, commits []*api.PayloadCommit, msgType string) *MatrixPayload { + p := MatrixPayload{} p.FormattedBody = text p.Body = getMessageBody(text) p.Format = "org.matrix.custom.html" @@ -262,52 +242,17 @@ func getMessageBody(htmlText string) string { return htmlText } -// getMatrixHookRequest creates a new request which contains an Authorization header. -// The access_token is removed from t.PayloadContent -func getMatrixHookRequest(w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, error) { - payloadunsafe := MatrixPayloadUnsafe{} - if err := json.Unmarshal([]byte(t.PayloadContent), &payloadunsafe); err != nil { - log.Error("Matrix Hook delivery failed: %v", err) - return nil, err - } - - payloadsafe := payloadunsafe.safePayload() - - var payload []byte - var err error - if payload, err = json.MarshalIndent(payloadsafe, "", " "); err != nil { - return nil, err - } - if len(payload) >= matrixPayloadSizeLimit { - return nil, fmt.Errorf("getMatrixHookRequest: payload size %d > %d", len(payload), matrixPayloadSizeLimit) - } - t.PayloadContent = string(payload) - - txnID, err := getMatrixTxnID(payload) - if err != nil { - return nil, fmt.Errorf("getMatrixHookRequest: unable to hash payload: %+v", err) - } - - url := fmt.Sprintf("%s/%s", w.URL, url.PathEscape(txnID)) - - req, err := http.NewRequest(w.HTTPMethod, url, strings.NewReader(string(payload))) - if err != nil { - return nil, err - } - - req.Header.Set("Content-Type", "application/json") - req.Header.Add("Authorization", "Bearer "+payloadunsafe.AccessToken) - - return req, nil -} - -// getMatrixTxnID creates a txnID based on the payload to ensure idempotency +// getMatrixTxnID computes the transaction ID to ensure idempotency func getMatrixTxnID(payload []byte) (string, error) { + if len(payload) >= matrixPayloadSizeLimit { + return "", fmt.Errorf("getMatrixTxnID: payload size %d > %d", len(payload), matrixPayloadSizeLimit) + } + h := sha1.New() _, err := h.Write(payload) if err != nil { return "", err } - return fmt.Sprintf("%x", h.Sum(nil)), nil + return hex.EncodeToString(h.Sum(nil)), nil } diff --git a/services/webhook/matrix_test.go b/services/webhook/matrix_test.go index 624986ee9..bbcdef356 100644 --- a/services/webhook/matrix_test.go +++ b/services/webhook/matrix_test.go @@ -18,275 +18,203 @@ func TestMatrixPayload(t *testing.T) { t.Run("Create", func(t *testing.T) { p := createTestPayload() - d := new(MatrixPayloadUnsafe) + d := new(MatrixPayload) pl, err := d.Create(p) require.NoError(t, err) require.NotNil(t, pl) - require.IsType(t, &MatrixPayloadUnsafe{}, pl) + require.IsType(t, &MatrixPayload{}, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo):[test](http://localhost:3000/test/repo/src/branch/test)] branch created by user1", pl.(*MatrixPayloadUnsafe).Body) - assert.Equal(t, `[test/repo:test] branch created by user1`, pl.(*MatrixPayloadUnsafe).FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo):[test](http://localhost:3000/test/repo/src/branch/test)] branch created by user1", pl.(*MatrixPayload).Body) + assert.Equal(t, `[test/repo:test] branch created by user1`, pl.(*MatrixPayload).FormattedBody) }) t.Run("Delete", func(t *testing.T) { p := deleteTestPayload() - d := new(MatrixPayloadUnsafe) + d := new(MatrixPayload) pl, err := d.Delete(p) require.NoError(t, err) require.NotNil(t, pl) - require.IsType(t, &MatrixPayloadUnsafe{}, pl) + require.IsType(t, &MatrixPayload{}, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo):test] branch deleted by user1", pl.(*MatrixPayloadUnsafe).Body) - assert.Equal(t, `[test/repo:test] branch deleted by user1`, pl.(*MatrixPayloadUnsafe).FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo):test] branch deleted by user1", pl.(*MatrixPayload).Body) + assert.Equal(t, `[test/repo:test] branch deleted by user1`, pl.(*MatrixPayload).FormattedBody) }) t.Run("Fork", func(t *testing.T) { p := forkTestPayload() - d := new(MatrixPayloadUnsafe) + d := new(MatrixPayload) pl, err := d.Fork(p) require.NoError(t, err) require.NotNil(t, pl) - require.IsType(t, &MatrixPayloadUnsafe{}, pl) + require.IsType(t, &MatrixPayload{}, pl) - assert.Equal(t, "[test/repo2](http://localhost:3000/test/repo2) is forked to [test/repo](http://localhost:3000/test/repo)", pl.(*MatrixPayloadUnsafe).Body) - assert.Equal(t, `test/repo2 is forked to test/repo`, pl.(*MatrixPayloadUnsafe).FormattedBody) + assert.Equal(t, "[test/repo2](http://localhost:3000/test/repo2) is forked to [test/repo](http://localhost:3000/test/repo)", pl.(*MatrixPayload).Body) + assert.Equal(t, `test/repo2 is forked to test/repo`, pl.(*MatrixPayload).FormattedBody) }) t.Run("Push", func(t *testing.T) { p := pushTestPayload() - d := new(MatrixPayloadUnsafe) + d := new(MatrixPayload) pl, err := d.Push(p) require.NoError(t, err) require.NotNil(t, pl) - require.IsType(t, &MatrixPayloadUnsafe{}, pl) + require.IsType(t, &MatrixPayload{}, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] user1 pushed 2 commits to [test](http://localhost:3000/test/repo/src/branch/test):\n[2020558](http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778): commit message - user1\n[2020558](http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778): commit message - user1", pl.(*MatrixPayloadUnsafe).Body) - assert.Equal(t, `[test/repo] user1 pushed 2 commits to test:
2020558: commit message - user1
2020558: commit message - user1`, pl.(*MatrixPayloadUnsafe).FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] user1 pushed 2 commits to [test](http://localhost:3000/test/repo/src/branch/test):\n[2020558](http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778): commit message - user1\n[2020558](http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778): commit message - user1", pl.(*MatrixPayload).Body) + assert.Equal(t, `[test/repo] user1 pushed 2 commits to test:
2020558: commit message - user1
2020558: commit message - user1`, pl.(*MatrixPayload).FormattedBody) }) t.Run("Issue", func(t *testing.T) { p := issueTestPayload() - d := new(MatrixPayloadUnsafe) + d := new(MatrixPayload) p.Action = api.HookIssueOpened pl, err := d.Issue(p) require.NoError(t, err) require.NotNil(t, pl) - require.IsType(t, &MatrixPayloadUnsafe{}, pl) + require.IsType(t, &MatrixPayload{}, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Issue opened: [#2 crash](http://localhost:3000/test/repo/issues/2) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body) - assert.Equal(t, `[test/repo] Issue opened: #2 crash by user1`, pl.(*MatrixPayloadUnsafe).FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Issue opened: [#2 crash](http://localhost:3000/test/repo/issues/2) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayload).Body) + assert.Equal(t, `[test/repo] Issue opened: #2 crash by user1`, pl.(*MatrixPayload).FormattedBody) p.Action = api.HookIssueClosed pl, err = d.Issue(p) require.NoError(t, err) require.NotNil(t, pl) - require.IsType(t, &MatrixPayloadUnsafe{}, pl) + require.IsType(t, &MatrixPayload{}, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Issue closed: [#2 crash](http://localhost:3000/test/repo/issues/2) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body) - assert.Equal(t, `[test/repo] Issue closed: #2 crash by user1`, pl.(*MatrixPayloadUnsafe).FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Issue closed: [#2 crash](http://localhost:3000/test/repo/issues/2) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayload).Body) + assert.Equal(t, `[test/repo] Issue closed: #2 crash by user1`, pl.(*MatrixPayload).FormattedBody) }) t.Run("IssueComment", func(t *testing.T) { p := issueCommentTestPayload() - d := new(MatrixPayloadUnsafe) + d := new(MatrixPayload) pl, err := d.IssueComment(p) require.NoError(t, err) require.NotNil(t, pl) - require.IsType(t, &MatrixPayloadUnsafe{}, pl) + require.IsType(t, &MatrixPayload{}, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] New comment on issue [#2 crash](http://localhost:3000/test/repo/issues/2) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body) - assert.Equal(t, `[test/repo] New comment on issue #2 crash by user1`, pl.(*MatrixPayloadUnsafe).FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] New comment on issue [#2 crash](http://localhost:3000/test/repo/issues/2) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayload).Body) + assert.Equal(t, `[test/repo] New comment on issue #2 crash by user1`, pl.(*MatrixPayload).FormattedBody) }) t.Run("PullRequest", func(t *testing.T) { p := pullRequestTestPayload() - d := new(MatrixPayloadUnsafe) + d := new(MatrixPayload) pl, err := d.PullRequest(p) require.NoError(t, err) require.NotNil(t, pl) - require.IsType(t, &MatrixPayloadUnsafe{}, pl) + require.IsType(t, &MatrixPayload{}, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Pull request opened: [#12 Fix bug](http://localhost:3000/test/repo/pulls/12) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body) - assert.Equal(t, `[test/repo] Pull request opened: #12 Fix bug by user1`, pl.(*MatrixPayloadUnsafe).FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Pull request opened: [#12 Fix bug](http://localhost:3000/test/repo/pulls/12) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayload).Body) + assert.Equal(t, `[test/repo] Pull request opened: #12 Fix bug by user1`, pl.(*MatrixPayload).FormattedBody) }) t.Run("PullRequestComment", func(t *testing.T) { p := pullRequestCommentTestPayload() - d := new(MatrixPayloadUnsafe) + d := new(MatrixPayload) pl, err := d.IssueComment(p) require.NoError(t, err) require.NotNil(t, pl) - require.IsType(t, &MatrixPayloadUnsafe{}, pl) + require.IsType(t, &MatrixPayload{}, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] New comment on pull request [#12 Fix bug](http://localhost:3000/test/repo/pulls/12) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body) - assert.Equal(t, `[test/repo] New comment on pull request #12 Fix bug by user1`, pl.(*MatrixPayloadUnsafe).FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] New comment on pull request [#12 Fix bug](http://localhost:3000/test/repo/pulls/12) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayload).Body) + assert.Equal(t, `[test/repo] New comment on pull request #12 Fix bug by user1`, pl.(*MatrixPayload).FormattedBody) }) t.Run("Review", func(t *testing.T) { p := pullRequestTestPayload() p.Action = api.HookIssueReviewed - d := new(MatrixPayloadUnsafe) + d := new(MatrixPayload) pl, err := d.Review(p, webhook_model.HookEventPullRequestReviewApproved) require.NoError(t, err) require.NotNil(t, pl) - require.IsType(t, &MatrixPayloadUnsafe{}, pl) + require.IsType(t, &MatrixPayload{}, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Pull request review approved: [#12 Fix bug](http://localhost:3000/test/repo/pulls/12) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body) - assert.Equal(t, `[test/repo] Pull request review approved: #12 Fix bug by user1`, pl.(*MatrixPayloadUnsafe).FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Pull request review approved: [#12 Fix bug](http://localhost:3000/test/repo/pulls/12) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayload).Body) + assert.Equal(t, `[test/repo] Pull request review approved: #12 Fix bug by user1`, pl.(*MatrixPayload).FormattedBody) }) t.Run("Repository", func(t *testing.T) { p := repositoryTestPayload() - d := new(MatrixPayloadUnsafe) + d := new(MatrixPayload) pl, err := d.Repository(p) require.NoError(t, err) require.NotNil(t, pl) - require.IsType(t, &MatrixPayloadUnsafe{}, pl) + require.IsType(t, &MatrixPayload{}, pl) - assert.Equal(t, `[[test/repo](http://localhost:3000/test/repo)] Repository created by [user1](https://try.gitea.io/user1)`, pl.(*MatrixPayloadUnsafe).Body) - assert.Equal(t, `[test/repo] Repository created by user1`, pl.(*MatrixPayloadUnsafe).FormattedBody) + assert.Equal(t, `[[test/repo](http://localhost:3000/test/repo)] Repository created by [user1](https://try.gitea.io/user1)`, pl.(*MatrixPayload).Body) + assert.Equal(t, `[test/repo] Repository created by user1`, pl.(*MatrixPayload).FormattedBody) }) t.Run("Wiki", func(t *testing.T) { p := wikiTestPayload() - d := new(MatrixPayloadUnsafe) + d := new(MatrixPayload) p.Action = api.HookWikiCreated pl, err := d.Wiki(p) require.NoError(t, err) require.NotNil(t, pl) - require.IsType(t, &MatrixPayloadUnsafe{}, pl) + require.IsType(t, &MatrixPayload{}, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] New wiki page '[index](http://localhost:3000/test/repo/wiki/index)' (Wiki change comment) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body) - assert.Equal(t, `[test/repo] New wiki page 'index' (Wiki change comment) by user1`, pl.(*MatrixPayloadUnsafe).FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] New wiki page '[index](http://localhost:3000/test/repo/wiki/index)' (Wiki change comment) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayload).Body) + assert.Equal(t, `[test/repo] New wiki page 'index' (Wiki change comment) by user1`, pl.(*MatrixPayload).FormattedBody) p.Action = api.HookWikiEdited pl, err = d.Wiki(p) require.NoError(t, err) require.NotNil(t, pl) - require.IsType(t, &MatrixPayloadUnsafe{}, pl) + require.IsType(t, &MatrixPayload{}, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Wiki page '[index](http://localhost:3000/test/repo/wiki/index)' edited (Wiki change comment) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body) - assert.Equal(t, `[test/repo] Wiki page 'index' edited (Wiki change comment) by user1`, pl.(*MatrixPayloadUnsafe).FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Wiki page '[index](http://localhost:3000/test/repo/wiki/index)' edited (Wiki change comment) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayload).Body) + assert.Equal(t, `[test/repo] Wiki page 'index' edited (Wiki change comment) by user1`, pl.(*MatrixPayload).FormattedBody) p.Action = api.HookWikiDeleted pl, err = d.Wiki(p) require.NoError(t, err) require.NotNil(t, pl) - require.IsType(t, &MatrixPayloadUnsafe{}, pl) + require.IsType(t, &MatrixPayload{}, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Wiki page '[index](http://localhost:3000/test/repo/wiki/index)' deleted by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body) - assert.Equal(t, `[test/repo] Wiki page 'index' deleted by user1`, pl.(*MatrixPayloadUnsafe).FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Wiki page '[index](http://localhost:3000/test/repo/wiki/index)' deleted by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayload).Body) + assert.Equal(t, `[test/repo] Wiki page 'index' deleted by user1`, pl.(*MatrixPayload).FormattedBody) }) t.Run("Release", func(t *testing.T) { p := pullReleaseTestPayload() - d := new(MatrixPayloadUnsafe) + d := new(MatrixPayload) pl, err := d.Release(p) require.NoError(t, err) require.NotNil(t, pl) - require.IsType(t, &MatrixPayloadUnsafe{}, pl) + require.IsType(t, &MatrixPayload{}, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Release created: [v1.0](http://localhost:3000/test/repo/releases/tag/v1.0) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body) - assert.Equal(t, `[test/repo] Release created: v1.0 by user1`, pl.(*MatrixPayloadUnsafe).FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Release created: [v1.0](http://localhost:3000/test/repo/releases/tag/v1.0) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayload).Body) + assert.Equal(t, `[test/repo] Release created: v1.0 by user1`, pl.(*MatrixPayload).FormattedBody) }) } func TestMatrixJSONPayload(t *testing.T) { p := pushTestPayload() - pl, err := new(MatrixPayloadUnsafe).Push(p) + pl, err := new(MatrixPayload).Push(p) require.NoError(t, err) require.NotNil(t, pl) - require.IsType(t, &MatrixPayloadUnsafe{}, pl) + require.IsType(t, &MatrixPayload{}, pl) json, err := pl.JSONPayload() require.NoError(t, err) assert.NotEmpty(t, json) } -func TestMatrixHookRequest(t *testing.T) { - w := &webhook_model.Webhook{} - - h := &webhook_model.HookTask{ - PayloadContent: `{ - "body": "[[user1/test](http://localhost:3000/user1/test)] user1 pushed 1 commit to [master](http://localhost:3000/user1/test/src/branch/master):\n[5175ef2](http://localhost:3000/user1/test/commit/5175ef26201c58b035a3404b3fe02b4e8d436eee): Merge pull request 'Change readme.md' (#2) from add-matrix-webhook into master\n\nReviewed-on: http://localhost:3000/user1/test/pulls/2\n - user1", - "msgtype": "m.notice", - "format": "org.matrix.custom.html", - "formatted_body": "[\u003ca href=\"http://localhost:3000/user1/test\"\u003euser1/test\u003c/a\u003e] user1 pushed 1 commit to \u003ca href=\"http://localhost:3000/user1/test/src/branch/master\"\u003emaster\u003c/a\u003e:\u003cbr\u003e\u003ca href=\"http://localhost:3000/user1/test/commit/5175ef26201c58b035a3404b3fe02b4e8d436eee\"\u003e5175ef2\u003c/a\u003e: Merge pull request 'Change readme.md' (#2) from add-matrix-webhook into master\n\nReviewed-on: http://localhost:3000/user1/test/pulls/2\n - user1", - "io.gitea.commits": [ - { - "id": "5175ef26201c58b035a3404b3fe02b4e8d436eee", - "message": "Merge pull request 'Change readme.md' (#2) from add-matrix-webhook into master\n\nReviewed-on: http://localhost:3000/user1/test/pulls/2\n", - "url": "http://localhost:3000/user1/test/commit/5175ef26201c58b035a3404b3fe02b4e8d436eee", - "author": { - "name": "user1", - "email": "user@mail.com", - "username": "" - }, - "committer": { - "name": "user1", - "email": "user@mail.com", - "username": "" - }, - "verification": null, - "timestamp": "0001-01-01T00:00:00Z", - "added": null, - "removed": null, - "modified": null - } - ], - "access_token": "dummy_access_token" -}`, - } - - wantPayloadContent := `{ - "body": "[[user1/test](http://localhost:3000/user1/test)] user1 pushed 1 commit to [master](http://localhost:3000/user1/test/src/branch/master):\n[5175ef2](http://localhost:3000/user1/test/commit/5175ef26201c58b035a3404b3fe02b4e8d436eee): Merge pull request 'Change readme.md' (#2) from add-matrix-webhook into master\n\nReviewed-on: http://localhost:3000/user1/test/pulls/2\n - user1", - "msgtype": "m.notice", - "format": "org.matrix.custom.html", - "formatted_body": "[\u003ca href=\"http://localhost:3000/user1/test\"\u003euser1/test\u003c/a\u003e] user1 pushed 1 commit to \u003ca href=\"http://localhost:3000/user1/test/src/branch/master\"\u003emaster\u003c/a\u003e:\u003cbr\u003e\u003ca href=\"http://localhost:3000/user1/test/commit/5175ef26201c58b035a3404b3fe02b4e8d436eee\"\u003e5175ef2\u003c/a\u003e: Merge pull request 'Change readme.md' (#2) from add-matrix-webhook into master\n\nReviewed-on: http://localhost:3000/user1/test/pulls/2\n - user1", - "io.gitea.commits": [ - { - "id": "5175ef26201c58b035a3404b3fe02b4e8d436eee", - "message": "Merge pull request 'Change readme.md' (#2) from add-matrix-webhook into master\n\nReviewed-on: http://localhost:3000/user1/test/pulls/2\n", - "url": "http://localhost:3000/user1/test/commit/5175ef26201c58b035a3404b3fe02b4e8d436eee", - "author": { - "name": "user1", - "email": "user@mail.com", - "username": "" - }, - "committer": { - "name": "user1", - "email": "user@mail.com", - "username": "" - }, - "verification": null, - "timestamp": "0001-01-01T00:00:00Z", - "added": null, - "removed": null, - "modified": null - } - ] -}` - - req, err := getMatrixHookRequest(w, h) - require.NoError(t, err) - require.NotNil(t, req) - - assert.Equal(t, "Bearer dummy_access_token", req.Header.Get("Authorization")) - assert.Equal(t, wantPayloadContent, h.PayloadContent) -} - func Test_getTxnID(t *testing.T) { type args struct { payload []byte diff --git a/templates/install.tmpl b/templates/install.tmpl index 36f58218d..0625f43cc 100644 --- a/templates/install.tmpl +++ b/templates/install.tmpl @@ -162,6 +162,13 @@ {{.locale.Tr "install.log_root_path_helper"}} +
+
+ + +
+ {{.locale.Tr "install.enable_update_checker_helper"}} +
@@ -195,13 +202,13 @@
- +
- +
@@ -214,73 +221,73 @@
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
diff --git a/templates/repo/branch/list.tmpl b/templates/repo/branch/list.tmpl index 09799fbec..2e1878acc 100644 --- a/templates/repo/branch/list.tmpl +++ b/templates/repo/branch/list.tmpl @@ -106,7 +106,7 @@ {{end}} {{end}} - + {{if and $.IsWriter (not $.Repository.IsArchived) (not .IsDeleted)}}
{{svg "octicon-git-branch"}} diff --git a/templates/repo/pulls/status.tmpl b/templates/repo/pulls/status.tmpl index b68802cd5..ca090ee84 100644 --- a/templates/repo/pulls/status.tmpl +++ b/templates/repo/pulls/status.tmpl @@ -18,14 +18,16 @@ {{end}} {{range $.LatestCommitStatuses}} -
- {{template "repo/commit_status" .}} - {{.Context}} {{.Description}} -
- {{if $.is_context_required}} - {{if (call $.is_context_required .Context)}}
{{$.locale.Tr "repo.pulls.status_checks_requested"}}
{{end}} - {{end}} - {{if .TargetURL}}{{$.locale.Tr "repo.pulls.status_checks_details"}}{{end}} +
+ {{template "repo/commit_status" .}} +
+ {{.Context}} {{.Description}} +
+ {{if $.is_context_required}} + {{if (call $.is_context_required .Context)}}
{{$.locale.Tr "repo.pulls.status_checks_requested"}}
{{end}} + {{end}} + {{if .TargetURL}}{{$.locale.Tr "repo.pulls.status_checks_details"}}{{end}} +
{{end}} diff --git a/templates/repo/settings/webhook/matrix.tmpl b/templates/repo/settings/webhook/matrix.tmpl index 8edab870c..d3ab5588b 100644 --- a/templates/repo/settings/webhook/matrix.tmpl +++ b/templates/repo/settings/webhook/matrix.tmpl @@ -10,10 +10,6 @@
-
- - -
+ +
+ + + {{if ne .HookType "matrix"}}{{/* Matrix doesn't make the authorization optional but it is implied by the help string, should be changed.*/}} + {{.locale.Tr "repo.settings.authorization_header_desc" "Bearer token123456, Basic YWxhZGRpbjpvcGVuc2VzYW1l" | Str2html}} + {{end}} +
+
diff --git a/templates/repo/view_file.tmpl b/templates/repo/view_file.tmpl index 2b4f279cb..60d2a812d 100644 --- a/templates/repo/view_file.tmpl +++ b/templates/repo/view_file.tmpl @@ -60,6 +60,11 @@ {{end}}
{{svg "octicon-download"}} + {{if or .IsMarkup .IsRenderedHTML (not .IsTextSource)}} + {{svg "octicon-copy" 14}} + {{else}} + {{svg "octicon-copy" 14}} + {{end}} {{if .Repository.CanEnableEditor}} {{if .CanEditFile}} {{svg "octicon-pencil"}} diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index eb9f2f815..74673da4d 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -14698,6 +14698,10 @@ "default": false, "x-go-name": "Active" }, + "authorization_header": { + "type": "string", + "x-go-name": "AuthorizationHeader" + }, "branch_filter": { "type": "string", "x-go-name": "BranchFilter" @@ -15687,6 +15691,10 @@ "type": "boolean", "x-go-name": "Active" }, + "authorization_header": { + "type": "string", + "x-go-name": "AuthorizationHeader" + }, "branch_filter": { "type": "string", "x-go-name": "BranchFilter" @@ -16794,6 +16802,10 @@ "type": "boolean", "x-go-name": "Active" }, + "authorization_header": { + "type": "string", + "x-go-name": "AuthorizationHeader" + }, "config": { "type": "object", "additionalProperties": { diff --git a/tests/integration/api_packages_pypi_test.go b/tests/integration/api_packages_pypi_test.go index 32b3304ca..0cd6ff7d1 100644 --- a/tests/integration/api_packages_pypi_test.go +++ b/tests/integration/api_packages_pypi_test.go @@ -29,7 +29,7 @@ func TestPackagePyPI(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) packageName := "test-package" - packageVersion := "1.0.1" + packageVersion := "1.0.1+r1234" packageAuthor := "KN4CK3R" packageDescription := "Test Description" @@ -164,7 +164,7 @@ func TestPackagePyPI(t *testing.T) { nodes := htmlDoc.doc.Find("a").Nodes assert.Len(t, nodes, 2) - hrefMatcher := regexp.MustCompile(fmt.Sprintf(`%s/files/%s/%s/test\..+#sha256-%s`, root, packageName, packageVersion, hashSHA256)) + hrefMatcher := regexp.MustCompile(fmt.Sprintf(`%s/files/%s/%s/test\..+#sha256-%s`, root, regexp.QuoteMeta(packageName), regexp.QuoteMeta(packageVersion), hashSHA256)) for _, a := range nodes { for _, att := range a.Attr { diff --git a/tests/integration/api_repo_hook_test.go b/tests/integration/api_repo_hook_test.go new file mode 100644 index 000000000..e503834e1 --- /dev/null +++ b/tests/integration/api_repo_hook_test.go @@ -0,0 +1,47 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package integration + +import ( + "fmt" + "net/http" + "testing" + + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unittest" + user_model "code.gitea.io/gitea/models/user" + api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/tests" + + "github.com/stretchr/testify/assert" +) + +func TestAPICreateHook(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 37}) + owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) + + // user1 is an admin user + session := loginUser(t, "user1") + token := getTokenForLoggedInUser(t, session) + completeURL := func(lastSegment string) string { + return fmt.Sprintf("/api/v1/repos/%s/%s/%s?token=%s", owner.Name, repo.Name, lastSegment, token) + } + req := NewRequestWithJSON(t, "POST", completeURL("hooks"), api.CreateHookOption{ + Type: "gitea", + Config: api.CreateHookOptionConfig{ + "content_type": "json", + "url": "http://example.com/", + }, + AuthorizationHeader: "Bearer s3cr3t", + }) + resp := MakeRequest(t, req, http.StatusCreated) + + var apiHook *api.Hook + DecodeJSON(t, resp, &apiHook) + assert.Equal(t, "http://example.com/", apiHook.Config["url"]) + assert.Equal(t, "Bearer s3cr3t", apiHook.AuthorizationHeader) +} diff --git a/tests/integration/migration-test/migration_test.go b/tests/integration/migration-test/migration_test.go index b63116834..0159fb4f3 100644 --- a/tests/integration/migration-test/migration_test.go +++ b/tests/integration/migration-test/migration_test.go @@ -20,6 +20,7 @@ import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/migrations" + migrate_base "code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/charset" @@ -302,7 +303,7 @@ func doMigrationTest(t *testing.T, version string) { err = db.InitEngineWithMigration(context.Background(), func(x *xorm.Engine) error { currentEngine = x - return migrations.RecreateTables(beans...)(x) + return migrate_base.RecreateTables(beans...)(x) }) assert.NoError(t, err) currentEngine.Close() @@ -310,7 +311,7 @@ func doMigrationTest(t *testing.T, version string) { // We do this a second time to ensure that there is not a problem with retained indices err = db.InitEngineWithMigration(context.Background(), func(x *xorm.Engine) error { currentEngine = x - return migrations.RecreateTables(beans...)(x) + return migrate_base.RecreateTables(beans...)(x) }) assert.NoError(t, err) diff --git a/tests/integration/pull_merge_test.go b/tests/integration/pull_merge_test.go index 9bd430084..bec85e8a8 100644 --- a/tests/integration/pull_merge_test.go +++ b/tests/integration/pull_merge_test.go @@ -245,11 +245,11 @@ func TestCantMergeConflict(t *testing.T) { gitRepo, err := git.OpenRepository(git.DefaultContext, repo_model.RepoPath(user1.Name, repo1.Name)) assert.NoError(t, err) - err = pull.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleMerge, "", "CONFLICT") + err = pull.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleMerge, "", "CONFLICT", false) assert.Error(t, err, "Merge should return an error due to conflict") assert.True(t, models.IsErrMergeConflicts(err), "Merge error is not a conflict error") - err = pull.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleRebase, "", "CONFLICT") + err = pull.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleRebase, "", "CONFLICT", false) assert.Error(t, err, "Merge should return an error due to conflict") assert.True(t, models.IsErrRebaseConflicts(err), "Merge error is not a conflict error") gitRepo.Close() @@ -344,7 +344,7 @@ func TestCantMergeUnrelated(t *testing.T) { BaseBranch: "base", }) - err = pull.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleMerge, "", "UNRELATED") + err = pull.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleMerge, "", "UNRELATED", false) assert.Error(t, err, "Merge should return an error due to unrelated") assert.True(t, models.IsErrMergeUnrelatedHistories(err), "Merge error is not a unrelated histories error") gitRepo.Close() diff --git a/tests/integration/user_test.go b/tests/integration/user_test.go index 110f5c89b..017700ad4 100644 --- a/tests/integration/user_test.go +++ b/tests/integration/user_test.go @@ -53,6 +53,22 @@ func TestRenameInvalidUsername(t *testing.T) { "%00", "thisHas ASpace", "ptho>lo [], }, + locale: { + type: Object, + default: () => {}, + } }, data: () => ({ colorRange: [ @@ -36,10 +40,6 @@ export default { 'var(--color-primary-dark-4)', ], endDate: new Date(), - locale: { - contributions: 'contributions', - no_contributions: 'No contributions', - }, }), computed: { sum() { diff --git a/web_src/js/features/heatmap.js b/web_src/js/features/heatmap.js index 6e6202e86..368ddd0d7 100644 --- a/web_src/js/features/heatmap.js +++ b/web_src/js/features/heatmap.js @@ -1,6 +1,6 @@ import {createApp} from 'vue'; import ActivityHeatmap from '../components/ActivityHeatmap.vue'; - +import {translateMonth, translateDay} from '../utils.js'; export default function initHeatmap() { const el = document.getElementById('user-heatmap'); if (!el) return; @@ -17,7 +17,14 @@ export default function initHeatmap() { return {date: new Date(v), count: heatmap[v]}; }); - const View = createApp(ActivityHeatmap, {values}); + const locale = { + months: new Array(12).fill().map((_, idx) => translateMonth(idx)), + days: new Array(7).fill().map((_, idx) => translateDay(idx)), + contributions: 'contributions', + no_contributions: 'No contributions', + }; + + const View = createApp(ActivityHeatmap, {values, locale}); View.mount(el); } catch (err) { diff --git a/web_src/js/features/repo-code.js b/web_src/js/features/repo-code.js index 002a25f6e..ad2703637 100644 --- a/web_src/js/features/repo-code.js +++ b/web_src/js/features/repo-code.js @@ -1,9 +1,11 @@ import $ from 'jquery'; import {svg} from '../svg.js'; import {invertFileFolding} from './file-fold.js'; -import {createTippy} from '../modules/tippy.js'; +import {createTippy, showTemporaryTooltip} from '../modules/tippy.js'; import {copyToClipboard} from './clipboard.js'; +const {i18n} = window.config; + function changeHash(hash) { if (window.history.pushState) { window.history.pushState(null, null, hash); @@ -110,6 +112,18 @@ function showLineButton() { }); } +function initCopyFileContent() { + // get raw text for copy content button, at the moment, only one button (and one related file content) is supported. + const copyFileContent = document.querySelector('#copy-file-content'); + if (!copyFileContent) return; + + copyFileContent.addEventListener('click', async () => { + const text = Array.from(document.querySelectorAll('.file-view .lines-code')).map((el) => el.textContent).join(''); + const success = await copyToClipboard(text); + showTemporaryTooltip(copyFileContent, success ? i18n.copy_success : i18n.copy_error); + }); +} + export function initRepoCodeView() { if ($('.code-view .lines-num').length > 0) { $(document).on('click', '.lines-num span', function (e) { @@ -185,4 +199,5 @@ export function initRepoCodeView() { if (!success) return; document.querySelector('.code-line-button')?._tippy?.hide(); }); + initCopyFileContent(); } diff --git a/web_src/js/markup/mermaid.js b/web_src/js/markup/mermaid.js index 62de9a3aa..984946045 100644 --- a/web_src/js/markup/mermaid.js +++ b/web_src/js/markup/mermaid.js @@ -2,6 +2,7 @@ import {isDarkTheme} from '../utils.js'; const {mermaidMaxSourceCharacters} = window.config; const iframeCss = ` + :root {color-scheme: normal} body {margin: 0; padding: 0} #mermaid {display: block; margin: 0 auto} `; diff --git a/web_src/js/utils.js b/web_src/js/utils.js index 4020b7a7f..9b8bf925a 100644 --- a/web_src/js/utils.js +++ b/web_src/js/utils.js @@ -70,3 +70,18 @@ export function prettyNumber(num, locale = 'en-US') { export function parseUrl(str) { return new URL(str, str.startsWith('http') ? undefined : window.location.origin); } + +// return current locale chosen by user +function getCurrentLocale() { + return document.documentElement.lang; +} + +// given a month (0-11), returns it in the documents language +export function translateMonth(month) { + return new Date(Date.UTC(2022, month, 12)).toLocaleString(getCurrentLocale(), {month: 'short'}); +} + +// given a weekday (0-6, Sunday to Saturday), returns it in the documents language +export function translateDay(day) { + return new Date(Date.UTC(2022, 7, day)).toLocaleString(getCurrentLocale(), {weekday: 'short'}); +} diff --git a/web_src/js/utils.test.js b/web_src/js/utils.test.js index 7bf5bb7eb..0567a5c64 100644 --- a/web_src/js/utils.test.js +++ b/web_src/js/utils.test.js @@ -1,7 +1,7 @@ import {expect, test} from 'vitest'; import { basename, extname, isObject, uniq, stripTags, joinPaths, parseIssueHref, - prettyNumber, parseUrl, + prettyNumber, parseUrl, translateMonth, translateDay } from './utils.js'; test('basename', () => { @@ -109,3 +109,25 @@ test('parseUrl', () => { expect(parseUrl('https://localhost/path?search').search).toEqual('?search'); expect(parseUrl('https://localhost/path?search#hash').hash).toEqual('#hash'); }); + +test('translateMonth', () => { + const originalLang = document.documentElement.lang; + document.documentElement.lang = 'en-US'; + expect(translateMonth(0)).toEqual('Jan'); + expect(translateMonth(4)).toEqual('May'); + document.documentElement.lang = 'es-ES'; + expect(translateMonth(5)).toEqual('jun'); + expect(translateMonth(6)).toEqual('jul'); + document.documentElement.lang = originalLang; +}); + +test('translateDay', () => { + const originalLang = document.documentElement.lang; + document.documentElement.lang = 'fr-FR'; + expect(translateDay(1)).toEqual('lun.'); + expect(translateDay(5)).toEqual('ven.'); + document.documentElement.lang = 'pl-PL'; + expect(translateDay(1)).toEqual('pon.'); + expect(translateDay(5)).toEqual('pt.'); + document.documentElement.lang = originalLang; +}); diff --git a/web_src/less/_base.less b/web_src/less/_base.less index 6846a21ef..f1691d815 100644 --- a/web_src/less/_base.less +++ b/web_src/less/_base.less @@ -168,6 +168,7 @@ --color-active-line: #fffbdd; accent-color: var(--color-accent); + color-scheme: light; } :root * { diff --git a/web_src/less/_install.less b/web_src/less/_install.less index 5769ef68b..515d727f8 100644 --- a/web_src/less/_install.less +++ b/web_src/less/_install.less @@ -1,36 +1,57 @@ .page-content.install { padding-top: 45px; - form { - @input-padding: 320px !important; + form.ui.form { + @input-padding: 30%; - .inline.field label { + .inline.field > label { text-align: right; width: @input-padding; + padding-right: 10px; + margin-right: 0; + } + + .inline.field > .ui.checkbox:first-child { + margin-left: @input-padding; + padding-left: 5px; + label { + width: auto; + } + } + + .title { + margin-left: @input-padding; + padding-left: 5px; } input { - width: 35% !important; + width: 60%; + } + + details.optional.field { + &[open] { + border-bottom: 1px solid var(--color-secondary); + padding-bottom: 10px; + + summary { + margin-bottom: 10px; + } + } + + * { + box-sizing: border-box; + } } .field { text-align: left; .help { - margin-left: @input-padding+15px; + margin-left: @input-padding; + padding-left: 5px; + width: 60%; } - &.optional { - .title { - margin-left: 38%; - } - .checkbox { - margin-left: 40% !important; - label { - width: auto !important; - } - } - } } } diff --git a/web_src/less/_repository.less b/web_src/less/_repository.less index 039c47130..193a73c70 100644 --- a/web_src/less/_repository.less +++ b/web_src/less/_repository.less @@ -3477,3 +3477,41 @@ td.blob-excerpt { max-width: 165px; } } + +.pr-status { + padding: 0 !important; // To clear fomantic's padding on .ui.segment elements + display: flex; + align-items: center; + + .commit-status { + margin: 1em; + flex-shrink: 0; + } + + .status-context { + display: flex; + justify-content: space-between; + width: 100%; + + > span { + padding: 1em 0; + } + } + + .status-details { + display: flex; + padding-right: .5em; + align-items: center; + justify-content: flex-end; + + @media @mediaSm { + flex-direction: column; + align-items: flex-end; + justify-content: center; + } + + > span { + padding-right: .5em; // To match the alignment with the "required" label + } + } +} diff --git a/web_src/less/features/codeeditor.less b/web_src/less/features/codeeditor.less index 3bd290876..f7e777740 100644 --- a/web_src/less/features/codeeditor.less +++ b/web_src/less/features/codeeditor.less @@ -1,4 +1,5 @@ -.monaco-editor-container { +.monaco-editor-container, +.editor-loading.is-loading { width: 100%; min-height: 200px; height: 90vh; diff --git a/web_src/less/markup/content.less b/web_src/less/markup/content.less index 7ee55ea7f..80c6267af 100644 --- a/web_src/less/markup/content.less +++ b/web_src/less/markup/content.less @@ -537,6 +537,7 @@ width: 100%; height: var(--height-loading); // actual height is set in JS after loading overflow: hidden; + color-scheme: normal; // match the value inside the iframe to allow it to become transparent } .markup-block-error { diff --git a/web_src/less/themes/theme-arc-green.less b/web_src/less/themes/theme-arc-green.less index a2d2e5d08..229ffd893 100644 --- a/web_src/less/themes/theme-arc-green.less +++ b/web_src/less/themes/theme-arc-green.less @@ -153,10 +153,9 @@ --color-accent: var(--color-primary-light-1); --color-small-accent: var(--color-primary-light-5); --color-active-line: #534d1b; -} -::-webkit-calendar-picker-indicator { - filter: invert(.8); + accent-color: var(--color-accent); + color-scheme: dark; } /* invert emojis that are hard to read otherwise */